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 #include "lp.h"
11 #include "errormsg.h"
12 #include "errorcodes.h"
13 #include "child.h"
14 #include "getopt.h"
15 #include "getqueue.h"
16 /**** ENDINCLUDE ****/
17 
18 #if defined(HAVE_SYSLOG_H)
19 # include <syslog.h>
20 #endif
21 
22 /****************************************************************************/
23 
24 
25  static void use_syslog( int kind, char *msg );
26 
27 /****************************************************************************
28  * char *Errormsg( int err )
29  *  returns a printable form of the
30  *  errormessage corresponding to the valie of err.
31  *  This is the poor man's version of sperror(), not available on all systems
32  *  Patrick Powell Tue Apr 11 08:05:05 PDT 1995
33  ****************************************************************************/
34 /****************************************************************************/
35 
36 #ifndef HAVE_STRERROR
Errormsg(int err)37 const char * Errormsg ( int err )
38 {
39 	if( err == 0 ){
40 		return "No Error";
41 	} else {
42 		static char msgbuf[32];     /* holds "errno=%d". */
43 		(void) plp_snprintf(msgbuf, sizeof(msgbuf), "errno=%d", err);
44 		return msgbuf;
45 	}
46 }
47 #endif
48 
49  struct msgkind {
50     int var;
51     const char *str;
52 };
53 
54  static struct msgkind msg_name[] = {
55     {LOG_CRIT, " (CRIT)"},
56     {LOG_ERR, " (ERR)"},
57     {LOG_WARNING, " (WARN)"},
58     {LOG_NOTICE, " (NOTICE)"},
59     {LOG_INFO, " (INFO)"},
60     {LOG_DEBUG, ""},
61     {0,0}
62 };
63 
putlogmsg(int kind)64  static const char * putlogmsg(int kind)
65 {
66     int i;
67     static char b[32];
68 
69 	b[0] = 0;
70 	if( kind < 0 ) return(b);
71     for (i = 0; msg_name[i].str; ++i) {
72 		if ( msg_name[i].var == kind) {
73 			return (msg_name[i].str);
74 		}
75     }
76 	/* SAFE USE of SNPRINTF */
77     (void) plp_snprintf(b, sizeof(b), "<BAD LOG FLAG %d>", kind);
78     return (b);
79 }
80 
81 
use_syslog(int kind,char * msg)82  static void use_syslog(int kind, char *msg)
83 {
84     /* testing mode indicates that this is not being used
85      * in the "real world", so don't get noisy. */
86 
87 	/* we get rid of first set of problems - stupid characters */
88 	char buffer[SMALLBUFFER];
89 	plp_snprintf(buffer,sizeof(buffer)-1, "%s",msg);
90 	msg = buffer;
91 
92 #ifndef HAVE_SYSLOG_H
93 	/* Note: some people would open "/dev/console", as default
94 		Bad programmer, BAD!  You should parameterize this
95 		and set it up as a default value.  This greatly aids
96 		in testing for portability.
97 		Patrick Powell Tue Apr 11 08:07:47 PDT 1995
98 	 */
99 	int Syslog_fd;
100 	if	(Syslog_fd = open( Syslog_device_DYN,
101 				O_WRONLY|O_APPEND|O_NOCTTY, Spool_file_perms_DYN )) > 0 ) ){
102 		int len;
103 
104 		Max_open( Syslog_fd);
105 		len = safestrlen(msg);
106 		msg[len] = '\n';
107 		msg[len+1] = 0;
108 		Write_fd_len( Syslog_fd, msg, len+1 );
109 		close( Syslog_fd );
110 		msg[len] = 0;
111     }
112 
113 #else                           /* HAVE_SYSLOG_H */
114 # ifdef HAVE_OPENLOG
115 	/* use the openlog facility */
116 	openlog(Name, LOG_PID | LOG_NOWAIT, SYSLOG_FACILITY );
117 	syslog(kind, "%s", msg);
118 	closelog();
119 
120 # else
121     (void) syslog(SYSLOG_FACILITY | kind, "%s", msg);
122 # endif							/* HAVE_OPENLOG */
123 #endif                          /* HAVE_SYSLOG_H */
124 }
125 
126 
log_backend(int kind,char * log_buf)127  static void log_backend (int kind, char *log_buf)
128 {
129     char stamp_buf[2*SMALLBUFFER];
130 	int n;
131 	char *s;
132 	/* plp_block_mask omask; / **/
133 	int err = errno;
134 
135     /* plp_block_all_signals (&omask); / **/
136 	/* put the error message into the status file as well */
137     /*
138      * Now build up the state info: timestamp, hostname, argv[0], pid, etc.
139      * Don't worry about efficiency here -- it shouldn't happen very often
140      * (unless we're debugging).
141      */
142 
143 	stamp_buf[0] = 0;
144 	/* remove trailing \n */
145 	if( (s = strrchr(log_buf, '\n')) && cval(s+1) == 0 ){
146 		*s = 0;
147 	}
148 
149 
150 	if( Is_server || DEBUGL1 ){
151 		/* log stuff */
152 		if( (LOG_EMERG < LOG_INFO && kind <= LOG_INFO )
153 			|| ( LOG_EMERG > LOG_INFO && kind >= LOG_INFO )){
154 			setstatus( 0, "%s", log_buf );
155 			use_syslog(kind, log_buf);
156 		}
157 		n = safestrlen(stamp_buf); s = stamp_buf+n; n = sizeof(stamp_buf)-n;
158 		(void) plp_snprintf( s, n, "%s", Time_str(0,0) );
159 		if (ShortHost_FQDN ) {
160 			n = safestrlen(stamp_buf); s = stamp_buf+n; n = sizeof(stamp_buf)-n;
161 			(void) plp_snprintf( s, n, " %s", ShortHost_FQDN );
162 		}
163 		if(Debug || DbgFlag){
164 			n = safestrlen(stamp_buf); s = stamp_buf+n; n = sizeof(stamp_buf)-n;
165 			(void) plp_snprintf(s, n, " [%ld]", (long)getpid());
166 			n = safestrlen(stamp_buf); s = stamp_buf+n; n = sizeof(stamp_buf)-n;
167 			if(Name) (void) plp_snprintf(s, n, " %s", Name);
168 			n = safestrlen(stamp_buf); s = stamp_buf+n; n = sizeof(stamp_buf)-n;
169 			(void) plp_snprintf(s, n, " %s", putlogmsg(kind) );
170 		}
171 		n = safestrlen(stamp_buf); s = stamp_buf+n; n = sizeof(stamp_buf)-n;
172 		(void) plp_snprintf(s, n, " %s", log_buf );
173 	} else {
174 		(void) plp_snprintf(stamp_buf, sizeof(stamp_buf), "%s", log_buf );
175 	}
176 
177 	if( safestrlen(stamp_buf) > (int)sizeof(stamp_buf) - 8 ){
178 		stamp_buf[sizeof(stamp_buf)-8] = 0;
179 		strcpy(stamp_buf+safestrlen(stamp_buf),"...");
180 	}
181 	n = safestrlen(stamp_buf); s = stamp_buf+n; n = sizeof(stamp_buf)-n;
182 	(void) plp_snprintf(s, n, "\n" );
183 
184 
185     /* use writes here: on HP/UX, using f p rintf really screws up. */
186 	/* if stdout or stderr is dead, you have big problems! */
187 
188 	Write_fd_str( 2, stamp_buf );
189 
190     /* plp_unblock_all_signals ( &omask ); / **/
191 	errno = err;
192 }
193 
194 /*****************************************************
195  * Put the printer name at the start of the log buffer
196  *****************************************************/
197 
prefix_printer(char * log_buf,int len)198  static void prefix_printer( char *log_buf, int len )
199 {
200 	log_buf[0] = 0;
201     if( Printer_DYN ){
202 		plp_snprintf( log_buf, len-4, "%s: ", Printer_DYN );
203 	}
204 }
205 
206 /* VARARGS2 */
207 #ifdef HAVE_STDARGS
logmsg(int kind,const char * msg,...)208  void logmsg(int kind, const char *msg,...)
209 #else
210  void logmsg(va_alist) va_dcl
211 #endif
212 {
213 #ifndef HAVE_STDARGS
214     int kind;
215     char *msg;
216 #endif
217 	int n;
218 	char *s;
219 	int err = errno;
220 	static int in_log;
221 	char log_buf[SMALLBUFFER];
222     VA_LOCAL_DECL
223     VA_START (msg);
224     VA_SHIFT (kind, int);
225     VA_SHIFT (msg, char *);
226 
227 	if( in_log == 0 ){
228 		++in_log;
229 		prefix_printer(log_buf, sizeof(log_buf));
230 		n = safestrlen(log_buf); s = log_buf+n; n = sizeof(log_buf)-n-4;
231 		(void) plp_vsnprintf(s, n, msg, ap);
232 		log_backend (kind,log_buf);
233 		in_log = 0;
234 	}
235     VA_END;
236 	errno = err;
237 }
238 
239 /* VARARGS2 */
240 #ifdef HAVE_STDARGS
fatal(int kind,const char * msg,...)241  void fatal (int kind, const char *msg,...)
242 #else
243  void fatal (va_alist) va_dcl
244 #endif
245 {
246 #ifndef HAVE_STDARGS
247     int kind;
248     char *msg;
249 #endif
250 	int n;
251 	char *s;
252 	char log_buf[SMALLBUFFER];
253 	static int in_log;
254     VA_LOCAL_DECL
255     VA_START (msg);
256     VA_SHIFT (kind, int);
257     VA_SHIFT (msg, char *);
258 
259 	if( in_log == 0 ){
260 		++in_log;
261 		prefix_printer(log_buf, sizeof(log_buf));
262 		n = safestrlen(log_buf); s = log_buf+n; n = sizeof(log_buf)-n-4;
263 		(void) plp_vsnprintf(s, n, msg, ap);
264 		log_backend (kind, log_buf);
265 		in_log = 0;
266 	}
267 
268     VA_END;
269     cleanup(0);
270 }
271 
272 /* VARARGS2 */
273 #ifdef HAVE_STDARGS
logerr(int kind,const char * msg,...)274  void logerr (int kind, const char *msg,...)
275 #else
276  void logerr (va_alist) va_dcl
277 #endif
278 {
279 #ifndef HAVE_STDARGS
280     int kind;
281     char *msg;
282 #endif
283 	int err = errno;
284 	char log_buf[SMALLBUFFER];
285 	static int in_log;
286     VA_LOCAL_DECL
287     VA_START (msg);
288     VA_SHIFT (kind, int);
289     VA_SHIFT (msg, char *);
290 
291 	if( in_log == 0 ){
292 		int n;
293 		char *s;
294 		++in_log;
295 		prefix_printer(log_buf, sizeof(log_buf)-4);
296 		n = safestrlen(log_buf); s = log_buf+n; n = sizeof(log_buf)-n-4;
297 		(void) plp_vsnprintf(s, n, msg, ap);
298 		n = safestrlen(log_buf); s = log_buf+n; n = sizeof(log_buf)-n-4;
299 		if( err ) (void) plp_snprintf(s, n, " - %s", Errormsg (err));
300 		log_backend (kind, log_buf);
301 		in_log = 0;
302 	}
303     VA_END;
304     errno = err;
305 }
306 
307 /* VARARGS2 */
308 #ifdef HAVE_STDARGS
logerr_die(int kind,const char * msg,...)309  void logerr_die (int kind, const char *msg,...)
310 #else
311  void logerr_die (va_alist) va_dcl
312 #endif
313 {
314 #ifndef HAVE_STDARGS
315     int kind;
316     char *msg;
317 #endif
318 	int err = errno;
319 	char log_buf[SMALLBUFFER];
320 	static int in_log;
321     VA_LOCAL_DECL
322 
323     VA_START (msg);
324     VA_SHIFT (kind, int);
325     VA_SHIFT (msg, char *);
326 
327 	if( in_log == 0 ){
328 		int n;
329 		char *s;
330 		++in_log;
331 		prefix_printer(log_buf, sizeof(log_buf));
332 		n = safestrlen(log_buf); s = log_buf+n; n = sizeof(log_buf)-n;
333 		(void) plp_vsnprintf(s, n, msg, ap);
334 		n = safestrlen(log_buf); s = log_buf+n; n = sizeof(log_buf)-n;
335 		if( err ) (void) plp_snprintf(s, n, " (errno %d)", err);
336 		if( err ) (void) plp_snprintf(s, n, " - %s", Errormsg (err));
337 		log_backend (kind, log_buf);
338 		in_log = 0;
339 	}
340     cleanup(0);
341     VA_END;
342 }
343 
344 /***************************************************************************
345  * Diemsg( char *m1, *m2, ...)
346  * print error message to stderr, and die
347  ***************************************************************************/
348 
349 /* VARARGS1 */
350 #ifdef HAVE_STDARGS
Diemsg(const char * msg,...)351  void Diemsg (const char *msg,...)
352 #else
353  void Diemsg (va_alist) va_dcl
354 #endif
355 {
356 #ifndef HAVE_STDARGS
357     char *msg;
358 #endif
359 	char buffer[SMALLBUFFER];
360 	char *s;
361 	int n;
362 	static int in_log;
363     VA_LOCAL_DECL
364 
365     VA_START (msg);
366     VA_SHIFT (msg, char *);
367 	if( in_log == 0 ){
368 		++in_log;
369 		buffer[0] = 0;
370 		n = safestrlen(buffer); s = buffer + n; n = sizeof(buffer) - n;
371 		(void) plp_snprintf(s, n, "Fatal error - ");
372 
373 		n = safestrlen(buffer); s = buffer + n; n = sizeof(buffer) - n;
374 		(void) plp_vsnprintf(s, n, msg, ap);
375 		n = safestrlen(buffer); s = buffer + n; n = sizeof(buffer) - n;
376 		(void) plp_snprintf(s, n, "\n" );
377 
378 		/* ignore error, we are dying anyways */
379 		Write_fd_str( 2, buffer );
380 		in_log = 0;
381 	}
382 
383     cleanup(0);
384     VA_END;
385 }
386 
387 /***************************************************************************
388  * Warnmsg( char *m1, *m2, ...)
389  * print warning message to stderr
390  ***************************************************************************/
391 
392 /* VARARGS1 */
393 #ifdef HAVE_STDARGS
Warnmsg(const char * msg,...)394  void Warnmsg (const char *msg,...)
395 #else
396  void Warnmsg (va_alist) va_dcl
397 #endif
398 {
399 #ifndef HAVE_STDARGS
400     char *msg;
401 #endif
402 	char buffer[SMALLBUFFER];
403 	char *s = buffer;
404 	int n;
405 	int err = errno;
406 	static int in_log;
407     VA_LOCAL_DECL
408     VA_START (msg);
409     VA_SHIFT (msg, char *);
410 
411 	if( in_log ) return;
412 	++in_log;
413 	buffer[0] = 0;
414 	n = safestrlen(buffer); s = buffer+n; n = sizeof(buffer)-n;
415     (void) plp_snprintf(s, n, "Warning - ");
416 	n = safestrlen(buffer); s = buffer+n; n = sizeof(buffer)-n;
417     (void) plp_vsnprintf(s, n, msg, ap);
418 	n = safestrlen(buffer); s = buffer+n; n = sizeof(buffer)-n;
419     (void) plp_snprintf(s, n, "\n");
420 
421 	Write_fd_str( 2, buffer );
422 	in_log = 0;
423 	errno = err;
424     VA_END;
425 }
426 
427 
428 /***************************************************************************
429  * Message( char *m1, *m2, ...)
430  * print warning message to stderr
431  ***************************************************************************/
432 
433 /* VARARGS1 */
434 #ifdef HAVE_STDARGS
Message(const char * msg,...)435  void Message (const char *msg,...)
436 #else
437  void Message (va_alist) va_dcl
438 #endif
439 {
440 #ifndef HAVE_STDARGS
441     char *msg;
442 #endif
443 	char buffer[SMALLBUFFER];
444 	char *s = buffer;
445 	int n;
446 	int err = errno;
447 	static int in_log;
448     VA_LOCAL_DECL
449     VA_START (msg);
450     VA_SHIFT (msg, char *);
451 
452 	if( in_log ) return;
453 	++in_log;
454 	buffer[0] = 0;
455 	n = safestrlen(buffer); s = buffer+n; n = sizeof(buffer)-n;
456     (void) plp_vsnprintf(s, n, msg, ap);
457 	n = safestrlen(buffer); s = buffer+n; n = sizeof(buffer)-n;
458     (void) plp_snprintf(s, n, "\n");
459 
460 	Write_fd_str( 2, buffer );
461 	in_log = 0;
462 	errno = err;
463     VA_END;
464 }
465 
466 /* VARARGS1 */
467 #ifdef HAVE_STDARGS
logDebug(const char * msg,...)468  void logDebug (const char *msg,...)
469 #else
470  void logDebug (va_alist) va_dcl
471 #endif
472 {
473 #ifndef HAVE_STDARGS
474     char *msg;
475 #endif
476 	int err = errno;
477 	char log_buf[SMALLBUFFER];
478 	static int in_log;
479     VA_LOCAL_DECL
480     VA_START (msg);
481     VA_SHIFT (msg, char *);
482 
483 	if( in_log == 0 ){
484 		int n;
485 		char *s;
486 
487 		++in_log;
488 		prefix_printer(log_buf, sizeof(log_buf));
489 		n = safestrlen(log_buf); s = log_buf+n; n = sizeof(log_buf)-n;
490 		(void) plp_vsnprintf(s, n, msg, ap);
491 		log_backend(LOG_DEBUG, log_buf);
492 		in_log = 0;
493 	}
494 	errno = err;
495     VA_END;
496 }
497 
498 /***************************************************************************
499  * char *Sigstr(n)
500  * Return a printable form the the signal
501  ***************************************************************************/
502 
503  struct signame {
504     const char *str;
505     int value;
506 };
507 
508 #undef PAIR
509 #ifndef _UNPROTO_
510 # define PAIR(X) { #X , X }
511 #else
512 # define __string(X) "X"
513 # define PAIR(X) { __string(X) , X }
514 #endif
515 
516  struct signame signals[] = {
517 { "NO SIGNAL", 0 },
518 #ifdef SIGHUP
519  PAIR(SIGHUP),
520 #endif
521 #ifdef SIGINT
522  PAIR(SIGINT),
523 #endif
524 #ifdef SIGQUIT
525  PAIR(SIGQUIT),
526 #endif
527 #ifdef SIGILL
528  PAIR(SIGILL),
529 #endif
530 #ifdef SIGTRAP
531  PAIR(SIGTRAP),
532 #endif
533 #ifdef SIGIOT
534  PAIR(SIGIOT),
535 #endif
536 #ifdef SIGABRT
537  PAIR(SIGABRT),
538 #endif
539 #ifdef SIGEMT
540  PAIR(SIGEMT),
541 #endif
542 #ifdef SIGFPE
543  PAIR(SIGFPE),
544 #endif
545 #ifdef SIGKILL
546  PAIR(SIGKILL),
547 #endif
548 #ifdef SIGBUS
549  PAIR(SIGBUS),
550 #endif
551 #ifdef SIGSEGV
552  PAIR(SIGSEGV),
553 #endif
554 #ifdef SIGSYS
555  PAIR(SIGSYS),
556 #endif
557 #ifdef SIGPIPE
558  PAIR(SIGPIPE),
559 #endif
560 #ifdef SIGALRM
561  PAIR(SIGALRM),
562 #endif
563 #ifdef SIGTERM
564  PAIR(SIGTERM),
565 #endif
566 #ifdef SIGURG
567  PAIR(SIGURG),
568 #endif
569 #ifdef SIGSTOP
570  PAIR(SIGSTOP),
571 #endif
572 #ifdef SIGTSTP
573  PAIR(SIGTSTP),
574 #endif
575 #ifdef SIGCONT
576  PAIR(SIGCONT),
577 #endif
578 #ifdef SIGCHLD
579  PAIR(SIGCHLD),
580 #endif
581 #ifdef SIGCLD
582  PAIR(SIGCLD),
583 #endif
584 #ifdef SIGTTIN
585  PAIR(SIGTTIN),
586 #endif
587 #ifdef SIGTTOU
588  PAIR(SIGTTOU),
589 #endif
590 #ifdef SIGIO
591  PAIR(SIGIO),
592 #endif
593 #ifdef SIGPOLL
594  PAIR(SIGPOLL),
595 #endif
596 #ifdef SIGXCPU
597  PAIR(SIGXCPU),
598 #endif
599 #ifdef SIGXFSZ
600  PAIR(SIGXFSZ),
601 #endif
602 #ifdef SIGVTALRM
603  PAIR(SIGVTALRM),
604 #endif
605 #ifdef SIGPROF
606  PAIR(SIGPROF),
607 #endif
608 #ifdef SIGWINCH
609  PAIR(SIGWINCH),
610 #endif
611 #ifdef SIGLOST
612  PAIR(SIGLOST),
613 #endif
614 #ifdef SIGUSR1
615  PAIR(SIGUSR1),
616 #endif
617 #ifdef SIGUSR2
618  PAIR(SIGUSR2),
619 #endif
620 {0,0}
621     /* that's all */
622 };
623 
624 #ifndef NSIG
625 # define  NSIG 32
626 #endif
627 
628 
Sigstr(int n)629 const char *Sigstr (int n)
630 {
631     static char buf[40];
632 	const char *s = 0;
633 
634 	if( n == 0 ){
635 		return( "No signal");
636 	}
637     if (n < NSIG && n >= 0) {
638 #if defined(HAVE_SYS_SIGLIST)
639 # if !defined(HAVE_SYS_SIGLIST_DEF)
640 		extern const char *sys_siglist[];
641 # endif
642 		s = sys_siglist[n];
643 #else
644 # if defined(HAVE__SYS_SIGLIST)
645 #  if !defined(HAVE__SYS_SIGLIST_DEF)
646 		extern const char *_sys_siglist[];
647 #  endif
648 		s = _sys_siglist[n];
649 # else
650 		int i;
651 		for( i = 0; signals[i].str && signals[i].value != n; ++i );
652 		s = signals[i].str;
653 # endif
654 #endif
655 	}
656 	if( s == 0 ){
657 		s = buf;
658 		(void) plp_snprintf(buf, sizeof(buf), "signal %d", n);
659 	}
660     return(s);
661 }
662 
663 /***************************************************************************
664  * Decode_status (plp_status_t *status)
665  * returns a printable string encoding return status
666  ***************************************************************************/
667 
Decode_status(plp_status_t * status)668 const char *Decode_status (plp_status_t *status)
669 {
670     static char msg[LINEBUFFER];
671 
672 	int n;
673     *msg = 0;		/* just in case! */
674     if (WIFEXITED (*status)) {
675 		n = WEXITSTATUS(*status);
676 		if( n > 0 && n < 32 ) n += JFAIL-1;
677 		(void) plp_snprintf(msg, sizeof(msg),
678 		"exit status %d (%s)", WEXITSTATUS(*status),
679 				 Server_status(n) );
680     } else if (WIFSTOPPED (*status)) {
681 		(void) strcpy(msg, "stopped");
682     } else {
683 		(void) plp_snprintf(msg, sizeof(msg), "died%s",
684 			WCOREDUMP (*status) ? " and dumped core" : "");
685 		if (WTERMSIG (*status)) {
686 			(void) plp_snprintf(msg + safestrlen (msg), sizeof(msg)-safestrlen(msg),
687 				 ", %s", Sigstr ((int) WTERMSIG (*status)));
688 		}
689     }
690     return (msg);
691 }
692 
693 /***************************************************************************
694  * char *Server_status( int d )
695  *  translate the server status;
696  ***************************************************************************/
697 
698 	static struct signame statname[] = {
699 	PAIR(JSUCC),
700 	PAIR(JFAIL),
701 	PAIR(JABORT),
702 	PAIR(JREMOVE),
703 	PAIR(JHOLD),
704 	PAIR(JNOSPOOL),
705 	PAIR(JNOPRINT),
706 	PAIR(JSIGNAL),
707 	PAIR(JFAILNORETRY),
708 	PAIR(JSUSP),
709 	PAIR(JTIMEOUT),
710 	PAIR(JWRERR),
711 	PAIR(JRDERR),
712 	PAIR(JCHILD),
713 	PAIR(JNOWAIT),
714 	{0,0}
715 	};
716 
Server_status(int d)717 const char *Server_status( int d )
718 {
719 	const char *s;
720 	int i;
721 	static char msg[LINEBUFFER];
722 
723 	if( d > 0 && d < 32 ) d += 31;
724 	for( i = 0; (s = statname[i].str) && statname[i].value != d; ++i );
725 	if( s == 0 ){
726 		s = msg;
727 		plp_snprintf( msg, sizeof(msg), "UNKNOWN STATUS '%d'", d );
728 	}
729 	return(s);
730 }
731 
732 /*
733  * Error status on STDERR
734  */
735 /* VARARGS2 */
736 #ifdef HAVE_STDARGS
setstatus(struct job * job,const char * fmt,...)737  void setstatus (struct job *job,const char *fmt,...)
738 #else
739  void setstatus (va_alist) va_dcl
740 #endif
741 {
742 #ifndef HAVE_STDARGS
743     struct job *job;
744     char *fmt;
745 #endif
746 	char msg_b[SMALLBUFFER];
747 	static int insetstatus;
748 	struct stat statb;
749     VA_LOCAL_DECL
750 
751     VA_START (fmt);
752     VA_SHIFT (job, struct job * );
753     VA_SHIFT (fmt, char *);
754 	if( Doing_cleanup || fmt == 0 || *fmt == 0 || insetstatus ) return;
755 
756 	insetstatus = 1;
757 	(void) plp_vsnprintf( msg_b, sizeof(msg_b)-4, fmt, ap);
758 	DEBUG1("setstatus: msg '%s'", msg_b);
759 	if( !Is_server ){
760 		if( Verbose || !Is_lpr ){
761 			(void) plp_vsnprintf(msg_b, sizeof(msg_b)-2, fmt, ap);
762 			strcat( msg_b,"\n" );
763 			if( Write_fd_str( 2, msg_b ) < 0 ) cleanup(0);
764 		} else {
765 			Add_line_list(&Status_lines,msg_b,0,0,0);
766 		}
767 	} else {
768 		if( Status_fd <= 0
769 			|| ( Max_status_size_DYN > 0 && fstat( Status_fd, &statb ) != -1
770 			&& (statb.st_size / 1024 ) > Max_status_size_DYN ) ){
771 			Status_fd = Trim_status_file( Status_fd, Queue_status_file_DYN,
772 				Max_status_size_DYN, Min_status_size_DYN );
773 		}
774 		send_to_logger( Status_fd, Mail_fd, job, PRSTATUS, msg_b );
775 	}
776 	insetstatus = 0;
777 	VA_END;
778 }
779 
780 
781 /***************************************************************************
782  * void setmessage (struct job *job,char *header, char *fmt,...)
783  * put the message out (if necessary) to the logger
784  ***************************************************************************/
785 
786 /* VARARGS2 */
787 #ifdef HAVE_STDARGS
setmessage(struct job * job,const char * header,const char * fmt,...)788  void setmessage (struct job *job,const char *header, const char *fmt,...)
789 #else
790  void setmessage (va_alist) va_dcl
791 #endif
792 {
793 #ifndef HAVE_STDARGS
794     struct job *job;
795     char *header;
796     char *fmt;
797 #endif
798 	char msg_b[SMALLBUFFER];
799 
800     VA_LOCAL_DECL
801 
802     VA_START (fmt);
803     VA_SHIFT (job, struct job * );
804     VA_SHIFT (header, char *);
805     VA_SHIFT (fmt, char *);
806 
807 	if( Doing_cleanup ) return;
808 	(void) plp_vsnprintf( msg_b, sizeof(msg_b)-4, fmt, ap);
809 	DEBUG1("setmessage: msg '%s'", msg_b);
810 	if( Is_server ){
811 		send_to_logger( -1, -1, job, header, msg_b );
812 	} else {
813 		strcat( msg_b,"\n" );
814 		if( Write_fd_str( 2, msg_b ) < 0 ) cleanup(0);
815 	}
816 	VA_END;
817 }
818 
819 
820 /***************************************************************************
821  * send_to_logger( struct job *job, char *msg )
822  *  This will try and send to the logger.
823  ***************************************************************************/
824 
send_to_logger(int send_to_status_fd,int send_to_mail_fd,struct job * job,const char * header,char * msg_b)825  void send_to_logger( int send_to_status_fd, int send_to_mail_fd,
826 	struct job *job, const char *header, char *msg_b )
827 {
828 	char *s, *t;
829 	char *id, *tstr;
830 	int num,pid;
831 	char out_b[4*SMALLBUFFER];
832 	struct line_list l;
833 
834 	if( !Is_server || Doing_cleanup ) return;
835 	Init_line_list(&l);
836 	if(DEBUGL4){
837 		char buffer[32];
838 		plp_snprintf(buffer,sizeof(buffer)-5, "%s", msg_b );
839 		if( msg_b ) safestrncat( buffer,"...");
840 		LOGDEBUG("send_to_logger: Logger_fd fd %d, send_to_status_fd %d, send_to_mail fd %d, header '%s', body '%s'",
841 			Logger_fd, send_to_status_fd, send_to_mail_fd, header, buffer );
842 	}
843 	if( send_to_status_fd <= 0 && send_to_mail_fd <= 0 && Logger_fd <= 0 ) return;
844 	s = t = id = tstr = 0;
845 	num = 0;
846 	if( job ){
847 		Set_str_value(&l,IDENTIFIER,
848 			(id = Find_str_value(&job->info,IDENTIFIER)) );
849 		Set_decimal_value(&l,NUMBER,
850 			(num = Find_decimal_value(&job->info,NUMBER)) );
851 	}
852 	Set_str_value(&l,UPDATE_TIME,(tstr=Time_str(0,0)));
853 	Set_decimal_value(&l,PROCESS,(pid=getpid()));
854 
855 	plp_snprintf( out_b, sizeof(out_b), "%s at %s ## %s=%s %s=%d %s=%d\n",
856 		msg_b, tstr, IDENTIFIER, id, NUMBER, num, PROCESS, pid );
857 
858 	if( send_to_status_fd > 0 && Write_fd_str( send_to_status_fd, out_b ) < 0 ){
859 		DEBUG4("send_to_logger: write to send_to_status_fd %d failed - %s",
860 			send_to_status_fd, Errormsg(errno) );
861 	}
862 	if( send_to_mail_fd > 0 && Write_fd_str( send_to_mail_fd, out_b ) < 0 ){
863 		DEBUG4("send_to_logger: write to send_to_mail_fd %d failed - %s",
864 			send_to_mail_fd, Errormsg(errno) );
865 	}
866 	if( Logger_fd > 0 ){
867 		Set_str_value(&l,PRINTER,Printer_DYN);
868 		Set_str_value(&l,HOST,FQDNHost_FQDN);
869 		s = Escape(msg_b,1);
870 		Set_str_value(&l,VALUE,s);
871 		if(s) free(s); s = 0;
872 		t = Join_line_list(&l,"\n");
873 		s = Escape(t,1);
874 		if(t) free(t); t = 0;
875 		t = safestrdup4(header,"=",s,"\n",__FILE__,__LINE__);
876 		Write_fd_str( Logger_fd, t );
877 		if( s ) free(s); s = 0;
878 		if( t ) free(t); t = 0;
879 	}
880 	Free_line_list(&l);
881 }
882 
883