xref: /illumos-gate/usr/src/cmd/lp/cmd/lpfilter.c (revision e0731422366620894c16c1ee6515551c5f00733d)
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 <stdio.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <locale.h>
34 
35 #include "lp.h"
36 #include "access.h"
37 #include "filters.h"
38 #include "msgs.h"
39 
40 #define	WHO_AM_I	I_AM_LPFILTER
41 #include "oam.h"
42 
43 #define	OPT_LIST	"f:F:ixl"
44 
45 int			add_filter(),
46 			reload_filter(),
47 			delete_filter(),
48 			list_filter();
49 
50 static void		alert_spooler(),
51 			same_complaints();
52 
53 static char		*opt();
54 
55 /*
56  * Unfortunately, the LP requirements show the listing of a filter
57  * to be in a different order than the stored filter table. We can't
58  * change the stored version because it's the same as UNISON uses.
59  * So, we can't reuse the "FL_..." #defines found in "filters.h".
60  * But the following have similar use.
61  */
62 #define FL_MAX_P	FL_MAX
63 # define FL_IGN_P	8
64 # define FL_PTYPS_P	2
65 # define FL_PRTRS_P	3
66 # define FL_ITYPS_P	0
67 # define FL_NAME_P	7
68 # define FL_OTYPS_P	1
69 # define FL_TYPE_P	4
70 # define FL_CMD_P	5
71 # define FL_TMPS_P	6
72 
73 #define	TABLE		0
74 #define	TABLE_I		1
75 
76 static struct headings {
77 	char			*v;
78 	short			len;
79 }		headings[FL_MAX_P] = {
80 
81 #define	ENTRY(X)	X, sizeof(X)-1
82 	ENTRY("Input types:"),
83 	ENTRY("Output types:"),
84 	ENTRY("Printer types:"),
85 	ENTRY("Printers:"),
86 	ENTRY("Filter type:"),
87 	ENTRY("Command:"),
88 	ENTRY("Options:"),
89 	ENTRY(""),
90 	ENTRY("")
91 #undef	ENTRY
92 
93 };
94 
95 /**
96  ** usage()
97  **/
98 
99 void			usage ()
100 {
101 	(void) printf (gettext(
102 "usage:\n"
103 "\n"
104 "  (add or change filter)\n"
105 "    lpfilter -f filter-name {-F path-name | -}\n"
106 "\n"
107 "  (restore delivered filter)\n"
108 "    lpfilter -f filter-name -i\n"
109 "\n"
110 "  (list a filter)\n"
111 "    lpfilter -f filter-name -l\n"
112 "\n"
113 "  (list all filters)\n"
114 "    lpfilter -f \"all\" -l\n"
115 "\n"
116 "  (delete filter)\n"
117 "    lpfilter -f filter-name -x\n"));
118 
119 	return;
120 }
121 
122 /**
123  ** main()
124  **/
125 
126 int			main (argc, argv)
127 	int			argc;
128 	char			*argv[];
129 {
130 	extern int		optind,
131 				opterr,
132 				optopt,
133 				getopt();
134 
135 	extern char		*optarg;
136 
137 	int			c,
138 				(*action)(),
139 				(*newaction)();
140 
141 	FILE			*input;
142 
143 	char			*filter,
144 				*p;
145 	char			stroptsw[] = "-X";
146 
147 
148 	(void) setlocale (LC_ALL, "");
149 #if !defined(TEXT_DOMAIN)
150 #define TEXT_DOMAIN "SYS_TEST"
151 #endif
152 	(void) textdomain(TEXT_DOMAIN);
153 
154 	if (!is_user_admin()) {
155 		LP_ERRMSG (ERROR, E_LP_NOTADM);
156 		exit (1);
157 	}
158 
159 	action = 0;
160 	input = 0;
161 	filter = 0;
162 
163 	opterr = 0;
164 
165 	while ((c = getopt(argc, argv, OPT_LIST)) != -1) switch (c) {
166 
167 	case 'f':
168 		if (filter)
169 			LP_ERRMSG1 (WARNING, E_LP_2MANY, 'f');
170 		filter = optarg;
171 		if (
172 			STREQU(NAME_ANY, filter)
173 		     || STREQU(NAME_NONE, filter)
174 		) {
175 			LP_ERRMSG (ERROR, E_LP_ANYNONE);
176 			exit (1);
177 		} else if (!syn_name(filter)) {
178 			LP_ERRMSG1 (ERROR, E_LP_NOTNAME, filter);
179 			exit (1);
180 		} else if (!*filter)
181 			filter = NAME_ALL;
182 		break;
183 
184 	case 'F':
185 		if (input)
186 			LP_ERRMSG1 (WARNING, E_LP_2MANY, 'F');
187 		if (!(input = fopen(optarg, "r"))) {
188 			LP_ERRMSG1 (ERROR, E_FL_OPEN, optarg);
189 			exit (1);
190 		}
191 		newaction = add_filter;
192 		goto Check;
193 
194 	case 'i':
195 		newaction = reload_filter;
196 		goto Check;
197 
198 	case 'x':
199 		newaction = delete_filter;
200 		goto Check;
201 
202 	case 'l':
203 		newaction = list_filter;
204 Check:		if (action && newaction != action) {
205 			LP_ERRMSG2 (
206 				ERROR,
207 				E_LP_AMBIG,
208 				opt(action),
209 				opt(newaction)
210 			);
211 			exit (1);
212 		}
213 		action = newaction;
214 		break;
215 
216 	default:
217 		if (optopt == '?') {
218 			usage ();
219 			exit (0);
220 		}
221 		stroptsw[1] = optopt;
222 		if (strchr(OPT_LIST, optopt))
223 			LP_ERRMSG1 (ERROR, E_LP_OPTARG, stroptsw);
224 		else
225 			LP_ERRMSG1 (ERROR, E_LP_OPTION, stroptsw);
226 		exit (1);
227 
228 	}
229 
230 	if (optind < argc && STREQU(argv[optind], "-"))
231 		if (action) {
232 	 		LP_ERRMSG2 (ERROR, E_LP_AMBIG, opt(action), "-");
233 			exit (1);
234 		} else {
235 			action = add_filter;
236 			optind++;
237 		}
238 
239 	if (!filter) {
240 		LP_ERRMSG (ERROR, E_FL_NOFILT);
241 		exit (1);
242 	}
243 
244 	if (!action) {
245 		LP_ERRMSG (ERROR, E_FL_NOACT);
246 		exit (1);
247 	}
248 
249 	if (optind < argc)
250 		LP_ERRMSG1 (WARNING, E_FL_IGNORE, argv[optind]);
251 
252 	return ((*action)(filter, input));
253 }
254 
255 /**
256  ** add_filter()
257  **/
258 
259 int			add_filter (filter, input)
260 	char			*filter;
261 	FILE			*input;
262 {
263 	register FILTER		*pf,
264 				*store,
265 				*ps;
266 
267 	register int		fld;
268 
269 	register char		*p;
270 
271 	char			buf[3 * BUFSIZ],
272 				*file;
273 
274 	int			line,
275 				bad_headings,
276 				real_fields[FL_MAX],
277 				at_least_one,
278 				ret;
279 
280 	FILTER			flbuf;
281 
282 
283 	/*
284 	 * First we read in the input and parse it into a filter,
285 	 * storing it in the filter buffer "flbuf". Keep track of
286 	 * which fields have been given, to avoid overwriting unchanged
287 	 * fields later.
288 	 */
289 
290 	if (!input)
291 		input = stdin;
292 
293 	for (fld = 0; fld < FL_MAX; fld++)
294 		real_fields[fld] = 0;
295 	flbuf.templates = 0;
296 
297 	line = bad_headings = 0;
298 	while (fgets(buf, sizeof(buf), input) != NULL) {
299 
300 		buf[strlen(buf) - 1] = 0;
301 
302 		line++;
303 
304 		p = buf + strspn(buf, " \t");
305 		if (!*p || *p == '#')
306 			continue;
307 
308 		for (fld = 0; fld < FL_MAX; fld++)
309 			if (
310 				headings[fld].v
311 			     && headings[fld].len
312 			     && CS_STRNEQU(
313 					p,
314 					headings[fld].v,
315 					headings[fld].len
316 				)
317 			) {
318 				real_fields[fld] = 1;
319 				p += headings[fld].len + 1;
320 				break;
321 			}
322 
323 		if (fld >= FL_MAX) {
324 
325 			if (bad_headings++ >= 5) {
326 				LP_ERRMSG (ERROR, E_FL_GARBAGE);
327 				return (1);
328 			}
329 			LP_ERRMSG1 (WARNING, E_FL_HEADING, line);
330 
331 		} else switch (fld) {
332 
333 			case FL_IGN_P:
334 			case FL_NAME_P:
335 				break;
336 			case FL_CMD_P:
337 				flbuf.command = strdup(strip(p));
338 				break;
339 			case FL_TYPE_P:
340 				flbuf.type = s_to_filtertype(strip(p));
341 				break;
342 			case FL_PTYPS_P:
343 				flbuf.printer_types = getlist(p, LP_WS, LP_SEP);
344 				break;
345 			case FL_ITYPS_P:
346 				flbuf.input_types = getlist(p, LP_WS, LP_SEP);
347 				break;
348 			case FL_OTYPS_P:
349 				flbuf.output_types = getlist(p, LP_WS, LP_SEP);
350 				break;
351 			case FL_PRTRS_P:
352 				flbuf.printers = getlist(p, LP_WS, LP_SEP);
353 				break;
354 			case FL_TMPS_P:
355 				if (flbuf.templates) {
356 					char			**temp;
357 
358 					temp = getlist(p, "", LP_SEP);
359 					mergelist (&(flbuf.templates), temp);
360 					freelist (temp);
361 				} else
362 					flbuf.templates = getlist(p, "", LP_SEP);
363 				break;
364 
365 		}
366 
367 	}
368 	if (ferror(input)) {
369 		LP_ERRMSG (ERROR, E_FL_READ);
370 		return (1);
371 	}
372 
373 	/*
374 	 * We have the input stored, now get the current copy of the
375 	 * filter(s). If no filter exists, we create it.
376 	 */
377 
378 	if (STREQU(NAME_ALL, filter)) {
379 
380 		/*
381 		 * Adding ``all'' means changing all filters to reflect
382 		 * the information in the input. We'll preload the
383 		 * filters so that we know how many there are.
384 		 */
385 		if (
386 			!(file = getfilterfile(FILTERTABLE))
387 		     || loadfilters(file) == -1
388 		) {
389 			switch (errno) {
390 			case ENOENT:
391 				LP_ERRMSG (ERROR, E_FL_NOTALL);
392 				break;
393 			default:
394 				same_complaints (FILTERTABLE, TABLE);
395 				break;
396 			}
397 			return (1);
398 		}
399 
400 		store = (FILTER *)malloc((nfilters + 1) * sizeof(FILTER));
401 		if (!store) {
402 			LP_ERRMSG (ERROR, E_LP_MALLOC);
403 			return (1);
404 		}
405 
406 		for (ps = store; (pf = getfilter(filter)); )
407 			*ps++ = *pf;
408 		ps->name = 0;
409 
410 		switch (errno) {
411 		case ENOENT:
412 			if (ps - store != nfilters) {
413 				LP_ERRMSG1 (
414 					ERROR,
415 					E_FL_STRANGE,
416 					getfilterfile(FILTERTABLE)
417 				);
418 				return (1);
419 			}
420 			break;
421 		default:
422 			same_complaints (FILTERTABLE, TABLE);
423 			return (1);
424 		}
425 
426 	} else {
427 
428 		store = (FILTER *)malloc(2 * sizeof(FILTER));
429 		if (!store) {
430 			LP_ERRMSG (ERROR, E_LP_MALLOC);
431 			return (1);
432 		}
433 
434 		if ((pf = getfilter(filter))) {
435 			store[0] = *pf;
436 		} else
437 			switch (errno) {
438 			case ENOENT:
439 				/*
440 				 * We must be adding a new filter, so
441 				 * set up default values. Check that
442 				 * we'll have something reasonable to add.
443 				 */
444 				pf = store;
445 				pf->name = strdup(filter);
446 				pf->command = 0;
447 				pf->type = fl_slow;
448 				pf->printer_types = 0;
449 				pf->printers = 0;
450 				pf->input_types = 0;
451 				pf->output_types = 0;
452 				pf->templates = 0;
453 				if (!flbuf.command) {
454 					LP_ERRMSG (ERROR, E_FL_NOCMD);
455 					return (1);
456 				}
457 				break;
458 			default:
459 				same_complaints (FILTERTABLE, TABLE);
460 				return (1);
461 			}
462 
463 		store[1].name = 0;
464 
465 	}
466 
467 	at_least_one = ret = 0;
468 	for (ps = store; ps->name; ps++) {
469 
470 		for (fld = 0; fld < FL_MAX; fld++)
471 			if (real_fields[fld]) switch(fld) {
472 			case FL_IGN_P:
473 			case FL_NAME_P:
474 				break;
475 			case FL_CMD_P:
476 				ps->command = flbuf.command;
477 				break;
478 			case FL_TYPE_P:
479 				ps->type = flbuf.type;
480 				break;
481 			case FL_PTYPS_P:
482 				ps->printer_types = flbuf.printer_types;
483 				break;
484 			case FL_ITYPS_P:
485 				ps->input_types = flbuf.input_types;
486 				break;
487 			case FL_OTYPS_P:
488 				ps->output_types = flbuf.output_types;
489 				break;
490 			case FL_PRTRS_P:
491 				ps->printers = flbuf.printers;
492 				break;
493 			case FL_TMPS_P:
494 				ps->templates = flbuf.templates;
495 				break;
496 			}
497 
498 		if (putfilter(ps->name, ps) == -1) {
499 			if (errno == EBADF)  switch (lp_errno) {
500 			case LP_ETEMPLATE:
501 				LP_ERRMSG (ERROR, E_FL_BADTEMPLATE);
502 				break;
503 			case LP_EKEYWORD:
504 				LP_ERRMSG (ERROR, E_FL_BADKEY);
505 				break;
506 			case LP_EPATTERN:
507 				LP_ERRMSG (ERROR, E_FL_BADPATT);
508 				break;
509 			case LP_EREGEX:
510 			{
511 				char *			why;
512 
513 				extern int		regerrno;
514 
515 
516 				switch (regerrno) {
517 				case 11:
518 					why = "range endpoint too large";
519 					break;
520 				case 16:
521 					why = "bad number";
522 					break;
523 				case 25:
524 					why = "\"\\digit\" out of range";
525 					break;
526 				case 36:
527 					why = "illegal or missing delimiter";
528 					break;
529 				case 41:
530 					why = "no remembered search string";
531 					break;
532 				case 42:
533 					why = "\\(...\\) imbalance";
534 					break;
535 				case 43:
536 					why = "too many \\(";
537 					break;
538 				case 44:
539 					why = "more than 2 numbers given in \\{...\\}";
540 					break;
541 				case 45:
542 					why = "} expected after \\";
543 					break;
544 				case 46:
545 					why = "first number exceeds second in \\{...\\}";
546 					break;
547 				case 49:
548 					why = "[...] imbalance";
549 					break;
550 				case 50:
551 					why = "regular expression overflow";
552 					break;
553 				}
554 				LP_ERRMSG1 (ERROR, E_FL_BADREGEX, why);
555 				break;
556 			}
557 			case LP_ERESULT:
558 				LP_ERRMSG (ERROR, E_FL_BADRESULT);
559 				break;
560 			case LP_ENOMEM:
561 				errno = ENOMEM;
562 				same_complaints (FILTERTABLE, TABLE);
563 				break;
564 			} else
565 				same_complaints (FILTERTABLE, TABLE);
566 			ret = 1;
567 			break;
568 		} else
569 			at_least_one = 1;
570 
571 	}
572 
573 	if (at_least_one)
574 		(void)alert_spooler ();
575 
576 	return (ret);
577 }
578 
579 /**
580  ** reload_filter()
581  **/
582 
583 int			reload_filter (filter)
584 	char			*filter;
585 {
586 	register FILTER		*pf,
587 				*store,
588 				*ps;
589 
590 	char			*factory_file;
591 
592 	int			ret,
593 				at_least_one;
594 
595 	/*
596 	 * ``Manually'' load the archived filters, so that a call
597 	 * to "getfilter()" will read from them instead of the regular
598 	 * table.
599 	 */
600 	if (
601 		!(factory_file = getfilterfile(FILTERTABLE_I))
602 	     || loadfilters(factory_file) == -1
603 	) {
604 		switch (errno) {
605 		case ENOENT:
606 			LP_ERRMSG (ERROR, E_FL_NOFACTY);
607 			break;
608 		default:
609 			same_complaints (FILTERTABLE_I, TABLE_I);
610 			break;
611 		}
612 		return (1);
613 	}
614 
615 	if (STREQU(NAME_ALL, filter)) {
616 
617 		store = (FILTER *)malloc((nfilters + 1) * sizeof(FILTER));
618 		if (!store) {
619 			LP_ERRMSG (ERROR, E_LP_MALLOC);
620 			return (1);
621 		}
622 
623 		for (ps = store; (pf = getfilter(filter)); )
624 			*ps++ = *pf;
625 		ps->name = 0;
626 
627 		switch (errno) {
628 		case ENOENT:
629 			if (ps - store != nfilters) {
630 				LP_ERRMSG1 (
631 					ERROR,
632 					E_FL_STRANGE,
633 					getfilterfile(FILTERTABLE_I)
634 				);
635 				return (1);
636 			}
637 			break;
638 		default:
639 			same_complaints (FILTERTABLE_I, TABLE_I);
640 			return (1);
641 		}
642 
643 	} else {
644 
645 		store = (FILTER *)malloc(2 * sizeof(FILTER));
646 		if (!store) {
647 			LP_ERRMSG (ERROR, E_LP_MALLOC);
648 			return (1);
649 		}
650 
651 		if (!(pf = getfilter(filter))) switch (errno) {
652 		case ENOENT:
653 			LP_ERRMSG (ERROR, E_FL_FACTYNM);
654 			return (1);
655 		default:
656 			same_complaints (FILTERTABLE_I, TABLE_I);
657 			return (1);
658 		}
659 
660 		store[0] = *pf;
661 		store[1].name = 0;
662 
663 	}
664 
665 	/*
666 	 * Having stored the archived filter(s) in our own area, clear
667 	 * the currently loaded table so that the subsequent calls to
668 	 * "putfilter()" will read in the regular table.
669 	 */
670 	trash_filters ();
671 
672 	at_least_one = ret = 0;
673 	for (ps = store; ps->name; ps++)
674 		if (putfilter(ps->name, ps) == -1) {
675 			same_complaints (FILTERTABLE, TABLE);
676 			ret = 1;
677 			break;
678 		} else
679 			at_least_one = 1;
680 
681 	if (at_least_one)
682 		(void)alert_spooler ();
683 
684 	return (ret);
685 }
686 
687 /**
688  ** delete_filter()
689  **/
690 
691 int			delete_filter (filter)
692 	char			*filter;
693 {
694 	if (delfilter(filter) == -1) switch (errno) {
695 	case ENOENT:
696 		LP_ERRMSG1 (ERROR, E_FL_UNKFILT, filter);
697 		return (1);
698 	default:
699 		same_complaints (FILTERTABLE, TABLE);
700 		return (1);
701 	}
702 
703 	(void)alert_spooler ();
704 
705 	return (0);
706 }
707 
708 /**
709  ** list_filter()
710  **/
711 
712 static void		_list_filter();
713 
714 int			list_filter (filter)
715 	char			*filter;
716 {
717 	register FILTER		*pf;
718 
719 	char			*nl;
720 
721 	if (STREQU(NAME_ALL, filter)) {
722 
723 		nl = "";
724 		while ((pf = getfilter(filter))) {
725 			printf (gettext("%s(Filter \"%s\")\n"), nl, pf->name);
726 			_list_filter (pf);
727 			nl = "\n";
728 		}
729 
730 		switch (errno) {
731 		case ENOENT:
732 			return (0);
733 		default:
734 			same_complaints (FILTERTABLE, TABLE);
735 			return (1);
736 		}
737 
738 	} else {
739 
740 		if ((pf = getfilter(filter))) {
741 			_list_filter (pf);
742 			return (0);
743 		}
744 
745 		switch (errno) {
746 		case ENOENT:
747 			LP_ERRMSG1 (ERROR, E_FL_UNKFILT, filter);
748 			return (1);
749 		default:
750 			same_complaints (FILTERTABLE, TABLE);
751 			return (1);
752 		}
753 
754 	}
755 }
756 
757 static void		_list_filter (pf)
758 	register FILTER		*pf;
759 {
760 	register char		**pp,
761 				*sep;
762 
763 	register int		fld;
764 
765 	char *			head;
766 
767 
768 	for (fld = 0; fld < FL_MAX_P; fld++) switch (fld) {
769 	case FL_IGN_P:
770 	case FL_NAME_P:
771 		break;
772 	case FL_CMD_P:
773 		printf (
774 			"%s %s\n",
775 			headings[fld].v,
776 			(pf->command? pf->command : "")
777 		);
778 		break;
779 	case FL_TYPE_P:
780 		printf (
781 			"%s %s\n",
782 			headings[fld].v,
783 			(pf->type == fl_fast? FL_FAST : FL_SLOW)
784 		);
785 		break;
786 	case FL_PTYPS_P:
787 		pp = pf->printer_types;
788 		goto Lists;
789 	case FL_ITYPS_P:
790 		pp = pf->input_types;
791 		goto Lists;
792 	case FL_OTYPS_P:
793 		pp = pf->output_types;
794 		goto Lists;
795 	case FL_PRTRS_P:
796 		pp = pf->printers;
797 Lists:		printlist_qsep = 1;
798 		printlist_setup ("", "", LP_SEP, "");
799 		printf ("%s ", headings[fld].v);
800 		printlist (stdout, pp);
801 		printf ("\n");
802 		break;
803 	case FL_TMPS_P:
804 		head = makestr(headings[fld].v, " ", (char *)0);
805 		printlist_qsep = 1;
806 		printlist_setup (head, "", "\n", "\n");
807 		printlist (stdout, pf->templates);
808 		break;
809 	}
810 
811 	return;
812 }
813 
814 /**
815  ** opt() - GENERATE OPTION FROM FUNCTION NAME
816  **/
817 
818 static char		*opt (fnc)
819 	int			(*fnc)();
820 {
821 	if (fnc == add_filter)
822 		return ("-F");
823 	else if (fnc == reload_filter)
824 		return ("-i");
825 	else if (fnc == list_filter)
826 		return ("-l");
827 	else if (fnc == delete_filter)
828 		return ("-x");
829 	else
830 		return ("-?");
831 }
832 
833 /**
834  ** alert_spooler() - TELL SPOOLER TO LOAD FILTER TABLE
835  **/
836 
837 static void		alert_spooler ()
838 {
839 	char			msgbuf[MSGMAX];
840 
841 	int			mtype;
842 
843 	short			status;
844 
845 	/*
846 	 * If the attempt to open a message queue to the
847 	 * Spooler fails, assume it isn't running and just
848 	 * return--don't say anything, `cause the user may
849 	 * know. Any other failure deserves an error message.
850 	 */
851 
852 	if (mopen() == -1)
853 		return;
854 
855 	(void)putmessage (msgbuf, S_LOAD_FILTER_TABLE);
856 
857 	if (msend(msgbuf) == -1)
858 		goto Error;
859 	if (mrecv(msgbuf, MSGMAX) == -1)
860 		goto Error;
861 
862 	mtype = getmessage(msgbuf, R_LOAD_FILTER_TABLE, &status);
863 	if (mtype != R_LOAD_FILTER_TABLE) {
864 		LP_ERRMSG1 (ERROR, E_LP_BADREPLY, mtype);
865 		(void)mclose ();
866 		exit (1);
867 	}
868 
869 	if (status == MOK)
870 		goto NoError;
871 
872 Error:	LP_ERRMSG (ERROR, E_FL_NOSPLOAD);
873 
874 NoError:(void)mclose ();
875 	return;
876 
877 }
878 
879 /**
880  ** same_complaints() - PRINT COMMON ERROR MESSAGES
881  **/
882 
883 static void		same_complaints (table, type)
884 	char			*table;
885 	int			type;
886 {
887 	switch (errno) {
888 	case EACCES:
889 		if (type == TABLE)
890 			LP_ERRMSG1 (
891 				ERROR,
892 				E_FL_ACCESS,
893 				getfilterfile(table)
894 			);
895 		else
896 			LP_ERRMSG1 (
897 				ERROR,
898 				E_FL_ACCESSI,
899 				getfilterfile(table)
900 			);
901 		break;
902 	case EAGAIN:
903 	case EDEADLK:
904 		LP_ERRMSG1 (ERROR, E_LP_AGAIN, getfilterfile(table));
905 		break;
906 	default:
907 		LP_ERRMSG2 (
908 			ERROR,
909 			E_FL_UNKNOWN,
910 			getfilterfile(table),
911 			strerror(errno)
912 		);
913 		break;
914 	}
915 	return;
916 }
917