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