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 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 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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__) 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