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