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