1/*************************************************************************** 2 * LPRng - An Extended Print Spooler System 3 * 4 * Copyright 1988-2003, Patrick Powell, San Diego, CA 5 * papowell@lprng.com 6 * See LICENSE for conditions of use. 7 * 8 ***************************************************************************/ 9 10 static char *const _id = 11"$Id: lprm.c,v 1.1.1.1 2008/10/15 03:28:27 james26_jang Exp $"; 12 13 14/*************************************************************************** 15 * LPRng - An Extended Print Spooler System 16 * 17 * Copyright 1988-2003, Patrick Powell, San Diego, CA 18 * papowell@lprng.com 19 * See LICENSE for conditions of use. 20 * 21 *************************************************************************** 22 * MODULE: lprm.c 23 * PURPOSE: 24 **************************************************************************/ 25 26/*************************************************************************** 27 * SYNOPSIS 28 * lprm [ -PPrinter_DYN ] 29 * lprm [-Pprinter ]*[-a][-s][-l][+[n]][-Ddebugopt][job#][user] 30 * DESCRIPTION 31 * lprm sends a status request to lpd(8) 32 * and reports the status of the 33 * specified jobs or all jobs associated with a user. lprm 34 * invoked without any arguments reports on the printer given 35 * by the default printer (see -P option). For each job sub- 36 * mitted (i.e. invocation of lpr(1)) lprm reports the user's 37 * name, current rank in the queue, the names of files compris- 38 * ing the job, the job identifier (a number which may be sup- 39 * plied to lprm(1) for removing a specific job), and the total 40 * size in bytes. Job ordering is dependent on the algorithm 41 * used to scan the spooling directory and is FIFO (First in 42 * First Out), in order of priority level. File names compris- 43 * ing a job may be unavailable (when lpr(1) is used as a sink 44 * in a pipeline) in which case the file is indicated as 45 * ``(STDIN)''. 46 * -P printer 47 * Specifies a particular printer, otherwise the default 48 * line printer is used (or the value of the PRINTER vari- 49 * able in the environment). If PRINTER is not defined, 50 * then the first entry in the /etc/printcap(5) file is 51 * reported. Multiple printers can be displayed by speci- 52 * fying more than one -P option. 53 * 54 * -a All printers listed in the /etc/printcap(5) file are 55 * reported. 56 * 57 * -l An alternate display format is used, which simply 58 * reports the user, jobnumber, and originating host. 59 * 60 * [+[n]] 61 * Forces lprm to periodically display the spool queues. 62 * Supplying a number immediately after the + sign indi- 63 * cates that lprm should sl eep n seconds in between scans 64 * of the queue. 65 * Note: the screen will be cleared at the start of each 66 * display using the 'curses.h' package. 67 **************************************************************************** 68 * 69 * Implementation Notes 70 * Patrick Powell Tue May 2 09:58:29 PDT 1995 71 * 72 * The LPD server will be returning the formatted status; 73 * The format can be the following: 74 * 75 * SHORT: 76 * Warning: lp is down: lp is ready and printing 77 * Warning: no daemon present 78 * Rank Owner Job Files Total Size 79 * active root 30 standard input 5 bytes 80 * 2nd root 31 standard input 5 bytes 81 * 82 * LONG: 83 * 84 * Warning: lp is down: lp is ready and printing 85 * Warning: no daemon present 86 * 87 * root: 1st [job 030taco] 88 * standard input 5 bytes 89 * 90 * root: 2nd [job 031taco] 91 * standard input 5 bytes 92 * 93 */ 94 95#include "lp.h" 96#include "child.h" 97#include "getopt.h" 98#include "getprinter.h" 99#include "getqueue.h" 100#include "initialize.h" 101#include "linksupport.h" 102#include "patchlevel.h" 103#include "sendreq.h" 104 105/**** ENDINCLUDE ****/ 106 107#undef EXTERN 108#undef DEFINE 109#define EXTERN 110#define DEFINE(X) X 111#include "lprm.h" 112/**** ENDINCLUDE ****/ 113 114 static char *Username_JOB; 115 116/*************************************************************************** 117 * main() 118 * - top level of LPRM 119 * 120 ****************************************************************************/ 121 122int main(int argc, char *argv[], char *envp[]) 123{ 124 int i; 125 struct line_list args; 126 127 Init_line_list(&args); 128 129 /* set signal handlers */ 130 (void) plp_signal (SIGHUP, cleanup_HUP); 131 (void) plp_signal (SIGINT, cleanup_INT); 132 (void) plp_signal (SIGQUIT, cleanup_QUIT); 133 (void) plp_signal (SIGTERM, cleanup_TERM); 134 (void) signal (SIGCHLD, SIG_DFL); 135 (void) signal (SIGPIPE, SIG_IGN); 136 137 /* 138 * set up the user state 139 */ 140#ifndef NODEBUG 141 Debug = 0; 142#endif 143 144 145 Initialize(argc, argv, envp, 'D' ); 146 Setup_configuration(); 147 Get_parms(argc, argv); /* scan input args */ 148 if( Auth && !getenv( "AUTH" ) ){ 149 FPRINTF(STDERR, 150 _("authentication requested (-A option) and AUTH environment variable not set") ); 151 usage(); 152 } 153 154 /* now force the printer list */ 155 if( All_printers || (Printer_DYN && safestrcasecmp(Printer_DYN,ALL) == 0 ) ){ 156 All_printers = 1; 157 Get_all_printcap_entries(); 158 if(DEBUGL1)Dump_line_list("lprm - final All_line_list", &All_line_list); 159 } 160 DEBUG1("lprm: Printer_DYN '%s', All_printers %d, All_line_list.count %d", 161 Printer_DYN, All_printers, All_line_list.count ); 162 if( Username_JOB && OriginalRUID ){ 163 struct line_list user_list; 164 char *str, *t; 165 struct passwd *pw; 166 int found; 167 uid_t uid; 168 169 DEBUG2("lprm: checking '%s' for -U perms", 170 Allow_user_setting_DYN ); 171 Init_line_list(&user_list); 172 Split( &user_list, Allow_user_setting_DYN,File_sep,0,0,0,0,0,0); 173 174 found = 0; 175 for( i = 0; !found && i < user_list.count; ++i ){ 176 str = user_list.list[i]; 177 DEBUG2("lprm: checking '%s'", str ); 178 uid = strtol( str, &t, 10 ); 179 if( str == t || *t ){ 180 /* try getpasswd */ 181 pw = getpwnam( str ); 182 if( pw ){ 183 uid = pw->pw_uid; 184 } 185 } 186 DEBUG2( "lprm: uid '%d'", uid ); 187 found = ( uid == OriginalRUID ); 188 DEBUG2( "lprm: found '%d'", found ); 189 } 190 if( !found ){ 191 DEBUG1( "-U (username) can only be used by ROOT or authorized users" ); 192 Username_JOB = 0; 193 } 194 } 195 if( Username_JOB ){ 196 Set_DYN( &Logname_DYN, Username_JOB ); 197 } 198 Add_line_list(&args,Logname_DYN,0,0,0); 199 for( i = Optind; argv[i]; ++i ){ 200 Add_line_list(&args,argv[i],0,0,0); 201 } 202 Check_max(&args,2); 203 args.list[args.count] = 0; 204 205 if( All_printers ){ 206 if( All_line_list.count == 0 ){ 207 FPRINTF(STDERR,"no printers\n"); 208 cleanup(0); 209 } 210 for( i = 0; i < All_line_list.count; ++i ){ 211 Set_DYN(&Printer_DYN,All_line_list.list[i] ); 212 Do_removal(args.list); 213 } 214 } else { 215 Get_printer(); 216 Do_removal(args.list); 217 } 218 Free_line_list(&args); 219 DEBUG1("lprm: done"); 220 Remove_tempfiles(); 221 DEBUG1("lprm: tempfiles removed"); 222 Errorcode = 0; 223 DEBUG1("lprm: cleaning up"); 224 cleanup(0); 225 return(0); 226} 227 228 229void Do_removal(char **argv) 230{ 231 int fd, n; 232 char msg[LINEBUFFER]; 233 234 DEBUG1("Do_removal: start"); 235 Fix_Rm_Rp_info(0,0); 236 237 if( ISNULL(RemotePrinter_DYN) ){ 238 SNPRINTF( msg, sizeof(msg)) 239 _("Printer: %s - cannot remove jobs from device '%s'\n"), 240 Printer_DYN, Lp_device_DYN ); 241 if( Write_fd_str( 1, msg ) < 0 ) cleanup(0); 242 return; 243 } 244 245 /* fix up authentication */ 246 if( Auth ){ 247 Set_DYN(&Auth_DYN, getenv("AUTH")); 248 } 249 if( Check_for_rg_group( Logname_DYN ) ){ 250 SNPRINTF( msg, sizeof(msg)) 251 _("Printer: %s - not in privileged group\n"), 252 Printer_DYN ); 253 if( Write_fd_str( 1, msg ) < 0 ) cleanup(0); 254 return; 255 } 256 if( Direct_DYN && Lp_device_DYN ){ 257 SNPRINTF( msg, sizeof(msg)) 258 _("Printer: %s - direct connection to device '%s'\n"), 259 Printer_DYN, Lp_device_DYN ); 260 if( Write_fd_str( 1, msg ) < 0 ) cleanup(0); 261 return; 262 } 263 fd = Send_request( 'M', REQ_REMOVE, 264 argv, Connect_timeout_DYN, Send_query_rw_timeout_DYN, 1 ); 265 if( fd > 0 ){ 266 shutdown( fd, 1 ); 267 while( (n = read(fd, msg, sizeof(msg)) ) > 0 ){ 268 if( write(1,msg,n) < 0 ) cleanup(0); 269 } 270 close(fd); 271 } 272 DEBUG1("Do_removal: end"); 273} 274 275/*************************************************************************** 276 * void Get_parms(int argc, char *argv[]) 277 * 1. Scan the argument list and get the flags 278 * 2. Check for duplicate information 279 ***************************************************************************/ 280 281 extern char *next_opt; 282 char LPRM_optstr[] /* LPRM options */ 283 = "AaD:P:U:V" ; 284 char CLEAN_optstr[] /* CLEAN options */ 285 = "AD:" ; 286 287void Get_parms(int argc, char *argv[] ) 288{ 289 int option; 290 char *name; 291 292 293 if( argv[0] && (Name = strrchr( argv[0], '/' )) ) { 294 ++Name; 295 } else { 296 Name = argv[0]; 297 } 298 /* check to see if we simulate (poorly) the LP options */ 299 if( Name && safestrcmp( Name, "clean" ) == 0 ){ 300 LP_mode = 1; 301 while ((option = Getopt (argc, argv, CLEAN_optstr )) != EOF) 302 switch (option) { 303 case 'A': Auth = 1; break; 304 case 'D': 305 Parse_debug( Optarg, 1 ); 306 break; 307 default: usage(); break; 308 } 309 if( Optind < argc ){ 310 name = argv[argc-1]; 311 Get_all_printcap_entries(); 312 if( safestrcasecmp(name,ALL) ){ 313 if( Find_exists_value( &All_line_list, name, Value_sep ) ){ 314 Set_DYN(&Printer_DYN,name); 315 argv[argc-1] = 0; 316 } 317 } else { 318 All_printers = 1; 319 Set_DYN(&Printer_DYN,"all"); 320 } 321 } 322 } else { 323 while ((option = Getopt (argc, argv, LPRM_optstr )) != EOF) 324 switch (option) { 325 case 'A': Auth = 1; break; 326 case 'a': All_printers = 1; Set_DYN(&Printer_DYN,"all"); break; 327 case 'D': Parse_debug(Optarg, 1); break; 328 case 'V': ++Verbose; break; 329 case 'U': Username_JOB = Optarg; break; 330 case 'P': Set_DYN(&Printer_DYN, Optarg); break; 331 default: usage(); break; 332 } 333 } 334 if( Verbose ){ 335 FPRINTF( STDERR, "%s\n", Version ); 336 if( Verbose > 1 ) Printlist( Copyright, 1 ); 337 } 338} 339 340 char *clean_msg[] = { 341 N_(" usage: %s [-A] [-Ddebuglevel] (jobid|user|'all')* [printer]\n"), 342 N_(" -A - use authentication\n"), 343 N_(" -Ddebuglevel - debug level\n"), 344 N_(" user removes user jobs\n"), 345 N_(" all removes all jobs\n"), 346 N_(" jobid removes job number jobid\n"), 347 N_(" Example:\n"), 348 N_(" 'clean 30 lp' removes job 30 on printer lp\n"), 349 N_(" 'clean' removes first job on default printer\n"), 350 N_(" 'clean all' removes all your jobs on default printer\n"), 351 N_(" 'clean all all' removes all your jobs on all printers\n"), 352 N_(" Note: clean removes only jobs for which you have removal permission\n"), 353 0 }; 354 355 char *lprm_msg[] = { 356 N_(" usage: %s [-A] [-a | -Pprinter] [-Ddebuglevel] (jobid|user|'all')*\n"), 357 N_(" -a - all printers\n"), 358 N_(" -A - use authentication\n"), 359 N_(" -Pprinter - printer (default PRINTER environment variable)\n"), 360 N_(" -Uuser - impersonate this user (root or privileged user only)\n"), 361 N_(" -Ddebuglevel - debug level\n"), 362 N_(" -V - show version information\n"), 363 N_(" user removes user jobs\n"), 364 N_(" all removes all jobs\n"), 365 N_(" jobid removes job number jobid\n"), 366 N_(" Example:\n"), 367 N_(" 'lprm -Plp 30' removes job 30 on printer lp\n"), 368 N_(" 'lprm -a' removes all your jobs on all printers\n"), 369 N_(" 'lprm -a all' removes all jobs on all printers\n"), 370 N_(" Note: lprm removes only jobs for which you have removal permission\n"), 371 0 }; 372 373void pr_msg( char **msg ) 374{ 375 int i; 376 char *s; 377 for( i = 0; (s = msg[i]); ++i ){ 378 if( i == 0 ){ 379 FPRINTF(STDERR, _(s), Name ); 380 } else { 381 FPRINTF(STDERR, "%s", _(s) ); 382 } 383 } 384} 385 386void usage(void) 387{ 388 if( !LP_mode ){ 389 pr_msg(lprm_msg); 390 } else { 391 pr_msg(clean_msg); 392 } 393 Parse_debug("=",-1); 394 FPRINTF( STDOUT, "%s\n", Version ); 395 exit(1); 396} 397