Tizen 2.1 base
[platform/upstream/epson-inkjet-printer-escpr.git] / src / wrapper.c
1 /*
2  * Epson Inkjet Printer Driver (ESC/P-R) for Linux
3  * Copyright (C) 2002-2005 AVASYS CORPORATION.
4  * Copyright (C) Seiko Epson Corporation 2002-2012.
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #  include <config.h>
23 #endif
24
25 #include <cups/cups.h>
26 #include <cups/ppd.h>
27 #include <cups/raster.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <ctype.h>
34 /* added 22-04-2004 */
35 #include <signal.h>
36
37 #define NAME_MAX 41
38
39 #define WIDTH_BYTES(bits) (((bits) + 31) / 32 * 4)
40
41 #define PIPSLITE_WRAPPER_VERSION "* epson-escpr-wrapepr is a part of " PACKAGE_STRING
42
43
44 typedef struct rtp_filter_option {
45         char model[NAME_MAX + 1];
46         char model_low[NAME_MAX + 1];
47         char ink[NAME_MAX + 1];
48         char media[NAME_MAX + 1];
49         char quality[NAME_MAX + 1];
50         char duplex[NAME_MAX + 1];
51 } filter_option_t;
52
53 /* Static functions */
54 static int get_option_for_ppd (const char *, filter_option_t *);
55 static int get_option_for_arg (const char *, filter_option_t *);
56 /* Get value for PPD. */
57 static char * get_default_choice (ppd_file_t *, const char *);
58
59 /* added 22-04-2004 */
60 static void sig_set (void);
61 static void sigterm_handler (int sig);
62
63 int cancel_flg;
64
65 #include <stdarg.h>
66 #define DEBUG_PATH "/tmp/eps_wrapper.txt"
67 static FILE *debug_f = NULL;
68 #define HAVE_DEBUG 0
69 static void debug_msg(const char *fmt, ...){
70 #if (HAVE_DEBUG)        
71         va_list ap;
72         
73         if(!debug_f){
74                 debug_f = fopen(DEBUG_PATH, "wb");
75                 if(debug_f == NULL){
76                         return;
77                 }
78                 fchmod (fileno (debug_f), 0777);
79         }
80         
81         va_start (ap, fmt);
82         vfprintf (debug_f, fmt, ap);
83         fflush(debug_f);
84         va_end (ap);
85 #endif
86         return;
87 }
88
89 /*
90  * $$$ CUPS Filter Options $$$
91  *
92  * printer  - The name of the printer queue
93  *            (normally this is the name of the program being run)
94  * job      - The numeric job ID for the job being printed
95  * user     - The string from the originating-user-name attribute
96  * title    - The string from the job-name attribute
97  * copies   - The numeric value from the number-copies attribute
98  * options  - String representations of the job template attributes, separated
99  *            by spaces. Boolean attributes are provided as "name" for true
100  *            values and "noname" for false values. All other attributes are
101  *            provided as "name=value" for single-valued attributes and
102  *            "name=value1,value2,...,valueN" for set attributes
103  * filename - The request file
104  */
105 int
106 main (int argc, char *argv[])
107 {
108         int fd;                 /* file descriptor */
109         FILE *pfp;
110         int i;                  /* loop */
111         cups_raster_t *ras;     /* raster stream for printing */
112         cups_page_header_t header; /* page device dictionary header */
113         filter_option_t fopt;
114
115 /* attach point */
116 #ifdef USE_DEBUGGER
117         int flag = 1;
118         while (flag) sleep (3);
119 #endif /* USE_DEBUGGER */
120
121
122         cancel_flg = 0;
123         memset (&fopt, 0, sizeof (filter_option_t));
124         /* added 22-04-2004 */
125         sig_set();
126
127         if (argc < 6 || argc > 7)
128         {
129                 for ( i = 1; i < argc; i++ ) {
130                         if ( (0 == strncmp(argv[i], "-v", (strlen("-v")+1)) )
131                                 || (0 == strncmp(argv[i], "--version", (strlen("--version")+1)) )
132                                 ) {
133                                 fprintf(stderr, "%s\n", PIPSLITE_WRAPPER_VERSION);
134                                 return 0;
135                         } else if ( (0 == strncmp(argv[i], "-h", (strlen("-h")+1)) )
136                                 || (0 == strncmp(argv[i], "--help", (strlen("--help")+1)) )
137                                 ) {
138                                 fprintf(stderr, "%s\n", PIPSLITE_WRAPPER_VERSION);
139                                 return 0;
140                         }
141                 }
142                 fprintf (stderr, "Insufficient options.\n");
143                 return 1;
144         }
145
146         if (argc == 7)
147         {
148                 fd = open (argv[6], O_RDONLY);
149                 if (fd < 0)
150                 {
151                         perror ("open");
152                         return 1;
153                 }
154         }
155         else
156         {
157                 fd = 0;
158         }
159          
160         if (get_option_for_arg (argv[5], &fopt))
161         {
162                 fprintf (stderr, "Cannot read filter option. Cannot get option of PIPS.");
163                 debug_msg("Cannot read filter option. Cannot get option of PIPS.");
164                 return 1;
165         }
166         if (get_option_for_ppd (argv[0], &fopt))
167         {
168                 fprintf (stderr, "PPD file not found, or PPD file is broken. Cannot get option of PIPS.");
169                 debug_msg("PPD file not found, or PPD file is broken. Cannot get option of PIPS.");
170                 return 1;
171         }
172         /* Print start */
173         ras = cupsRasterOpen (fd, CUPS_RASTER_READ);
174         if (ras == NULL)
175         {
176                 fprintf (stderr, "Can't open CUPS raster file.");
177                 debug_msg("Can't open CUPS raster file");
178                 return 1;
179         }
180
181         pfp = NULL;
182         while (cupsRasterReadHeader (ras, &header) && !cancel_flg)
183         {
184                 int image_bytes;
185                 char *image_raw;
186                 int write_size = 0;
187
188                 if (pfp == NULL)
189                 {
190                         char tmpbuf[256];
191
192                         sprintf (tmpbuf, "%s/%s \"%s\" %d %d %d %s %s %s %s",
193                                  CUPS_FILTER_PATH,
194                                  CUPS_FILTER_NAME,
195                                  fopt.model,
196                                  header.cupsWidth,
197                                  header.cupsHeight,
198                                  header.HWResolution[0],
199                                  fopt.ink,
200                                  fopt.media,
201                                  fopt.quality,
202                                  fopt.duplex);
203                         
204                         debug_msg("tmpbuf = [%s]\n", tmpbuf);
205                         pfp = popen (tmpbuf, "w");
206
207                         if (pfp == NULL)
208                         {
209                                 debug_msg("popen error");
210                                 perror ("popen");
211                                 return 1;
212                         }
213                 }
214
215                 image_bytes = WIDTH_BYTES(header.cupsBytesPerLine * 8);
216                 image_raw = (char *)calloc (sizeof (char), image_bytes);
217
218                 for (i = 0; i < header.cupsHeight && !cancel_flg; i ++)
219                 {
220                         if (!cupsRasterReadPixels (ras, (unsigned char*)image_raw, header.cupsBytesPerLine))
221                         {
222                                 fprintf (stderr, "cupsRasterReadPixels");
223                                 debug_msg("cupsRasterReadPixels error");
224                                 return 1;
225                         }
226                         
227                         write_size = fwrite (image_raw, image_bytes, 1, pfp);
228                         if (write_size != 1)
229                         {
230                                 perror ("fwrite");
231                                 debug_msg("fwrite error");
232                                 return 8;
233                         }
234                 }
235                 
236                 free (image_raw);
237         }
238         
239         pclose (pfp);
240         cupsRasterClose (ras);
241         return 0;
242 }
243
244
245 static int
246 get_option_for_ppd (const char *printer, filter_option_t *filter_opt_p)
247 {
248         char *ppd_path;         /* Path of PPD */
249         ppd_file_t *ppd_p;      /* Struct of PPD */
250         char *opt;              /* Temporary buffer (PPD option) */
251         int i;                  /* loop */
252
253         /* Get option from PPD. */
254         ppd_path = (char *) cupsGetPPD (printer);
255         ppd_p = ppdOpenFile (ppd_path);
256         if(NULL == ppd_p){
257                 return 1;
258         }
259
260         /* Make library file name */
261         strcpy (filter_opt_p->model, ppd_p->modelname);
262         for (i = 0; filter_opt_p->model[i] != '\0' && i < NAME_MAX; i ++)
263                 filter_opt_p->model_low[i] = tolower (filter_opt_p->model[i]);
264         filter_opt_p->model_low[i] = '\0';
265
266         /* media */
267         if (filter_opt_p->media[0] == '\0')
268         {
269                 opt = get_default_choice (ppd_p, "PageSize");
270                 if (!opt)
271                         return 1;
272
273                 strcpy (filter_opt_p->media, opt);
274         }
275
276         /* ink */
277         if (filter_opt_p->ink[0] == '\0')
278         {
279                 opt = get_default_choice (ppd_p, "Ink");
280                 if (!opt)
281                         return 1;
282
283                 strcpy (filter_opt_p->ink, opt);
284         }
285
286         /* quality */
287         if (filter_opt_p->quality[0] == '\0')
288         {
289                 opt = get_default_choice (ppd_p, "Quality");
290                 if (!opt)
291                         return 1;
292
293                 strcpy (filter_opt_p->quality, opt);
294         }
295
296         /* duplex */
297         if (filter_opt_p->duplex[0] == '\0')
298         {
299                 opt = get_default_choice (ppd_p, "Duplex");
300                 if (!opt)
301                 {
302                         debug_msg("can not get duplex\n");
303                         strcpy (filter_opt_p->duplex, "None");
304                         
305                 }
306                 else
307                 strcpy (filter_opt_p->duplex, opt);
308         }
309
310 #ifdef INK_CHANGE_SYSTEM
311         /* inkset */
312         if (filter_opt_p->inkset[0] == '\0')
313         {
314                 opt = get_default_choice (ppd_p, "InkSet");
315                 if (!opt)
316                         return 1;
317
318                 strcpy (filter_opt_p->inkset, opt);
319         }
320 #endif
321
322         ppdClose (ppd_p);
323         return 0;
324 }
325
326
327 static int
328 get_option_for_arg (const char *opt_str, filter_option_t *filter_opt_p)
329 {
330         int opt_num;
331         cups_option_t *option_p;
332         const char *opt;
333         
334         const char *media_names[] = { "PageSize", "PageRegion",  "media", "" };
335         int i;
336         
337         if (strlen (opt_str) == 0)
338                 return 0;
339
340         opt_num = 0;
341         option_p = NULL;
342         opt_num = cupsParseOptions (opt_str, opt_num, &option_p);
343
344         for (i = 0; *media_names[i] != '\0'; i ++)  /* chenged Wed Jan 28 2009 */
345         {
346                 opt = cupsGetOption (media_names[i], opt_num, option_p);
347                 if (opt)
348                 {
349                         int num;
350
351                         num = strcspn (opt, ",");
352                         if (num >= PPD_MAX_NAME)
353                         {
354                                 return 1;
355                         }
356
357                         strncpy (filter_opt_p->media, opt, num);
358                         filter_opt_p->media[num] = '\0';
359
360                         break;
361                 }
362         }
363
364         opt = cupsGetOption ("Ink", opt_num, option_p);
365         if (opt)
366                 strcpy (filter_opt_p->ink, opt);
367
368         opt = cupsGetOption ("Quality", opt_num, option_p);
369         if (opt)
370         {
371                 strcpy (filter_opt_p->quality, opt);
372                 debug_msg("Quality = [%s]\n", opt);
373         }
374
375         opt = cupsGetOption ("Duplex", opt_num, option_p);
376         if (opt)
377                 strcpy (filter_opt_p->duplex, opt);
378
379         return 0;
380 }
381
382
383 /* Get value for PPD */
384 static char *
385 get_default_choice (ppd_file_t *ppd_p, const char *key)
386 {
387         ppd_option_t *option;
388         ppd_choice_t *choice;
389
390         option = ppdFindOption (ppd_p, key);
391         if (!option)
392                 return NULL;
393         
394         choice = ppdFindChoice (option, option->defchoice);
395         if (!choice)
396                 return NULL;
397
398         return choice->choice;
399 }
400
401 static void
402 sig_set (void)
403 {
404
405 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
406         sigset (SIGTERM, sigterm_handler);
407 #elif defined(HAVE_SIGACTION)
408         {
409           struct sigaction action;
410
411           memset (&action, 0, sizeof(action));
412
413           sigemptyset (&action.sa_mask);
414           action.sa_handler = sigterm_handler;
415           sigaction (SIGTERM, &action, NULL);
416         }
417 #else
418         signal (SIGTERM, sigterm_handler);
419 #endif /* HAVE_SIGSET */
420
421   return;
422 }
423
424
425 static void
426 sigterm_handler (int sig)
427 {
428   cancel_flg = 1;
429
430   return;
431 }