1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #include <locale.h>
31 #include "stdio.h"
32 #include "errno.h"
33 #include "string.h"
34 #include "sys/types.h"
35 #include "sys/stat.h"
36 #include "stdlib.h"
37
38 #include "lp.h"
39 #include "access.h"
40 #include "form.h"
41 #include "msgs.h"
42
43 #define WHO_AM_I I_AM_LPFORMS
44 #include "oam.h"
45
46 #define OPT_LIST "f:F:xlLA:u:W:Q:P:d"
47
48 #define TMPDIR "/usr/tmp"
49
50 typedef int (*Action)();
51
52 #if defined(__STDC__)
53
54 static int add_form ( char * , FILE * , FALERT * , char * );
55 static int add_alert ( char * , FILE * , FALERT * , char * );
56 static int delete_form ( char * );
57 static int list_form ( char * );
58 static int list_alert ( char * );
59 static int list_both ( char * );
60 static int any_alert ( char * , FILE * , FALERT * );
61 static int quiet_alert ( char * );
62 static int notify_spooler ( int , int , char * );
63 static int onerror ( int , int , int );
64
65 static Action set_action ( int (*)() , char * );
66
67 #else
68
69 static int add_form();
70 static int add_alert();
71 static int delete_form();
72 static int list_form();
73 static int list_alert();
74 static int list_both();
75 static int any_alert();
76 static int quiet_alert();
77 static int notify_spooler();
78 static int onerror();
79
80 static Action set_action();
81
82 #endif
83
84 /**
85 ** usage()
86 **/
87
usage()88 void usage ()
89 {
90 (void) printf (gettext(
91 "usage:\n"
92 "\n"
93 " (add or change form)\n"
94 " lpforms -f form-name [options]\n"
95 " [-F path-name | - | -P paper [-d] | -d ] (form definition)\n"
96 " -F path-name (initialize from file)\n"
97 " - (initialize from stdin)\n"
98 " -P paper [-d] (initialize with paper (as default))\n"
99 " -d (create form with paper of same name)\n"
100 " [-u allow:user-list | deny:user-list] (who's allowed to use)\n"
101 " [-A mail | write | shell-command] (alert definition)\n"
102 " [-Q threshold] (# needed for alert)\n"
103 " [-W interval] (minutes between alerts)\n"
104 "\n"
105 " (list form)\n"
106 " lpforms -f form-name -l\n"
107 " lpforms -f form-name -L (verbose for -P forms)\n"
108 "\n"
109 " (delete form)\n"
110 " lpforms -f form-name -x\n"
111 "\n"
112 " (define alert for forms with no alert yet)\n"
113 " lpforms -f any -A {mail | write | shell-command}\n"
114 "\n"
115 " (define alert for all forms)\n"
116 " lpforms -f all -A {mail | write | shell-command}\n"
117 "\n"
118 " (examine alerting)\n"
119 " lpforms -f form-name -A list\n"
120 "\n"
121 " (stop alerting)\n"
122 " lpforms -f form-name -A quiet (temporarily)\n"
123 " lpforms -f form-name -A none (for good)"
124 "\n"
125 ));
126
127 return;
128 }
129
130 static char *P = NULL;
131 static int d = 0;
132 static int L = 0;
133 /**
134 ** main()
135 **/
136
137 int
main(int argc,char * argv[])138 main(int argc, char *argv[])
139 {
140 extern int optind;
141 extern int opterr;
142 extern int optopt;
143
144 extern char * optarg;
145
146 int c;
147 int cnt = 0;
148
149 char * form = 0;
150 char * u = 0;
151 char * cp;
152 char * rest;
153 char stroptsw[] = "-X";
154
155 Action action = 0;
156
157 FILE *input = 0;
158
159 FORM fbuf;
160
161 FALERT alert = { (char *)0, -1, -1 };
162
163 struct stat statbuf;
164
165
166 (void) setlocale (LC_ALL, "");
167
168 #if !defined(TEXT_DOMAIN)
169 #define TEXT_DOMAIN "SYS_TEST"
170 #endif
171 (void) textdomain(TEXT_DOMAIN);
172
173 if (!is_user_admin()) {
174 LP_ERRMSG (ERROR, E_LP_NOTADM);
175 exit (1);
176 }
177
178 opterr = 0;
179
180 while ((c = getopt(argc, argv, OPT_LIST)) != -1) {
181
182 /*
183 * These options take values; "getopt()" passes values
184 * that begin with a dash without checking if they're
185 * options. If a value is missing, we want to complain
186 * about it.
187 */
188 switch (c) {
189 case 'W':
190 case 'Q':
191 /*
192 * These options take numeric values, which might
193 * be negative. Negative values are handled later,
194 * but here we just screen them.
195 */
196 (void)strtol (optarg, &rest, 10);
197 if (!rest || (!*rest && rest != optarg))
198 break;
199 /*FALLTHROUGH*/
200 case 'f':
201 case 'F':
202 case 'A':
203 case 'u':
204 if (!*optarg) {
205 stroptsw[1] = c;
206 LP_ERRMSG1 (ERROR, E_LP_NULLARG, stroptsw);
207 exit (1);
208 }
209 if (*optarg == '-') {
210 stroptsw[1] = c;
211 LP_ERRMSG1 (ERROR, E_LP_OPTARG, stroptsw);
212 exit (1);
213 }
214 break;
215 }
216
217 switch (c) {
218
219 case 'f':
220 if (form)
221 LP_ERRMSG1 (WARNING, E_LP_2MANY, 'f');
222 form = optarg;
223 if (!syn_name(form)) {
224 LP_ERRMSG1 (ERROR, E_LP_NOTNAME, form);
225 exit (1);
226 } else if (!*form)
227 form = NAME_ALL;
228 break;
229
230 case 'F':
231 if (input)
232 LP_ERRMSG1 (WARNING, E_LP_2MANY, 'F');
233 if (!(input = fopen(optarg, "r"))) {
234 LP_ERRMSG1 (ERROR, E_FOR_OPEN, optarg);
235 exit (1);
236 }
237 action = set_action(add_form, "-F");
238 break;
239
240 case 'A':
241 if (STREQU(NAME_LIST, optarg))
242 action = set_action(list_alert, "\"-A list\"");
243
244 else if (STREQU(NAME_QUIET, optarg))
245 action = set_action(quiet_alert, "\"-A quiet\"");
246
247 else {
248 if (STREQU(MAIL, optarg) || STREQU(WRITE, optarg))
249 alert.shcmd = makestr(optarg, " ", getname(), (char *)0);
250 else
251 alert.shcmd = strdup(optarg);
252 action = set_action(add_alert, "-A");
253 }
254 break;
255
256 case 'Q':
257 if (alert.Q != -1)
258 LP_ERRMSG1 (WARNING, E_LP_2MANY, 'Q');
259 if (STREQU(NAME_ANY, optarg))
260 alert.Q = 1;
261 else {
262 alert.Q = strtol(optarg, &rest, 10);
263 if (alert.Q < 0) {
264 LP_ERRMSG1 (ERROR, E_LP_NEGARG, 'Q');
265 exit (1);
266 }
267 if (rest && *rest) {
268 LP_ERRMSG1 (ERROR, E_LP_GARBNMB, 'Q');
269 exit (1);
270 }
271 if (alert.Q == 0) {
272 LP_ERRMSG1 (ERROR, E_LP_ZEROARG, 'Q');
273 exit (1);
274 }
275 }
276 action = set_action(add_alert, "-Q");
277 break;
278
279 case 'W':
280 if (alert.W != -1)
281 LP_ERRMSG1 (WARNING, E_LP_2MANY, 'W');
282 if (STREQU(NAME_ONCE, optarg))
283 alert.W = 0;
284 else {
285 alert.W = strtol(optarg, &rest, 10);
286 if (alert.W < 0) {
287 LP_ERRMSG1 (ERROR, E_LP_NEGARG, 'W');
288 exit (1);
289 }
290 if (rest && *rest) {
291 LP_ERRMSG1 (ERROR, E_LP_GARBNMB, 'W');
292 exit (1);
293 }
294 }
295 action = set_action(add_alert, "-W");
296 break;
297
298 case 'u':
299 if (u)
300 LP_ERRMSG1 (WARNING, E_LP_2MANY, 'u');
301 u = strdup(optarg);
302 action = set_action(add_form, "-u");
303 break;
304
305 case 'x':
306 action = set_action(delete_form, "-x");
307 break;
308
309 case 'L':
310 L = 1;
311 action = set_action(list_form, "-L");
312 break;
313 case 'l':
314 action = set_action(list_form, "-l");
315 break;
316
317 case 'd':
318 d = 1;
319 action = set_action(add_form, "-d");
320 break;
321
322 case 'P':
323 if (P)
324 LP_ERRMSG1 (WARNING, E_LP_2MANY, 'P');
325 action = set_action(add_form, "-P");
326 P = strdup(optarg);
327 break;
328
329 default:
330 if (optopt == '?') {
331 usage ();
332 exit (0);
333 }
334 stroptsw[1] = optopt;
335 if (strchr(OPT_LIST, optopt))
336 LP_ERRMSG1 (ERROR, E_LP_OPTARG, stroptsw);
337 else
338 LP_ERRMSG1 (ERROR, E_LP_OPTION, stroptsw);
339 exit (1);
340
341 }
342 }
343
344 if (!form) {
345 LP_ERRMSG (ERROR, E_FOR_FORMNAME);
346 exit (1);
347 }
348
349 if (STREQU(NAME_ANY, form))
350 action = set_action(any_alert, "\"-f any\"");
351
352 if (optind < argc && STREQU(argv[optind], "-")) {
353 action = set_action(add_form, "-");
354 input = stdin;
355 optind++;
356 }
357 if (optind < argc)
358 LP_ERRMSG1 (WARNING, E_FOR_EXTRAARG, argv[optind]);
359
360 if (!action) {
361 LP_ERRMSG (ERROR, E_FOR_NOACT);
362 exit (1);
363 }
364
365 if (action == any_alert && STREQU(alert.shcmd, NAME_NONE)) {
366 LP_ERRMSG (WARNING, E_FOR_ANYDEL);
367 exit (0);
368 }
369
370 /*
371 * We must have a shell command for the alert if:
372 *
373 * (1) we're adding a new form and the -W or -Q options
374 * have been given, or
375 *
376 * (2) the -f any option was given.
377 */
378 if (
379 (
380 action == add_form
381 && !alert.shcmd
382 && (alert.Q != -1 || alert.W != -1)
383 && !STREQU(NAME_ALL, form)
384 && getform(form, &fbuf, (FALERT *)0, (FILE **)0) != 0
385 )
386 || action == any_alert && !alert.shcmd
387 ) {
388 LP_ERRMSG (ERROR, E_FOR_NOSHCMDERR);
389 return (1);
390 }
391
392 if (P && (! STREQU(P,form))) {
393 while (P && (cnt++ < 2)) {
394 /*
395 * two times should do it unless user has edited
396 * files directly
397 */
398 if (getform(P, &fbuf, (FALERT *)0, (FILE **)0) != -1) {
399 if (!fbuf.paper) {
400 LP_ERRMSG3(ERROR, E_FOR_ALSO_SEP_FORM,
401 form, P, P);
402 return (1);
403 } else if (!STREQU(fbuf.paper, P))
404 P = Strdup(fbuf.paper);
405 else
406 break; /* we found a good paper */
407 } else {
408 int result;
409 int saveD;
410
411 saveD = d;
412 d = 1;
413 result = ((*action)(P, NULL, &alert, u));
414 d = saveD;
415 return (result ? result :
416 ((*action)(form, input, &alert, u)));
417 }
418 }
419 }
420
421 if (d && !P)
422 P = Strdup(form);
423
424 return ((*action)(form, input, &alert, u));
425 }
426
427 /**
428 ** add_alert()
429 ** add_form()
430 **/
431
432 /*
433 * "add_alert()" exists just to simplify the checking of mixed
434 * options in "set_action()".
435 */
436
437 static int
438 #if defined(__STDC__)
add_alert(char * form,FILE * input,FALERT * p_new_alert,char * u)439 add_alert (
440 char * form,
441 FILE * input,
442 FALERT * p_new_alert,
443 char * u
444 )
445 #else
446 add_alert (form, input, new_alert, u)
447 char * form;
448 FILE * input;
449 FALERT * p_new_alert;
450 char * u;
451 #endif
452 {
453 return (add_form(form, input, p_new_alert, u));
454 }
455
456 static int
457 #if defined(__STDC__)
add_form(char * form,FILE * input,FALERT * p_new_alert,char * u)458 add_form (
459 char * form,
460 FILE * input,
461 FALERT * p_new_alert,
462 char * u
463 )
464 #else
465 add_form (form, input, new_alert, u)
466 char * form;
467 FILE * input;
468 FALERT * p_new_alert;
469 char * u;
470 #endif
471 {
472 int fld;
473 int which_set[FO_MAX];
474 int new_form = 0;
475 int nform;
476 int return_code;
477
478 char * all_list[] = { NAME_ALL, 0 };
479 char ** u_allow = 0;
480 char ** u_deny = 0;
481
482 FILE * align_fp = 0;
483
484 FORM fbuf;
485 FORM new_fbuf;
486
487 FALERT alert;
488
489
490 /*
491 * Read the input configuration (if any) and parse it into a form,
492 * storing it in the form buffer "fbuf". Keep track of
493 * which fields have been given, to avoid overwriting unchanged
494 * fields later.
495 */
496 if (input) {
497 for (fld = 0; fld < FO_MAX; fld++)
498 which_set[fld] = 0;
499
500 if (rdform(form, &new_fbuf, fileno(input), onerror,
501 which_set) == -1) {
502 LP_ERRMSG2 (ERROR, E_FOR_UNKNOWN, "(input)", PERROR);
503 return (1);
504 }
505 for (fld = 0; fld < FO_MAX; fld++)
506 if (which_set[fld])
507 break;
508 if (fld >= FO_MAX)
509 LP_ERRMSG (WARNING, E_FOR_EMPTYFILE);
510
511 /*
512 * Read the alignment pattern (if any) into a temporary
513 * file so that it can be used for (potentially) many
514 * forms.
515 */
516 if (which_set[FO_ALIGN]) {
517
518 size_t n;
519
520 char buf[BUFSIZ];
521
522
523
524 if ((align_fp = tmpfile()) == NULL) {
525 LP_ERRMSG (ERROR, E_FOR_CTMPFILE);
526 exit (1);
527 }
528
529 while ((n = fread(buf, 1, BUFSIZ, input)))
530 fwrite (buf, 1, n, align_fp);
531 }
532 }
533
534 /*
535 * Parse the user allow/deny list (if any).
536 */
537 if (u) {
538
539 char * cp;
540 char * type;
541
542
543 type = strtok(u, ":");
544 cp = strtok((char *)0, ":");
545
546 if (STREQU(type, NAME_ALLOW) && cp) {
547 if (!(u_allow = getlist(cp, LP_WS, LP_SEP)))
548 LP_ERRMSG1 (
549 WARNING,
550 E_LP_MISSING,
551 NAME_ALLOW
552 );
553
554 } else if (STREQU(type, NAME_DENY) && cp) {
555 if (!(u_deny = getlist(cp, LP_WS, LP_SEP)))
556 LP_ERRMSG1 (
557 WARNING,
558 E_LP_MISSING,
559 NAME_DENY
560 );
561
562 } else {
563 LP_ERRMSG (ERROR, E_LP_UALLOWDENY);
564 exit (1);
565 }
566 }
567
568 /*
569 * The following loop gets either a particular form or
570 * all forms (one at a time). The value of "return_code"
571 * controls the loop and is also the value to use in the
572 * "return()" at the end.
573 */
574 nform = 0;
575 return_code = -1;
576 while (return_code == -1) {
577
578 /*
579 * If we are adding/changing a single form, set
580 * the loop control to get us out.
581 */
582 if (!STREQU(NAME_ALL, form))
583 return_code = 0;
584
585 nform++;
586
587 if (P) {
588 memset ((char *)&fbuf, 0, sizeof(FORM));
589 fbuf.name = strdup(form);
590 fbuf.plen.val = DPLEN;
591 fbuf.plen.sc = 0;
592 fbuf.pwid.val = DPWIDTH;
593 fbuf.pwid.sc = 0;
594 fbuf.lpi.val = DLPITCH;
595 fbuf.lpi.sc = 0;
596 fbuf.cpi.val = DCPITCH;
597 fbuf.cpi.sc = 0;
598 fbuf.np = DNP;
599 fbuf.chset = strdup(DCHSET);
600 fbuf.mandatory = 0;
601 fbuf.rcolor = strdup(DRCOLOR);
602 fbuf.conttype = strdup(DCONTYP);
603 fbuf.paper = P;
604 fbuf.isDefault = d;
605 alert.shcmd = 0;
606 alert.W = alert.Q = -1;
607 new_form = 1;
608
609 } else if (getform(form, &fbuf, &alert, (FILE **)0) == -1)
610 switch (errno) {
611
612 case ENOENT:
613 /*
614 * This is a problem only if it occurs
615 * immediately on trying to get ``all''.
616 */
617 if (STREQU(NAME_ALL, form)) {
618 if (nform > 1)
619 return_code = 0;
620 else {
621 LP_ERRMSG (ERROR, E_FOR_NOFORMS);
622 return_code = 1;
623 }
624 continue;
625 }
626
627 /*
628 * We're adding a new form,
629 * so set up default values.
630 */
631 memset ((char *)&fbuf, 0, sizeof(FORM));
632 fbuf.name = strdup(form);
633 fbuf.plen.val = DPLEN;
634 fbuf.plen.sc = 0;
635 fbuf.pwid.val = DPWIDTH;
636 fbuf.pwid.sc = 0;
637 fbuf.lpi.val = DLPITCH;
638 fbuf.lpi.sc = 0;
639 fbuf.cpi.val = DCPITCH;
640 fbuf.cpi.sc = 0;
641 fbuf.np = DNP;
642 fbuf.chset = strdup(DCHSET);
643 fbuf.mandatory = 0;
644 fbuf.rcolor = strdup(DRCOLOR);
645 fbuf.conttype = strdup(DCONTYP);
646 alert.shcmd = 0;
647 alert.W = alert.Q = -1;
648
649 new_form = 1;
650 break;
651
652 default:
653 /*
654 * Don't know if we'll have a good name
655 * in the "all" case on getting here, so
656 * punt on naming the form in the error
657 * message.
658 */
659 LP_ERRMSG2 (ERROR, E_LP_GETFORM, form, PERROR);
660 return_code = 1;
661 continue;
662 }
663
664 /*
665 * Copy just those items that were given in the input.
666 */
667 if (!input && new_form && !P) {
668 LP_ERRMSG1 (ERROR, E_LP_NOFORM, form);
669 return (1);
670 }
671 if (input)
672 for (fld = 0; fld < FO_MAX; fld++)
673 if (which_set[fld]) switch(fld) {
674
675 case FO_PLEN:
676 fbuf.plen = new_fbuf.plen;
677 break;
678
679 case FO_PWID:
680 fbuf.pwid = new_fbuf.pwid;
681 break;
682
683 case FO_CPI:
684 fbuf.cpi = new_fbuf.cpi;
685 break;
686
687 case FO_LPI:
688 fbuf.lpi = new_fbuf.lpi;
689 break;
690
691 case FO_NP:
692 fbuf.np = new_fbuf.np;
693 break;
694
695 case FO_CHSET:
696 fbuf.chset = new_fbuf.chset;
697 fbuf.mandatory = new_fbuf.mandatory;
698 break;
699
700 case FO_RCOLOR:
701 fbuf.rcolor = new_fbuf.rcolor;
702 break;
703
704 case FO_CMT:
705 fbuf.comment = new_fbuf.comment;
706 break;
707
708 case FO_ALIGN:
709 fbuf.conttype = new_fbuf.conttype;
710 rewind (align_fp);
711 break;
712
713 case FO_PAPER:
714 fbuf.paper = new_fbuf.paper;
715 fbuf.isDefault = new_fbuf.isDefault;
716 break;
717
718 }
719
720 /*
721 * Set just those alert elements that were given.
722 * However, complain about those form(s) that don't have
723 * a shell command yet, and none was given, yet -W or -Q
724 * were given.
725 */
726 if (
727 !alert.shcmd && !p_new_alert->shcmd
728 && (p_new_alert->W != -1 || p_new_alert->Q != -1)
729 )
730 LP_ERRMSG1 (WARNING, E_FOR_NOSHCMDWARN, fbuf.name);
731 else {
732 if (p_new_alert->shcmd)
733 alert.shcmd = p_new_alert->shcmd;
734 if (p_new_alert->Q != -1)
735 alert.Q = p_new_alert->Q;
736 if (p_new_alert->W != -1)
737 alert.W = p_new_alert->W;
738 }
739
740 /*
741 * Create/update the form.
742 */
743 #define P_FBUF (new_form || input? &fbuf : (FORM *)0)
744 if (putform(fbuf.name, P_FBUF, &alert, &align_fp) == -1) {
745 LP_ERRMSG2 (ERROR, E_LP_PUTFORM, fbuf.name, PERROR);
746 return_code = 1;
747 continue;
748 }
749
750 /*
751 * Allow/deny users.
752 */
753 if (new_form && allow_user_form(all_list, fbuf.name) == -1) {
754 LP_ERRMSG1 (ERROR, E_LP_ACCESSINFO, PERROR);
755 return_code = 1;
756 continue;
757 }
758 if (u_allow && allow_user_form(u_allow, fbuf.name) == -1) {
759 LP_ERRMSG1 (ERROR, E_LP_ACCESSINFO, PERROR);
760 return_code = 1;
761 continue;
762 }
763 if (u_deny && deny_user_form(u_deny, fbuf.name) == -1) {
764 LP_ERRMSG1 (ERROR, E_LP_ACCESSINFO, PERROR);
765 return_code = 1;
766 continue;
767 }
768
769 notify_spooler (S_LOAD_FORM, R_LOAD_FORM, fbuf.name);
770
771 }
772
773 if (align_fp)
774 close_lpfile (align_fp);
775
776 return (return_code);
777 }
778
779 /**
780 ** list_form()
781 ** list_alert()
782 ** list_both()
783 **/
784
785 #if defined(__STDC__)
786
787 static int list ( char * , void (*)() );
788 static void _list_form ( FORM * , FALERT * , FILE * );
789 static void _list_alert ( FORM * , FALERT * );
790 static void _list_both ( FORM * , FALERT * , FILE * );
791
792 #else
793
794 static int list();
795 static void _list_form();
796 static void _list_alert();
797 static void _list_both();
798
799 #endif
800
801 static int
802 #if defined(__STDC__)
list_form(char * form)803 list_form (
804 char *form
805 )
806 #else
807 list_form (form)
808 char *form;
809 #endif
810 {
811 return (list(form, _list_form));
812 }
813
814 static int
815 #if defined(__STDC__)
list_alert(char * form)816 list_alert (
817 char *form
818 )
819 #else
820 list_alert (form)
821 char *form;
822 #endif
823 {
824 return (list(form, _list_alert));
825 }
826
827 static int
828 #if defined(__STDC__)
list_both(char * form)829 list_both (
830 char *form
831 )
832 #else
833 list_both (form)
834 char *form;
835 #endif
836 {
837 return (list(form, _list_both));
838 }
839
840 static int
841 #if defined(__STDC__)
list(char * form,void (* subaction)())842 list (
843 char *form,
844 void (*subaction)()
845 )
846 #else
847 list (form, subaction)
848 char *form;
849 void (*subaction)();
850 #endif
851 {
852 FORM fbuf;
853
854 FALERT alert;
855
856 FILE * align_fp;
857
858 char *nl;
859
860
861 if (STREQU(NAME_ALL, form)) {
862
863 nl = "";
864 while (getform(form, &fbuf, &alert, &align_fp) == 0) {
865 printf (gettext("%sForm name: %s\n"), nl, fbuf.name);
866 (*subaction) (&fbuf, &alert, align_fp);
867 nl = "\n";
868 }
869
870 switch (errno) {
871 case ENOENT:
872 return (0);
873 default:
874 /*
875 * Don't know if we'll have a good name
876 * in the "all" case on getting here, so
877 * punt on naming the form in the error
878 * message.
879 */
880 LP_ERRMSG2 (ERROR, E_LP_GETFORM, form, PERROR);
881 return (1);
882 }
883
884 } else {
885
886 if (getform(form, &fbuf, &alert, &align_fp) == 0) {
887 (*subaction) (&fbuf, &alert, align_fp);
888 return (0);
889 }
890
891 switch (errno) {
892 case ENOENT:
893 LP_ERRMSG1 (ERROR, E_LP_NOFORM, form);
894 return (1);
895 default:
896 LP_ERRMSG2 (ERROR, E_LP_GETFORM, form, PERROR);
897 return (1);
898 }
899
900 }
901 }
902
903 /**
904 ** _list_form()
905 **/
906
907 static void
908 #if defined(__STDC__)
_list_form(FORM * pf,FALERT * palert,FILE * align_fp)909 _list_form (
910 FORM * pf,
911 FALERT * palert,
912 FILE * align_fp
913 )
914 #else
915 _list_form (pf, palert, align_fp)
916 FORM * pf;
917 FALERT * palert;
918 FILE * align_fp;
919 #endif
920 {
921 size_t n;
922
923 char buf[BUFSIZ];
924
925 int which_set[FO_MAX];
926 int fld,whichVal;
927
928
929 whichVal = (pf->paper && (L == 0) ? 0 : 1);
930 for (fld = 0; fld < FO_MAX; fld++)
931 which_set[fld] = whichVal;
932 if (!align_fp)
933 which_set[FO_ALIGN] = 0;
934 if (pf->paper)
935 which_set[FO_PAPER] = 1;
936 wrform (pf->name, pf, 1, onerror, which_set);
937 if (align_fp)
938 while ((n = fread(buf, 1, BUFSIZ, align_fp)))
939 write (1, buf, n);
940 }
941
942 /**
943 ** _list_alert()
944 **/
945
946 static void
947 #if defined(__STDC__)
_list_alert(FORM * ignore,FALERT * palert)948 _list_alert (
949 FORM * ignore,
950 FALERT * palert
951 )
952 #else
953 _list_alert (ignore, palert)
954 FORM * ignore;
955 FALERT * palert;
956 #endif
957 {
958 printalert (stdout, palert, 0);
959 }
960
961 /**
962 ** _list_both()
963 **/
964
965 static void
966 #if defined(__STDC__)
_list_both(FORM * pf,FALERT * palert,FILE * align_fp)967 _list_both (
968 FORM * pf,
969 FALERT * palert,
970 FILE * align_fp
971 )
972 #else
973 _list_both (pf, palert, align_fp)
974 FORM * pf;
975 FALERT * palert;
976 FILE * align_fp;
977 #endif
978 {
979 _list_alert (pf, palert);
980 _list_form (pf, palert, align_fp);
981 }
982
983 /**
984 ** any_alert()
985 **/
986
987 static int
988 #if defined(__STDC__)
any_alert(char * form,FILE * ignore,FALERT * p_new_alert)989 any_alert (
990 char * form,
991 FILE * ignore,
992 FALERT * p_new_alert
993 )
994 #else
995 any_alert (form, ignore, p_new_alert)
996 char * form;
997 FILE * ignore;
998 FALERT * p_new_alert;
999 #endif
1000 {
1001 FORM fbuf;
1002
1003 FALERT alert;
1004
1005
1006 while (getform(NAME_ALL, &fbuf, &alert, (FILE **)0) == 0)
1007 if (!alert.shcmd)
1008 if (putform(fbuf.name, (FORM *)0, p_new_alert, (FILE **)0) == -1) {
1009 LP_ERRMSG2 (ERROR, E_LP_PUTFORM, fbuf.name, PERROR);
1010 return (1);
1011 }
1012
1013 return (0);
1014 }
1015
1016 /**
1017 ** delete_form()
1018 ** quiet_alert()
1019 **/
1020
1021 #if defined(__STDC__)
1022
1023 static int dq ( char * , int (*)() );
1024 static int _delete_form ( char * );
1025 static int _quiet_alert ( char * );
1026
1027 #else
1028
1029 static int dq();
1030 static int _delete_form();
1031 static int _quiet_alert();
1032
1033 #endif
1034
1035 static int
1036 #if defined(__STDC__)
delete_form(char * form)1037 delete_form (
1038 char *form
1039 )
1040 #else
1041 delete_form (form)
1042 char *form;
1043 #endif
1044 {
1045 return (dq(form, _delete_form));
1046 }
1047
1048 static int
1049 #if defined(__STDC__)
quiet_alert(char * form)1050 quiet_alert (
1051 char * form
1052 )
1053 #else
1054 quiet_alert (form)
1055 char * form;
1056 #endif
1057 {
1058 return (dq(form, _quiet_alert));
1059 }
1060
1061 static int
1062 #if defined(__STDC__)
dq(char * form,int (* subaction)())1063 dq (
1064 char *form,
1065 int (*subaction)()
1066 )
1067 #else
1068 dq (form, subaction)
1069 char *form;
1070 int (*subaction)();
1071 #endif
1072 {
1073 FORM fbuf;
1074
1075
1076 if (STREQU(NAME_ANY, form) || STREQU(NAME_NONE, form)) {
1077 LP_ERRMSG (ERROR, E_FOR_ANYNONE);
1078 exit (1);
1079 }
1080
1081 if (STREQU(NAME_ALL, form)) {
1082
1083 while (getform(form, &fbuf, (FALERT *)0, (FILE **)0) == 0)
1084 if ((*subaction)(fbuf.name) == 1)
1085 return (1);
1086
1087 switch (errno) {
1088 case ENOENT:
1089 return (0);
1090 default:
1091 /*
1092 * Don't know if we'll have a good name
1093 * in the "all" case on getting here, so
1094 * punt on naming the form in the error
1095 * message.
1096 */
1097 LP_ERRMSG2 (ERROR, E_LP_GETFORM, form, PERROR);
1098 return (1);
1099 }
1100
1101 } else {
1102
1103 if (getform(form, &fbuf, (FALERT *)0, (FILE **)0) == 0)
1104 return ((*subaction)(fbuf.name));
1105
1106 switch (errno) {
1107 case ENOENT:
1108 LP_ERRMSG1 (ERROR, E_LP_NOFORM, form);
1109 return (1);
1110 default:
1111 LP_ERRMSG2 (ERROR, E_LP_GETFORM, form, PERROR);
1112 return (1);
1113 }
1114 }
1115 }
1116
1117 static int
1118 #if defined(__STDC__)
_delete_form(char * form)1119 _delete_form (
1120 char *form
1121 )
1122 #else
1123 _delete_form (form)
1124 char *form;
1125 #endif
1126 {
1127 switch (notify_spooler(S_UNLOAD_FORM, R_UNLOAD_FORM, form)) {
1128
1129 case -1:
1130 if (anyrequests()) {
1131 LP_ERRMSG (ERROR, E_FOR_MOPENREQX);
1132 return (1);
1133 }
1134 /*FALLTHROUGH*/
1135
1136 case MNODEST:
1137 if (delform(form) == -1) {
1138 if (errno == ENOENT) {
1139 LP_ERRMSG1 (ERROR, E_LP_NOFORM, form);
1140 return (1);
1141 } else {
1142 LP_ERRMSG2 (
1143 ERROR,
1144 E_FOR_UNKNOWN,
1145 form,
1146 PERROR
1147 );
1148 return (1);
1149 }
1150 }
1151 break;
1152
1153 case MOK:
1154 if (delform(form) == -1) {
1155 LP_ERRMSG (ERROR, E_FOR_DELSTRANGE);
1156 return (1);
1157 }
1158 break;
1159 }
1160 return (0);
1161 }
1162
1163 static int
1164 #if defined(__STDC__)
_quiet_alert(char * form)1165 _quiet_alert (
1166 char * form
1167 )
1168 #else
1169 _quiet_alert (form)
1170 char * form;
1171 #endif
1172 {
1173 char *msgbuf;
1174
1175 int mtype;
1176
1177 int size;
1178
1179 short status;
1180
1181 /*
1182 * If the attempt to open a message queue to the
1183 * Spooler fails, assume it isn't running and just
1184 * return--don't say anything, `cause the user may
1185 * know. Any other failure deserves an error message.
1186 */
1187
1188 if (mopen() == -1)
1189 return (0);
1190
1191 size = putmessage (NULL, S_QUIET_ALERT, form, QA_FORM);
1192 msgbuf = malloc(size);
1193 putmessage (msgbuf, S_QUIET_ALERT, form, QA_FORM);
1194
1195 if (msend(msgbuf) == -1) {
1196 LP_ERRMSG (ERROR, E_LP_MSEND);
1197 mclose ();
1198 return (1);
1199 }
1200
1201 if (mrecv(msgbuf, size) == -1) {
1202 LP_ERRMSG (ERROR, E_LP_MRECV);
1203 mclose ();
1204 return (1);
1205 }
1206
1207 mtype = getmessage(msgbuf, R_QUIET_ALERT, &status);
1208 free (msgbuf);
1209 mclose ();
1210 if (mtype != R_QUIET_ALERT) {
1211 LP_ERRMSG (ERROR, E_LP_BADREPLY);
1212 return (1);
1213 }
1214
1215 switch (status) {
1216
1217 case MOK:
1218 break;
1219
1220 case MNODEST: /* not quite, but not a lie either */
1221 case MERRDEST:
1222 LP_ERRMSG1 (WARNING, E_LP_NOQUIET, form);
1223 break;
1224
1225 case MNOPERM: /* taken care of up front */
1226 default:
1227 LP_ERRMSG1 (ERROR, E_LP_BADSTATUS, status);
1228 return (1);
1229 /*NOTREACHED*/
1230 }
1231
1232 return (0);
1233 }
1234
1235 /**
1236 ** set_action() - CHECK FOR AMBIGUOUS ACTIONS
1237 **/
1238
1239 static Action
1240 #if defined(__STDC__)
set_action(Action action,char * option)1241 set_action (
1242 Action action,
1243 char * option
1244 )
1245 #else
1246 set_action (action, option)
1247 Action action;
1248 char * option;
1249 #endif
1250 {
1251 static Action prev_action = 0;
1252
1253 static char * prev_option;
1254
1255
1256 if (
1257 action == list_form && prev_action == list_alert
1258 || action == list_alert && prev_action == list_form
1259 )
1260 action = list_both;
1261
1262 else if (
1263 action == add_form && prev_action == add_alert
1264 || action == add_alert && prev_action == add_form
1265 )
1266 action = add_form;
1267
1268 else if (
1269 action == any_alert && prev_action == add_alert
1270 || action == add_alert && prev_action == any_alert
1271 )
1272 action = any_alert;
1273
1274 else if (prev_action && prev_action != action) {
1275 LP_ERRMSG2 (ERROR, E_LP_AMBIG, option, prev_option);
1276 exit (1);
1277 }
1278
1279 OK: prev_action = action;
1280 prev_option = option;
1281 return (action);
1282 }
1283
1284 /**
1285 ** notify_spooler() - NOTIFY SPOOLER OF ACTION ON FORMS DB
1286 **/
1287
1288 static int
1289 #if defined(__STDC__)
notify_spooler(int sendmsg,int replymsg,char * form)1290 notify_spooler (
1291 int sendmsg,
1292 int replymsg,
1293 char * form
1294 )
1295 #else
1296 notify_spooler (sendmsg, replymsg, form)
1297 int sendmsg;
1298 int replymsg;
1299 char * form;
1300 #endif
1301 {
1302 char * msgbuf;
1303
1304 int mtype;
1305 int size;
1306
1307 short status;
1308
1309 /*
1310 * If the attempt to open a message queue to the
1311 * Spooler fails, assume it isn't running and just
1312 * return--don't say anything, `cause the user may
1313 * know. Any other failure deserves an error message.
1314 */
1315
1316 if (mopen() == -1)
1317 return (-1);
1318
1319 size = putmessage((char *)0, sendmsg, form);
1320 msgbuf = malloc(size);
1321 putmessage (msgbuf, sendmsg, form);
1322
1323 if (msend(msgbuf) == -1) {
1324 LP_ERRMSG (ERROR, E_LP_MSEND);
1325 mclose ();
1326 exit (1);
1327 }
1328 if (mrecv(msgbuf, size) == -1) {
1329 LP_ERRMSG (ERROR, E_LP_MRECV);
1330 mclose ();
1331 exit (1);
1332 }
1333 mclose ();
1334
1335 mtype = getmessage(msgbuf, replymsg, &status);
1336 free (msgbuf);
1337 if (mtype != replymsg) {
1338 LP_ERRMSG (ERROR, E_LP_BADREPLY);
1339 exit (1);
1340 }
1341
1342 if (status == MOK)
1343 return (MOK);
1344
1345 if (sendmsg == S_LOAD_FORM)
1346 switch (status) {
1347 case MNOSPACE:
1348 LP_ERRMSG (ERROR, E_FOR_NOSPACE);
1349 break;
1350 case MNOPERM:
1351 LP_ERRMSG (ERROR, E_LP_NOTADM);
1352 break;
1353
1354 /*
1355 * The following two error conditions should have
1356 * already been trapped, so treat them as bad status
1357 * should they occur.
1358 */
1359 case MNODEST:
1360 case MERRDEST:
1361 default:
1362 LP_ERRMSG1 (ERROR, E_LP_BADSTATUS, status);
1363 break;
1364 }
1365
1366 if (sendmsg == S_UNLOAD_FORM)
1367 switch (status) {
1368 case MBUSY:
1369 LP_ERRMSG1 (ERROR, E_FOR_FORMBUSY, form);
1370 break;
1371 case MNODEST:
1372 return (MNODEST);
1373 case MNOPERM:
1374 LP_ERRMSG (ERROR, E_LP_NOTADM);
1375 break;
1376 default:
1377 LP_ERRMSG (ERROR, E_LP_BADSTATUS);
1378 break;
1379 }
1380
1381 exit (1);
1382 }
1383
1384 /**
1385 ** onerror()
1386 **/
1387
1388 static int
1389 #if defined(__STDC__)
onerror(int Errno,int lp_errno,int linenum)1390 onerror (
1391 int Errno,
1392 int lp_errno,
1393 int linenum
1394 )
1395 #else
1396 onerror (Errno, lp_errno, linenum)
1397 int Errno;
1398 int lp_errno;
1399 int linenum;
1400 #endif
1401 {
1402 static int nerrors = 0;
1403
1404
1405 if (Errno == EBADF) {
1406 switch (lp_errno) {
1407 case LP_EBADSDN:
1408 LP_ERRMSG1 (WARNING, E_FOR_BADSCALE, linenum);
1409 break;
1410 case LP_EBADINT:
1411 LP_ERRMSG1 (WARNING, E_FOR_BADINT, linenum);
1412 break;
1413 case LP_EBADNAME:
1414 LP_ERRMSG1 (WARNING, E_FOR_NOTNAME, linenum);
1415 break;
1416 case LP_EBADARG:
1417 LP_ERRMSG1 (WARNING, E_FOR_BADCHSETQUALIFIER, linenum);
1418 break;
1419 case LP_ETRAILIN:
1420 LP_ERRMSG1 (WARNING, E_FOR_TRAILIN, linenum);
1421 break;
1422 case LP_EBADCTYPE:
1423 LP_ERRMSG1 (WARNING, E_FOR_NOTCTYPE, linenum);
1424 break;
1425 case LP_EBADHDR:
1426 LP_ERRMSG1 (WARNING, E_FOR_BADHDR, linenum);
1427 break;
1428 }
1429 if (nerrors++ >= 5) {
1430 LP_ERRMSG (ERROR, E_LP_GARBAGE);
1431 return (-1);
1432 }
1433 return (0);
1434 } else {
1435 LP_ERRMSG2 (ERROR, E_FOR_UNKNOWN, "(stdin)", PERROR);
1436 return (-1);
1437 }
1438 }
1439