1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17/*************************************************************************** 18 * LPRng - An Extended Print Spooler System 19 * 20 * Copyright 1988-2003, Patrick Powell, San Diego, CA 21 * papowell@lprng.com 22 * See LICENSE for conditions of use. 23 * 24 ***************************************************************************/ 25 26 static char *const _id = 27"$Id: lpr.c,v 1.1.1.1 2008/10/15 03:28:27 james26_jang Exp $"; 28 29 30#include "lp.h" 31#include "child.h" 32#include "errorcodes.h" 33#include "fileopen.h" 34#include "getopt.h" 35#include "getprinter.h" 36#include "getqueue.h" 37#include "gethostinfo.h" 38#include "initialize.h" 39#include "linksupport.h" 40#include "patchlevel.h" 41#include "printjob.h" 42#include "sendjob.h" 43#include "lpd_jobs.h" 44 45/**** ENDINCLUDE ****/ 46 47#undef EXTERN 48#undef DEFINE 49#define EXTERN 50#define DEFINE(X) X 51#include "lpr.h" 52 53/**** ENDINCLUDE ****/ 54 55/*************************************************************************** 56 * main() 57 * - top level of LPR Lite. This is a cannonical method of handling 58 * input. Note that we assume that the LPD daemon will handle all 59 * of the dirty work associated with formatting, printing, etc. 60 * 61 * 1. get the debug level from command line arguments 62 * 2. set signal handlers for cleanup 63 * 3. get the Host computer Name and user Name 64 * 4. scan command line arguments 65 * 5. check command line arguments for consistency 66 * 6. if we are spooling from STDIN, copy stdin to a file. 67 * 7. if we have a list of files, check each for access 68 * 8. create a control file 69 * 9. send control file to server 70 * 71 ****************************************************************************/ 72 73int main(int argc, char *argv[], char *envp[]) 74{ 75 off_t job_size; 76 char *s, *t, buffer[SMALLBUFFER], *send_to_pr = 0; 77 struct job prjob; 78 struct line_list opts, newargs; 79 int attempt = 0; 80 int n; 81 82#ifndef NODEBUG 83 Debug = 0; 84#endif 85 86 /* set signal handlers */ 87 Is_lpr = 1; 88 Init_line_list( &newargs ); 89 Init_line_list( &opts ); 90 memset(&prjob, 0, sizeof(prjob) ); 91 (void) plp_signal (SIGHUP, cleanup_HUP); 92 (void) plp_signal (SIGINT, cleanup_INT); 93 (void) plp_signal (SIGQUIT, cleanup_QUIT); 94 (void) plp_signal (SIGTERM, cleanup_TERM); 95 (void) signal(SIGCHLD, SIG_DFL); 96 (void) signal(SIGPIPE, SIG_IGN); 97 98 /* 99 * set up the defaults 100 */ 101 Errorcode = 1; 102 Initialize(argc, argv, envp, 'D' ); 103 Setup_configuration(); 104 Job_number = DbgTest; 105 106 107 /* scan the input arguments, setting up values */ 108 Get_parms(argc, argv); /* scan input args */ 109 if( Auth_JOB && !getenv( "AUTH" ) ){ 110 FPRINTF(STDERR, 111 _("authentication requested (-A option) and AUTH environment variable not set") ); 112 usage(); 113 } 114 115 /* Note: we may need the open connection to the remote printer 116 to get our IP address if it is not available */ 117 118 if(DEBUGL3){ 119 struct stat statb; 120 int i; 121 LOGDEBUG("lpr: after init open fd's"); 122 for( i = 0; i < 20; ++i ){ 123 if( fstat(i,&statb) == 0 ){ 124 LOGDEBUG(" fd %d (0%o)", i, statb.st_mode&S_IFMT); 125 } 126 } 127 } 128 129 again: 130 131 Free_job(&prjob); 132 Get_printer(); 133 Fix_Rm_Rp_info(0,0); 134 135 DEBUG1("lpr: Lpr_opts_DYN '%s', argc %d", Lpr_opts_DYN, argc ); 136 if( Lpr_opts_DYN ){ 137 int i, j; 138 139 Split_cmd_line( &opts, Lpr_opts_DYN ); 140 Check_max( &newargs, argc+2+opts.count+2 ); 141 i = j = 0; 142 143 newargs.list[newargs.count++] = argv[0]; 144 for( j = 0; j < opts.count; ++j ){ 145 newargs.list[newargs.count++] = opts.list[j]; 146 } 147 for( j = 1; j < argc; ++j ){ 148 newargs.list[newargs.count++] = argv[j]; 149 } 150 newargs.list[newargs.count] = 0; 151 if(DEBUGL1)Dump_line_list("lpr - new options",&newargs ); 152 Optind = 0; 153 Files.count = 0; 154 Getopt(0,0,0); 155 Get_parms(newargs.count, newargs.list); /* scan input args */ 156 newargs.count = 0; 157 } 158 job_size = Make_job(&prjob); 159 160 if(DEBUGL3){ 161 struct stat statb; 162 int i; 163 LOGDEBUG("lpr: after Make_job open fd's"); 164 for( i = 0; i < 20; ++i ){ 165 if( fstat(i,&statb) == 0 ){ 166 LOGDEBUG(" fd %d (0%o)", i, statb.st_mode&S_IFMT); 167 } 168 } 169 } 170 171 /* 172 * Fix the rest of the control file 173 */ 174 if( job_size == 0 ){ 175 Free_job(&prjob); 176 Errorcode = 1; 177 FATAL(LOG_INFO)_("nothing to print")); 178 } 179 180 if( Check_for_rg_group( Logname_DYN ) ){ 181 Errorcode = 1; 182 FATAL(LOG_INFO)_("cannot use printer - not in privileged group\n") ); 183 } 184 185 if( Remote_support_DYN ) uppercase( Remote_support_DYN ); 186 if( safestrchr( Remote_support_DYN, 'R' ) == 0 ){ 187 Errorcode = 1; 188 FATAL(LOG_INFO) _("no remote support for %s@%s"), 189 RemotePrinter_DYN,RemoteHost_DYN ); 190 } 191 192 /* we check to see if we need to do control file filtering */ 193 /* we do not do any translation of formats */ 194 s = 0; 195 196 n = Find_flag_value( &prjob.info,DATAFILE_COUNT,Value_sep); 197 if( Max_datafiles_DYN > 0 && n > Max_datafiles_DYN ){ 198 Errorcode = 1; 199 FATAL(LOG_INFO) _("%d data files and maximum allowed %d"), 200 n, Max_datafiles_DYN ); 201 } 202 203 send_to_pr = 0; 204 if( Direct_JOB ){ 205 /* check to see if we have a socket connection specified */ 206 send_to_pr = Printer_JOB; 207 } else if( Direct_DYN ){ 208 send_to_pr = Lp_device_DYN; 209 } 210 Force_localhost_DYN = 0; 211 if( send_to_pr ){ 212 Force_localhost_DYN = 0; 213 Lpr_bounce_DYN = Lpr_bounce_JOB = 0; 214 send_to_pr = safestrdup(send_to_pr,__FILE__,__LINE__); 215 Expand_percent(&send_to_pr); 216 } 217 218 DEBUG1("lpr: send_to_pr '%s'", send_to_pr ); 219 220 if( Lpr_bounce_DYN || Lpr_bounce_JOB ){ 221 int tempfd; 222 struct stat statb; 223 char *tempfile, *old_lp_value; 224 struct line_list *lp; 225 226 if(DEBUGL2) Dump_job( "lpr - before filtering", &prjob ); 227 tempfd = Make_temp_fd(&tempfile); 228 229 old_lp_value = safestrdup(Find_str_value( &PC_entry_line_list, "lp", Value_sep ), 230 __FILE__,__LINE__); 231 Set_str_value( &PC_entry_line_list, LP, tempfile ); 232 /* Print_job( output_device, status_device, job, timeout, poll_for_status ) */ 233 Print_job( tempfd, -1, &prjob, 0, 0, User_filter_JOB ); 234 Set_str_value( &PC_entry_line_list, LP, old_lp_value ); 235 if( old_lp_value ) free( old_lp_value ); old_lp_value = 0; 236 237 close(tempfd); 238 tempfd = Checkread( tempfile, &statb ); 239 if( tempfd < 0 ){ 240 Errorcode = JABORT; 241 FATAL(LOG_INFO) _("Cannot open file '%s', %s"), tempfile, Errormsg( errno ) ); 242 } 243 close(tempfd); 244 DEBUG2("lpr: jobs size now %0.0f", (double)(statb.st_size)); 245 job_size = statb.st_size; 246 Free_listof_line_list(&prjob.datafiles); 247 lp = malloc_or_die(sizeof(lp[0]),__FILE__,__LINE__); 248 memset(lp,0,sizeof(lp[0])); 249 Check_max(&prjob.datafiles,1); 250 prjob.datafiles.list[prjob.datafiles.count++] = (void *)lp; 251 Set_str_value(lp,OPENNAME,tempfile); 252 Set_str_value(lp,"N",_("(lpr_filter)")); 253 Set_flag_value(lp,COPIES,1); 254 Set_double_value(lp,SIZE,job_size); 255 Fix_bq_format( 'f', lp ); 256 User_filter_JOB = 0; 257 } 258 259 if(DEBUGL1)Dump_job("lpr - before Fix_control",&prjob); 260 Fix_control( &prjob, Control_filter_DYN, 0 ); 261 if(DEBUGL1)Dump_job("lpr - after Fix_control",&prjob); 262 263 if( send_to_pr && 264 ((!strchr(send_to_pr,'@') && strchr(send_to_pr,'%')) 265 || (send_to_pr[0] == '/') || strchr(send_to_pr,'|')) ){ 266 int fd, pid, status_fd, poll_for_status; 267 char *id; 268 269 SETSTATUS(&prjob)"destination '%s'", send_to_pr ); 270 Errorcode = 0; 271 fd = pid = status_fd = poll_for_status = 0; 272 fd = Printer_open(send_to_pr, &status_fd, &prjob, 273 Lpr_send_try_DYN, Connect_interval_DYN, Max_connect_interval_DYN, 274 Connect_grace_DYN, Connect_timeout_DYN, &pid, &poll_for_status ); 275 276 /* note: we NEVER return fd == 0 or horrible things have happened */ 277 DEBUG1("lpr: fd %d", fd ); 278 if( fd <= 0 ){ 279 Errorcode = JFAIL; 280 goto exit; 281 } 282 id = Find_str_value(&prjob.info,IDENTIFIER,Value_sep); 283 SETSTATUS(&prjob)"transferring job '%s'", id ); 284 /* Print_job( output_device, status_device, job, timeout, poll_for_status, filter ) */ 285 Set_str_value( &PC_entry_line_list, LP, s ); 286 Errorcode = Print_job( fd, status_fd, &prjob, Send_job_rw_timeout_DYN, poll_for_status, User_filter_JOB ); 287 /* we close close device */ 288 DEBUG1("lpr: shutting down fd %d", fd ); 289 290 fd = Shutdown_or_close( fd ); 291 DEBUG1("lpr: after shutdown fd %d, status_fd %d", fd, status_fd ); 292 if( status_fd > 0 ){ 293 /* we shut down this connection as well */ 294 shutdown(status_fd,1); 295 /* we wait for eof on status_fd */ 296 buffer[0] = 0; 297 Get_status_from_OF(&prjob,"LP",pid, 298 status_fd, buffer, sizeof(buffer)-1, Send_job_rw_timeout_DYN, 0, 0, 0 ); 299 } 300 if( fd > 0 ) close( fd ); fd = -1; 301 if( status_fd > 0 ) close( status_fd ); status_fd = -1; 302 if( pid > 0 ){ 303 SETSTATUS(&prjob)"waiting for printer filter to exit"); 304 Errorcode = Wait_for_pid( pid, "LP", 0, Send_job_rw_timeout_DYN ); 305 } 306 DEBUG1("lpr: status %s", Server_status(Errorcode) ); 307 } else { 308 Errorcode = 0; 309 attempt = 1; 310 do { 311 if( Errorcode ){ 312 if(DEBUGL1)Dump_job("lpr - after error",&prjob); 313 buffer[0] = 0; 314 SNPRINTF(buffer,sizeof(buffer)) 315 _("Status Information, attempt %d:\n"), attempt); 316 if( Lpr_send_try_DYN ){ 317 n = strlen(buffer)-2; 318 SNPRINTF(buffer+n,sizeof(buffer)-n) 319 _(" of %d:\n"), Lpr_send_try_DYN); 320 } 321 Write_fd_str(2,buffer); 322 s = Join_line_list(&Status_lines,"\n "); 323 if( (t = safestrrchr(s,' ')) ) *t = 0; 324 Write_fd_str(2,s); 325 if(s) free(s); s = 0; 326 Init_line_list( &Status_lines ); 327 ++attempt; 328 n = Connect_interval_DYN + Connect_grace_DYN; 329 if( n > 0 ){ 330 buffer[0] = 0; 331 SNPRINTF(buffer,sizeof(buffer)) 332 _("Waiting %d seconds before retry\n"), n); 333 Write_fd_str(2,buffer); 334 plp_sleep( n ); 335 } 336 Errorcode = 0; 337 } 338 Errorcode = Send_job( &prjob, &prjob, Connect_timeout_DYN, 339 Connect_interval_DYN, 340 Max_connect_interval_DYN, 341 Send_job_rw_timeout_DYN, User_filter_JOB ); 342 } while( Errorcode && (Lpr_send_try_DYN == 0 || attempt < Lpr_send_try_DYN) ); 343 } 344 345 exit: 346 if( send_to_pr ) free(send_to_pr); send_to_pr = 0; 347 if( Errorcode ){ 348 Errorcode = 1; 349 if(DEBUGL1)Dump_job("lpr - after error",&prjob); 350 buffer[0] = 0; 351 SNPRINTF(buffer,sizeof(buffer)) 352 _("Status Information, attempt %d:\n"), attempt); 353 if( Lpr_send_try_DYN ){ 354 n = strlen(buffer)-2; 355 SNPRINTF(buffer+n,sizeof(buffer)-n) 356 _(" of %d:\n"), Lpr_send_try_DYN); 357 } 358 s = Join_line_list(&Status_lines,"\n "); 359 if( (t = safestrrchr(s,' ')) ) *t = 0; 360 Write_fd_str(2,s); 361 if(s) free(s); s = 0; 362 cleanup(0); 363 } 364 365 if( LP_mode_JOB && !Silent_JOB ){ 366 char *id; 367 int n; 368 char msg[SMALLBUFFER]; 369 id = Find_str_value(&prjob.info,IDENTIFIER,Value_sep); 370 if( id ){ 371 SNPRINTF(msg,sizeof(msg)-1)_("request id is %s\n"), id ); 372 } else { 373 n = Find_decimal_value(&prjob.info,NUMBER,Value_sep); 374 SNPRINTF(msg,sizeof(msg)-1)_("request id is %d\n"), n ); 375 } 376 Write_fd_str(1, msg ); 377 } 378 379 /* the dreaded -r (remove files) option */ 380 if( Removefiles_JOB && !Errorcode ){ 381 int i; 382 /* eliminate any possible game playing */ 383 To_user(); 384 for( i = 0; i < Files.count; ++i ){ 385 if( unlink( Files.list[i] ) == -1 ){ 386 WARNMSG(_("Error unlinking '%s' - %s"), 387 Files.list[i], Errormsg( errno ) ); 388 389 } 390 } 391 } 392 393 if( Job_number ){ 394 SNPRINTF(buffer,sizeof(buffer))_("Done %d\n"), Job_number); 395 Write_fd_str(1,buffer); 396 ++Job_number; 397 goto again; 398 } 399 Free_line_list( &newargs ); 400 Free_line_list( &opts ); 401 Free_job(&prjob); 402 Free_line_list(&Files); 403 cleanup(0); 404 return(0); 405} 406 407 408/*************************************************************************** 409 * void Get_parms(int argc, char *argv[]) 410 * 1. Scan the argument list and get the flags 411 * 2. Check for duplicate information 412 ***************************************************************************/ 413 414 void usage(void); 415 416 417 char LPR_optstr[] /* LPR options */ 418 = "1:2:3:4:#:ABC:D:F:GJ:K:NP:QR:T:U:VX:YZ:bcdfghi:klm:nprstvw:" ; 419 char LPR_bsd_optstr[] /* LPR options */ 420 = "1:2:3:4:#:ABC:D:F:GJ:K:NP:QR:T:U:VX:YZ:bcdfghi:klmnprstvw:" ; 421 char LP_optstr[] /* LP options */ 422 = "ckmprswd:BD:f:GH:n:o:P:q:S:t:T:X:Yy:"; 423 424void Get_parms(int argc, char *argv[] ) 425{ 426 int option, i; 427 char *name, *s; 428 429 Verbose = 0; 430 if( argv[0] && (name = safestrrchr( argv[0], '/' )) ) { 431 ++name; 432 } else { 433 name = argv[0]; 434 } 435 /* check to see if we simulate (poorly) the LP options */ 436 if( name && safestrcmp( name, "lp" ) == 0 ){ 437 LP_mode_JOB = 1; 438 } 439 DEBUG1("Get_parms: LP_mode %d", LP_mode_JOB ); 440 if( LP_mode_JOB ){ 441 while( (option = Getopt( argc, argv, LP_optstr)) != EOF ){ 442 DEBUG1("Get_parms: option %c", option ); 443 switch( option ){ 444 case 'A': Auth_JOB = 1; break; 445 case 'B': Lpr_bounce_JOB = 1; break; 446 case 'c': break; /* use symbolic link */ 447 case 'k': Lpr_zero_file_JOB = 1; break; /* send input with 0 length */ 448 case 'm': /* send mail */ 449 Mailname_JOB = getenv( "USER" ); 450 if( Mailname_JOB == 0 ){ 451 DIEMSG( _("USER environment variable undefined") ); 452 } 453 break; 454 case 'p': break; /* ignore notification */ 455 case 'r': break; /* ignore this option */ 456 case 's': Verbose = 0; Silent_JOB = 1; break; /* suppress messages flag */ 457 case 'w': break; /* no writing of message */ 458 case 'd': Set_DYN(&Printer_DYN, Optarg); /* destination */ 459 Printer_JOB = Optarg; 460 break; 461 case 'D': Parse_debug(Optarg,1); 462 break; 463 case 'f': Classname_JOB = Optarg; 464 break; 465 case 'H': /* special handling - ignore */ 466 break; 467 case 'n': Copies_JOB = atoi( Optarg ); /* copies */ 468 if( Copies_JOB <= 0 ){ 469 DIEMSG( _("-ncopies -number of copies must be greater than 0\n")); 470 } 471 break; 472 case 'o': if( safestrcasecmp( Optarg, "nobanner" ) == 0 473 || safestrcasecmp( Optarg,_("nobanner") ) == 0 ){ 474 No_header_JOB = 1; 475 } else if( safestrncasecmp( Optarg, "width", 5 ) == 0 476 || safestrncasecmp( Optarg,_("width"), 5 ) == 0 ){ 477 s = safestrchr( Optarg, '=' ); 478 if( s ){ 479 Pwidth_JOB = atoi( s+1 ); 480 } 481 } else { 482 /* pass as Zopts */ 483 if( Zopts_JOB ){ 484 s = Zopts_JOB; 485 Zopts_JOB = safestrdup3(s,",",Optarg, 486 __FILE__,__LINE__); 487 free(s); 488 } else { 489 Zopts_JOB = safestrdup(Optarg, 490 __FILE__,__LINE__); 491 } 492 } 493 break; 494 case 'P': break; /* ignore page lis */ 495 case 'q': Priority_JOB = 'Z' - atoi(Optarg); /* get priority */ 496 if(Priority_JOB < 'A' ) Priority_JOB = 'A'; 497 if(Priority_JOB > 'Z' ) Priority_JOB = 'Z'; 498 break; 499 /* pass these as Zopts */ 500 case 'S': 501 case 'T': 502 case 'y': 503 /* pass as Zopts */ 504 if( Zopts_JOB ){ 505 s = Zopts_JOB; 506 Zopts_JOB = safestrdup3(s,",",Optarg, 507 __FILE__,__LINE__); 508 free(s); 509 } else { 510 Zopts_JOB = safestrdup(Optarg, 511 __FILE__,__LINE__); 512 } 513 break; 514 case 't': 515 Check_str_dup( option, &Jobname_JOB, Optarg, M_JOBNAME); 516 break; 517 case 'X': 518 Check_str_dup( option, &User_filter_JOB, Optarg, M_JOBNAME); 519 break; 520 case 'Y': Direct_JOB = 1; break; 521 default: 522 usage(); 523 break; 524 } 525 } 526 } else { 527 while( (option = Getopt (argc, argv, LPR_bsd_DYN?LPR_bsd_optstr:LPR_optstr )) != EOF ) { 528 DEBUG1("Get_parms: option %c", option ); 529 switch( option ){ 530 case 'A': Auth_JOB = 1; break; 531 case 'B': Lpr_bounce_JOB = 1; break; 532 case '1': 533 Check_str_dup( option, &Font1_JOB, Optarg, M_FONT); 534 break; 535 case '2': 536 Check_str_dup( option, &Font2_JOB, Optarg, M_FONT); 537 break; 538 case '3': 539 Check_str_dup( option, &Font3_JOB, Optarg, M_FONT); 540 break; 541 case '4': 542 Check_str_dup( option, &Font4_JOB, Optarg, M_FONT); 543 break; 544 case 'C': 545 Check_str_dup( option, &Classname_JOB, Optarg, 546 M_CLASSNAME); 547 break; 548 case 'D': Parse_debug(Optarg,1); 549 break; 550 case 'F': 551 if( safestrlen (Optarg) != 1 ){ 552 DIEMSG( _("bad -F format string '%s'\n"), Optarg); 553 } 554 if( Format_JOB ){ 555 DIEMSG( _("duplicate format specification -F%s\n"), Optarg); 556 } else { 557 Format_JOB = *Optarg; 558 } 559 break; 560 case 'J': 561 Check_str_dup( option, &Jobname_JOB, Optarg, M_JOBNAME); 562 break; 563 case 'K': 564 case '#': 565 Check_int_dup( option, &Copies_JOB, Optarg, 0); 566 if( Copies_JOB <= 0 ){ 567 DIEMSG( _("-Kcopies -number of copies must be greater than 0\n")); 568 } 569 break; 570 case 'N': 571 Check_for_nonprintable_DYN = 0; 572 break; 573 case 'P': 574 Printer_JOB = Optarg; 575 Set_DYN(&Printer_DYN,Optarg); 576 break; 577 case 'Q': 578 Use_queuename_flag_DYN = 1; 579 break; 580 case 'R': 581 Check_str_dup( option, &Accntname_JOB, Optarg, M_ACCNTNAME ); 582 break; 583 case 'T': 584 Check_str_dup( option, &Prtitle_JOB, Optarg, M_PRTITLE); 585 break; 586 case 'U': Check_str_dup( option, &Username_JOB, Optarg, M_BNRNAME ); 587 break; 588 case 'V': 589 ++Verbose; 590 break; 591 case 'X': 592 Check_str_dup( option, &User_filter_JOB, Optarg, M_JOBNAME); 593 break; 594 case 'Y': Direct_JOB = 1; break; 595 case 'o': /* same as Z */ 596 case 'Z': 597 if( Zopts_JOB ){ 598 s = Zopts_JOB; 599 Zopts_JOB = safestrdup3(s,",",Optarg, 600 __FILE__,__LINE__); 601 free(s); 602 } else { 603 Zopts_JOB = safestrdup(Optarg, 604 __FILE__,__LINE__); 605 } 606 break; 607 case 'k': Lpr_zero_file_JOB = 1; break; /* send input with 0 length */ 608 case 'l': 609 case 'b': 610 Binary_JOB = 1; 611 break; 612 case 'h': 613 Check_dup( option, &No_header_JOB); 614 break; 615 case 'i': 616 Check_int_dup( option, &Indent_JOB, Optarg, 0); 617 break; 618 case 'm': 619 /* 620 * -m Mailname 621 */ 622 if( LPR_bsd_DYN ){ 623 Mailname_JOB = getenv( "USER" ); 624 if( Mailname_JOB == 0 ){ 625 DIEMSG( _("USER environment variable undefined") ); 626 } 627 break; 628 } 629 if( Optarg[0] == '-' ){ 630 DIEMSG( _("Missing mail name") ); 631 } else { 632 Mailname_JOB = Optarg; 633 } 634 break; 635 case 'c': 636 case 'd': 637 case 'f': 638 case 'g': 639 case 'n': 640 case 'p': 641 case 't': 642 case 'v': 643 if( Format_JOB ){ 644 DIEMSG( _("duplicate format specification -%c\n"), option); 645 } else { 646 Format_JOB = option; 647 } 648 break; 649 case 'w': 650 Check_int_dup( option, &Pwidth_JOB, Optarg, 0); 651 break; 652 653 /* Throw a sop to the whiners - let them wipe themselves out... */ 654 /* remove files */ 655 case 'r': 656 Removefiles_JOB = 1; 657 break; 658 case 's': 659 /* symbolic link - quietly ignored */ 660 break; 661 default: 662 usage(); 663 break; 664 } 665 } 666 } 667 668 /* 669 * set up the Parms[] array 670 */ 671 for( i = Optind; i < argc; ++i ){ 672 Add_line_list(&Files,argv[i],0,0,0); 673 } 674 if( Verbose ){ 675 if( Verbose > 1 ){ 676 Printlist( Copyright, 1 ); 677 } else { 678 Write_fd_str( 2, Version ); 679 Write_fd_str( 2, "\n" ); 680 } 681 } 682} 683 684 685 char *LPR_msg [] = 686{ 687 N_("Usage: %s [-Pprinter[@host]] [-A] [-B] [-Cclass] [-Fformat] [-G] [-Jinfo]\n"), 688 N_(" [-(K|#)copies] [-Q] [-Raccountname] [-Ttitle] [-Uuser[@host]] [-V]\n"), 689 N_(" [-Zoptions] [-b] [-m mailaddr] [-h] [-i indent] [-l] [-w width ] [-r]\n"), 690 N_(" [-Ddebugopt ] [--] [ filenames ... ]\n"), 691 N_(" -A - use authentication specified by AUTH environment variable\n"), 692 N_(" -B - filter files and reduce job to single file before sending\n"), 693 N_(" -C class - job class\n"), 694 N_(" -D debugopt - debugging flags\n"), 695 N_(" -F format - job format\n"), 696 N_(" -b,-l - binary or literal format\n"), 697 N_(" c,d,f,g,l,m,p,t,v are also format options\n"), 698 N_(" -G - filter individual job files before sending\n"), 699 N_(" -J info - banner and job information\n"), 700 N_(" -K copies, -# copies - number of copies\n"), 701 N_(" -P printer[@host] - printer on host\n"), 702 N_(" -Q - put 'queuename' in control file\n"), 703 N_(" -Raccntname - accounting information\n"), 704 N_(" -T title - title for 'pr' (-p) formatting\n"), 705 N_(" -U username - override user name (restricted)\n"), 706 N_(" -V - Verbose information during spooling\n"), 707 N_(" -X path - user specified filter for job files\n"), 708 N_(" -Y - connect and send to TCP/IP port (direct mode)\n"), 709 N_(" -Z options - options to pass to filter\n"), 710 N_(" -h - no header or banner page\n"), 711 N_(" -i indent - indentation\n"), 712 N_(" -k - do not use tempfile when sending to server\n"), 713 N_(" -m mailaddr - mail final status to mailaddr\n"), 714 N_(" -r - remove files after spooling\n"), 715 N_(" -w width - width to use\n"), 716 N_(" -- - end of options, files follow\n"), 717 N_(" filename '-' reads from STDIN\n"), 718 N_(" PRINTER, LPDEST, NPRINTER, NGPRINTER environment variables set default printer.\n"), 719 0 }; 720 721 char *LP_msg [] = { 722 N_("Usage: %s [-A] [-B] [-c] [-G] [-m] [-p] [-s] [-w] [-d printer@[host]]\n"), 723 N_(" [-f form-name] [-H special-handling]\n"), 724 N_(" [-n number] [-o options] [-P page-list]\n"), 725 N_(" [-q priority-level] [-S character-set]\n"), 726 N_(" [-S print-wheel] [-t title]\n"), 727 N_(" [-T content-type [-r]] [-y mode-list]\n"), 728 N_(" [-Ddebugopt ] [ filenames ... ]\n"), 729 N_(" lp simulator using LPRng, functionality may differ slightly\n"), 730 N_(" -A - use authentication specified by AUTH environment variable\n"), 731 N_(" -B - filter files and reduce job to single file before sending\n"), 732 N_(" -c - (make copy before printing - ignored)\n"), 733 N_(" -d printer[@host] - printer on host\n"), 734 N_(" -D debugflags - debugging flags\n"), 735 N_(" -f formname - first letter used as job format\n"), 736 N_(" -G - filter individual job files before sending\n"), 737 N_(" -H handling - (passed as -Z handling)\n"), 738 N_(" -m - mail sent to $USER on completion\n"), 739 N_(" -n copies - number of copies\n"), 740 N_(" -o option nobanner, width recognized\n"), 741 N_(" (others passed as -Z option)\n"), 742 N_(" -P pagelist - (print page list - ignored)\n"), 743 N_(" -p - (notification on completion - ignored)\n"), 744 N_(" -q - priority - 0 -> Z (highest), 25 -> A (lowest)\n"), 745 N_(" -s - (suppress messages - ignored)\n"), 746 N_(" -S charset - (passed as -Z charset)\n"), 747 N_(" -t title - job title\n"), 748 N_(" -T content - (passed as -Z content)\n"), 749 N_(" -w - (write message on completion - ignored)\n"), 750 N_(" -X path - user specified filter for job files\n"), 751 N_(" -Y - connect and send to TCP/IP port (direct mode)\n"), 752 N_(" -y mode - (passed as -Z mode)\n"), 753 N_(" -- - end of options, files follow\n"), 754 N_(" filename '-' reads from STDIN\n"), 755 N_(" PRINTER, LPDEST, NGPRINTER, NPRINTER environment variables set default printer.\n"), 756 0 }; 757 758void prmsg( char **msg ) 759{ 760 int i; 761 char *s; 762 for( i = 0; (s = msg[i]); ++i ){ 763 if(i == 0 ){ 764 FPRINTF( STDERR,_(s), Name ); 765 } else { 766 FPRINTF( STDERR, "%s",_(s) ); 767 } 768 } 769} 770 771void usage(void) 772{ 773 if(LP_mode_JOB ){ 774 prmsg( LP_msg ); 775 } else { 776 prmsg( LPR_msg ); 777 } 778 Parse_debug("=",-1); 779 FPRINTF( STDERR, "%s\n", Version ); 780 exit(1); 781} 782 783 784/*************************************************************************** 785 * Make_job Parms() 786 * 1. we determine the name of the printer - Printer_DYN variable 787 * 2. we determine the host name to be used - RemoteHost_DYN variable 788 * 3. check the user name for consistency: 789 * We have the user name from the environment 790 * We have the user name from the -U option 791 * Allow override if we are root or some silly system (like DOS) 792 * that does not support multiple users 793 ***************************************************************************/ 794 795 796 void get_job_number( struct job *job ); 797 double Copy_STDIN( struct job *job ); 798 double Check_files( struct job *job ); 799 800/*************************************************************************** 801 * Commentary: 802 * The struct control_file{} data structure contains fields that point to 803 * complete lines in the control file, i.e.- 'Jjobname', 'Hhostname' 804 * We set up this information in a data structure. 805 * Note that this is specific to the LPR program 806 * 807 * Make_job() 808 * 1. Get the control file number and name information 809 * 2. scan the set of variables, and determine how much space is needed. 810 * 3. scan the data files, and determine how much space is needed 811 * 4. allocate the space. 812 * 5. Copy variables to the allocated space, setting up pointers in the 813 * control_file data structure. 814 **************************************************************************/ 815 816int Make_job( struct job *job ) 817{ 818 char nstr[SMALLBUFFER]; /* information */ 819 struct jobwords *keys; /* keyword entry in the parameter list */ 820 char *s, *name; /* buffer where we allocate stuff */ 821 void *p; 822 char *originate_hostname = 0; 823 int i, n; 824 double job_size = 0; 825 826 if( Auth_JOB ){ 827 Set_DYN(&Auth_DYN, getenv("AUTH") ); 828 } 829 830 if(DEBUGL4)Dump_line_list("Make_job - PC_entry",&PC_entry_line_list ); 831 if(DEBUGL4)Dump_parms("Make_job",Pc_var_list); 832 if(DEBUGL4)Dump_line_list("Make_job - job at start",&job->info ); 833 834 /* check for priority in range */ 835 if( Priority_JOB == 0 && Classname_JOB 836 && !Break_classname_priority_link_DYN ) Priority_JOB = cval(Classname_JOB); 837 if( Priority_JOB == 0 && Default_priority_DYN ) Priority_JOB = cval(Default_priority_DYN); 838 if( Priority_JOB == 0 ) Priority_JOB = 'A'; 839 if( islower(Priority_JOB) ) Priority_JOB = toupper( Priority_JOB ); 840 if( !isupper( Priority_JOB ) ){ 841 DIEMSG( 842 _("Priority (first letter of Class) not 'A' (lowest) to 'Z' (highest)") ); 843 } 844 845 SNPRINTF(nstr,sizeof(nstr))"%c",Priority_JOB); 846 Set_str_value(&job->info,PRIORITY,nstr); 847 848 /* fix up the Classname_JOB 'C' option */ 849 850 if( Classname_JOB == 0 ){ 851 if( Backwards_compatible_DYN ){ 852 Classname_JOB = ShortHost_FQDN; 853 } else { 854 SNPRINTF(nstr,sizeof(nstr))"%c",Priority_JOB); 855 Classname_JOB = nstr; 856 } 857 } 858 Set_str_value(&job->info,CLASS,Classname_JOB); 859 860 if( Files.count == 1 && !safestrcmp("-", Files.list[0]) ){ 861 Files.count = 0; 862 } 863 /* fix up the jobname */ 864 if( Jobname_JOB == 0 ){ 865 if( Files.count == 0 ){ 866 Set_str_value(&job->info,JOBNAME,_("(STDIN)") ); 867 } else { 868 name = 0; 869 for( i = 0; i < Files.count; ++i ){ 870 s = Files.list[i]; 871 if( safestrcmp(s, "-" ) == 0 ) s = _("(STDIN)"); 872 name = safeextend3(name,name?",":"",s,__FILE__,__LINE__); 873 } 874 Set_str_value(&job->info,JOBNAME, name ); 875 if( name ) free(name); name = 0; 876 } 877 } else { 878 Set_str_value(&job->info,JOBNAME,Jobname_JOB ); 879 } 880 if(DEBUGL4)Dump_line_list("Make_job - after jobname",&job->info); 881 882 /* fix up the banner name. 883 * if you used the -U option, 884 * check to see if you have root permissions 885 * set to -U value 886 * else set to log name of user 887 * if No_header suppress banner 888 */ 889 if( Username_JOB ){ 890 /* check to see if you were root */ 891 if( 0 != OriginalRUID ){ 892 struct line_list user_list; 893 char *str, *t; 894 struct passwd *pw; 895 int found; 896 uid_t uid; 897 898 DEBUG2("Make_job: checking '%s' for -U perms", 899 Allow_user_setting_DYN ); 900 Init_line_list(&user_list); 901 Split( &user_list, Allow_user_setting_DYN,File_sep,0,0,0,0,0,0); 902 903 found = 0; 904 for( i = 0; !found && i < user_list.count; ++i ){ 905 str = user_list.list[i]; 906 DEBUG2("Make_job: checking '%s'", str ); 907 uid = strtol( str, &t, 10 ); 908 if( str == t || *t ){ 909 /* try getpasswd */ 910 pw = getpwnam( str ); 911 if( pw ){ 912 uid = pw->pw_uid; 913 } 914 } 915 DEBUG2( "Make_job: uid '%d'", uid ); 916 found = ( uid == OriginalRUID ); 917 DEBUG2( "Make_job: found '%d'", found ); 918 } 919 if( !found ){ 920 DEBUG1( _("-U (username) can only be used by ROOT") ); 921 Username_JOB = 0; 922 } 923 } 924 } 925 if( Username_JOB ){ 926 Clean_meta(Username_JOB); 927 if( (originate_hostname = strchr(Username_JOB,'@')) ){ 928 *originate_hostname++ = 0; 929 for( s = originate_hostname; cval(s); ++s ){ 930 if( isspace(cval(s)) ){ 931 *s = '_'; 932 } 933 } 934 if( (s = Find_fqdn( &LookupHost_IP, originate_hostname )) == 0 ){ 935 Errorcode = JABORT; 936 FATAL(LOG_ERR) _("Get_local_host: '%s' FQDN name not found!"), originate_hostname ); 937 } else { 938 originate_hostname = s; 939 } 940 } 941 Set_DYN(&Logname_DYN, Username_JOB ); 942 } 943 if( !originate_hostname ) originate_hostname = FQDNHost_FQDN; 944 Bnrname_JOB = Logname_DYN; 945 if( No_header_JOB || Suppress_header_DYN ){ 946 Bnrname_JOB = 0; 947 } 948 Set_str_value(&job->info,BNRNAME, Bnrname_JOB ); 949 950 /* check the format */ 951 952 DEBUG1("Make_job: before checking format '%c'", Format_JOB ); 953 if( Binary_JOB ){ 954 Format_JOB = 'l'; 955 } 956 if( Format_JOB == 0 && Default_format_DYN ) Format_JOB = *Default_format_DYN; 957 if( Format_JOB == 0 ) Format_JOB = 'f'; 958 if( isupper(Format_JOB) ) Format_JOB = tolower(Format_JOB); 959 960 DEBUG1("Make_job: after checking format '%c'", Format_JOB ); 961 if( safestrchr( "aios", Format_JOB ) 962 || (Formats_allowed_DYN && !safestrchr( Formats_allowed_DYN, Format_JOB ) )){ 963 DIEMSG( _("Bad format specification '%c'"), Format_JOB ); 964 } 965 966 SNPRINTF(nstr,sizeof(nstr))"%c",Format_JOB); 967 Set_str_value(&job->info,FORMAT,nstr); 968 /* check to see how many files you want to print- limit of 52 */ 969 if( Max_datafiles_DYN > 0 && Files.count > Max_datafiles_DYN ){ 970 DIEMSG( _("Sorry, can only print %d files at a time, split job up"), Max_datafiles_DYN); 971 } 972 if( Copies_JOB == 0 ){ 973 Copies_JOB = 1; 974 } 975 if( Max_copies_DYN && Copies_JOB > Max_copies_DYN ){ 976 DIEMSG( _("Maximum of %d copies allowed"), Max_copies_DYN ); 977 } 978 Set_flag_value(&job->info,COPIES,Copies_JOB); 979 980 /* check the for the -Q flag */ 981 DEBUG1("Make_job: 'qq' flag %d, queue '%s', force_queuename '%s'", 982 Use_queuename_flag_DYN, Queue_name_DYN, Force_queuename_DYN ); 983 if( Use_queuename_flag_DYN ){ 984 Set_str_value(&job->info,QUEUENAME,Queue_name_DYN); 985 } 986 if( Force_queuename_DYN ){ 987 Set_str_value(&job->info,QUEUENAME,Force_queuename_DYN); 988 } 989 990 get_job_number(job); 991 992 Set_str_value(&job->info,FROMHOST,originate_hostname); 993 if( isdigit(cval(originate_hostname)) ){ 994 s = safestrdup2("ADDR",originate_hostname,__FILE__,__LINE__); 995 Set_str_value(&job->info,FILE_HOSTNAME,s); 996 if( s ) free(s); s = 0; 997 } else { 998 Set_str_value(&job->info,FILE_HOSTNAME,originate_hostname); 999 } 1000 1001 /* we put the option strings in the buffer */ 1002 for( keys = Lpr_parms; keys->key; ++keys ){ 1003 DEBUG2("Make_job: key '%s', maxlen %d, use '%s'", 1004 keys->keyword?*keys->keyword:0,keys->maxlen,keys->key); 1005 s = 0; 1006 /* see if we already have a value for this parameter. If not, 1007 then we set it 1008 */ 1009 if( keys->keyword ){ 1010 s = Find_str_value(&job->info,*keys->keyword,Value_sep); 1011 } 1012 p = keys->variable; 1013 nstr[0] = 0; 1014 n = 0; 1015 switch( keys->type ){ 1016 case INTEGER_K: 1017 if( s ){ 1018 n = strtol(s,0,0); 1019 } else if( p ){ 1020 n = *(int *)p; 1021 } 1022 if( n ) Set_decimal_value(&job->info,keys->key,n); 1023 break; 1024 case STRING_K: 1025 if( s == 0 && p ) s = *(char **)p; 1026 if( s ) Set_str_value(&job->info,keys->key,s); 1027 break; 1028 default: break; 1029 } 1030 } 1031 if(DEBUGL2)Dump_job("Make_job - job after", job ); 1032 1033 /* 1034 * copy from standard in? 1035 */ 1036 1037 /* now we check to see if we have zero length flag */ 1038 if( Lpr_zero_file_JOB ){ 1039 if( Auth_JOB || Auth_DYN ){ 1040 DIEMSG( _("authentication conficts with -k option")); 1041 } 1042 if( Send_block_format_DYN ){ 1043 DIEMSG( _("send_block_format configuration option conficts with -k option")); 1044 } 1045 if( Send_data_first_DYN ){ 1046 DIEMSG( _("send_data_first configuration option conficts with -k option")); 1047 } 1048 if(Copies_JOB > 1 ){ 1049 DIEMSG( _("multiple copies conficts with -k option")); 1050 } 1051 if(Files.count ){ 1052 DIEMSG( _("files on command line conflicts with -k option")); 1053 } 1054 } 1055 if( Files.count == 0 ){ 1056 if( Lpr_zero_file_JOB || Direct_JOB ){ 1057 struct line_list *lp; 1058 lp = malloc_or_die(sizeof(lp[0]),__FILE__,__LINE__); 1059 memset(lp,0,sizeof(lp[0])); 1060 Check_max(&job->datafiles,1); 1061 job->datafiles.list[job->datafiles.count++] = (void *) lp; 1062 Set_str_value(lp,"N","(STDIN)"); 1063 Set_flag_value(lp,COPIES,1); 1064 SNPRINTF(nstr,sizeof(nstr))"%c",Format_JOB); 1065 Set_str_value(lp,FORMAT,nstr); 1066 Set_double_value(lp,SIZE,0 ); 1067 job_size = 1; /* make checker happy */ 1068 } else { 1069 job_size = Copy_STDIN( job ); 1070 job_size *= Copies_JOB; 1071 } 1072 } else { 1073 /* 1074 * check to see that the input files are printable 1075 */ 1076 job_size = Check_files( job ); 1077 job_size *= Copies_JOB; 1078 } 1079 1080 if(DEBUGL2) Dump_job( "Make_job - final value", job ); 1081 return( job_size ); 1082} 1083 1084/************************************************************************** 1085 * int get_job_number(); 1086 * - get an integer value for the job number 1087 **************************************************************************/ 1088 1089void get_job_number( struct job *job ) 1090{ 1091 int number = Job_number; 1092 if( number == 0 ) number = getpid(); 1093 Fix_job_number( job, number ); 1094} 1095 1096 struct jobwords Lpr_parms[] 1097 = { 1098{ 0, STRING_K , &Accntname_JOB, M_ACCNTNAME, "R" }, 1099{ &BNRNAME, STRING_K , &Bnrname_JOB, M_BNRNAME, "L" }, 1100{ &CLASS, STRING_K , &Classname_JOB, M_CLASSNAME, "C" }, 1101{ 0, STRING_K , &Font1_JOB, M_FONT, "1" }, 1102{ 0, STRING_K , &Font2_JOB, M_FONT, "2" }, 1103{ 0, STRING_K , &Font3_JOB, M_FONT, "3" }, 1104{ 0, STRING_K , &Font4_JOB, M_FONT, "4" }, 1105{ &FROMHOST, STRING_K , &FQDNHost_FQDN, M_FROMHOST, "H" }, 1106{ 0, INTEGER_K , &Indent_JOB, M_INDENT, "I" }, 1107{ &JOBNAME, STRING_K , &Jobname_JOB, M_JOBNAME, "J" }, 1108{ &LOGNAME, STRING_K , &Logname_DYN, M_BNRNAME, "P" }, 1109{ 0, STRING_K , &Mailname_JOB, M_MAILNAME, "M" }, 1110{ 0, STRING_K , &Prtitle_JOB, M_PRTITLE, "T" }, 1111{ 0, INTEGER_K , &Pwidth_JOB, M_PWIDTH, "W" }, 1112{ 0, STRING_K , &Zopts_JOB, M_ZOPTS, "Z" }, 1113{ 0,0,0,0,0 } 1114} ; 1115 1116 1117/*************************************************************************** 1118 * off_t Copy_STDIN() 1119 * 1. we get the name of a temporary file 1120 * 2. we open the temporary file and read from STDIN until we get 1121 * no more. 1122 * 3. stat the temporary file to prevent games 1123 ***************************************************************************/ 1124 1125double Copy_STDIN( struct job *job ) 1126{ 1127 int fd, count, printable = 1; 1128 double size = 0; 1129 char *tempfile; 1130 struct line_list *lp; 1131 struct stat statb; 1132 char buffer[LARGEBUFFER]; 1133 1134 /* get a tempfile */ 1135 if( Copies_JOB == 0 ) Copies_JOB = 1; 1136 fd = Make_temp_fd( &tempfile ); 1137 1138 if( fd < 0 ){ 1139 LOGERR_DIE(LOG_INFO) _("Make_temp_fd failed") ); 1140 } else if( fd == 0 ){ 1141 DIEMSG( _("You have closed STDIN! cannot pipe from a closed connection")); 1142 } 1143 DEBUG1("Temporary file '%s', fd %d", tempfile, fd ); 1144 size = 0; 1145 while( (count = read( 0, buffer, sizeof(buffer))) > 0 ){ 1146 if( write( fd, buffer, count ) < 0 ){ 1147 Errorcode = JABORT; 1148 LOGERR_DIE(LOG_INFO) _("Copy_STDIN: write to temp file failed")); 1149 } 1150 } 1151 if( fstat( fd, &statb ) != 0 ){ 1152 Errorcode = JABORT; 1153 LOGERR_DIE(LOG_INFO) _("Copy_STDIN: stat of temp fd '%d' failed"), fd); 1154 } 1155 printable = Check_lpr_printable( tempfile, fd, &statb, Format_JOB ); 1156 if( printable ){ 1157 size = statb.st_size; 1158 lp = malloc_or_die(sizeof(lp[0]),__FILE__,__LINE__); 1159 memset(lp,0,sizeof(lp[0])); 1160 Check_max(&job->datafiles,1); 1161 job->datafiles.list[job->datafiles.count++] = (void *) lp; 1162 Set_str_value(lp,"N","(STDIN)"); 1163 Set_str_value(lp,OPENNAME,tempfile); 1164 Set_str_value(lp,TRANSFERNAME,tempfile); 1165 Set_flag_value(lp,COPIES,1); 1166 SNPRINTF(buffer,sizeof(buffer))"%c",Format_JOB); 1167 Set_str_value(lp,FORMAT,buffer); 1168 Set_double_value(lp,SIZE,size); 1169 } else { 1170 size = 0; 1171 } 1172 close(fd); 1173 return( size ); 1174} 1175 1176/*************************************************************************** 1177 * off_t Check_files( char **files, int filecount ) 1178 * 2. check each of the input files for access 1179 * 3. stat the files and get the size 1180 * 4. Check for printability 1181 * 5. Put information in the data_file{} entry 1182 ***************************************************************************/ 1183 1184double Check_files( struct job *job ) 1185{ 1186 double size = 0; 1187 int i, fd, printable = 1; 1188 struct stat statb; 1189 char *s, *tempfile; 1190 char buffer[SMALLBUFFER]; 1191 struct line_list *lp; 1192 1193 for( i = 0; i < Files.count; ++i){ 1194 tempfile = s = Files.list[i]; 1195 DEBUG2( "Check_files: doing '%s'", s ); 1196 if( safestrcmp( s, "-" ) == 0 ){ 1197 size += Copy_STDIN( job ); 1198 continue; 1199 } 1200 fd = Checkread( s, &statb ); 1201 if( fd < 0 ){ 1202 WARNMSG( _("Cannot open file '%s', %s"), s, Errormsg( errno ) ); 1203 continue; 1204 } 1205 printable = 1; 1206 if( User_filter_JOB == 0 ){ 1207 if( fstat( fd, &statb ) != 0 ){ 1208 Errorcode = JABORT; 1209 LOGERR_DIE(LOG_INFO) _("Check_files: stat of temp fd '%d' failed"), fd); 1210 } 1211 printable = Check_lpr_printable( s, fd, &statb, Format_JOB ); 1212 } 1213 close( fd ); 1214 if( printable > 0 ){ 1215 lp = malloc_or_die(sizeof(lp[0]),__FILE__,__LINE__); 1216 memset(lp,0,sizeof(lp[0])); 1217 Check_max(&job->datafiles,1); 1218 job->datafiles.list[job->datafiles.count++] = (void *) lp; 1219 Set_str_value(lp,OPENNAME,tempfile); 1220 Set_str_value(lp,TRANSFERNAME,s); 1221 Clean_meta(s); 1222 Set_str_value(lp,"N",s); 1223 Set_flag_value(lp,COPIES,1); 1224 SNPRINTF(buffer,sizeof(buffer))"%c",Format_JOB); 1225 Set_str_value(lp,FORMAT,buffer); 1226 size = size + statb.st_size; 1227 Set_double_value(lp,SIZE,(double)(statb.st_size) ); 1228 DEBUG2( "Check_files: printing '%s'", s ); 1229 } else { 1230 DEBUG2( "Check_files: not printing '%s'", s ); 1231 } 1232 } 1233 if( Copies_JOB ) size *= Copies_JOB; 1234 DEBUG2( "Check_files: %d files, size %0.0f", job->datafiles.count, size ); 1235 return( size ); 1236} 1237 1238/*************************************************************************** 1239 * int Check_lpr_printable(char *file, int fd, struct stat *statb, int format ) 1240 * 1. Check to make sure it is a regular file. 1241 * 2. Check to make sure that it is not 'binary data' file 1242 * 3. If a text file, check to see if it has some control characters 1243 * 1244 ***************************************************************************/ 1245 1246int Check_lpr_printable(char *file, int fd, struct stat *statb, int format ) 1247{ 1248 char buf[LINEBUFFER]; 1249 int n, i, c; /* Acme Integers, Inc. */ 1250 int printable = 0; 1251 char *err = _("cannot print '%s': %s"); 1252 1253 if( Check_for_nonprintable_DYN == 0 ) return(1); 1254 /* 1255 * Do an LSEEK on the file, i.e.- see to the start 1256 * Ignore any error return 1257 */ 1258 lseek( fd, 0, SEEK_SET ); 1259 if(!S_ISREG( statb->st_mode )) { 1260 DIEMSG(err, file,_("not a regular file")); 1261 } else if(statb->st_size == 0) { 1262 /* empty file */ 1263 printable = -1; 1264 } else if ((n = read (fd, buf, sizeof(buf))) <= 0) { 1265 DIEMSG (err, file,_("cannot read it")); 1266 } else if (format != 'p' && format != 'f' ){ 1267 printable = 1; 1268 } else if (is_exec ( buf, n)) { 1269 DIEMSG (err, file,_("executable program")); 1270 } else if (is_arch ( buf, n)) { 1271 DIEMSG (err, file,_("archive file")); 1272 } else { 1273 printable = 1; 1274 if( Min_printable_count_DYN && n > Min_printable_count_DYN ){ 1275 n = Min_printable_count_DYN; 1276 } 1277 for (i = 0; printable && i < n; ++i) { 1278 c = cval(buf+i); 1279 /* we allow backspace, escape, ^D */ 1280 if( !isprint( c ) && !isspace( c ) 1281 && c != 0x08 && c != 0x1B && c!= 0x04 ) printable = 0; 1282 } 1283 if( !printable ) DIEMSG (err, file, 1284 _("unprintable characters at start of file, check your LANG environment variable as well as the input file")); 1285 } 1286 return(printable); 1287} 1288 1289/*************************************************************************** 1290 * The is_exec and is_arch are system dependent functions which 1291 * check if a file is an executable or archive file, based on the 1292 * information in the header. Note that most of the time we will end 1293 * up with a non-printable character in the first 100 characters, so 1294 * this test is moot. 1295 * 1296 * I swear I must have been out of my mind when I put these tests in. 1297 * In fact, why bother with them? 1298 * 1299 * Patrick Powell Wed Apr 12 19:58:58 PDT 1995 1300 * On review, I agree with myself. Sun Jan 31 06:36:28 PST 1999 1301 ***************************************************************************/ 1302 1303#if defined(HAVE_A_OUT_H) && !defined(_AIX41) 1304#include <a.out.h> 1305#endif 1306 1307#ifdef HAVE_EXECHDR_H 1308#include <sys/exechdr.h> 1309#endif 1310 1311/* this causes trouble, eg. on SunOS. */ 1312#ifdef IS_NEXT 1313# ifdef HAVE_SYS_LOADER_H 1314# include <sys/loader.h> 1315# endif 1316# ifdef HAVE_NLIST_H 1317# include <nlist.h> 1318# endif 1319# ifdef HAVE_STAB_H 1320# include <stab.h> 1321# endif 1322# ifdef HAVE_RELOC_H 1323# include <reloc.h> 1324# endif 1325#endif /* IS_NEXT */ 1326 1327#if defined(HAVE_FILEHDR_H) && !defined(HAVE_A_OUT_H) 1328#include <filehdr.h> 1329#endif 1330 1331#if defined(HAVE_AOUTHDR_H) && !defined(HAVE_A_OUT_H) 1332#include <aouthdr.h> 1333#endif 1334 1335#ifdef HAVE_SGS_H 1336#include <sgs.h> 1337#endif 1338 1339/*************************************************************************** 1340 * I really don't want to know. This alone tempts me to rip the code out 1341 * Patrick Powell Wed Apr 12 19:58:58 PDT 1995 1342 ***************************************************************************/ 1343#ifndef XYZZQ_ 1344#define XYZZQ_ 1 /* ugh! antediluvian BSDism, I think */ 1345#endif 1346 1347#ifndef N_BADMAG 1348# ifdef NMAGIC 1349# define N_BADMAG(x) \ 1350 ((x).a_magic!=OMAGIC && (x).a_magic!=NMAGIC && (x).a_magic!=ZMAGIC) 1351# else /* no NMAGIC */ 1352# ifdef MAG_OVERLAY /* AIX */ 1353# define N_BADMAG(x) (x.a_magic == MAG_OVERLAY) 1354# endif /* MAG_OVERLAY */ 1355# endif /* NMAGIC */ 1356#endif /* N_BADMAG */ 1357 1358int is_exec( char *buf, int n) 1359{ 1360 int i = 0; 1361 1362#ifdef N_BADMAG /* BSD, non-mips Ultrix */ 1363# ifdef HAVE_STRUCT_EXEC 1364 if (n >= (int)sizeof (struct exec)){ 1365 i |= !(N_BADMAG ((*(struct exec *) buf))); 1366 } 1367# else 1368 if (n >= (int)sizeof (struct aouthdr)){ 1369 i |= !(N_BADMAG ((*(struct aouthdr *) buf))); 1370 } 1371# endif 1372#endif 1373 1374#ifdef ISCOFF /* SVR4, mips Ultrix */ 1375 if (n >= (int)sizeof (struct filehdr)){ 1376 i |= (ISCOFF (((struct filehdr *) buf)->f_magic)); 1377 } 1378#endif 1379 1380#ifdef MH_MAGIC /* NeXT */ 1381 if (n >= (int)sizeof (struct mach_header)){ 1382 i |= (((struct mach_header *) buf)->magic == MH_MAGIC); 1383 } 1384#endif 1385 1386#ifdef IS_DATAGEN /* Data General (forget it! ;) */ 1387 { 1388 if( n > (int)sizeof (struct header)){ 1389 i |= ISMAGIC (((struct header *)buff->magic_number)); 1390 } 1391 } 1392#endif 1393 1394 return (i); 1395} 1396 1397#include <ar.h> 1398 1399int is_arch(char *buf, int n) 1400{ 1401 int i = 0; 1402#ifdef ARMAG 1403 if( n >= SARMAG ){ 1404 i = !memcmp( buf, ARMAG, SARMAG); 1405 } 1406#endif /* ARMAG */ 1407 return(i); 1408} 1409 1410void Dienoarg(int option) 1411{ 1412 DIEMSG (_("option '%c' missing argument"), option); 1413} 1414 1415/*************************************************************************** 1416 * Check_int_dup (int option, int *value, char *arg) 1417 * 1. check to see if value has been set 1418 * 2. if not, then get integer value from arg 1419 ***************************************************************************/ 1420 1421void Check_int_dup (int option, int *value, char *arg, int maxvalue) 1422{ 1423 char *convert; 1424 1425 if (arg == 0) { 1426 Dienoarg (option); 1427 } 1428 convert = arg; 1429 *value = strtol( arg, &convert, 10 ); 1430 if( *value < 0 || convert == arg || *convert ){ 1431 DIEMSG (_("option %c parameter `%s` is not positive integer value"), 1432 option, arg ); 1433 } 1434 if( maxvalue > 0 && *value > maxvalue ){ 1435 DIEMSG (_("option %c parameter `%s` is not integer value from 0 - %d"), 1436 option, arg, maxvalue ); 1437 } 1438} 1439 1440/*************************************************************************** 1441 * Check_str_dup(int option, char *value, char *arg) 1442 * 1. check to see if value has been set 1443 * 2. if not, then set it 1444 ***************************************************************************/ 1445 1446void Check_str_dup(int option, char **value, char *arg, int maxlen ) 1447{ 1448 if (arg == 0) { 1449 Dienoarg (option); 1450 } 1451 *value = arg; 1452} 1453 1454/*************************************************************************** 1455 * 1. check to see if value has been set 1456 * 2. if not, then set it 1457 ***************************************************************************/ 1458 1459void Check_dup(int option, int *value) 1460{ 1461 *value = 1; 1462} 1463