View difference between Paste ID: 7RfFC8vX and vfnzTwGJ
SHOW: | | - or go back to the newest paste.
1
/*
2
 *  CUPS add-on module for Canon Inkjet Printer.
3
 *  Copyright CANON INC. 2001-2013
4
 *  All Rights Reserved.
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; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
18
 */
19
20
#if HAVE_CONFIG_H
21
#include	<config.h>
22
#endif	// HAVE_CONFIG_H
23
24
#include <cups/cups.h>
25
#include <cups/language.h>
26
#include <cups/ppd.h>
27
#include <cups/ipp.h>
28
#include <unistd.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <popt.h>
32
#include <sys/types.h>
33
#include <sys/wait.h>
34
35
#include "cncl.h"
36
#include "cncldef.h"
37
#include "cncl2def.h"
38
#include "cncludef.h"
39
#include "cnclucom.h"
40
41
#include "paramlist.h"
42
#include "bjipc.h"
43
#include "bjcups.h"
44
#include "bjutil.h"
45
46
#define	BJCUPS_VERSION	"cngpij Ver.3.90  Copyright CANON INC. 2002-2013\n"
47
#define BJCUPS_INTVER	"cngpij Internal Version : 3.90.01.001\n"
48
49
#define	BJ_SOCKET		"/tmp/ijui"
50
51
#define	UI_PATH			PROG_PATH
52
//#define	UI_PATH			"/usr/local/bin/"
53
#define	UI_SLASH		"/"
54
#define	UI_NAME			"printui"
55
56
#define	UI_OPT_VERSION	1
57
#define	UI_OPT_PRINTER	2
58
#define	UI_OPT_OTHERS	4
59
#define	UI_OPT_INTVER	8
60
#define	UI_OPT_CHECKENTRY	16
61
62
#define	LINE_BUF_SIZE	1024
63
#define CNPPD_SETTINGS_SUPPORT_DEVURI_OPT		"EnableDEVURIOption"
64
#define CNPPD_SETTINGS_SUPPORT_FRONTEND_OPT		"EnableFrontEnd" /* Ver.3.80 */
65
#define TRUE 1
66
#define FALSE 0
67
68
char* g_printer_name = NULL;
69
70
71
extern int GetIPCData(LPIPCU pipc, char *sname);
72
static short getDeviceURI( const char *pDestName, char *pDeviceURI, short bufSize);
73
74
75
int get_value_and_param_array(short id, short** value, char*** param)
76
{
77
	int count;
78
79
	switch( id )
80
	{
81
	case CNCL_MEDIATYPE:	// Media Type.
82
		*value = g_media_value;
83
		*param  = g_media_param;
84
		count = sizeof(g_media_value) / sizeof(short);
85
		break;
86
87
	case CNCL_MEDIASUPPLY:	// Media Supply.
88
		*value = g_supply_value;
89
		*param  = g_supply_param;
90
		count = sizeof(g_supply_value) / sizeof(short);
91
		break;
92
93
	case CNCL_PAPERSIZE:	// Paper Size.
94
		*value = g_size_value;
95
		*param  = g_size_param;
96
		count = sizeof(g_size_value) / sizeof(short);
97
		break;
98
99
	case CNCL_DITHER_PAT:		// Halftoning.
100
		*value = g_halftoning_value;
101
		*param  = g_halftoning_param;
102
		count = sizeof(g_halftoning_value) / sizeof(short);
103
		break;
104
105
	case CNCL_CARTRIDGE:		// Cartridge.
106
		*value = g_cartridge_value;
107
		*param  = g_cartridge_param;
108
		count = sizeof(g_cartridge_value) / sizeof(short);
109
		break;
110
111
	case CNCL_PRINTQUALITY:		// Print quality.
112
		*value = g_quality_value;
113
		*param  = g_quality_param;
114
		count = sizeof(g_quality_value) / sizeof(short);
115
		break;
116
117
	case CNCL_INPUT_GAMMA:		// Input gamma.
118
		*value = g_input_gamma_value;
119
		*param  = g_input_gamma_param;
120
		count = sizeof(g_input_gamma_value) / sizeof(short);
121
		break;
122
123
	case CNCL_GRAYSCALE:		// Grayscale.
124
		*value = g_grayscale_value;
125
		*param  = g_grayscale_param;
126
		count = sizeof(g_grayscale_value) / sizeof(short);
127
		break;
128
129
	case CNCL_PAPERGAP_COMMAND:	// Paper gap.
130
		*value = g_paper_gap_value;
131
		*param  = g_paper_gap_param;
132
		count = sizeof(g_paper_gap_value) / sizeof(short);
133
		break;
134
135
	case CNCL_DUPLEX_PRINTING:	// Duplex printing.
136
		*value = g_duplex_value;
137
		*param  = g_duplex_param;
138
		count = sizeof(g_duplex_value) / sizeof(short);
139
		break;
140
141
	case EXT_CNCL_INTENT:		// Intent.
142
		*value = g_intent_value;
143
		*param  = g_intent_param;
144
		count = sizeof(g_intent_value) / sizeof(short);
145
		break;
146
147
	case EXT_CNCL_LOCATION:		// Location.
148
		*value = g_location_value;
149
		*param  = g_location_param_lpr;	/* Ver.3.00 */
150
		count = sizeof(g_location_value) / sizeof(short);
151
		break;
152
153
	case EXT_CNCL_STAPLESIDE:	// Staple side.
154
		*value = g_staple_side_value;
155
		*param  = g_staple_side_param;
156
		count = sizeof(g_staple_side_value) / sizeof(short);
157
		break;
158
159
	case CNCL_INKCARTRIDGESETTINGS:	// InkCartridgeSettings.
160
		*value = g_cartridge_value;
161
		*param  = g_cartridge_param;
162
		count = sizeof(g_cartridge_value) / sizeof(short);
163
		break;
164
165
	default:
166
		*value = NULL;
167
		*param  = NULL;
168
		count = 0;
169
		break;
170
	}
171
172
	return count;
173
}
174
175
char *value_to_param(short id, short value)
176
{
177
	short *value_array;
178
	char **key_array;
179
	int count;
180
	int i;
181
182
	count = get_value_and_param_array(id, &value_array, &key_array);
183
184
	for( i = 0 ; i < count ; i++ )
185
	{
186
		if( value_array[i] == value )
187
			break;
188
	}
189
	return (i < count)? key_array[i] :  "";
190
}
191
192
void add_option_param(ParamList **pp_list, char *key, int id, int value)
193
{
194
	char param[1024];
195
196
	snprintf(param, 1023, "%s=%s", key, value_to_param(id, value));
197
	param_list_add_multi(pp_list, "-o", param, strlen(param) + 1, 1);
198
}
199
200
/* Ver.3.00 */
201
void add_option_param_bl(ParamList **pp_list, char *key, int id, int value)
202
{
203
	char param[1024];
204
205
	snprintf(param, 1023, "%s=%s.bl", key, value_to_param(id, value));
206
	param_list_add_multi(pp_list, "-o", param, strlen(param) + 1, 1);
207
}
208
209
210
void add_option_value(ParamList **pp_list, char *key, int value)
211
{
212
	char param[1024];
213
214
	snprintf(param, 1023, "%s=%d", key, value);
215
	param_list_add_multi(pp_list, "-o", param, strlen(param) + 1, 1);
216
}
217
218
void add_option_string(ParamList **pp_list, char *key, char *str)
219
{
220
	char param[1024];
221
222
	snprintf(param, 1023, "%s=%s", key, str);
223
	param_list_add_multi(pp_list, "-o", param, strlen(param) + 1, 1);
224
}
225
226
227
/* Ver.3.20 */
228
static void char_lower( char *string, short len )
229
{
230
	short	count;
231
	short	dis;
232
	char	*current_char = string;
233
	
234
	dis='a'-'A';
235
	
236
	for( count = 0; count < len ; count++ )
237
	{
238
		if( (*current_char >= 'A') && (*current_char <= 'Z') ) *current_char += dis;
239
		current_char++;
240
	}
241
}
242
243
244
/* Ver.3.20:check entry exist or not (use cupsGetDests2) */
245
static short check_entry_name(const char *printer_name)
246
{
247
	http_t			*pHTTP = NULL;			// Pointer to HTTP connection.
248
	int				num = 0;
249
	int				count;
250
	cups_dest_t		*dests = NULL;
251
	cups_dest_t		*current_dests;
252
	char			target_name[256];
253
	char			compare_name[256];
254
	short			target_name_len;
255
	short			result = 1;				/* not exist */
256
	char	devURIBuf[10224];
257
258
	getDeviceURI( printer_name, devURIBuf, sizeof(devURIBuf) );
259
260
	target_name_len = strlen( printer_name );
261
	if( target_name_len > 255 )
262
	{
263
		fputs("ERROR: too long name\n", stderr);
264
		goto onErr;
265
	}
266
267
	memset( target_name , 0x00 , 256 );
268
	strncpy( target_name , printer_name , target_name_len );
269
	char_lower( target_name , target_name_len );
270
271
	
272
	pHTTP = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
273
	if( pHTTP == NULL){
274
		fputs("ERROR: IPP ERROR\n", stderr);
275
		goto onErr;
276
	}
277
	else
278
	{
279
		num = cupsGetDests2( pHTTP , &dests );
280
		current_dests = dests;
281
		for( count = 0; count < num ; count++ )
282
		{
283
			memset( compare_name , 0x00 , 256 );
284
285
			if( strlen(current_dests->name) == target_name_len )		/* length compare first */
286
			{
287
				strncpy( compare_name , current_dests->name , strlen( current_dests->name ) );
288
				char_lower( compare_name , strlen( compare_name ) );
289
290
	
291
				if( !strncmp( target_name , compare_name , target_name_len ) )
292
				{
293
					result = 0;		/* exist */
294
					goto onErr;
295
				}
296
			}
297
			else
298
			{
299
			}
300
			current_dests++;
301
		}
302
	}
303
	
304
onErr:
305
	if( pHTTP != NULL ) httpClose(pHTTP);
306
	if( dests != NULL ) cupsFreeDests(num,dests);
307
	
308
	return result;
309
}
310
311
312
313
int init_option(ParamList **pp_list, int argc, char* argv[])
314
{
315
	static struct poptOption option_table[] =
316
	{
317
		{"version", 'v',               0, NULL, UI_OPT_VERSION},
318
		{"internalversion", 0,  POPT_ARG_NONE,    NULL,  UI_OPT_INTVER },	/* Ver.2.70 */
319
		{"checkentryexist", 0,  POPT_ARG_STRING,    NULL,  UI_OPT_CHECKENTRY },	/* Ver.3.20 */
320
		{NULL,      'P', POPT_ARG_STRING, NULL, UI_OPT_PRINTER},
321
		{NULL,      'o', POPT_ARG_STRING, NULL, UI_OPT_OTHERS },
322
		{NULL,        0,               0, NULL, 0}
323
	};
324
325
	poptContext context
326
		= poptGetContext("cngpij", argc, (const char**)argv, option_table, 0);
327
	int rc;
328
329
	while( (rc = poptGetNextOpt(context)) > 0 )
330
	{
331
		switch( rc )
332
		{
333
		case UI_OPT_VERSION:
334
			fputs(BJCUPS_VERSION, stderr);
335
			exit(1);
336
337
		case UI_OPT_CHECKENTRY:
338
		{
339
			g_printer_name = strdup(poptGetOptArg(context));
340
			if( check_entry_name(g_printer_name) == 1 )
341
			{
342
				fputs("ERROR: Illegal printer name.\n", stderr);
343
				exit(1);
344
			}
345
			else{
346
				fputs("Exist\n", stderr);
347
				exit(0);
348
			}
349
		}
350
		case UI_OPT_PRINTER:
351
			g_printer_name = strdup(poptGetOptArg(context));
352
			break;
353
354
		case UI_OPT_OTHERS:
355
		{
356
			const char *option = poptGetOptArg(context);
357
			param_list_add(pp_list, "-o", option, strlen(option) + 1);
358
			break;
359
		}
360
		case UI_OPT_INTVER:
361
		{
362
			fputs(BJCUPS_INTVER, stderr);
363
			exit(1);
364
		}
365
		default:
366
			break;
367
		}
368
	}
369
370
	if( rc < -1 )
371
	{
372
		fprintf(stderr, "Unknown switch, %s\n",
373
			poptBadOption(context, POPT_BADOPTION_NOALIAS));
374
375
		return rc;
376
	}
377
	return 0;
378
}
379
380
static
381
char *parse_product_name(char *ppd_product, char *product, int len)
382
{
383
	char *p_product = product;
384
	char *p_cc;
385
	int count = 0;
386
387
	memset(product, 0, len);
388
	p_cc = ppd_product;
389
390
	while( *p_cc == '(' )
391
		p_cc++;
392
393
	while( *p_cc != ')' && *p_cc != '\0' && count < len - 1 )
394
	{
395
		*p_product++ = *p_cc++;
396
		count++;
397
	}
398
	*p_product = '\0';
399
400
	return product;
401
}
402
403
char *get_product_name(const char *printer_name, char *product_name, int len)
404
{
405
	const char *ppd_name = cupsGetPPD(printer_name);
406
	char *p_product = NULL;
407
	static char product[256];
408
409
	if( len < 1 )
410
		return NULL;
411
412
	if( ppd_name != NULL )
413
	{
414
		ppd_file_t *p_ppd;
415
416
		if( (p_ppd = ppdOpenFile(ppd_name)) != NULL )
417
		{
418
			if( !strcmp(p_ppd->manufacturer, "Canon") )
419
			{
420
				p_product = parse_product_name(p_ppd->product, product, 256);
421
				strncpy(product_name, product, len - 1);
422
			}
423
			ppdClose(p_ppd);
424
		}
425
		unlink( ppd_name );	/* Ver.3.00 : You should remove the copy of the PPD file. */
426
		
427
	}
428
	return p_product;
429
}
430
431
void get_paper_dimension_points(IPCU *p_ipc, double *p_pw, double* p_ph)
432
{
433
	BJFLTDEVICE *p_fltdev = &p_ipc->parm.bjfltdev;
434
	CNCLPAPERSIZE *p_papersize = &p_ipc->parm.papersize;
435
	double pw_pt = (double)p_fltdev->bjfltPaperWidth * 72.0 / 2540.0;
436
	double ph_pt = (double)p_fltdev->bjfltPaperHeight * 72.0 / 2540.0;
437
	long rw_mm = (long)(pw_pt * 2540.0 / 72.0);
438
	long rh_mm = (long)(ph_pt * 2540.0 / 72.0);
439
	long minw_mm = p_papersize->nMinCustomWidth;
440
	long maxw_mm = p_papersize->nMaxCustomWidth;
441
	long minh_mm = p_papersize->nMinCustomLength;
442
	long maxh_mm = p_papersize->nMaxCustomLength;
443
	long dw = 0;
444
	long dh = 0;
445
446
	while( rw_mm < minw_mm )
447
	{
448
		dw++;
449
		pw_pt = (double)(p_fltdev->bjfltPaperWidth + dw) * 72.0 / 2540.0;
450
		rw_mm = (long)(pw_pt * 2540.0 / 72.0);
451
	}
452
	while( rw_mm > maxw_mm )
453
	{
454
		dw--;
455
		pw_pt = (double)(p_fltdev->bjfltPaperWidth + dw) * 72.0 / 2540.0;
456
		rw_mm = (long)(pw_pt * 2540.0 / 72.0);
457
	}
458
	while( rh_mm < minh_mm )
459
	{
460
		dh++;
461
		ph_pt = (double)(p_fltdev->bjfltPaperHeight + dh) * 72.0 / 2540.0;
462
		rh_mm = (long)(ph_pt * 2540.0 / 72.0);
463
	}
464
	while( rh_mm > maxh_mm )
465
	{
466
		dh--;
467
		ph_pt = (double)(p_fltdev->bjfltPaperHeight + dh) * 72.0 / 2540.0;
468
		rh_mm = (long)(ph_pt * 2540.0 / 72.0);
469
	}
470
471
	*p_pw = pw_pt;
472
	*p_ph = ph_pt;
473
}
474
475
char **make_lpr_param(ParamList **pp_list, char *printer,
476
						IPCU *p_ipc, char *print_file)
477
{
478
	BJFLTDEVICE *p_fltdev = &p_ipc->parm.bjfltdev;
479
	BJFLTCOLORSYSTEM *p_fltcol = &p_ipc->parm.bjfltcolor;
480
	BJFLT_UISETUP *p_uiset = &p_ipc->parm.bjflt_uisetup;
481
	CNCLPAPERSIZE *p_papersize = &p_ipc->parm.papersize;
482
	char **cmd_buf;
483
	int cmd_buf_index;
484
	int cmd_num;
485
486
	add_option_param(pp_list, "CNCartridge",
487
			CNCL_CARTRIDGE, p_fltdev->bjfltInkType);
488
489
	add_option_param(pp_list, "MediaType",
490
			CNCL_MEDIATYPE, p_fltdev->bjfltMediaType);
491
492
	if( p_fltdev->bjfltPaperSize == CND_SIZE_USER )
493
	{
494
		double pw, ph;
495
		char custom_size[256];
496
497
		get_paper_dimension_points(p_ipc, &pw, &ph);
498
		snprintf(custom_size, 255, "Custom.%lfx%lf", pw, ph);
499
500
		add_option_string(pp_list, "PageSize", custom_size);
501
	}
502
	else
503
	{
504
		/* If Borderless Printing is ON, add ".bl" to PageSize parameter. (Ver.3.00) */
505
		if( p_fltdev->bjfltMarginType == CND_MARGIN_MINUS )
506
		{
507
			add_option_param_bl(pp_list, "PageSize",
508
				CNCL_PAPERSIZE, p_fltdev->bjfltPaperSize);
509
		}else{
510
			add_option_param(pp_list, "PageSize",
511
				CNCL_PAPERSIZE, p_fltdev->bjfltPaperSize);
512
		}
513
	}
514
515
	add_option_param(pp_list, "InputSlot",
516
			CNCL_MEDIASUPPLY, p_fltdev->bjfltMediaSupply);
517
518
	/* Ver.3.60: disable CNHalftoning */
519
	if ( p_fltdev->bjfltBinMethod != CND_UIBIN_NA ){
520
		add_option_param(pp_list, "CNHalftoning",
521
				CNCL_DITHER_PAT, p_fltdev->bjfltBinMethod);
522
	}
523
524
	add_option_param(pp_list, "CNGrayscale",
525
			CNCL_GRAYSCALE, p_fltdev->bjfltGrayScale);
526
527
	add_option_param(pp_list, "CNQuality",
528
			CNCL_PRINTQUALITY, p_fltdev->bjfltPrintQuality);
529
530
	add_option_param(pp_list, "CNGamma",
531
			CNCL_INPUT_GAMMA, p_fltcol->bjfltGamma);
532
533
	if( p_fltdev->bjfltPaperGap != CND_PGAP_CMD_NA )
534
	{
535
		add_option_param(pp_list, "CNPaperGap",
536
			CNCL_PAPERGAP_COMMAND, p_fltdev->bjfltPaperGap);
537
	}
538
539
	add_option_param(pp_list, "CNRenderIntent",
540
			EXT_CNCL_INTENT, p_fltcol->bjfltIntent);
541
542
	/* Use "position" instead of "CNLocation" (Ver.3.00) */
543
	add_option_param(pp_list, "position",
544
			EXT_CNCL_LOCATION, p_uiset->bjflt_location);
545
546
	if( p_fltdev->bjfltDuplex == CND_DUPLEX_AUTO )
547
	{
548
		add_option_param(pp_list, "Duplex",
549
			CNCL_DUPLEX_PRINTING, p_fltdev->bjfltDuplex);
550
551
		add_option_param(pp_list, "CNStapleSide",
552
			EXT_CNCL_STAPLESIDE, p_uiset->bjflt_stapleside);
553
	}
554
555
	if( p_fltdev->bjfltInkcartridgesettings != CND_CARTRIDGE_NA )
556
	{
557
		add_option_param(pp_list, "CNInkCartridgeSettings",
558
			CNCL_INKCARTRIDGESETTINGS, p_fltdev->bjfltInkcartridgesettings);
559
	}
560
561
	add_option_value(pp_list, "CNBalanceC", p_fltcol->bjfltBalanceC);
562
	add_option_value(pp_list, "CNBalanceM", p_fltcol->bjfltBalanceM);
563
	add_option_value(pp_list, "CNBalanceY", p_fltcol->bjfltBalanceY);
564
565
	/* Ver.2.70 */
566
	if( p_fltcol->bjfltBalanceK != 0 )		/* 0...option not supported or default value */
567
	{	
568
		if( p_fltcol->bjfltBalanceK >= -50 && p_fltcol->bjfltBalanceK <= 50 ){
569
			add_option_value(pp_list, "CNBalanceK", p_fltcol->bjfltBalanceK);
570
		}
571
	}
572
	
573
	if( p_fltcol->bjfltContrast != 0 )		/* 0...option not supported or default value */
574
	{
575
		if( p_fltcol->bjfltContrast >= -50 && p_fltcol->bjfltContrast <= 50 ){
576
			add_option_value(pp_list, "CNContrast", p_fltcol->bjfltContrast);
577
		}
578
	}
579
580
	add_option_value(pp_list, "CNDensity",  p_fltcol->bjfltDensity);
581
582
	/* Ver.3.00 */
583
	/* Fit-to-Page Printing and Scaled Printing cannot be specified at the same time. */
584
	if( p_uiset->bjflt_fit == FIT_SHORT)
585
	{
586
		add_option_value(pp_list, "scaling",  100 );	//scaling=100
587
	}
588
	else if( p_uiset->bjflt_percent != 100)
589
	{
590
		/* If bjflt_percent is "100", "Scaled Printing" is not selected. */
591
		add_option_value(pp_list, "natural-scaling",  p_uiset->bjflt_percent);
592
	}
593
	
594
595
596
	/* Ver.3.00 */
597
	/* If Borderless Printing is ON, add CNExtension. */
598
	if( p_fltdev->bjfltMarginType == CND_MARGIN_MINUS )
599
	{
600
		add_option_value(pp_list, "CNExtension",  p_uiset->bjflt_extension);
601
	}
602
603
	/* Ver.3.40 */
604
	if( p_fltcol->bjfltMonochromeTone != 0 ){		/* 0...option not supported or default value */
605
		if( p_fltcol->bjfltMonochromeTone >= -50 && p_fltcol->bjfltMonochromeTone <= 50 ){
606
			add_option_value(pp_list, "CNTone", p_fltcol->bjfltMonochromeTone);
607
		}
608
	}
609
610
	add_option_value(pp_list, "CNCopies",   p_uiset->bjflt_copies);
611
612
	add_option_value(pp_list, "CNMinWidth",  p_papersize->nMinCustomWidth);
613
	add_option_value(pp_list, "CNMaxWidth",  p_papersize->nMaxCustomWidth);
614
	add_option_value(pp_list, "CNMinLength", p_papersize->nMinCustomLength);
615
	add_option_value(pp_list, "CNMaxLength", p_papersize->nMaxCustomLength);
616
617
#ifdef DEBUG_PARAM_LIST
618
	param_list_print(*pp_list);
619
#endif
620
	cmd_num = param_list_num(*pp_list);
621
	cmd_buf = (char**)malloc((cmd_num * 2 + 5) * sizeof(char*));
622
623
	if( cmd_buf )
624
	{
625
		ParamList *curs;
626
627
		cmd_buf[0] = "lpr";
628
		cmd_buf[1] = "-P";
629
		cmd_buf[2] = printer;
630
631
		cmd_buf_index = 3;
632
633
		for( curs = *pp_list ; curs != NULL ; curs = curs->next )
634
		{
635
			cmd_buf[cmd_buf_index++] = curs->key;
636
			cmd_buf[cmd_buf_index++] = curs->value;
637
		}
638
		cmd_buf[cmd_buf_index++] = print_file;
639
		cmd_buf[cmd_buf_index] = NULL;
640
	}
641
642
	return cmd_buf;
643
}
644
645
void exec_lpr(char **lpr_param)
646
{
647
	int pid = fork();
648
649
	if( pid == -1 )
650
		return;
651
652
	if( pid == 0 )
653
	{
654
		execv("/usr/bin/lpr", lpr_param);
655
		fputs("ERROR: Can't execute lpr command.\n", stderr);
656
	}
657
	else
658
	{
659
		waitpid(pid, NULL, 0);
660
	}
661
}
662
663
664
665
static cups_lang_t * bjcupsLangDefault( )
666
{
667
	cups_lang_t	*pLanguage;
668
	char		*tLang;	
669
	
670
	if( (tLang = getenv("LC_ALL"))==NULL)
671
			tLang = getenv("LANG");
672
	
673
	pLanguage = cupsLangDefault();
674
	setlocale(LC_ALL,tLang);
675
	
676
	return pLanguage;
677
}
678
679
680
681
static short getDeviceURI( const char *pDestName, char *pDeviceURI, short bufSize)
682
{
683
/*** Parameters start ***/
684
	http_t			*pHTTP;						// Pointer to HTTP connection.
685
	ipp_t			*pRequest,					// Pointer to CUPS IPP request.
686
					*pResponse;					// Pointer to CUPS IPP response.
687
	ipp_attribute_t	*pAttribute;				// Pointer to CUPS attributes.
688
	cups_lang_t		*pLanguage;					// Pointer to language.
689
	char			*pPrinter = NULL;			// Pointer to printer name.
690
	char			*pDUri = NULL;				// Pointer to Device uri.
691
	short			retVal = -1;	// Return value.
692
/*** Parameters end ***/
693
	
694
	// CUPS http connect.
695
	if ((pHTTP = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL) {
696
		fputs("ERROR: IPP ERROR\n", stderr);
697
		goto onErr;
698
	}
699
	else {
700
		pRequest = ippNew();
701
		
702
		pRequest->request.op.operation_id = CUPS_GET_PRINTERS;
703
		pRequest->request.op.request_id   = 1;
704
		
705
		pLanguage = bjcupsLangDefault();	// cupsLangDefault() -> bjcupsLangDefault() for cups-1.1.19
706
		
707
		ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, cupsLangEncoding(pLanguage));
708
		ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, pLanguage->language);
709
		ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, NULL);
710
		
711
		if ((pResponse = cupsDoRequest(pHTTP, pRequest, "/")) != NULL) {
712
			if (pResponse->request.status.status_code > IPP_OK_CONFLICT) {
713
				fputs("ERROR: IPP ERROR\n", stderr);
714
				goto onErr;
715
			}
716
			else {
717
				pAttribute = pResponse->attrs;
718
719
				while (pAttribute != NULL) {
720
					while (pAttribute != NULL && pAttribute->group_tag != IPP_TAG_PRINTER) {
721
						pAttribute = pAttribute->next;
722
					}
723
					if (pAttribute == NULL) {
724
						break;
725
					}
726
					
727
					while (pAttribute != NULL && pAttribute->group_tag == IPP_TAG_PRINTER) {
728
						if (strcmp(pAttribute->name, "printer-name") == 0 && pAttribute->value_tag == IPP_TAG_NAME) {
729
							pPrinter = pAttribute->values[0].string.text;
730
						}
731
						if (strcmp(pAttribute->name, "device-uri") == 0 && pAttribute->value_tag == IPP_TAG_URI) {
732
							pDUri = pAttribute->values[0].string.text;
733
						}
734
						pAttribute = pAttribute->next;
735
					}
736
737
					if (strcasecmp(pDestName, pPrinter) == 0) {
738
						strncpy(pDeviceURI, pDUri, bufSize);
739
						break;
740
					}
741
					
742
					if (pAttribute != NULL)
743
						 pAttribute = pAttribute->next;
744
				}
745
			}
746
			
747
			ippDelete(pResponse);
748
		}
749
		else {
750
			pDeviceURI = '\0';
751
			goto onErr;
752
		}
753
		
754
		cupsLangFree(pLanguage);
755
		httpClose(pHTTP);
756
	}
757
	
758
onErr:
759
	return(retVal);
760
}// End getDeviceURI
761
762
763
static int read_line(FILE *fp, char *buf, int buf_size)
764
{
765
	int cc = EOF;
766
	int i = 0;
767
768
	if( buf != NULL && buf_size > 0 )
769
	{
770
		while( (cc = fgetc(fp)) != EOF )
771
		{
772
			if( cc == 0x0d || cc == 0x0a )
773
				break;
774
			if( i < buf_size - 1 )
775
				buf[i++] = cc;
776
		}
777
		buf[i] = 0;
778
	}
779
780
	return (cc == EOF)? -1 : i;
781
}
782
783
784
static int ParseCNPpdOption( int *value, char *key )
785
{
786
	const char *p_ppd_name = cupsGetPPD( g_printer_name );
787
	char *keyStr;
788
	FILE *fp = NULL;
789
	char line_buf[LINE_BUF_SIZE];
790
	int result = -1;
791
792
	if ( (value == NULL) || (key == NULL) ) goto onErr1;
793
	*value = 0;	
794
795
	if ( (fp = fopen( p_ppd_name, "r" )) == NULL ) goto onErr1;
796
797
	while( read_line( fp, line_buf, LINE_BUF_SIZE ) >= 0 ){
798
		if( line_buf[0] == '*' && line_buf[1] == '%' ){
799
			keyStr = strtok(line_buf, " ");
800
			if ( (keyStr != NULL) && (!strcmp(keyStr, "*%CNPpdOptions")) ){
801
				keyStr = strtok(NULL, " ");
802
				while ( keyStr != NULL ){
803
					if ( !strcmp(keyStr, key) ){
804
						*value = 1;
805
						break;
806
					}								
807
					keyStr = strtok(NULL, " ");
808
				}
809
			}
810
		}
811
	}
812
813
	result = 0;
814
	if ( fp != NULL ) fclose( fp );
815
onErr1:
816
	return result;
817
}
818
819
static int isSupportMSI( void )
820
{
821
	int value;
822
	int result = FALSE;
823
824
	if ( ParseCNPpdOption( &value, CNPPD_SETTINGS_SUPPORT_DEVURI_OPT ) < 0 ) goto onErr;
825
826
	if ( value == 1 ) {
827
		result = TRUE;
828
	}
829
	else {
830
		result = FALSE;
831
	}
832
833
onErr:
834
	return result;
835
}
836
837
/* Ver.3.80 */
838
static int isSupportFrontEnd( void )
839
{
840
	int value;
841
	int result = FALSE;
842
843
	if ( ParseCNPpdOption( &value, CNPPD_SETTINGS_SUPPORT_FRONTEND_OPT ) < 0 ) goto onErr;
844
845
	if ( value == 1 ) {
846
		result = TRUE;
847
	}
848
	else {
849
		result = FALSE;
850
	}
851
852
onErr:
853
	return result;
854
}
855
856
857
int main(int argc, char* argv[])
858
{
859
	ParamList *p_list = NULL;
860
	int ui_pid;
861
	char *print_file;
862
	char product_name[64];
863
//	char ui_path[256];
864
	char *ui_path = NULL;
865
	char ui_name[256];
866
	char socket_name[64];
867
	char *ui_arg[8];
868
869
	/* Ver.3.20 */
870
	short		ret=-1;
871
	char		device_uri_buf[1024];
872
	short		device_uri_buf_len = 1024;
873
	char		*canon_usb_backend_str = "cnijusb:";
874
	char		*canon_net_backend_str = "cnijnet:";
875
	short		canon_backend_flag = 0;
876
	short		add_bidi = 0;
877
	short		add_direct = 0;
878
	const char 		*p_ppd_name;
879
	ppd_file_t	*p_ppd;
880
881
	/* Ver.3.70 */
882
	int arg_num;	
883
884
	if( argc == 1 )
885
	{
886
		fputs(BJCUPS_VERSION, stderr);
887
		fputs("Usage: cngpij [-P printer name] <file name>\n", stderr);
888
		exit(1);
889
	}
890
891
	print_file = argv[argc - 1];
892
893
	if( init_option(&p_list, argc, argv) < 0 )
894
		exit(1);
895
896
	if( g_printer_name == NULL )
897
	{
898
		const char *printer_name;
899
900
		if( (printer_name = cupsGetDefault()) != NULL )
901
			g_printer_name = strdup(printer_name);
902
		else
903
		{
904
			fputs("ERROR: Can't get default printer name.\n", stderr);
905
			exit(1);
906
		}
907
	}
908
909
	if( get_product_name(g_printer_name, product_name, 64) == NULL )
910
	{
911
		fputs("ERROR: Illegal printer name.\n", stderr);
912
		exit(1);
913
	}
914
915
	/* Ver.3.80 */
916
	if( isSupportFrontEnd() == TRUE )
917
	{
918
		fputs("ERROR: The specified printer is not supported.\n", stderr);
919
		exit(1);
920
	}
921
922
	/* Ver.3.20: Set canon_backend_flag. */
923
	{
924
		memset( device_uri_buf , 0x00 , device_uri_buf_len );
925
		ret = getDeviceURI( g_printer_name , device_uri_buf , device_uri_buf_len );
926
		if( ret < -1 )
927
		{
928
			fputs("ERROR: Can't get device URI.\n", stderr);
929
			exit(1);
930
		}
931
		
932
		if( !strncmp( device_uri_buf , canon_usb_backend_str , strlen( canon_usb_backend_str ) ) ) canon_backend_flag = 1;
933
		else if( !strncmp( device_uri_buf , canon_net_backend_str , strlen( canon_net_backend_str ) ) ) canon_backend_flag = 1;
934
		
935
		
936
		/* PPD open and check cupsModelNumber */
937
		p_ppd_name = cupsGetPPD( g_printer_name );
938
		if( p_ppd_name ==NULL ){
939
			fputs("ERROR: Can't get PPD name.\n", stderr);
940
			exit(1);
941
		}
942
		p_ppd = ppdOpenFile(p_ppd_name);
943
		if( p_ppd ==NULL ){
944
			fputs("ERROR: Can't open PPD file.\n", stderr);
945
			unlink( p_ppd_name );	/* You should remove the copy of the PPD file. */
946
			exit(1);
947
		}
948
		
949
		add_bidi = canon_backend_flag;
950
		if( p_ppd->model_number < 356 ) add_bidi = 0;
951
		
952
		ppdClose(p_ppd);
953
		unlink( p_ppd_name );	/* You should remove the copy of the PPD file. */
954
		
955
	}
956
957
	
958
	ui_path = (char *)malloc(strlen(UI_PATH) + strlen(UI_SLASH) + strlen(UI_NAME) + strlen(product_name) + 1);
959
	strcpy(ui_path, UI_PATH);
960
	strcat(ui_path, UI_SLASH);
961
	strcat(ui_path, UI_NAME);
962
	strcat(ui_path, product_name);
963
964
	strcpy(ui_name, UI_NAME);
965
	strcat(ui_name, product_name);
966
967
	snprintf(socket_name, 63, "%s%d", BJ_SOCKET, getpid());
968
969
970
	for ( arg_num=0; arg_num<sizeof(ui_arg)/sizeof(char*); arg_num++ ) {
971
		ui_arg[arg_num] = NULL;
972
	}
973
974
	arg_num = 0;
975
	ui_arg[arg_num] = ui_name; arg_num++;
976
	ui_arg[arg_num] = "-s"; arg_num++;
977
	ui_arg[arg_num] = socket_name; arg_num++;
978
	ui_arg[arg_num] = "--cups"; arg_num++;
979
980
	/* Ver.3.20 */
981
	if( add_bidi ) {
982
		ui_arg[arg_num] = "--bidi"; arg_num++;
983
	}
984
985
	/* Ver.3.70 */
986
	if ( canon_backend_flag ) {
987
		if ( isSupportMSI() == 1 ) {
988
			ui_arg[arg_num] = "--devuri"; arg_num++;
989
			ui_arg[arg_num] = device_uri_buf; arg_num++;
990
		}
991
	}
992
993
994
995
#if 0
996
	/* for debug */
997
	{
998
		short i=0;
999
		while( ui_arg[i]!=NULL )
1000
		{
1001
			fprintf(stderr,"ui_arg[%d]=%s\n",i,ui_arg[i]);
1002
			i++;
1003
		}
1004
	}
1005
#endif
1006
1007
	ui_pid = fork();
1008
1009
	if( ui_pid == 0 )
1010
	{
1011
		execv(ui_path, ui_arg);
1012
	}
1013
	else
1014
	{		
1015
		while(1){
1016
			IPCU ipc;
1017
			int ret;
1018
			memset(&ipc, 0, sizeof(IPCU));
1019
			
1020
			ret = GetIPCData(&ipc, socket_name);
1021
			
1022
			if( ret == RET_PRINT )
1023
			{
1024
				char **lpr_param
1025
				= make_lpr_param(&p_list, g_printer_name, &ipc, print_file);
1026
				if( lpr_param )
1027
				{
1028
					exec_lpr(lpr_param);
1029
					free(lpr_param);
1030
				}
1031
				break;
1032
			}
1033
			else if( ret == RET_PDATA ){	// For Maintenance
1034
				char **lpr_param;
1035
				/* Ver.3.20 */
1036
				/* If canon backend is NOT used, add "CNBjDirect" */
1037
				if( canon_backend_flag ) add_direct = 0;
1038
				else add_direct = 1;
1039
1040
				lpr_param = make_pdata_lpr_param( g_printer_name, &ipc, add_direct );
1041
					
1042
				if( lpr_param )
1043
				{
1044
					exec_lpr(lpr_param);
1045
					free_util_cmd_param( lpr_param );
1046
				}
1047
1048
			}
1049
			else if( ret == RET_FDATA ){	// For Maintenance i250/i255
1050
				char **lpr_param
1051
						= make_fdata_lpr_param( g_printer_name, &ipc );	
1052
1053
				if( lpr_param )
1054
				{
1055
					exec_lpr(lpr_param);
1056
					free_util_cmd_param(lpr_param); 
1057
					lpr_param = NULL;
1058
				}
1059
			}
1060
			else if( ret == RET_WDATA ){	// For Maintenance i250/i255
1061
				char **lpr_param
1062
				= make_wdata_lpr_param( g_printer_name, &ipc);
1063
				if( lpr_param )
1064
				{
1065
					exec_lpr(lpr_param);
1066
					free_util_cmd_param(lpr_param); 
1067
					lpr_param = NULL;
1068
				}
1069
			}
1070
			/* Ver.3.20 for PowerOFF */
1071
			else if( ret == RET_POWEROFF ){
1072
				char **lpr_param
1073
						= make_pdata_lpr_param( g_printer_name, &ipc, 1);	/* PowerOFF -> always add "--CNBjDirect" */
1074
					
1075
				if( lpr_param )
1076
				{
1077
					exec_lpr(lpr_param);
1078
					free_util_cmd_param( lpr_param );
1079
				}
1080
			}
1081
			else if( ret == RET_CANCEL ){
1082
				break;	
1083
	
1084
			}
1085
			else if ( ret == RET_ERROR ){
1086
				break;
1087
			}
1088
		}
1089
		
1090
		if( p_list != NULL )
1091
			param_list_free(p_list);
1092
1093
		waitpid(ui_pid, NULL, 0);
1094
	}
1095
1096
	free(g_printer_name);
1097
	return 0;
1098
}