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
init_memory(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
init_printers()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
init_classes()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
init_forms()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
init_pwheels()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
init_requests(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
init_exec()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