xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/msgs.c (revision 2a8bcb4e)
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 # include	<stdarg.h>
31 # include	<limits.h>
32 # include	<sys/types.h>
33 # include	<poll.h>
34 # include	<stropts.h>
35 # include	<unistd.h>
36 #include <syslog.h>
37 
38 # include	"lpsched.h"
39 
40 #define TURN_OFF(X,F)	(void)Fcntl(X, F_SETFL, (Fcntl(X, F_GETFL, 0) & ~(F)))
41 
42 
43 static void	conn_shutdown();
44 
45 extern int		Filter_Status;
46 extern void		dispatch();
47 extern int		Waitrequest;
48 void			shutdown_messages();
49 static char		*Message;
50 static int		MaxClients		= 0,
51 			do_msg();
52 extern int		Reserve_Fds;
53 extern int		Shutdown;
54 
55 MESG			*Net_md;
56 
57 /*
58 ** take_message() - WAIT FOR INTERRUPT OR ONE MESSAGE FROM USER PROCESS
59 */
60 
take_message(void)61 void take_message(void)
62 {
63     int		bytes;
64     int		i;
65     MESG *	md;
66 
67     for (EVER) {	/* not really forever...returns are in the loop */
68 	if ((md = mlisten()) == NULL)
69 	    switch(errno) {
70 	      case EAGAIN:
71 	      case EINTR:
72 		return;
73 
74 	      case ENOMEM:
75 		mallocfail();
76 		/* NOTREACHED */
77 
78 	      default:
79 		fail ("Unexpected streams error in mlisten (%s).\n" , PERROR);
80 	    }
81 
82 	/*
83 	 * Check for a dropped connection to a child.
84 	 * Normally a child should tell us that it is dying
85 	 * (with S_SHUTDOWN or S_SEND_CHILD), but it may have
86 	 * died a fast death. We'll simulate the message we
87 	 * wanted to get so we can use the same code to clean up.
88 	 */
89 	if ((md->event & POLLHUP) && !(md->event & POLLIN) ||
90 	    (md->event & (POLLERR|POLLNVAL))) {
91 		switch (md->type) {
92 
93 		case MD_CHILD:
94 			/*
95 			 * If the message descriptor is found in the
96 			 * exec table, it must be an interface pgm,
97 			 * notification, etc. Otherwise, it must be
98 			 * a network child.
99 			 */
100 			for (i = 0; Exec_Table[i] != NULL; i++)
101 				if (Exec_Table[i]->md == md)
102 					break;
103 
104 			if (Exec_Table[i] != NULL) {
105 				(void) putmessage(Message, S_CHILD_DONE,
106 					Exec_Table[i]->key, 0, 0);
107 			} else {
108 				(void) putmessage(Message, S_SHUTDOWN, 1);
109 			}
110 			bytes = 1;
111 			break;
112 
113 		default:
114 			bytes = -1;
115 			break;
116 
117 		}
118 
119 	} else {
120 		if (md->readfd == -1) { /* something happened to the readfd */
121 			syslog(LOG_DEBUG, "take_message: readfd is -1");
122 			return;
123 		}
124 		bytes = mread(md, Message, MSGMAX);
125 	}
126 
127 	switch (bytes) {
128 	  case -1:
129 	    if (errno == EINTR)
130 		return;
131 	    else
132 		fail ("Unexpected streams error (%s).\n" , PERROR);
133 	    break;
134 
135 	  case 0:
136 	    break;
137 
138 	  default:
139 	    if (do_msg(md))
140 		return;
141 	    break;
142 	}
143     }
144 }
145 
146 /*
147 ** do_msg() - HANDLE AN INCOMING MESSAGE
148 */
149 
150 static int
do_msg(MESG * md)151 do_msg(MESG *md)
152 {
153     int			type = mtype(Message);
154 
155     if (type != S_GOODBYE) {
156 	    md->wait = 0;
157 	    dispatch (type, Message, md);
158 	    /*
159 	     * The message may have caused the need to
160 	     * schedule something, so go back and check.
161 	     */
162 	    return(1);
163     }
164     return(0);
165 }
166 
167 /*
168 ** calculate_nopen() - DETERMINE # FILE DESCRIPTORS AVAILABLE FOR QUEUES
169 */
170 
171 static void
calculate_nopen(void)172 calculate_nopen(void)
173 {
174     int		fd, nopen;
175 
176     /*
177      * How many file descriptorss are currently being used?
178      */
179     for (fd = nopen = 0; fd < OpenMax; fd++)
180 	if (fcntl(fd, F_GETFL, 0) != -1)
181 	    nopen++;
182 
183     /*
184      * How many file descriptors are available for use
185      * as open FIFOs? Leave one spare as a way to tell
186      * clients we don't have any to spare (hmmm....) and
187      * one for the incoming fifo.
188      */
189 
190     MaxClients = OpenMax;
191     MaxClients -= nopen;	/* current overhead */
192     MaxClients -= Reserve_Fds;
193     MaxClients -= 2;		/* incoming FIFO and spare outgoing */
194     MaxClients--;		/* the requests log */
195     MaxClients--;		/* HPI routines and lpsched log */
196 
197     return;
198 }
199 
conn_shutdown()200 static void conn_shutdown ( )
201 {
202     if (!Shutdown) {
203 	note ("The public connection \"%s\", has failed.\n", Lp_FIFO);
204 	lpshut(1);
205     }
206 }
207 
208 /*
209 ** init_messages() - INITIALIZE MAIN MESSAGE QUEUE
210 */
211 
212 void
init_messages(void)213 init_messages(void)
214 {
215     char	*cmd;
216     MESG *	md;
217 
218     (void) signal(SIGPIPE, SIG_IGN);
219 
220     calculate_nopen ();
221 
222     Message = (char *)Malloc(MSGMAX);
223 
224     (void) Chmod(Lp_Tmp, 0711);
225 
226     if ((md = mcreate(Lp_FIFO)) == NULL)
227 	fail ("Can't create public message device (%s).\n", PERROR);
228     mon_discon(md, conn_shutdown);
229 
230     if (mlisteninit(md) != 0)
231 	if (errno == ENOMEM)
232 	    mallocfail();
233 	else
234 	    fail ("Unexpected streams error (%s).\n" , PERROR);
235 
236     (void) Chmod(Lp_FIFO, 0666);
237     return;
238 }
239 
240 
241 void
shutdown_messages(void)242 shutdown_messages(void)
243 {
244     MESG	*md;
245 
246     (void) Chmod(Lp_Tmp, 0700);
247     (void) Chmod(Lp_FIFO, 0600);
248     md = mlistenreset();
249     mdestroy(md);
250 }
251