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