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