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