xref: /titanic_41/usr/src/cmd/lp/cmd/lpsched/init.c (revision 70025d765b044c6d8594bb965a2247a61e991a99)
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 1998 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"	/* SVr4.0 1.10.1.8	*/
32 
33 #include "lpsched.h"
34 #include <syslog.h>
35 
36 CSTATUS		*CStatus;		/* Status of same          */
37 EXEC		*Exec_Table;		/* Running processes       */
38 EXEC		*Exec_Slow;		/*   Slow filters	   */
39 EXEC		*Exec_Notify;		/*   Notifications	   */
40 FSTATUS		*FStatus;		/* status of same	   */
41 PSTATUS		*PStatus;		/* Status of same          */
42 PWSTATUS	*PWStatus;		/* Status of same          */
43 RSTATUS		*Request_List;		/* Queue of print requests */
44 
45 int		CT_Size,
46 		ET_Size,
47 		ET_SlowSize	= 1,
48 		ET_NotifySize	= 1,
49 		FT_Size,
50 		PT_Size,
51 		PWT_Size;
52 
53 static ALERT	*Alert_Table;		/* Printer fault alerts    */
54 static ALERT	*FAlert_Table;		/* Form mount alerts       */
55 static ALERT	*PAlert_Table;		/* PrintWheel mount alerts */
56 static CLASS	*Class_Table;		/* Known classes           */
57 static _FORM	*Form_Table;		/* Known forms             */
58 static PRINTER	*Printer_Table;		/* Known printers          */
59 static PWHEEL	*PrintWheel_Table;	/* Known print wheels      */
60 
61 /*
62 **
63 **	CLRMEM clears memory pointed to by <addr> over the range of
64 **	<addr>[<cnt> .. <size>].  <datum> is the size of an element of <addr>.
65 **
66 */
67 # define	CLRMEM(addr, cnt, size, datum) \
68                       (void) memset((char *)(addr + cnt), 0, \
69 		                    (int)((size - cnt ) * sizeof(datum)))
70 
71 #define	ACLUSTERSIZE	10
72 
73 
74 static void	init_printers(),
75 		init_classes(),
76 		init_forms(),
77 		init_pwheels(),
78 		init_exec();
79 
80 
81 static RSTATUS	*init_requests();
82 
83 void
84 init_memory(void)
85 {
86     init_printers();
87     init_classes();
88     init_forms();
89     init_pwheels();
90     init_exec();
91 
92     /*
93      * Load the status after the basic structures have been loaded,
94      * but before loading requests still in the queue. This is so
95      * the requests can be compared against accurate status information
96      * (except rejection status--accept the jobs anyway).
97      */
98     load_status();
99 
100     Loadfilters(Lp_A_Filters);
101 
102     Request_List = init_requests();
103 }
104 
105 static void
106 init_printers()
107 {
108     PRINTER	*p;
109     PRINTER	*pt_pointer;
110     int		pt_allocation;
111     int		at_allocation;
112     int		PT_Count;
113     int		i;
114     char	**paperDenied;
115 
116 
117     PT_Size = 10;
118     PT_Count = 0;
119     pt_allocation = PT_Size * sizeof(PRINTER);
120 
121     Printer_Table = (PRINTER *)Malloc(pt_allocation);
122 
123     CLRMEM(Printer_Table, PT_Count, PT_Size, PRINTER);
124 
125     pt_pointer = Printer_Table;
126 
127     while((p = Getprinter(NAME_ALL)) != NULL || errno != ENOENT) {
128 	if (!p)
129 	    continue;
130 
131 	if (p->remote)	/* this is remote, ignore it */
132 		continue;
133 
134 	syslog(LOG_DEBUG, "Loaded printer: %s\n", p->name);
135 
136 	*pt_pointer = *p;
137 	pt_pointer++;
138 
139 	if (++PT_Count < PT_Size)
140 	    continue;
141 
142 	PT_Size += 10;
143 	pt_allocation = PT_Size * sizeof(PRINTER);
144 
145 	Printer_Table = (PRINTER *)Realloc(Printer_Table, pt_allocation);
146 
147 	CLRMEM(Printer_Table, PT_Count, PT_Size, PRINTER);
148 
149 	pt_pointer = Printer_Table + PT_Count;
150     }
151 
152     PT_Size = PT_Count + 40;
153 
154     pt_allocation = PT_Size * sizeof(PRINTER);
155 
156     Printer_Table = (PRINTER *)Realloc(Printer_Table, pt_allocation);
157 
158     CLRMEM(Printer_Table, PT_Count, PT_Size, PRINTER);
159 
160     at_allocation = PT_Size * sizeof(ALERT);
161 
162     Alert_Table = (ALERT *)Malloc(at_allocation);
163 
164     CLRMEM(Alert_Table, 0, PT_Size, ALERT);
165 
166     pt_allocation = PT_Size * sizeof(PSTATUS);
167 
168     PStatus = (PSTATUS *)Malloc(pt_allocation);
169 
170     CLRMEM(PStatus, 0, PT_Size, PSTATUS);
171 
172     for (i = 0; i < PT_Size; i++)
173     {
174 	char	buf[15];
175 	PSTATUS	*psp;
176 
177 	psp = PStatus + i;
178 	p = psp->printer = Printer_Table + i;
179 	psp->alert = Alert_Table + i;
180 	sprintf(buf, "A-%d", i);
181 	Alert_Table[i].msgfile = makepath(Lp_Temp, buf, (char *)0);
182 	(void) Unlink(Alert_Table[i].msgfile);
183 	if (i < PT_Count)
184 	{
185 	    load_userprinter_access (
186 		    p->name,
187 		    &(psp->users_allowed),
188 		    &(psp->users_denied)
189 	    );
190 	    load_formprinter_access (
191 		    p->name,
192 		    &(psp->forms_allowed),
193 		    &(psp->forms_denied)
194 	    );
195 		 load_paperprinter_access (
196 			 p->name,
197 			 &psp->paper_allowed,
198 			 &paperDenied
199 			 );
200 		 freelist(paperDenied);
201 	    load_sdn (&(psp->cpi), p->cpi);
202 	    load_sdn (&(psp->lpi), p->lpi);
203 	    load_sdn (&(psp->plen), p->plen);
204 	    load_sdn (&(psp->pwid), p->pwid);
205 	}
206     }
207 }
208 
209 static void
210 init_classes()
211 {
212     CLASS	*p;
213     CLASS	*ct_pointer;
214     int		ct_allocation;
215     int		CT_Count;
216     int		i;
217 
218 
219     CT_Size = 10;
220     CT_Count = 0;
221     ct_allocation = CT_Size * sizeof(CLASS);
222 
223     Class_Table = (CLASS *)Malloc(ct_allocation);
224 
225     CLRMEM(Class_Table, CT_Count, CT_Size, CLASS);
226 
227     ct_pointer = Class_Table;
228 
229     while((p = Getclass(NAME_ALL)) != NULL || errno != ENOENT)
230     {
231 	if (!p)
232 	    continue;
233 
234 	*ct_pointer = *p;
235 	ct_pointer++;
236 
237 	if (++CT_Count < CT_Size)
238 	    continue;
239 
240 	CT_Size += 10;
241 	ct_allocation = CT_Size * sizeof(CLASS);
242 
243 	Class_Table = (CLASS *)Realloc(Class_Table, ct_allocation);
244 
245 	CLRMEM(Class_Table, CT_Count, CT_Size, CLASS);
246 
247 	ct_pointer = Class_Table + CT_Count;
248 
249     }
250 
251     CT_Size = CT_Count + 40;
252 
253     ct_allocation = CT_Size * sizeof(CLASS);
254 
255     Class_Table = (CLASS *)Realloc(Class_Table, ct_allocation);
256 
257     CLRMEM(Class_Table, CT_Count, CT_Size, CLASS);
258 
259     ct_allocation = CT_Size * sizeof(CSTATUS);
260 
261     CStatus = (CSTATUS *)Malloc(ct_allocation);
262 
263     CLRMEM(CStatus, 0, CT_Size, CSTATUS);
264 
265     for (i = 0; i < CT_Size; i++)
266 	CStatus[i].class = Class_Table + i;
267 }
268 
269 static void
270 init_forms()
271 {
272     _FORM	*ft_pointer,
273 		*f;
274     int		at_allocation;
275     int		ft_allocation;
276     int		FT_Count;
277     int		i;
278 
279 
280     FT_Size = 10;
281     FT_Count = 0;
282     ft_allocation = FT_Size * sizeof(_FORM);
283 
284     Form_Table = (_FORM *)Malloc(ft_allocation);
285 
286     CLRMEM(Form_Table, FT_Count, FT_Size, _FORM);
287 
288     ft_pointer = Form_Table;
289 
290     ft_pointer->plen.val = 0.0;
291     ft_pointer->plen.sc = 'i';
292     ft_pointer->pwid.val = 0.0;
293     ft_pointer->pwid.sc = 'i';
294     ft_pointer->lpi.val = 0.0;
295     ft_pointer->lpi.sc = 'i';
296     ft_pointer->cpi.val = 0.0;
297     ft_pointer->cpi.sc = 'i';
298     ft_pointer->np = 0;
299     ft_pointer->chset = NULL;
300     ft_pointer->mandatory = 0;
301     ft_pointer->rcolor = NULL;
302     ft_pointer->comment = NULL;
303     ft_pointer->conttype = NULL;
304     ft_pointer->name = NULL;
305     ft_pointer->alert.shcmd = NULL;
306     ft_pointer->alert.Q = 0;
307     ft_pointer->alert.W = 0;
308     ft_pointer->paper = NULL;
309     ft_pointer->isDefault = 0;
310 
311     ft_pointer++;
312     FT_Count++;
313 
314     while ((f = Getform(NAME_ALL)) != NULL) {
315 	*(ft_pointer++) = *f;
316 
317 	if (++FT_Count < FT_Size)
318 	    continue;
319 
320 	FT_Size += 10;
321 	ft_allocation = FT_Size * sizeof(_FORM);
322 
323 	Form_Table = (_FORM *)Realloc(Form_Table, ft_allocation);
324 
325 	CLRMEM(Form_Table, FT_Count, FT_Size, _FORM);
326 
327 	ft_pointer = Form_Table + FT_Count;
328     }
329 
330     FT_Size = FT_Count + 40;
331 
332     ft_allocation = FT_Size * sizeof(_FORM);
333 
334     Form_Table = (_FORM *)Realloc(Form_Table, ft_allocation);
335 
336     CLRMEM(Form_Table, FT_Count, FT_Size, _FORM);
337 
338     at_allocation = FT_Size * sizeof(ALERT);
339 
340     FAlert_Table = (ALERT *)Malloc(at_allocation);
341 
342     CLRMEM(FAlert_Table, 0, FT_Size, ALERT);
343 
344     ft_allocation = FT_Size * sizeof(FSTATUS);
345 
346     FStatus = (FSTATUS *)Malloc(ft_allocation);
347 
348     CLRMEM(FStatus, 0, FT_Size, FSTATUS);
349 
350     for (i = 0; i < FT_Size; i++) {
351 	char	buf[15];
352 
353 	FStatus[i].form = Form_Table + i;
354 	FStatus[i].alert = FAlert_Table + i;
355 	FStatus[i].trigger = Form_Table[i].alert.Q;
356 	sprintf(buf, "F-%d", i);
357 	FAlert_Table[i].msgfile = makepath(Lp_Temp, buf, (char *)0);
358 	(void) Unlink(FAlert_Table[i].msgfile);
359 
360 	if (i < FT_Count) {
361 	    load_userform_access (
362 		    Form_Table[i].name,
363 		    &(FStatus[i].users_allowed),
364 		    &(FStatus[i].users_denied)
365 	    );
366 	    load_sdn (&(FStatus[i].cpi), Form_Table[i].cpi);
367 	    load_sdn (&(FStatus[i].lpi), Form_Table[i].lpi);
368 	    load_sdn (&(FStatus[i].plen), Form_Table[i].plen);
369 	    load_sdn (&(FStatus[i].pwid), Form_Table[i].pwid);
370 	}
371     }
372     FStatus[0].users_denied = Calloc(2,sizeof(char *));
373     /* for BSD_FORM, make sure it denies no one */
374 }
375 
376 static void
377 init_pwheels()
378 {
379     PWHEEL	*pwt_pointer;
380     PWHEEL	*p;
381     int		at_allocation;
382     int		pwt_allocation;
383     int		PWT_Count;
384     int		i;
385 
386 
387     PWT_Count = 0;
388     PWT_Size = 10;
389     pwt_allocation = PWT_Size * sizeof(PWHEEL);
390 
391     PrintWheel_Table = (PWHEEL *)Malloc(pwt_allocation);
392 
393     CLRMEM(PrintWheel_Table, PWT_Count, PWT_Size, PWHEEL);
394 
395     pwt_pointer = PrintWheel_Table;
396 
397     while((p = Getpwheel(NAME_ALL)) != NULL || errno != ENOENT)
398     {
399 	if (!p)
400 	    continue;
401 
402 	*pwt_pointer = *p;
403 	pwt_pointer++;
404 
405 	if (++PWT_Count < PWT_Size)
406 	    continue;
407 
408 	PWT_Size += 10;
409 	pwt_allocation = PWT_Size * sizeof(PWHEEL);
410 
411 	PrintWheel_Table = (PWHEEL *)Realloc(PrintWheel_Table, pwt_allocation);
412 
413 	CLRMEM(PrintWheel_Table, PWT_Count, PWT_Size, PWHEEL);
414 
415 	pwt_pointer = &PrintWheel_Table[PWT_Count];
416 
417     }
418 
419     PWT_Size = PWT_Count + 40;
420 
421     pwt_allocation = PWT_Size * sizeof(PWHEEL);
422 
423     PrintWheel_Table = (PWHEEL *)Realloc(PrintWheel_Table, pwt_allocation);
424 
425     CLRMEM(PrintWheel_Table, PWT_Count, PWT_Size, PWHEEL);
426 
427     at_allocation = PWT_Size * sizeof(ALERT);
428 
429     PAlert_Table = (ALERT *)Malloc(at_allocation);
430 
431     CLRMEM(PAlert_Table, 0, PWT_Size, ALERT);
432 
433     pwt_allocation = PWT_Size * sizeof(PWSTATUS);
434 
435     PWStatus = (PWSTATUS *)Malloc(pwt_allocation);
436 
437     CLRMEM(PWStatus, 0, PWT_Size, PWSTATUS);
438 
439     for (i = 0; i < PWT_Size; i++)
440     {
441 	char	buf[15];
442 
443 	PWStatus[i].pwheel = PrintWheel_Table + i;
444 	PWStatus[i].trigger = PrintWheel_Table[i].alert.Q;
445 	PWStatus[i].alert = PAlert_Table + i;
446 	sprintf(buf, "P-%d", i);
447 	PAlert_Table[i].msgfile = makepath(Lp_Temp, buf, (char *)0);
448 	(void) Unlink(PAlert_Table[i].msgfile);
449     }
450 }
451 
452 static RSTATUS *
453 init_requests(void)
454 {
455     REQUEST		*r;
456     RSTATUS		**table;
457     RSTATUS		*rp = NULL;
458     SECURE		*s;
459     char		*name;
460     char		*sysdir;
461     char		*sysname;
462     char		*reqfile = NULL;
463     int			count;
464     int			i;
465     long		addr = -1;
466     long		sysaddr = -1;
467     unsigned long	size;
468     short		vr_ret;
469 
470     size = 20;
471     count = 0;
472 
473 
474     table = (RSTATUS **)Malloc(size * sizeof(RSTATUS *));
475 
476     while((sysname = next_dir(Lp_Requests, &addr)) != NULL) {
477 
478 	sysdir = makepath(Lp_Requests, sysname, NULL);
479 
480 	while((name = next_file(sysdir, &sysaddr)) != NULL) {
481 	    table[count] = allocr();
482 
483 	    reqfile = makepath(sysname, name, NULL);
484 	    Free(name);
485 	    syslog(LOG_DEBUG, "Loaded request: %s\n", reqfile);
486 
487 	    if ((s = Getsecure(reqfile)) == NULL) {
488 		table[count]->req_file = reqfile;	/* fix for 1103890 */
489 		reqfile = NULL;				/* fix for 1103890 */
490 		rmfiles(table[count], 0);
491 		freerstatus(table[count]);
492 		continue;
493 	    }
494 	    *(table[count]->secure) = *s;
495 	    table[count]->secure->req_id = Strdup(s->req_id);
496 	    table[count]->secure->user = Strdup(s->user);
497 	    table[count]->secure->system = Strdup(s->system);
498 	    freesecure(s);
499 
500 	    if((r = Getrequest(reqfile)) == NULL) {
501 		rmfiles(table[count], 0);
502 		freerstatus(table[count]);
503 		Free(reqfile);
504 		continue;
505 	    }
506 	    r->outcome &= ~RS_ACTIVE;	/* it can't be! */
507 	    *(table[count]->request) = *r;
508 
509 	    table[count]->req_file = reqfile;
510 	    reqfile = NULL;
511 
512 	    if ((r->outcome & (RS_CANCELLED|RS_FAILED)) &&
513 		!(r->outcome & RS_NOTIFY))
514 	    {
515 		rmfiles(table[count], 0);
516 		freerstatus(table[count]);
517 		continue;
518 	    }
519 
520 	    /*
521 	     * So far, the only way RS_NOTIFY can be set without there
522 	     * being a notification file containing the message to the
523 	     * user, is if the request was cancelled. This is because
524 	     * cancelling a request does not cause the creation of the
525 	     * message if the request is currently printing or filtering.
526 	     * (The message is created after the child process dies.)
527 	     * Thus, we know what to say.
528 	     *
529 	     * If this behaviour changes, we may have to find another way
530 	     * of determining what to say in the message.
531 	     */
532 	    if (r->outcome & RS_NOTIFY) {
533 		char	*file = makereqerr(table[count]);
534 
535 		if (Access(file, F_OK) == -1) {
536 		    if (!(r->outcome & RS_CANCELLED)) {
537 			Free(file);
538 			rmfiles(table[count], 0);
539 			freerstatus(table[count]);
540 			continue;
541 		    }
542 		    notify(table[count], NULL, 0, 0, 0);
543 		}
544 		Free(file);
545 	    }
546 
547 	    /* fix for bugid 1103709. if validate_request returns
548 	     * MNODEST, then the printer for the request doesn't exist
549 	     * anymore! E.g. lpadmin -x was issued, and the request
550 	     * hasn't been cleaned up. In this case, the "printer"
551 	     * element of table[] will be NULL, and cancel will
552 	     * core dump! So we clean this up here.
553 	     */
554 
555 	    /*
556 	     * Well actually this happens with MDENYDEST too. The real problem
557 	     * is if the printer is NULL, so test for it
558 	     */
559 
560 	    if ((vr_ret=validate_request(table[count], NULL, 1)) != MOK) {
561 		if (vr_ret == MNODEST || (table[count]->printer == NULL)) {
562 			rmfiles(table[count], 0);
563 			freerstatus(table[count]);
564 			continue;
565 		}
566 		cancel(table[count], 1);
567 	    }
568 
569 
570 	    if (++count < size)
571 		continue;
572 
573 	    size += 20;
574 
575 	    table = (RSTATUS **)Realloc((char *)table, size * sizeof(RSTATUS *));
576 	}
577 	Free(sysdir);
578 	Free(sysname);
579 	sysaddr = -1;
580     }
581 
582     if (!count)
583 	Free ((char *)table);
584     else
585 	if ((size = count) > 0) {
586 	    table = (RSTATUS **)Realloc((char *)table,
587 					size * sizeof(RSTATUS *));
588 
589 	    qsort((void *)table, size, sizeof(RSTATUS *),
590 			(int (*)(const void * , const void *))rsort);
591 
592 	    for (i = 0; i < size - 1; i++) {
593 		table[i]->next = table[i + 1];
594 		table[i + 1]->prev = table[i];
595 	    }
596 
597 	    table[0]->prev = 0;
598 	    table[size - 1]->next = 0;
599 
600 	    rp = *table;
601 	    Free(table);
602 
603 	}
604 
605     return(rp);
606 }
607 
608 static void
609 init_exec()
610 {
611     EXEC	*et_pointer;
612     int		et_allocation;
613     int		i;
614 
615     ET_Size	= ET_SlowSize
616 		+ ET_NotifySize
617     		+ PT_Size * 3	/* 1 each for interface, alert, fault msg */
618 		+ PWT_Size
619 		+ FT_Size;
620 
621     et_allocation = ET_Size * sizeof(EXEC);
622 
623     Exec_Table = (EXEC *)Malloc(et_allocation);
624 
625     CLRMEM(Exec_Table, 0, ET_Size, EXEC);
626 
627     et_pointer = Exec_Table;
628 
629     Exec_Slow = et_pointer;
630     for (i = 0; i < ET_SlowSize; i++)
631 	(et_pointer++)->type = EX_SLOWF;
632 
633     Exec_Notify = et_pointer;
634     for (i = 0; i < ET_NotifySize; i++)
635 	(et_pointer++)->type = EX_NOTIFY;
636 
637     for (i = 0; i < PT_Size; i++) {
638 	PStatus[i].exec = et_pointer;
639 	et_pointer->type = EX_INTERF;
640 	et_pointer->ex.printer = PStatus + i;
641 	et_pointer++;
642 
643 	PStatus[i].alert->exec = et_pointer;
644 	et_pointer->type = EX_ALERT;
645 	et_pointer->ex.printer = PStatus + i;
646 	et_pointer++;
647 
648 	PStatus[i].fault_exec = et_pointer;
649 	et_pointer->type = EX_FAULT_MESSAGE;
650 	et_pointer->ex.printer = PStatus + i;
651 	et_pointer++;
652     }
653 
654     for (i = 0; i < PWT_Size; i++) {
655 	PWStatus[i].alert->exec = et_pointer;
656 	et_pointer->type = EX_PALERT;
657 	et_pointer->ex.pwheel = PWStatus + i;
658 	et_pointer++;
659     }
660 
661     for (i = 0; i < FT_Size; i++) {
662 	FStatus[i].alert->exec = et_pointer;
663 	et_pointer->type = EX_FALERT;
664 	et_pointer->ex.form = FStatus + i;
665 	et_pointer++;
666     }
667 
668 }
669