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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2000 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" /* SVr4.0 1.9.1.5 */ 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 slot; 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 (slot = 0; slot < ET_Size; slot++) 104 if (Exec_Table[slot].md == md) 105 break; 106 107 if (slot < ET_Size) { 108 (void) putmessage(Message, S_CHILD_DONE, 109 Exec_Table[slot].key, slot, 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 defined(DEBUG) 159 if (debug & DB_MESSAGES) { 160 int size = stoh(Message + MESG_SIZE); 161 int ntype = stoh(Message + MESG_TYPE); 162 163 syslog(LOG_DEBUG, "RECV: type %d size %d: %-.*s\n", ntype, size, 164 size, Message); 165 } 166 # endif 167 168 #if defined(DEBUG) 169 syslog(LOG_DEBUG,"MESSAGE ACCEPTED: client %#0x", md); 170 #endif 171 if (type != S_GOODBYE) { 172 md->wait = 0; 173 dispatch (type, Message, md); 174 /* 175 * The message may have caused the need to 176 * schedule something, so go back and check. 177 */ 178 return(1); 179 } 180 return(0); 181 } 182 183 /* 184 ** calculate_nopen() - DETERMINE # FILE DESCRIPTORS AVAILABLE FOR QUEUES 185 */ 186 187 static void 188 calculate_nopen(void) 189 { 190 int fd, nopen; 191 192 /* 193 * How many file descriptorss are currently being used? 194 */ 195 for (fd = nopen = 0; fd < OpenMax; fd++) 196 if (fcntl(fd, F_GETFL, 0) != -1) 197 nopen++; 198 199 /* 200 * How many file descriptors are available for use 201 * as open FIFOs? Leave one spare as a way to tell 202 * clients we don't have any to spare (hmmm....) and 203 * one for the incoming fifo. 204 */ 205 206 MaxClients = OpenMax; 207 MaxClients -= nopen; /* current overhead */ 208 MaxClients -= Reserve_Fds; 209 MaxClients -= 2; /* incoming FIFO and spare outgoing */ 210 MaxClients--; /* the requests log */ 211 MaxClients--; /* HPI routines and lpsched log */ 212 213 return; 214 } 215 216 static void conn_shutdown ( ) 217 { 218 if (!Shutdown) { 219 note ("The public connection \"%s\", has failed.\n", Lp_FIFO); 220 lpshut(1); 221 } 222 } 223 224 /* 225 ** init_messages() - INITIALIZE MAIN MESSAGE QUEUE 226 */ 227 228 void 229 init_messages(void) 230 { 231 char *cmd; 232 MESG * md; 233 234 (void) signal(SIGPIPE, SIG_IGN); 235 236 calculate_nopen (); 237 238 if (cmd = makestr(RMCMD, " ", Lp_Public_FIFOs, "/*", (char *)0)) 239 { 240 (void) system(cmd); 241 Free(cmd); 242 } 243 if (cmd = makestr(RMCMD, " ", Lp_Private_FIFOs, "/*", (char *)0)) 244 { 245 (void) system(cmd); 246 Free(cmd); 247 } 248 249 Message = (char *)Malloc(MSGMAX); 250 251 (void) Chmod(Lp_Public_FIFOs, 0773); 252 (void) Chmod(Lp_Private_FIFOs, 0771); 253 (void) Chmod(Lp_Tmp, 0711); 254 255 if ((md = mcreate(Lp_FIFO)) == NULL) 256 fail ("Can't create public message device (%s).\n", PERROR); 257 mon_discon(md, conn_shutdown); 258 259 if (mlisteninit(md) != 0) 260 if (errno == ENOMEM) 261 mallocfail(); 262 else 263 fail ("Unexpected streams error (%s).\n" , PERROR); 264 265 (void) Chmod(Lp_FIFO, 0666); 266 return; 267 } 268 269 270 void 271 shutdown_messages(void) 272 { 273 MESG *md; 274 275 (void) Chmod(Lp_Public_FIFOs, 0770); 276 (void) Chmod(Lp_Tmp, 0700); 277 (void) Chmod(Lp_FIFO, 0600); 278 md = mlistenreset(); 279 mdestroy(md); 280 } 281