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