Home | History | Annotate | Download | only in lpsched
      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