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