xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/init.c (revision dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 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 "lpsched.h"
34 #include <syslog.h>
35 
36 CSTATUS		**CStatus = NULL;		/* Status of same          */
37 PSTATUS		**PStatus = NULL;		/* Status of same          */
38 FSTATUS		**FStatus = NULL;		/* status of same	   */
39 PWSTATUS	**PWStatus = NULL;		/* Status of same          */
40 EXEC		**Exec_Table = NULL;		/* Running processes       */
41 EXEC		**Exec_Slow = NULL;		/*   Slow filters	   */
42 EXEC		**Exec_Notify = NULL;		/*   Notifications	   */
43 RSTATUS		*Request_List = NULL;		/* Queue of print requests */
44 
45 int		ET_SlowSize	= 1,
46 		ET_NotifySize	= 1;
47 
48 static void	init_printers(),
49 		init_classes(),
50 		init_forms(),
51 		init_pwheels(),
52 		init_exec();
53 
54 
55 static void	init_requests();
56 
57 void
58 init_memory(void)
59 {
60     init_exec();
61     init_printers();
62     init_classes();
63     init_forms();
64     init_pwheels();
65 
66     /*
67      * Load the status after the basic structures have been loaded,
68      * but before loading requests still in the queue. This is so
69      * the requests can be compared against accurate status information
70      * (except rejection status--accept the jobs anyway).
71      */
72     load_status();
73 
74     Loadfilters(Lp_A_Filters);
75 
76     init_requests();
77 }
78 
79 static void
80 init_printers()
81 {
82     PRINTER	*p;
83     int i = 0;
84 
85     while((p = Getprinter(NAME_ALL)) != NULL || errno != ENOENT) {
86 	if ((!p) || (p->remote))	/* NULL or this is remote, ignore it */
87 		continue;
88 
89 	(void) new_pstatus(p);
90 	syslog(LOG_DEBUG, "Loaded printer: %s", p->name);
91     }
92 }
93 
94 static void
95 init_classes()
96 {
97     CLASS       *c;
98 
99     while((c = Getclass(NAME_ALL)) != NULL) {
100 	(void) new_cstatus(c);
101         syslog(LOG_DEBUG, "Loaded class: %s", c->name);
102     }
103 }
104 
105 static void
106 init_forms()
107 {
108     _FORM	*f;
109     int		i = 0;
110 
111     while ((f = Getform(NAME_ALL)) != NULL) {
112 	(void) new_fstatus(f);
113 	syslog(LOG_DEBUG, "Loaded form: %s", f->name);
114     }
115 }
116 
117 static void
118 init_pwheels()
119 {
120     PWHEEL	*p;
121     int i = 0;
122 
123     while((p = Getpwheel(NAME_ALL)) != NULL || errno != ENOENT)
124     {
125 	if (!p)			/* NULL, ignore it. */
126 	    continue;
127 
128 	(void) new_pwstatus(p);
129     	syslog(LOG_DEBUG, "Loaded print-wheel: %s", p->name);
130     }
131 }
132 
133 static void
134 init_requests(void)
135 {
136     RSTATUS		**table = NULL;
137     REQUEST		*r;
138     SECURE		*s;
139     char		*name;
140     char		*sysdir;
141     char		*sysname;
142     char		*reqfile = NULL;
143     long		addr = -1;
144     long		sysaddr = -1;
145     short		vr_ret;
146 
147     while((sysname = next_dir(Lp_Requests, &addr)) != NULL) {
148     	RSTATUS		*rsp;
149 
150 	sysdir = makepath(Lp_Requests, sysname, NULL);
151 
152 	while((name = next_file(sysdir, &sysaddr)) != NULL) {
153 	    reqfile = makepath(sysname, name, NULL);
154 	    Free(name);
155 
156 	    if ((s = Getsecure(reqfile)) == NULL) {
157 		RSTATUS tmp;
158 
159 		memset(&tmp, 0, sizeof (tmp));
160 		tmp.req_file = reqfile;	/* fix for 1103890 */
161 		rmfiles(&tmp, 0);
162 		free(tmp.req_file);
163 		continue;
164 	    }
165 	    syslog(LOG_DEBUG, "Loaded request: %s", reqfile);
166 
167 	    if((r = Getrequest(reqfile)) == NULL) {
168 		RSTATUS tmp;
169 
170 		memset(&tmp, 0, sizeof (tmp));
171 		tmp.req_file = reqfile;	/* fix for 1103890 */
172 		rmfiles(&tmp, 0);
173 		freesecure(s);
174 		free(tmp.req_file);
175 		continue;
176 	    }
177 	    syslog(LOG_DEBUG, "Loaded secure: %s", s->req_id);
178 
179 	    rsp = new_rstatus(r, s);
180 
181 	    r->outcome &= ~RS_ACTIVE;	/* it can't be! */
182 	    rsp->req_file = reqfile;
183 
184 	    if ((r->outcome & (RS_CANCELLED|RS_FAILED)) &&
185 		!(r->outcome & RS_NOTIFY)) {
186 			rmfiles(rsp, 0);
187 			free_rstatus(rsp);
188 			continue;
189 	    }
190 
191 	    /*
192 	     * So far, the only way RS_NOTIFY can be set without there
193 	     * being a notification file containing the message to the
194 	     * user, is if the request was cancelled. This is because
195 	     * cancelling a request does not cause the creation of the
196 	     * message if the request is currently printing or filtering.
197 	     * (The message is created after the child process dies.)
198 	     * Thus, we know what to say.
199 	     *
200 	     * If this behaviour changes, we may have to find another way
201 	     * of determining what to say in the message.
202 	     */
203 	    if (r->outcome & RS_NOTIFY) {
204 		char	*file = makereqerr(rsp);
205 
206 		if (Access(file, F_OK) == -1) {
207 		    if (!(r->outcome & RS_CANCELLED)) {
208 			Free(file);
209 			rmfiles(rsp, 0);
210 			free_rstatus(rsp);
211 			continue;
212 		    }
213 		    notify(rsp, NULL, 0, 0, 0);
214 		}
215 		Free(file);
216 	    }
217 
218 	    /* fix for bugid 1103709. if validate_request returns
219 	     * MNODEST, then the printer for the request doesn't exist
220 	     * anymore! E.g. lpadmin -x was issued, and the request
221 	     * hasn't been cleaned up. In this case, the "printer"
222 	     * element of table[] will be NULL, and cancel will
223 	     * core dump! So we clean this up here.
224 	     */
225 
226 	    /*
227 	     * Well actually this happens with MDENYDEST too. The real problem
228 	     * is if the printer is NULL, so test for it
229 	     */
230 
231 	    if ((vr_ret=validate_request(rsp, NULL, 1)) != MOK) {
232 		if (vr_ret == MNODEST || (rsp->printer == NULL)) {
233 			rmfiles(rsp, 0);
234 			free_rstatus(rsp);
235 			continue;
236 		}
237 		cancel(rsp, 1);
238 	    }
239 
240 	    list_append((void ***)&table, (void *)rsp);
241 	}
242 	Free(sysdir);
243 	Free(sysname);
244 	sysaddr = -1;
245     }
246 
247     if (table != NULL) {
248 	unsigned long i;
249 
250 	for (i = 0; table[i] != NULL; i++);
251 
252 	qsort((void *)table, i, sizeof(RSTATUS *),
253 			(int (*)(const void * , const void *))rsort);
254 
255 	for (i = 0; table[i] != NULL; i++) {
256 		table[i]->next = table[i + 1];
257 		if (table[i + 1] != NULL)
258 			table[i + 1]->prev = table[i];
259 	}
260 
261 	Request_List = *table;
262 	Free(table);
263     }
264 }
265 
266 static void
267 init_exec()
268 {
269     EXEC	*ep;
270     int		i;
271 
272     for (i = 0; i < ET_SlowSize; i++) {
273 	ep = new_exec(EX_SLOWF, NULL);
274 	list_append((void ***)&Exec_Slow, (void *)ep);
275     }
276 
277     for (i = 0; i < ET_NotifySize; i++) {
278 	ep = new_exec(EX_NOTIFY, NULL);
279 	list_append((void ***)&Exec_Notify, (void *)ep);
280     }
281 }
282