xref: /illumos-gate/usr/src/cmd/listen/listen.c (revision 25b601ca6246156206dbe2b37be633d695100eb0)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate 
23052519c2SGarrett D'Amore /*
24052519c2SGarrett D'Amore  * Copyright 2014 Garrett D'Amore
25052519c2SGarrett D'Amore  */
267c478bd9Sstevel@tonic-gate /*
27113f4232Sakaplan  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
28113f4232Sakaplan  * Use is subject to license terms.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
31113f4232Sakaplan /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
32113f4232Sakaplan /*	  All Rights Reserved  	*/
33113f4232Sakaplan 
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate  * Network Listener Process
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  *		command line:
387c478bd9Sstevel@tonic-gate  *
397c478bd9Sstevel@tonic-gate  *		listen [ -m minor_prefix ] netspec
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /* system include files	*/
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #include <fcntl.h>
467c478bd9Sstevel@tonic-gate #include <signal.h>
477c478bd9Sstevel@tonic-gate #include <stdio.h>
487c478bd9Sstevel@tonic-gate #include <unistd.h>
497c478bd9Sstevel@tonic-gate #include <string.h>
507c478bd9Sstevel@tonic-gate #include <errno.h>
517c478bd9Sstevel@tonic-gate #include <memory.h>
527c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
537c478bd9Sstevel@tonic-gate #include <sys/tiuser.h>
547c478bd9Sstevel@tonic-gate #include <sys/param.h>
557c478bd9Sstevel@tonic-gate #include <sys/types.h>
567c478bd9Sstevel@tonic-gate #include <sys/stat.h>
577c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
587c478bd9Sstevel@tonic-gate #include <values.h>
597c478bd9Sstevel@tonic-gate #include <ctype.h>
607c478bd9Sstevel@tonic-gate #include <pwd.h>
617c478bd9Sstevel@tonic-gate #include <grp.h>
627c478bd9Sstevel@tonic-gate #include <sys/ipc.h>
637c478bd9Sstevel@tonic-gate #include <sys/poll.h>
647c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
657c478bd9Sstevel@tonic-gate #include <sac.h>
667c478bd9Sstevel@tonic-gate #include <utmpx.h>
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /* listener include files */
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #include "lsparam.h"		/* listener parameters		*/
717c478bd9Sstevel@tonic-gate #include "lsfiles.h"		/* listener files info		*/
727c478bd9Sstevel@tonic-gate #include "lserror.h"		/* listener error codes		*/
737c478bd9Sstevel@tonic-gate #include "lsnlsmsg.h"		/* NLPS listener protocol	*/
747c478bd9Sstevel@tonic-gate #include "lssmbmsg.h"		/* MS_NET identifier		*/
757c478bd9Sstevel@tonic-gate #include "lsdbf.h"		/* data base file stuff		*/
767c478bd9Sstevel@tonic-gate #include "listen.h"
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /* defines	*/
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate #define NAMESIZE	(NAMEBUFSZ-1)
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate #define SPLhi()		Splflag = 1
837c478bd9Sstevel@tonic-gate #define SPLlo()		Splflag = 0
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate #define GEN	1
867c478bd9Sstevel@tonic-gate #define LOGIN	0
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /* global variables	*/
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate int	NLPS_proc = 0;	/* set if process is a listener child		*/
917c478bd9Sstevel@tonic-gate pid_t	Pid;		/* listener's process ID 			*/
927c478bd9Sstevel@tonic-gate char	*Progname;	/* listener's basename (from argv[0])		*/
937c478bd9Sstevel@tonic-gate static	char Provbuf[PATHSIZE];
947c478bd9Sstevel@tonic-gate char	*Provider = Provbuf;	/* name of transport provider		*/
957c478bd9Sstevel@tonic-gate char	*Netspec = NETSPEC;
967c478bd9Sstevel@tonic-gate char	*Minor_prefix;		/* prefix for minor device names	*/
977c478bd9Sstevel@tonic-gate int	Dbf_entries;		/* number of private addresses in dbf file*/
987c478bd9Sstevel@tonic-gate int	Valid_addrs;		/* number of addresses bound		*/
997c478bd9Sstevel@tonic-gate struct	pollfd *Pollfds;	/* for polling fds			*/
1007c478bd9Sstevel@tonic-gate dbf_t	*Dbfhead;		/* Beginning of in-memory database	*/
1017c478bd9Sstevel@tonic-gate dbf_t	*Newdbf;		/* Beginning of in-memory database (reread) */
1027c478bd9Sstevel@tonic-gate char	*Server_cmd_lines;	/* database space			*/
1037c478bd9Sstevel@tonic-gate char	*New_cmd_lines;		/* database space (reread) 		*/
1047c478bd9Sstevel@tonic-gate long	Ndesc;			/* Number of per-process file descriptors */
1057c478bd9Sstevel@tonic-gate int	Readdb;			/* set to TRUE by SAC_READDB message	*/
1067c478bd9Sstevel@tonic-gate struct	netconfig *Netconf;	/* netconfig structure for this network	*/
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate struct	call_list	Free_call;
1097c478bd9Sstevel@tonic-gate struct	call_list	*Free_call_p = &Free_call; /* call free list 	*/
1107c478bd9Sstevel@tonic-gate struct	call_list	*Priv_call;	/* call save pending list 	*/
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /* FILE DESCRIPTOR MANAGEMENT:
1137c478bd9Sstevel@tonic-gate  *
1147c478bd9Sstevel@tonic-gate  * The listener uses 6 (sometimes 7) file descriptors:
1157c478bd9Sstevel@tonic-gate  *	fd 0:	Originally opened to /dev/null, used to accept incoming calls.
1167c478bd9Sstevel@tonic-gate  *	fd 1:	In the parent, a connection to _sacpipe.  Closed in the child
1177c478bd9Sstevel@tonic-gate  *		and dup'ed to 0.
1187c478bd9Sstevel@tonic-gate  *	fd 2:	In the parent, a connection to _pmpipe.  Dup'ed in the child
1197c478bd9Sstevel@tonic-gate  *		to 0.
1207c478bd9Sstevel@tonic-gate  *	fd 3:	Originally opened to /dev/null, this file descriptor is
1217c478bd9Sstevel@tonic-gate  *		reserved to open the STREAMS pipe when passing the connection
1227c478bd9Sstevel@tonic-gate  *		to a standing server.
1237c478bd9Sstevel@tonic-gate  *	fd 4:	Opened to the pid file.  We have to keep it open to keep the
1247c478bd9Sstevel@tonic-gate  *		lock active.
1257c478bd9Sstevel@tonic-gate  *	fd 5:	Opened to the log file.
1267c478bd9Sstevel@tonic-gate  *	fd 6:	Opened to the debug file ONLY when compiled with DEBUGMODE.
1277c478bd9Sstevel@tonic-gate  *
1287c478bd9Sstevel@tonic-gate  * The remaining file descriptors are available for binding private addresses.
1297c478bd9Sstevel@tonic-gate  */
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate #ifndef DEBUGMODE
1327c478bd9Sstevel@tonic-gate #define USEDFDS	6
1337c478bd9Sstevel@tonic-gate #else
1347c478bd9Sstevel@tonic-gate #define	USEDFDS	7
1357c478bd9Sstevel@tonic-gate FILE	*Debugfp;		/* for the debugging file	*/
1367c478bd9Sstevel@tonic-gate #endif
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate int	Acceptfd;		/* to accept connections (fd 0)	*/
1397c478bd9Sstevel@tonic-gate int	Sacpipefd;		/* pipe TO sac process (fd 1)	*/
1407c478bd9Sstevel@tonic-gate int	Pmpipefd;		/* pipe FROM sac process (fd 2) */
1417c478bd9Sstevel@tonic-gate int	Passfd;			/* pipe used to pass FD (fd 3)	*/
1427c478bd9Sstevel@tonic-gate int	Pidfd;			/* locked pid file (fd 4)	*/
1437c478bd9Sstevel@tonic-gate FILE	*Logfp;			/* for logging listener activity*/
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate struct	pmmsg	Pmmsg;		/* to respond to SAC		*/
1467c478bd9Sstevel@tonic-gate int	State = PM_STARTING;	/* current SAC state		*/
1477c478bd9Sstevel@tonic-gate char	Mytag[15];
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate char	Lastmsg[BUFSIZ];	/* contains last msg logged (by stampbuf) */
1507c478bd9Sstevel@tonic-gate int	Logmax = LOGMAX;	/* number of entriet to allow in logfile  */
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate int	Splflag;		/* logfile critical region flag		  */
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate static char *badnspmsg = "Bad netspec on command line ( Pathname too long )";
1557c478bd9Sstevel@tonic-gate static char *badstart  = "Listener failed to start properly";
1567c478bd9Sstevel@tonic-gate static char *nologfile = "Unable to open listener log file during initialization";
1577c478bd9Sstevel@tonic-gate static char *usage     = "Usage: listen [ -m minor_prefix ] network_device";
1587c478bd9Sstevel@tonic-gate static char *nopmtag   = "Fatal error: Unable to get PMTAG from environment";
1597c478bd9Sstevel@tonic-gate static char tzenv[BUFSIZ];
1607c478bd9Sstevel@tonic-gate 
161052519c2SGarrett D'Amore #define TZFILE	"/etc/default/init"
1627c478bd9Sstevel@tonic-gate #define TZSTR	"TZ="
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate void	check_sac_mesg();	/* routine to process messages from sac */
1657c478bd9Sstevel@tonic-gate void	rpc_register();		/* routine to register rpc services */
1667c478bd9Sstevel@tonic-gate void	rpc_unregister();	/* routine to unregister rpc services */
1677c478bd9Sstevel@tonic-gate extern	struct	netconfig	*getnetconfigent();
1687c478bd9Sstevel@tonic-gate extern	char	*t_alloc();
1697c478bd9Sstevel@tonic-gate extern	void	logexit();
1707c478bd9Sstevel@tonic-gate extern	int	t_errno;
1717c478bd9Sstevel@tonic-gate extern	int	errno;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate #ifndef TRUE
1747c478bd9Sstevel@tonic-gate #define	TRUE	1
1757c478bd9Sstevel@tonic-gate #define FALSE	0
1767c478bd9Sstevel@tonic-gate #endif
1777c478bd9Sstevel@tonic-gate 
178113f4232Sakaplan static void mod_prvaddr(void);
179113f4232Sakaplan static void pitchcall(struct call_list *pending, struct t_discon *discon);
180113f4232Sakaplan static void clr_call(struct t_call *call);
181113f4232Sakaplan static void trycon(struct call_list *phead, int fd);
182113f4232Sakaplan static void send_dis(struct call_list *phead, int fd);
183113f4232Sakaplan static void doevent(struct call_list *phead, int fd);
184113f4232Sakaplan static void listen(void);
185113f4232Sakaplan static void rst_signals(void);
186113f4232Sakaplan static void catch_signals(void);
187113f4232Sakaplan static void net_open(void);
188113f4232Sakaplan static void init_files(void);
189113f4232Sakaplan static void pid_open(void);
190113f4232Sakaplan 
191113f4232Sakaplan int
192113f4232Sakaplan main(int argc, char **argv)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	struct stat buf;
1957c478bd9Sstevel@tonic-gate 	int ret;
1967c478bd9Sstevel@tonic-gate 	char scratch[BUFSIZ];
1977c478bd9Sstevel@tonic-gate 	char log[BUFSIZ];
1987c478bd9Sstevel@tonic-gate 	char olog[BUFSIZ];
1997c478bd9Sstevel@tonic-gate 	char *scratch_p = scratch;
2007c478bd9Sstevel@tonic-gate 	char *mytag_p;
2017c478bd9Sstevel@tonic-gate 	FILE *fp;
2027c478bd9Sstevel@tonic-gate 	extern char *getenv();
2037c478bd9Sstevel@tonic-gate 	char *parse();
2047c478bd9Sstevel@tonic-gate 	int	c;
2057c478bd9Sstevel@tonic-gate 	extern	char *optarg;
2067c478bd9Sstevel@tonic-gate 	extern	int optind;
207113f4232Sakaplan 	int i;
2087c478bd9Sstevel@tonic-gate 	char	*Mytag_p = Mytag;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	/* Get my port monitor tag out of the environment		*/
2117c478bd9Sstevel@tonic-gate 	if ((mytag_p = getenv("PMTAG")) == NULL) {
2127c478bd9Sstevel@tonic-gate 		/* no place to write */
2137c478bd9Sstevel@tonic-gate 		exit(1);
2147c478bd9Sstevel@tonic-gate 	}
2157c478bd9Sstevel@tonic-gate 	strcpy(Mytag, mytag_p);
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	/* open log file */
2187c478bd9Sstevel@tonic-gate 	sprintf(log, "%s/%s/%s", ALTDIR, Mytag_p, LOGNAME);
2197c478bd9Sstevel@tonic-gate 	sprintf(olog, "%s/%s/%s", ALTDIR, Mytag_p, OLOGNAME);
2207c478bd9Sstevel@tonic-gate 	if (stat(log, &buf) == 0) {
2217c478bd9Sstevel@tonic-gate 		/* file exists, try and save it but if we can't don't worry */
2227c478bd9Sstevel@tonic-gate 		unlink(olog);
2237c478bd9Sstevel@tonic-gate 		rename(log, olog);
2247c478bd9Sstevel@tonic-gate 	}
2257c478bd9Sstevel@tonic-gate 	if ((i = open(log, O_WRONLY|O_CREAT|O_APPEND, 0444)) < 0)
2267c478bd9Sstevel@tonic-gate 		logexit(1, nologfile);
2277c478bd9Sstevel@tonic-gate 	/* as stated above, the log file should be file descriptor 5 */
2287c478bd9Sstevel@tonic-gate 	if ((ret = fcntl(i, F_DUPFD, 5)) != 5)
2297c478bd9Sstevel@tonic-gate 		logexit(1, nologfile);
2307c478bd9Sstevel@tonic-gate 	Logfp = fdopen(ret, "a+");
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	/* Get my port monitor tag out of the environment		*/
2337c478bd9Sstevel@tonic-gate 	if ((mytag_p = getenv("PMTAG")) == NULL) {
2347c478bd9Sstevel@tonic-gate 		logexit(1, nopmtag);
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 	strcpy(Mytag, mytag_p);
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	(void) umask(022);
2397c478bd9Sstevel@tonic-gate 	Readdb = FALSE;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	if (geteuid() != (uid_t) 0) {
2427c478bd9Sstevel@tonic-gate 		logmessage("Must be root to start listener");
2437c478bd9Sstevel@tonic-gate 		logexit(1, badstart);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "m:")) != EOF)
2477c478bd9Sstevel@tonic-gate 		switch (c) {
2487c478bd9Sstevel@tonic-gate 		case 'm':
2497c478bd9Sstevel@tonic-gate 			Minor_prefix = optarg;
2507c478bd9Sstevel@tonic-gate 			break;
2517c478bd9Sstevel@tonic-gate 		default:
2527c478bd9Sstevel@tonic-gate 			logexit(1, usage);
2537c478bd9Sstevel@tonic-gate 			break;
2547c478bd9Sstevel@tonic-gate 		}
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	if ((Netspec = argv[optind]) == NULL) {
2577c478bd9Sstevel@tonic-gate 		logexit(1, usage);
2587c478bd9Sstevel@tonic-gate 	}
2597c478bd9Sstevel@tonic-gate 	if ((Netconf = getnetconfigent(Netspec)) == NULL) {
2607c478bd9Sstevel@tonic-gate 		sprintf(scratch, "no netconfig entry for <%s>", Netspec);
2617c478bd9Sstevel@tonic-gate 		logmessage(scratch);
2627c478bd9Sstevel@tonic-gate 		logexit(1, badstart);
2637c478bd9Sstevel@tonic-gate 	}
2647c478bd9Sstevel@tonic-gate 	if (!Minor_prefix)
2657c478bd9Sstevel@tonic-gate 		Minor_prefix = argv[optind];
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	if ((int) strlen(Netspec) > PATHSIZE)  {
2687c478bd9Sstevel@tonic-gate 		logmessage(badnspmsg);
2697c478bd9Sstevel@tonic-gate 		logexit(1, badstart);
2707c478bd9Sstevel@tonic-gate 	}
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	/*
2737c478bd9Sstevel@tonic-gate 	 * SAC will start the listener in the correct directory, so we
2747c478bd9Sstevel@tonic-gate 	 * don't need to chdir there, as we did in older versions
2757c478bd9Sstevel@tonic-gate 	 */
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	strcpy(Provbuf, "/dev/");
2787c478bd9Sstevel@tonic-gate 	strcat(Provbuf, Netspec);
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	(void) umask(0);
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	init_files();		/* open Accept, Sac, Pm, Pass files	*/
2837c478bd9Sstevel@tonic-gate 	pid_open();		/* create pid file			*/
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate #ifdef	DEBUGMODE
2867c478bd9Sstevel@tonic-gate 	sprintf(scratch, "%s/%s/%s", ALTDIR, Mytag, DBGNAME);
2877c478bd9Sstevel@tonic-gate 	Debugfp = fopen(scratch, "w");
2887c478bd9Sstevel@tonic-gate #endif
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate #ifdef	DEBUGMODE
2927c478bd9Sstevel@tonic-gate 	if ((!Logfp) || (!Debugfp))
2937c478bd9Sstevel@tonic-gate #else
2947c478bd9Sstevel@tonic-gate 	if (!Logfp)
2957c478bd9Sstevel@tonic-gate #endif
2967c478bd9Sstevel@tonic-gate 		logexit(1, badstart);
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate  * In case we started with no environment, find out what timezone we're
3007c478bd9Sstevel@tonic-gate  * in.  This will get passed to children, so only need to do once.
3017c478bd9Sstevel@tonic-gate  */
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	if (getenv("TZ") == NULL) {
304052519c2SGarrett D'Amore 		fp = fopen(TZFILE, "r");
3057c478bd9Sstevel@tonic-gate 		if (fp) {
3067c478bd9Sstevel@tonic-gate 			while (fgets(tzenv, BUFSIZ, fp)) {
3077c478bd9Sstevel@tonic-gate 				if (tzenv[strlen(tzenv) - 1] == '\n')
3087c478bd9Sstevel@tonic-gate 					tzenv[strlen(tzenv) - 1] = '\0';
3097c478bd9Sstevel@tonic-gate 				if (!strncmp(TZSTR, tzenv, strlen(TZSTR))) {
3107c478bd9Sstevel@tonic-gate 					putenv(parse(tzenv));
3117c478bd9Sstevel@tonic-gate 					break;
3127c478bd9Sstevel@tonic-gate 				}
3137c478bd9Sstevel@tonic-gate 			}
3147c478bd9Sstevel@tonic-gate 			fclose(fp);
3157c478bd9Sstevel@tonic-gate 		}
3167c478bd9Sstevel@tonic-gate 		else {
317052519c2SGarrett D'Amore 			sprintf(scratch, "couldn't open %s, default to GMT",
318052519c2SGarrett D'Amore 			    TZFILE);
3197c478bd9Sstevel@tonic-gate 			logmessage(scratch);
3207c478bd9Sstevel@tonic-gate 		}
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	logmessage("@(#)listen:listen.c	1.19.9.1");
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate #ifdef	DEBUGMODE
3267c478bd9Sstevel@tonic-gate 	logmessage("Listener process with DEBUG capability");
3277c478bd9Sstevel@tonic-gate #endif
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	sprintf(scratch, "Listener port monitor tag: %s", Mytag_p);
3307c478bd9Sstevel@tonic-gate 	logmessage(scratch);
3317c478bd9Sstevel@tonic-gate 	DEBUG((9, "Minor prefix: %s  Netspec %s", Minor_prefix, Netspec));
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	/* fill in Pmmesg fields that always stay the same */
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	Pmmsg.pm_maxclass = MAXCLASS;
3367c478bd9Sstevel@tonic-gate 	strcpy(Pmmsg.pm_tag, Mytag_p);
3377c478bd9Sstevel@tonic-gate 	Pmmsg.pm_size = 0;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	/* Find out what state to start in.  If not in env, exit */
3407c478bd9Sstevel@tonic-gate 	if ((scratch_p = getenv("ISTATE")) == NULL)
3417c478bd9Sstevel@tonic-gate 		logexit(1, "ERROR: ISTATE variable not set in environment");
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	if (!strcmp(scratch_p, "enabled")) {
3447c478bd9Sstevel@tonic-gate 		State = PM_ENABLED;
3457c478bd9Sstevel@tonic-gate 		logmessage("Starting state: ENABLED");
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate 	else {
3487c478bd9Sstevel@tonic-gate 		State = PM_DISABLED;
3497c478bd9Sstevel@tonic-gate 		logmessage("Starting state: DISABLED");
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	/* try to get my "basename"		*/
3537c478bd9Sstevel@tonic-gate 	Progname = strrchr(argv[0], '/');
3547c478bd9Sstevel@tonic-gate 	if (Progname && Progname[1])
3557c478bd9Sstevel@tonic-gate 		++Progname;
3567c478bd9Sstevel@tonic-gate 	else
3577c478bd9Sstevel@tonic-gate 		Progname = argv[0];
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	catch_signals();
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	/*
3627c478bd9Sstevel@tonic-gate 	 * Allocate memory for private address and file descriptor table
3637c478bd9Sstevel@tonic-gate 	 * Here we are assuming that no matter how many private addresses
3647c478bd9Sstevel@tonic-gate 	 * exist in the system if the system limit is 20 then we will only
3657c478bd9Sstevel@tonic-gate 	 * get 20 file descriptors
3667c478bd9Sstevel@tonic-gate 	 */
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	Ndesc = ulimit(4,0L);		/* get num of file des on system */
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	read_dbf(DB_INIT);
3717c478bd9Sstevel@tonic-gate 	net_open();			/* init, open, bind names 	*/
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	for (i = 3; i < Ndesc; i++)  {	/* leave stdout, stderr open	*/
3747c478bd9Sstevel@tonic-gate 		fcntl(i, F_SETFD, 1);	/* set close on exec flag*/
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	logmessage("Initialization Complete");
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	listen();
380113f4232Sakaplan 	return (0);
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate /*
3857c478bd9Sstevel@tonic-gate  * pid_open:
3867c478bd9Sstevel@tonic-gate  *
3877c478bd9Sstevel@tonic-gate  * open pidfile with specified oflags and modes and lock it
3887c478bd9Sstevel@tonic-gate  *
3897c478bd9Sstevel@tonic-gate  */
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate static char *pidopenmsg ="Can't create process ID file in home directory";
3927c478bd9Sstevel@tonic-gate static char *pidlockmsg ="Can't lock PID file: listener may already be running";
3937c478bd9Sstevel@tonic-gate 
394113f4232Sakaplan static void
395113f4232Sakaplan pid_open(void)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate 	int ret;
398113f4232Sakaplan 	unsigned int i;
3997c478bd9Sstevel@tonic-gate 	char pidstring[20];
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	if ((Pidfd = open(PIDNAME, PIDOFLAG, PIDMODE)) == -1)  {
4027c478bd9Sstevel@tonic-gate 		logmessage(pidopenmsg);
4037c478bd9Sstevel@tonic-gate 		error(E_CREAT, EXIT | NOCORE | NO_MSG);
4047c478bd9Sstevel@tonic-gate 	}
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	if (lockf(Pidfd, 2, 0L) == -1)  {
4077c478bd9Sstevel@tonic-gate 		logmessage(pidlockmsg);
4087c478bd9Sstevel@tonic-gate 		logexit(1, badstart);
4097c478bd9Sstevel@tonic-gate 	}
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	Pid = getpid();
4127c478bd9Sstevel@tonic-gate 	i = sprintf(pidstring, "%ld", Pid) + 1;
4137c478bd9Sstevel@tonic-gate 	ftruncate(Pidfd, 0);
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	while ((ret = write(Pidfd, pidstring, i)) != i) {
4167c478bd9Sstevel@tonic-gate 		if (errno == EINTR)
4177c478bd9Sstevel@tonic-gate 			continue;
4187c478bd9Sstevel@tonic-gate 		if (ret < 0)
4197c478bd9Sstevel@tonic-gate 			sys_error(E_PIDWRITE, EXIT);
4207c478bd9Sstevel@tonic-gate 		else
4217c478bd9Sstevel@tonic-gate 			error(E_PIDWRITE, EXIT);
4227c478bd9Sstevel@tonic-gate 	}
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate /*
4277c478bd9Sstevel@tonic-gate  * init_files: open initial files for the listener (see FILE DESC MGMT comment)
4287c478bd9Sstevel@tonic-gate  */
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate static char *pmopenmsg = "Can't open pipe to read SAC messages";
4317c478bd9Sstevel@tonic-gate static char *sacopenmsg = "Can't open pipe to respond to SAC messages";
4327c478bd9Sstevel@tonic-gate 
433113f4232Sakaplan static void
434113f4232Sakaplan init_files(void)
4357c478bd9Sstevel@tonic-gate {
4367c478bd9Sstevel@tonic-gate 	close(0);
4377c478bd9Sstevel@tonic-gate         if ((Acceptfd = open("/dev/null", O_RDWR)) != 0) {
4387c478bd9Sstevel@tonic-gate 		logmessage("Trouble opening /dev/null");
4397c478bd9Sstevel@tonic-gate                 sys_error(E_SYS_ERROR, EXIT | NOCORE);
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	close(1);
4437c478bd9Sstevel@tonic-gate 	if ((Sacpipefd = open(SACPIPE, O_RDWR|O_NDELAY)) != 1) {
4447c478bd9Sstevel@tonic-gate 		logmessage(sacopenmsg);
4457c478bd9Sstevel@tonic-gate 		error(E_CREAT, EXIT | NOCORE | NO_MSG);
4467c478bd9Sstevel@tonic-gate 	}
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	close(2);
4497c478bd9Sstevel@tonic-gate 	if ((Pmpipefd = open(PMPIPE, O_RDWR|O_NDELAY)) != 2) {
4507c478bd9Sstevel@tonic-gate 		logmessage(pmopenmsg);
4517c478bd9Sstevel@tonic-gate 		error(E_CREAT, EXIT | NOCORE | NO_MSG);
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	close(3);
4557c478bd9Sstevel@tonic-gate 	if ((Passfd = dup(Acceptfd)) != 3) {
4567c478bd9Sstevel@tonic-gate 		logmessage("Trouble duping /dev/null");
4577c478bd9Sstevel@tonic-gate                 sys_error(E_SYS_ERROR, EXIT | NOCORE);
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate  * net_open: open and bind communications channels
4657c478bd9Sstevel@tonic-gate  *		The name generation code in net_open, open_bind and bind is,
4667c478bd9Sstevel@tonic-gate  * 		for the	most part, specific to STARLAN NETWORK.
4677c478bd9Sstevel@tonic-gate  *		This name generation code is included in the listener
4687c478bd9Sstevel@tonic-gate  *		as a developer debugging aid.
4697c478bd9Sstevel@tonic-gate  */
4707c478bd9Sstevel@tonic-gate 
471113f4232Sakaplan static void
472113f4232Sakaplan net_open(void)
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate #ifdef	CHARADDR
4757c478bd9Sstevel@tonic-gate 	char pbuf[NAMEBUFSZ + 1];
4767c478bd9Sstevel@tonic-gate #endif	/* CHARADDR	*/
477113f4232Sakaplan 	int i;
478113f4232Sakaplan 	dbf_t *dp;
4797c478bd9Sstevel@tonic-gate 	char scratch[BUFSIZ];
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	DEBUG((9,"in net_open"));
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	/* set up free call list and pending connection lists */
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	Free_call_p->cl_head = (struct callsave *) NULL;
4867c478bd9Sstevel@tonic-gate 	Free_call_p->cl_tail = (struct callsave *) NULL;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	/* Pending calls are linked in a structure, one per fild descriptor */
4897c478bd9Sstevel@tonic-gate 	if ((Priv_call = (struct call_list *) malloc(Ndesc *(sizeof(
4907c478bd9Sstevel@tonic-gate 				struct call_list)))) == NULL)
4917c478bd9Sstevel@tonic-gate 		error(E_MALLOC,NOCORE | EXIT);
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	i = 0;
4947c478bd9Sstevel@tonic-gate 	Valid_addrs = 0;
4957c478bd9Sstevel@tonic-gate 	/* first do static addrs */
4967c478bd9Sstevel@tonic-gate 	while ( (i < Dbf_entries) ) {
4977c478bd9Sstevel@tonic-gate 		dp = &Dbfhead[i];
4987c478bd9Sstevel@tonic-gate 		if (!(dp->dbf_sflags & DFLAG)) {
4997c478bd9Sstevel@tonic-gate 			if (add_prvaddr(dp) == 0)
5007c478bd9Sstevel@tonic-gate 				Valid_addrs++;
5017c478bd9Sstevel@tonic-gate 		}
5027c478bd9Sstevel@tonic-gate 		i++;
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 	i = 0;
5057c478bd9Sstevel@tonic-gate 	/* second pass for dynamic addrs */
5067c478bd9Sstevel@tonic-gate 	while ( (i < Dbf_entries) ) {
5077c478bd9Sstevel@tonic-gate 		dp = &Dbfhead[i];
5087c478bd9Sstevel@tonic-gate 		if (dp->dbf_sflags & DFLAG) {
5097c478bd9Sstevel@tonic-gate 			if (add_prvaddr(dp) == 0)
5107c478bd9Sstevel@tonic-gate 				Valid_addrs++;
5117c478bd9Sstevel@tonic-gate 		}
5127c478bd9Sstevel@tonic-gate 		i++;
5137c478bd9Sstevel@tonic-gate 	}
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	sprintf(scratch, "Net opened, %d %s bound, %d fds free", Valid_addrs,
5167c478bd9Sstevel@tonic-gate 		(Valid_addrs == 1) ? "address" : "addresses",
5177c478bd9Sstevel@tonic-gate 		Ndesc-Valid_addrs-USEDFDS);
5187c478bd9Sstevel@tonic-gate 	logmessage(scratch);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate /*
5237c478bd9Sstevel@tonic-gate  * Following are some general queueing routines.  The call list head contains
5247c478bd9Sstevel@tonic-gate  * a pointer to the head of the queue and to the tail of the queue.  Normally,
5257c478bd9Sstevel@tonic-gate  * calls are added to the tail and removed from the head to ensure they are
5267c478bd9Sstevel@tonic-gate  * processed in the order received, however, because of the possible interruption
5277c478bd9Sstevel@tonic-gate  * of an acceptance with the resulting requeueing, it is necessary to have a
5287c478bd9Sstevel@tonic-gate  * way to do a "priority queueing" which inserts at the head of the queue for
5297c478bd9Sstevel@tonic-gate  * immediate processing
5307c478bd9Sstevel@tonic-gate  */
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate /*
5337c478bd9Sstevel@tonic-gate  * queue:
5347c478bd9Sstevel@tonic-gate  *
5357c478bd9Sstevel@tonic-gate  * add calls to tail of queue
5367c478bd9Sstevel@tonic-gate  */
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate void
5407c478bd9Sstevel@tonic-gate queue(head, cp)
541113f4232Sakaplan struct call_list *head;
542113f4232Sakaplan struct callsave *cp;
5437c478bd9Sstevel@tonic-gate {
5447c478bd9Sstevel@tonic-gate 	DEBUG((9,"in queue"));
5457c478bd9Sstevel@tonic-gate 	if (head->cl_tail == (struct callsave *) NULL) {
5467c478bd9Sstevel@tonic-gate 		cp->c_np = (struct callsave *) NULL;
5477c478bd9Sstevel@tonic-gate 		head->cl_head = head->cl_tail = cp;
5487c478bd9Sstevel@tonic-gate 	}
5497c478bd9Sstevel@tonic-gate 	else {
5507c478bd9Sstevel@tonic-gate 		cp->c_np = head->cl_tail->c_np;
5517c478bd9Sstevel@tonic-gate 		head->cl_tail->c_np = cp;
5527c478bd9Sstevel@tonic-gate 		head->cl_tail = cp;
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate /*
5587c478bd9Sstevel@tonic-gate  * pqueue:
5597c478bd9Sstevel@tonic-gate  *
5607c478bd9Sstevel@tonic-gate  * priority queuer, add calls to head of queue
5617c478bd9Sstevel@tonic-gate  */
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate void
5647c478bd9Sstevel@tonic-gate pqueue(head, cp)
565113f4232Sakaplan struct call_list *head;
566113f4232Sakaplan struct callsave *cp;
5677c478bd9Sstevel@tonic-gate {
5687c478bd9Sstevel@tonic-gate 	if (head->cl_head == (struct callsave *) NULL) {
5697c478bd9Sstevel@tonic-gate 		cp->c_np = (struct callsave *) NULL;
5707c478bd9Sstevel@tonic-gate 		head->cl_head = head->cl_tail = cp;
5717c478bd9Sstevel@tonic-gate 	}
5727c478bd9Sstevel@tonic-gate 	else {
5737c478bd9Sstevel@tonic-gate 		cp->c_np = head->cl_head;
5747c478bd9Sstevel@tonic-gate 		head->cl_head = cp;
5757c478bd9Sstevel@tonic-gate 	}
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate /*
5807c478bd9Sstevel@tonic-gate  * dequeue:
5817c478bd9Sstevel@tonic-gate  *
5827c478bd9Sstevel@tonic-gate  * remove a call from the head of queue
5837c478bd9Sstevel@tonic-gate  */
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate struct callsave *
5877c478bd9Sstevel@tonic-gate dequeue(head)
588113f4232Sakaplan struct call_list *head;
5897c478bd9Sstevel@tonic-gate {
590113f4232Sakaplan 	struct callsave *ret;
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	DEBUG((9,"in dequeue"));
5937c478bd9Sstevel@tonic-gate 	if (head->cl_head == (struct callsave *) NULL)  {
5947c478bd9Sstevel@tonic-gate #ifdef OLD
5957c478bd9Sstevel@tonic-gate 		DEBUG((9,"cl_head = null"));
5967c478bd9Sstevel@tonic-gate 		error(E_CANT_HAPPEN, EXIT);
5977c478bd9Sstevel@tonic-gate #endif
5987c478bd9Sstevel@tonic-gate 		DEBUG((9, "NULL return"));
5997c478bd9Sstevel@tonic-gate 		return((struct callsave *) NULL);
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate 	ret = head->cl_head;
6027c478bd9Sstevel@tonic-gate 	head->cl_head = ret->c_np;
6037c478bd9Sstevel@tonic-gate 	if (head->cl_head == (struct callsave *) NULL)
6047c478bd9Sstevel@tonic-gate 		head->cl_tail = (struct callsave *) NULL;
6057c478bd9Sstevel@tonic-gate 	return(ret);
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate /*
6107c478bd9Sstevel@tonic-gate  * open_bind:
6117c478bd9Sstevel@tonic-gate  *
6127c478bd9Sstevel@tonic-gate  * open the network and bind the endpoint to 'name'
6137c478bd9Sstevel@tonic-gate  * this routine is also used by listen(), so it can't exit
6147c478bd9Sstevel@tonic-gate  * under all error conditions:
6157c478bd9Sstevel@tonic-gate  *	if there are no minor devices avaliable in the network driver,
6167c478bd9Sstevel@tonic-gate  * 		open_bind returns -1.  (error message will be logged).
6177c478bd9Sstevel@tonic-gate  *	if the open fails because all file descriptors are in use,
6187c478bd9Sstevel@tonic-gate  *		open_bind returns -2.  (no message logged).  This should
6197c478bd9Sstevel@tonic-gate  *		only happen when too many private addresses are specified.
6207c478bd9Sstevel@tonic-gate  *	if the bind fails, open_bind returns -3  (no message logged).  This
6217c478bd9Sstevel@tonic-gate  *		happens when a duplicate address is bound, and the message
6227c478bd9Sstevel@tonic-gate  *		should be logged by the routine that calls open_bind.
6237c478bd9Sstevel@tonic-gate  * All other errors cause an exit.
6247c478bd9Sstevel@tonic-gate  *
6257c478bd9Sstevel@tonic-gate  * If clen is zero, transport provider picks the name and these
6267c478bd9Sstevel@tonic-gate  * routines (open_bind and bind) ignore name and qlen --
6277c478bd9Sstevel@tonic-gate  * this option is used when binding a name for accepting a connection
6287c478bd9Sstevel@tonic-gate  * (not for listening.)  You MUST supply a name, qlen and clen when
6297c478bd9Sstevel@tonic-gate  * opening/binding a name for listening.
6307c478bd9Sstevel@tonic-gate  *
6317c478bd9Sstevel@tonic-gate  * Assumptions: driver returns ENXIO when all devices are allocated.
6327c478bd9Sstevel@tonic-gate  */
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate int
6357c478bd9Sstevel@tonic-gate open_bind(name, qlen, clen, conp, adrp)
6367c478bd9Sstevel@tonic-gate char *name;
6377c478bd9Sstevel@tonic-gate int qlen;
6387c478bd9Sstevel@tonic-gate int clen;
6397c478bd9Sstevel@tonic-gate unsigned int *conp;
6407c478bd9Sstevel@tonic-gate char **adrp;
6417c478bd9Sstevel@tonic-gate {
642113f4232Sakaplan 	int fd;
6437c478bd9Sstevel@tonic-gate 	int ret;
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	DEBUG((9,"in open_bind, qlen=%d clen=%d conp=%d",qlen,clen,conp));
6467c478bd9Sstevel@tonic-gate 	while ((fd = t_open(Provider, NETOFLAG, NULL)) < 0) {
6477c478bd9Sstevel@tonic-gate 		if (t_errno == TSYSERR) {
6487c478bd9Sstevel@tonic-gate 			switch (errno) {
6497c478bd9Sstevel@tonic-gate 			case EINTR:
6507c478bd9Sstevel@tonic-gate 				continue;
6517c478bd9Sstevel@tonic-gate 			case EMFILE:
6527c478bd9Sstevel@tonic-gate 				return(-2);
6537c478bd9Sstevel@tonic-gate 				break;
6547c478bd9Sstevel@tonic-gate 			case ENXIO:
6557c478bd9Sstevel@tonic-gate 			case ENOSR:
6567c478bd9Sstevel@tonic-gate 			case ENOSPC:
6577c478bd9Sstevel@tonic-gate 			case EAGAIN:
6587c478bd9Sstevel@tonic-gate 				tli_error(E_FD1OPEN, CONTINUE);
6597c478bd9Sstevel@tonic-gate 				logmessage("No network minor devices (ENXIO/ENOSR)");
6607c478bd9Sstevel@tonic-gate 				return(-1);
6617c478bd9Sstevel@tonic-gate 				break;
6627c478bd9Sstevel@tonic-gate 			}
6637c478bd9Sstevel@tonic-gate 			DEBUG((9,"problem in t_open"));
6647c478bd9Sstevel@tonic-gate 			tli_error(E_FD1OPEN, EXIT);
6657c478bd9Sstevel@tonic-gate 		}
6667c478bd9Sstevel@tonic-gate 	}
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	ret = bind(fd, name, qlen, clen, adrp);
6697c478bd9Sstevel@tonic-gate 	DEBUG((9, "bind returns %d", ret));
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	if (ret < 0) {
6727c478bd9Sstevel@tonic-gate 		t_close(fd);
6737c478bd9Sstevel@tonic-gate 		return(-3);
6747c478bd9Sstevel@tonic-gate 	}
6757c478bd9Sstevel@tonic-gate 	if (conp)
6767c478bd9Sstevel@tonic-gate 		*conp = ret;
6777c478bd9Sstevel@tonic-gate 	return(fd);
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate int
6827c478bd9Sstevel@tonic-gate bind(fd, name, qlen, clen, ap)
683113f4232Sakaplan int fd;
6847c478bd9Sstevel@tonic-gate char *name;
6857c478bd9Sstevel@tonic-gate int qlen;
686113f4232Sakaplan int clen;
6877c478bd9Sstevel@tonic-gate char **ap;
6887c478bd9Sstevel@tonic-gate {
689113f4232Sakaplan 	struct t_bind *req = (struct t_bind *)0;
690113f4232Sakaplan 	struct t_bind *ret = (struct t_bind *)0;
691113f4232Sakaplan 	char	*p, *q;
6927c478bd9Sstevel@tonic-gate 	unsigned int	retval;
6937c478bd9Sstevel@tonic-gate 	extern void	nlsaddr2c();
6947c478bd9Sstevel@tonic-gate 	extern int	memcmp();
6957c478bd9Sstevel@tonic-gate 	extern int	errno;
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate #ifdef	CHARADDR
6987c478bd9Sstevel@tonic-gate 	char pbuf[NAMEBUFSZ + 1];
6997c478bd9Sstevel@tonic-gate #endif
7007c478bd9Sstevel@tonic-gate 	char scratch[BUFSIZ];
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	DEBUG((9,"in bind, fd = %d, clen = %d", fd, clen));
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	if (clen)  {
7057c478bd9Sstevel@tonic-gate 		errno = t_errno = 0;
7067c478bd9Sstevel@tonic-gate 		while (!(req = (struct t_bind *)t_alloc(fd,T_BIND,T_ALL)) ) {
7077c478bd9Sstevel@tonic-gate 			if ((t_errno != TSYSERR) || (errno != EAGAIN))
7087c478bd9Sstevel@tonic-gate 				tli_error( E_T_ALLOC, EXIT);
7097c478bd9Sstevel@tonic-gate 			else
7107c478bd9Sstevel@tonic-gate 				tli_error( E_T_ALLOC, CONTINUE);
7117c478bd9Sstevel@tonic-gate 		}
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 		errno = t_errno = 0;
7147c478bd9Sstevel@tonic-gate 		while (!(ret = (struct t_bind *)t_alloc(fd,T_BIND,T_ALL)) ) {
7157c478bd9Sstevel@tonic-gate 			if ((t_errno != TSYSERR) || (errno != EAGAIN))
7167c478bd9Sstevel@tonic-gate 				tli_error( E_T_ALLOC, EXIT);
7177c478bd9Sstevel@tonic-gate 			else
7187c478bd9Sstevel@tonic-gate 				tli_error( E_T_ALLOC, CONTINUE);
7197c478bd9Sstevel@tonic-gate 		}
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 		if (clen > (int) req->addr.maxlen)  {
7227c478bd9Sstevel@tonic-gate 			sprintf(scratch,"Truncating name size from %d to %d",
7237c478bd9Sstevel@tonic-gate 				clen, req->addr.maxlen);
7247c478bd9Sstevel@tonic-gate 			logmessage(scratch);
7257c478bd9Sstevel@tonic-gate 			clen = req->addr.maxlen;
7267c478bd9Sstevel@tonic-gate 		}
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 		if (clen == -1) {
7297c478bd9Sstevel@tonic-gate 			req->addr.len = 0;
7307c478bd9Sstevel@tonic-gate 		}
7317c478bd9Sstevel@tonic-gate 		else {
7327c478bd9Sstevel@tonic-gate 			(void)memcpy(req->addr.buf, name, clen);
7337c478bd9Sstevel@tonic-gate 			req->addr.len = clen;
7347c478bd9Sstevel@tonic-gate 		}
7357c478bd9Sstevel@tonic-gate 		req->qlen = qlen;
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate #if defined(CHARADDR) && defined(DEBUGMODE)
7387c478bd9Sstevel@tonic-gate 		(void)memcpy(pbuf, req->addr.buf, req->addr.len);
7397c478bd9Sstevel@tonic-gate 		pbuf[req->addr.len] = (char)0;
7407c478bd9Sstevel@tonic-gate 		DEBUG((3,"bind: fd=%d, logical name=%c%s%c, len=%d",
7417c478bd9Sstevel@tonic-gate 			fd, '\"',pbuf, '\"', req->addr.len));
7427c478bd9Sstevel@tonic-gate #endif	/* CHARADDR  && DEBUGMODE */
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate #if defined(CHARADDR) && defined(DEBUGMODE)
7467c478bd9Sstevel@tonic-gate 		(void)memcpy(pbuf, req->addr.buf, req->addr.len);
7477c478bd9Sstevel@tonic-gate 		pbuf[req->addr.len] = (char)0;
7487c478bd9Sstevel@tonic-gate 		DEBUG((3,"bind: fd=%d, address=%c%s%c, len=%d",
7497c478bd9Sstevel@tonic-gate 			fd, '\"',pbuf, '\"', req->addr.len));
7507c478bd9Sstevel@tonic-gate #endif	/* CHARADDR  && DEBUGMODE */
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 	}
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate 	if (t_bind(fd, req, ret))  {
7567c478bd9Sstevel@tonic-gate 		DEBUG((1,"t_bind failed; t_errno %d errno %d", t_errno, errno));
7577c478bd9Sstevel@tonic-gate 		if (qlen)	/* starup only */
7587c478bd9Sstevel@tonic-gate 			tli_error(E_T_BIND, EXIT | NOCORE);
7597c478bd9Sstevel@tonic-gate 		/* here during normal service */
7607c478bd9Sstevel@tonic-gate 		if ((t_errno == TNOADDR) || ((t_errno == TSYSERR) && (errno == EAGAIN))) {
7617c478bd9Sstevel@tonic-gate 			/* our name space is all used up */
7627c478bd9Sstevel@tonic-gate 			tli_error(E_T_BIND, CONTINUE);
7637c478bd9Sstevel@tonic-gate 			t_close(fd);
7647c478bd9Sstevel@tonic-gate 			if (clen)  {
7657c478bd9Sstevel@tonic-gate 				if ( t_free((char *)req, T_BIND) )
7667c478bd9Sstevel@tonic-gate 					tli_error(E_T_FREE, EXIT);
7677c478bd9Sstevel@tonic-gate 				if ( t_free((char *)ret, T_BIND) )
7687c478bd9Sstevel@tonic-gate 					tli_error(E_T_FREE, EXIT);
7697c478bd9Sstevel@tonic-gate 			}
7707c478bd9Sstevel@tonic-gate 			return(-1);
7717c478bd9Sstevel@tonic-gate 		}
7727c478bd9Sstevel@tonic-gate 		/* otherwise, irrecoverable error */
7737c478bd9Sstevel@tonic-gate 		tli_error(E_T_BIND, EXIT | NOCORE);
7747c478bd9Sstevel@tonic-gate 	}
7757c478bd9Sstevel@tonic-gate 	DEBUG((9, "t_bind succeeded"));
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	if (clen)  {
7787c478bd9Sstevel@tonic-gate 		retval = ret->qlen;
7797c478bd9Sstevel@tonic-gate 		if (clen == -1) {
7807c478bd9Sstevel@tonic-gate 			/* dynamic address */
7817c478bd9Sstevel@tonic-gate 			*ap = (char *) malloc(((ret->addr.len) << 1) + 3);
7827c478bd9Sstevel@tonic-gate 			if (*ap) {
7837c478bd9Sstevel@tonic-gate 				(*ap)[0] = '\\';
7847c478bd9Sstevel@tonic-gate 				(*ap)[1] = 'x';
7857c478bd9Sstevel@tonic-gate 				nlsaddr2c(*ap+2,ret->addr.buf,(int)ret->addr.len);
7867c478bd9Sstevel@tonic-gate 			}
7877c478bd9Sstevel@tonic-gate 		}
7887c478bd9Sstevel@tonic-gate 		else if ( (ret->addr.len != req->addr.len) ||
7897c478bd9Sstevel@tonic-gate 		     (memcmp( req->addr.buf, ret->addr.buf, (int) req->addr.len)) )  {
7907c478bd9Sstevel@tonic-gate 			p = (char *) malloc(((ret->addr.len) << 1) + 1);
7917c478bd9Sstevel@tonic-gate 			q = (char *) malloc(((req->addr.len) << 1) + 1);
7927c478bd9Sstevel@tonic-gate 			if (p && q) {
7937c478bd9Sstevel@tonic-gate 				nlsaddr2c(p, ret->addr.buf, (int)ret->addr.len);
7947c478bd9Sstevel@tonic-gate 				nlsaddr2c(q, req->addr.buf, (int)req->addr.len);
7957c478bd9Sstevel@tonic-gate 				sprintf(scratch, "Requested address \\x%s", q);
7967c478bd9Sstevel@tonic-gate 				logmessage(scratch);
7977c478bd9Sstevel@tonic-gate 				sprintf(scratch, "Actual address    \\x%s", p);
7987c478bd9Sstevel@tonic-gate 				logmessage(scratch);
7997c478bd9Sstevel@tonic-gate 				free(p);
8007c478bd9Sstevel@tonic-gate 				free(q);
8017c478bd9Sstevel@tonic-gate 			}
8027c478bd9Sstevel@tonic-gate 			DEBUG((9, "failed to bind requested address"));
8037c478bd9Sstevel@tonic-gate 			t_unbind(fd);
8047c478bd9Sstevel@tonic-gate 			t_close(fd);
8057c478bd9Sstevel@tonic-gate 			if ( t_free((char *)req, T_BIND) )
8067c478bd9Sstevel@tonic-gate 				tli_error(E_T_FREE, EXIT);
8077c478bd9Sstevel@tonic-gate 			if ( t_free((char *)ret, T_BIND) )
8087c478bd9Sstevel@tonic-gate 				tli_error(E_T_FREE, EXIT);
8097c478bd9Sstevel@tonic-gate 			return(-1);
8107c478bd9Sstevel@tonic-gate 		}
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 		if ( t_free((char *)req, T_BIND) )
8137c478bd9Sstevel@tonic-gate 			tli_error(E_T_FREE, EXIT);
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 		if ( t_free((char *)ret, T_BIND) )
8167c478bd9Sstevel@tonic-gate 			tli_error(E_T_FREE, EXIT);
8177c478bd9Sstevel@tonic-gate 		return(retval);
8187c478bd9Sstevel@tonic-gate 	}
8197c478bd9Sstevel@tonic-gate 	return((unsigned int) 0);
8207c478bd9Sstevel@tonic-gate }
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate /*
8247c478bd9Sstevel@tonic-gate  * catch_signals:
8257c478bd9Sstevel@tonic-gate  *		Ignore some, catch the rest. Use SIGTERM to kill me.
8267c478bd9Sstevel@tonic-gate  */
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate sigset_t Oset;
8297c478bd9Sstevel@tonic-gate struct sigaction Sigterm;
8307c478bd9Sstevel@tonic-gate struct sigaction Sigcld;
8317c478bd9Sstevel@tonic-gate 
832113f4232Sakaplan static void
833113f4232Sakaplan catch_signals(void)
8347c478bd9Sstevel@tonic-gate {
8357c478bd9Sstevel@tonic-gate 	sigset_t sset;
8367c478bd9Sstevel@tonic-gate 	sigset_t eset;
8377c478bd9Sstevel@tonic-gate 	struct sigaction sigact;
8387c478bd9Sstevel@tonic-gate 	extern void sigterm();
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 	(void) sigfillset(&sset);
8417c478bd9Sstevel@tonic-gate 	(void) sigdelset(&sset, SIGTERM);
8427c478bd9Sstevel@tonic-gate 	(void) sigdelset(&sset, SIGCLD);
8437c478bd9Sstevel@tonic-gate 	(void) sigprocmask(SIG_SETMASK, &sset, &Oset);
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	sigact.sa_flags = 0;
8467c478bd9Sstevel@tonic-gate 	sigact.sa_handler = sigterm;
8477c478bd9Sstevel@tonic-gate 	sigact.sa_mask = sset;
8487c478bd9Sstevel@tonic-gate 	sigaction(SIGTERM, &sigact, &Sigterm);
8497c478bd9Sstevel@tonic-gate 	sigact.sa_flags = SA_NOCLDWAIT;
8507c478bd9Sstevel@tonic-gate 	sigact.sa_handler = SIG_IGN;
8517c478bd9Sstevel@tonic-gate 	sigact.sa_mask = sset;
8527c478bd9Sstevel@tonic-gate 	sigaction(SIGCLD, &sigact, &Sigcld);
8537c478bd9Sstevel@tonic-gate }
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate /*
8577c478bd9Sstevel@tonic-gate  * rst_signals:
8587c478bd9Sstevel@tonic-gate  *		After forking but before exec'ing a server,
8597c478bd9Sstevel@tonic-gate  *		reset all signals to original setting.
8607c478bd9Sstevel@tonic-gate  */
8617c478bd9Sstevel@tonic-gate 
862113f4232Sakaplan static void
863113f4232Sakaplan rst_signals(void)
8647c478bd9Sstevel@tonic-gate {
8657c478bd9Sstevel@tonic-gate 	struct sigaction sigact;
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	sigaction(SIGTERM, &Sigterm, NULL);
8687c478bd9Sstevel@tonic-gate 	sigaction(SIGCLD, &Sigcld, NULL);
8697c478bd9Sstevel@tonic-gate 	sigprocmask(SIG_SETMASK, &Oset, NULL);
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate /*
8747c478bd9Sstevel@tonic-gate  * sigterm:	Clean up and exit.
8757c478bd9Sstevel@tonic-gate  */
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate void
8787c478bd9Sstevel@tonic-gate sigterm()
8797c478bd9Sstevel@tonic-gate {
8807c478bd9Sstevel@tonic-gate 	extern char *shaddr;
8817c478bd9Sstevel@tonic-gate 	extern char *sh2addr;
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	error(E_SIGTERM, EXIT | NORMAL | NOCORE);	/* calls cleanup */
8847c478bd9Sstevel@tonic-gate }
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate /*
8887c478bd9Sstevel@tonic-gate  * listen:	listen for and process connection requests.
8897c478bd9Sstevel@tonic-gate  */
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate static char *dbfnewdmsg = "Using new data base file";
8927c478bd9Sstevel@tonic-gate 
893113f4232Sakaplan static void
894113f4232Sakaplan listen(void)
8957c478bd9Sstevel@tonic-gate {
896113f4232Sakaplan 	int	i;
897113f4232Sakaplan 	dbf_t	*dbp	= Dbfhead;
898113f4232Sakaplan 	struct	pollfd	*sp;
8997c478bd9Sstevel@tonic-gate 	struct		call_list *phead; /* pending head */
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	DEBUG((9,"in listen, tag %s", Pmmsg.pm_tag));
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 	if ((Pollfds = (struct pollfd *) malloc(Ndesc * sizeof(struct pollfd)))
9047c478bd9Sstevel@tonic-gate 			== NULL)
9057c478bd9Sstevel@tonic-gate 		error(E_MALLOC,NOCORE | EXIT);
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	/* setup poll structures for sac messages and private addresses */
9087c478bd9Sstevel@tonic-gate 	sp = Pollfds;
9097c478bd9Sstevel@tonic-gate 	sp->fd = Pmpipefd;
9107c478bd9Sstevel@tonic-gate 	sp->events = POLLIN;
9117c478bd9Sstevel@tonic-gate 	sp->revents = 0;
9127c478bd9Sstevel@tonic-gate 	sp++;
9137c478bd9Sstevel@tonic-gate 	for (dbp = Dbfhead; dbp && dbp->dbf_svc_code; dbp++) {
9147c478bd9Sstevel@tonic-gate 		if (dbp->dbf_fd >= 0) {
9157c478bd9Sstevel@tonic-gate 			sp->fd = dbp->dbf_fd;
9167c478bd9Sstevel@tonic-gate 			DEBUG((9, "adding %d to poll struct", dbp->dbf_fd));
9177c478bd9Sstevel@tonic-gate 			sp->events = POLLIN;
9187c478bd9Sstevel@tonic-gate 			sp->revents = 0;
9197c478bd9Sstevel@tonic-gate 			sp++;
9207c478bd9Sstevel@tonic-gate 		}
9217c478bd9Sstevel@tonic-gate 	}
9227c478bd9Sstevel@tonic-gate 	errno = t_errno = 0;
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 	for (;;) {
9257c478bd9Sstevel@tonic-gate 		DEBUG((9,"listen(): TOP of loop"));
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 		/* +1 for Pmpipefd */
9287c478bd9Sstevel@tonic-gate 		if (poll(Pollfds, Valid_addrs + 1, -1) < 0) {
9297c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
9307c478bd9Sstevel@tonic-gate 				continue;
9317c478bd9Sstevel@tonic-gate 			/* poll error */
9327c478bd9Sstevel@tonic-gate 			sys_error(E_POLL, EXIT);
9337c478bd9Sstevel@tonic-gate 		}
9347c478bd9Sstevel@tonic-gate 		else {
9357c478bd9Sstevel@tonic-gate 			/* incoming request or message */
9367c478bd9Sstevel@tonic-gate 			for (i = 0, sp = Pollfds; i < Valid_addrs + 1; i++, sp++) {
9377c478bd9Sstevel@tonic-gate 				switch (sp->revents) {
9387c478bd9Sstevel@tonic-gate 				case POLLIN:
9397c478bd9Sstevel@tonic-gate 					if (sp->fd == Pmpipefd) {
9407c478bd9Sstevel@tonic-gate 						DEBUG((9,"sac message received"));
9417c478bd9Sstevel@tonic-gate 						check_sac_mesg();
9427c478bd9Sstevel@tonic-gate 					}
9437c478bd9Sstevel@tonic-gate 					else {
9447c478bd9Sstevel@tonic-gate 						DEBUG((9,"Connection requested "));
9457c478bd9Sstevel@tonic-gate 						phead = ((sp->fd) + Priv_call);
9467c478bd9Sstevel@tonic-gate 						doevent(phead, (sp->fd));
9477c478bd9Sstevel@tonic-gate 						if (State == PM_ENABLED)
9487c478bd9Sstevel@tonic-gate 							trycon(phead, (sp->fd));
9497c478bd9Sstevel@tonic-gate 						else
9507c478bd9Sstevel@tonic-gate 							send_dis(phead, (sp->fd));
9517c478bd9Sstevel@tonic-gate 					}
9527c478bd9Sstevel@tonic-gate 					break;
9537c478bd9Sstevel@tonic-gate 				case 0:
9547c478bd9Sstevel@tonic-gate 					break;
9557c478bd9Sstevel@tonic-gate 				/* distinguish the various errors for the user */
9567c478bd9Sstevel@tonic-gate 				case POLLERR:
9577c478bd9Sstevel@tonic-gate 					logmessage("poll() returned POLLERR");
9587c478bd9Sstevel@tonic-gate 					error(E_SYS_ERROR, EXIT | NO_MSG);
959*25b601caSToomas Soome 					break;
9607c478bd9Sstevel@tonic-gate 				case POLLHUP:
9617c478bd9Sstevel@tonic-gate 					logmessage("poll() returned POLLHUP");
9627c478bd9Sstevel@tonic-gate 					error(E_SYS_ERROR, EXIT | NO_MSG);
963*25b601caSToomas Soome 					break;
9647c478bd9Sstevel@tonic-gate 				case POLLNVAL:
9657c478bd9Sstevel@tonic-gate 					logmessage("poll() returned POLLNVAL");
9667c478bd9Sstevel@tonic-gate 					error(E_SYS_ERROR, EXIT | NO_MSG);
967*25b601caSToomas Soome 					break;
9687c478bd9Sstevel@tonic-gate 				case POLLPRI:
9697c478bd9Sstevel@tonic-gate 					logmessage("poll() returned POLLPRI");
9707c478bd9Sstevel@tonic-gate 					error(E_SYS_ERROR, EXIT | NO_MSG);
971*25b601caSToomas Soome 					break;
9727c478bd9Sstevel@tonic-gate 				case POLLOUT:
9737c478bd9Sstevel@tonic-gate 					logmessage("poll() returned POLLOUT");
9747c478bd9Sstevel@tonic-gate 					error(E_SYS_ERROR, EXIT | NO_MSG);
975*25b601caSToomas Soome 					break;
9767c478bd9Sstevel@tonic-gate 				default:
9777c478bd9Sstevel@tonic-gate 					logmessage("poll() returned unrecognized event");
9787c478bd9Sstevel@tonic-gate 					error(E_SYS_ERROR, EXIT | NO_MSG);
9797c478bd9Sstevel@tonic-gate 				}
9807c478bd9Sstevel@tonic-gate 				sp->revents = 0;
9817c478bd9Sstevel@tonic-gate 			}
9827c478bd9Sstevel@tonic-gate 		}
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 		if (Readdb) {
9857c478bd9Sstevel@tonic-gate 			DEBUG((9,"dbf file has been modified"));
9867c478bd9Sstevel@tonic-gate 			logmessage("Re-reading database");
9877c478bd9Sstevel@tonic-gate 			/* have to close an fd because read_dbf needs it */
9887c478bd9Sstevel@tonic-gate 			close(Acceptfd);
9897c478bd9Sstevel@tonic-gate 			if (!read_dbf(DB_REREAD)) {
9907c478bd9Sstevel@tonic-gate 				/* MUST re-open Acceptfd to insure it is free later */
9917c478bd9Sstevel@tonic-gate 				dup(Passfd);
9927c478bd9Sstevel@tonic-gate 				mod_prvaddr();
9937c478bd9Sstevel@tonic-gate 			}
9947c478bd9Sstevel@tonic-gate 			else {
9957c478bd9Sstevel@tonic-gate 				dup(Passfd);
9967c478bd9Sstevel@tonic-gate 				logmessage(dbfnewdmsg);
9977c478bd9Sstevel@tonic-gate 			}
9987c478bd9Sstevel@tonic-gate 			Readdb = FALSE;
9997c478bd9Sstevel@tonic-gate 		}
10007c478bd9Sstevel@tonic-gate 	}
10017c478bd9Sstevel@tonic-gate }
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate /*
10057c478bd9Sstevel@tonic-gate  * check_sac_mesg:	check the pipe to see if SAC has sent a message
10067c478bd9Sstevel@tonic-gate  */
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate void
10097c478bd9Sstevel@tonic-gate check_sac_mesg()
10107c478bd9Sstevel@tonic-gate {
10117c478bd9Sstevel@tonic-gate 	int	length;
10127c478bd9Sstevel@tonic-gate 	struct	sacmsg sacmsg;
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	DEBUG((9, "in check_sac_mesg..."));
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	/* read all messages out of pipe */
10177c478bd9Sstevel@tonic-gate 	while ((length = read(Pmpipefd, &sacmsg, sizeof(sacmsg))) != 0) {
10187c478bd9Sstevel@tonic-gate 		if (length < 0) {
10197c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
10207c478bd9Sstevel@tonic-gate 				continue;
10217c478bd9Sstevel@tonic-gate 			DEBUG((9, "read of _pmpipe failed"));
10227c478bd9Sstevel@tonic-gate 			return;
10237c478bd9Sstevel@tonic-gate 		}
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 		switch (sacmsg.sc_type) {
10267c478bd9Sstevel@tonic-gate 		case SC_STATUS:
10277c478bd9Sstevel@tonic-gate 			DEBUG((9, "Got SC_STATUS message"));
10287c478bd9Sstevel@tonic-gate 			Pmmsg.pm_type = PM_STATUS;
10297c478bd9Sstevel@tonic-gate 			Pmmsg.pm_state = State;
10307c478bd9Sstevel@tonic-gate 			break;
10317c478bd9Sstevel@tonic-gate 		case SC_ENABLE:
10327c478bd9Sstevel@tonic-gate 			DEBUG((9, "Got SC_ENABLE message"));
10337c478bd9Sstevel@tonic-gate 			if (State != PM_ENABLED)
10347c478bd9Sstevel@tonic-gate 				logmessage("New state: ENABLED");
10357c478bd9Sstevel@tonic-gate 			Pmmsg.pm_type = PM_STATUS;
10367c478bd9Sstevel@tonic-gate 			State = PM_ENABLED;
10377c478bd9Sstevel@tonic-gate 			Pmmsg.pm_state = PM_ENABLED;
10387c478bd9Sstevel@tonic-gate 			break;
10397c478bd9Sstevel@tonic-gate 		case SC_DISABLE:
10407c478bd9Sstevel@tonic-gate 			DEBUG((9, "Got SC_DISABLE message"));
10417c478bd9Sstevel@tonic-gate 			if (State != PM_DISABLED)
10427c478bd9Sstevel@tonic-gate 				logmessage("New state: DISABLED");
10437c478bd9Sstevel@tonic-gate 			Pmmsg.pm_type = PM_STATUS;
10447c478bd9Sstevel@tonic-gate 			State = PM_DISABLED;
10457c478bd9Sstevel@tonic-gate 			Pmmsg.pm_state = PM_DISABLED;
10467c478bd9Sstevel@tonic-gate 			break;
10477c478bd9Sstevel@tonic-gate 		case SC_READDB:
10487c478bd9Sstevel@tonic-gate 			DEBUG((9, "Got SC_READDB message"));
10497c478bd9Sstevel@tonic-gate 			Readdb = TRUE;
10507c478bd9Sstevel@tonic-gate 			Pmmsg.pm_type = PM_STATUS;
10517c478bd9Sstevel@tonic-gate 			Pmmsg.pm_state = State;
10527c478bd9Sstevel@tonic-gate 			break;
10537c478bd9Sstevel@tonic-gate 		default:
10547c478bd9Sstevel@tonic-gate 			DEBUG((9, "Got UNKNOWN message"));
10557c478bd9Sstevel@tonic-gate 			Pmmsg.pm_type = PM_UNKNOWN;
10567c478bd9Sstevel@tonic-gate 			Pmmsg.pm_state = State;
10577c478bd9Sstevel@tonic-gate 			logmessage("Received unknown message from sac -- ignored");
10587c478bd9Sstevel@tonic-gate 			break;
10597c478bd9Sstevel@tonic-gate 		}
10607c478bd9Sstevel@tonic-gate 		DEBUG((9, "Responding with state %d", Pmmsg.pm_state));
10617c478bd9Sstevel@tonic-gate 		while (write(Sacpipefd, &Pmmsg, sizeof(Pmmsg)) != sizeof(Pmmsg)) {
10627c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
10637c478bd9Sstevel@tonic-gate 				continue;
10647c478bd9Sstevel@tonic-gate 			DEBUG((9, "sanity response failed"));
10657c478bd9Sstevel@tonic-gate 			break;
10667c478bd9Sstevel@tonic-gate 		}
10677c478bd9Sstevel@tonic-gate 	}
10687c478bd9Sstevel@tonic-gate }
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate /*
10727c478bd9Sstevel@tonic-gate  * doevent:	handle an asynchronous event
10737c478bd9Sstevel@tonic-gate  */
10747c478bd9Sstevel@tonic-gate 
1075113f4232Sakaplan static void
1076113f4232Sakaplan doevent(struct call_list *phead, int fd)
10777c478bd9Sstevel@tonic-gate {
10787c478bd9Sstevel@tonic-gate 	static struct t_discon *disc;
1079113f4232Sakaplan 	struct callsave *current;
1080113f4232Sakaplan 	struct t_call *call;
10817c478bd9Sstevel@tonic-gate 	char scratch[BUFSIZ];
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	DEBUG((9, "in doevent"));
10847c478bd9Sstevel@tonic-gate 	switch (t_look(fd)) {
10857c478bd9Sstevel@tonic-gate 	case 0:
10867c478bd9Sstevel@tonic-gate 		sys_error(E_POLL, EXIT);
10877c478bd9Sstevel@tonic-gate 		/* no return */
1088*25b601caSToomas Soome 		break;
10897c478bd9Sstevel@tonic-gate 	case T_LISTEN:
10907c478bd9Sstevel@tonic-gate 	DEBUG((9, "case t_listen "));
10917c478bd9Sstevel@tonic-gate 		current = dequeue(Free_call_p);
10927c478bd9Sstevel@tonic-gate 		call = current->c_cp;
10937c478bd9Sstevel@tonic-gate 		if (t_listen(fd, call) < 0) {
10947c478bd9Sstevel@tonic-gate 			tli_error(E_T_LISTEN, CONTINUE);
10957c478bd9Sstevel@tonic-gate 			clr_call(call);
10967c478bd9Sstevel@tonic-gate 			queue(Free_call_p, current);
10977c478bd9Sstevel@tonic-gate 			return;
10987c478bd9Sstevel@tonic-gate 		}
10997c478bd9Sstevel@tonic-gate 		queue(phead, current);
11007c478bd9Sstevel@tonic-gate 		DEBUG((9, "incoming call seq # %d", call->sequence));
11017c478bd9Sstevel@tonic-gate 		break;
11027c478bd9Sstevel@tonic-gate 	case T_DISCONNECT:
11037c478bd9Sstevel@tonic-gate 	DEBUG((9, "case t_disconnect"));
11047c478bd9Sstevel@tonic-gate 		if (disc == NULL) {
11057c478bd9Sstevel@tonic-gate 			while (!(disc = (struct t_discon *)t_alloc(fd, T_DIS, T_ALL)) ) {
11067c478bd9Sstevel@tonic-gate 		   		if (t_errno == TBADF)
11077c478bd9Sstevel@tonic-gate 					DEBUG((9,"listen - fd not transport end point"));
11087c478bd9Sstevel@tonic-gate 				if ((t_errno != TSYSERR) || (errno != EAGAIN))
11097c478bd9Sstevel@tonic-gate 					tli_error(E_T_ALLOC, EXIT);
11107c478bd9Sstevel@tonic-gate 				else
11117c478bd9Sstevel@tonic-gate 					tli_error(E_T_ALLOC, CONTINUE);
11127c478bd9Sstevel@tonic-gate 			}
11137c478bd9Sstevel@tonic-gate 		}
11147c478bd9Sstevel@tonic-gate 		if (t_rcvdis(fd, disc) < 0) {
11157c478bd9Sstevel@tonic-gate 			tli_error(E_T_RCVDIS, EXIT);
11167c478bd9Sstevel@tonic-gate 			/* no return */
11177c478bd9Sstevel@tonic-gate 		}
11187c478bd9Sstevel@tonic-gate 		sprintf(scratch, "Disconnect on fd %d, seq # %d", fd, disc->sequence);
11197c478bd9Sstevel@tonic-gate 		logmessage(scratch);
11207c478bd9Sstevel@tonic-gate 		DEBUG((9, "incoming disconnect seq # %d", disc->sequence));
11217c478bd9Sstevel@tonic-gate 		pitchcall(phead, disc);
11227c478bd9Sstevel@tonic-gate 		break;
11237c478bd9Sstevel@tonic-gate 	default:
11247c478bd9Sstevel@tonic-gate 	DEBUG((9, "case default"));
11257c478bd9Sstevel@tonic-gate 		tli_error(E_T_LOOK, CONTINUE);
11267c478bd9Sstevel@tonic-gate 		break;
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate 	}
11297c478bd9Sstevel@tonic-gate }
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate /*
11327c478bd9Sstevel@tonic-gate  * send_dis:	send a disconnect
11337c478bd9Sstevel@tonic-gate  *		called when we are in state PM_DISABLED
11347c478bd9Sstevel@tonic-gate  */
11357c478bd9Sstevel@tonic-gate 
1136113f4232Sakaplan static void
1137113f4232Sakaplan send_dis(struct call_list *phead, int fd)
11387c478bd9Sstevel@tonic-gate {
1139113f4232Sakaplan 	struct t_call *call;
1140113f4232Sakaplan 	struct callsave *current;
11417c478bd9Sstevel@tonic-gate 	char	scratch[BUFSIZ];
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate 	DEBUG((9, "sending disconnect"));
11447c478bd9Sstevel@tonic-gate 	while (!EMPTYLIST(phead)) {
11457c478bd9Sstevel@tonic-gate 		current = dequeue(phead);
11467c478bd9Sstevel@tonic-gate 		call = current->c_cp;
11477c478bd9Sstevel@tonic-gate 		if (t_snddis(fd, call) < 0) {
11487c478bd9Sstevel@tonic-gate 			if (t_errno == TLOOK) {
11497c478bd9Sstevel@tonic-gate 				DEBUG((9, "collision during snddis"));
11507c478bd9Sstevel@tonic-gate 				pqueue(phead, current);
11517c478bd9Sstevel@tonic-gate 				return;
11527c478bd9Sstevel@tonic-gate 			}
11537c478bd9Sstevel@tonic-gate 			else
11547c478bd9Sstevel@tonic-gate 				tli_error(E_T_SNDDIS, CONTINUE);
11557c478bd9Sstevel@tonic-gate 		}
11567c478bd9Sstevel@tonic-gate 		sprintf(scratch, "Incoming call while disabled: fd %d, seq %d", fd, call->sequence);
11577c478bd9Sstevel@tonic-gate 		logmessage(scratch);
11587c478bd9Sstevel@tonic-gate 		clr_call(call);
11597c478bd9Sstevel@tonic-gate 		queue(Free_call_p, current);
11607c478bd9Sstevel@tonic-gate 	}
11617c478bd9Sstevel@tonic-gate 	return;
11627c478bd9Sstevel@tonic-gate }
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate /*
11667c478bd9Sstevel@tonic-gate  * trycon:	try to accept a connection
11677c478bd9Sstevel@tonic-gate  */
11687c478bd9Sstevel@tonic-gate 
1169113f4232Sakaplan static void
1170113f4232Sakaplan trycon(struct call_list *phead, int fd)
11717c478bd9Sstevel@tonic-gate {
1172113f4232Sakaplan 	struct callsave *current;
1173113f4232Sakaplan 	struct t_call *call;
11747c478bd9Sstevel@tonic-gate 	int i;
11757c478bd9Sstevel@tonic-gate 	pid_t pid;
11767c478bd9Sstevel@tonic-gate 	dbf_t *dbp;
11777c478bd9Sstevel@tonic-gate 	char scratch[BUFSIZ];
11787c478bd9Sstevel@tonic-gate 	extern dbf_t *getentry();
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 	DEBUG((9, "in trycon"));
11817c478bd9Sstevel@tonic-gate 	while (!EMPTYLIST(phead)) {
11827c478bd9Sstevel@tonic-gate 		current = dequeue(phead);
11837c478bd9Sstevel@tonic-gate 		call = current->c_cp;
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 		if ((dbp = getentry(fd)) == NULL) {
11867c478bd9Sstevel@tonic-gate 			sprintf(scratch, "No service bound to incoming fd %d: call disconnected", fd);
11877c478bd9Sstevel@tonic-gate 			logmessage(scratch);
11887c478bd9Sstevel@tonic-gate 			t_snddis(fd, call);
11897c478bd9Sstevel@tonic-gate 			clr_call(call);
11907c478bd9Sstevel@tonic-gate 			queue(Free_call_p, current);
11917c478bd9Sstevel@tonic-gate 			continue;
11927c478bd9Sstevel@tonic-gate 		}
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate 		if (dbp->dbf_flags & DBF_OFF) {
11957c478bd9Sstevel@tonic-gate 			sprintf(scratch, "Request for service on fd %d denied: disabled", fd);
11967c478bd9Sstevel@tonic-gate 			logmessage(scratch);
11977c478bd9Sstevel@tonic-gate 			t_snddis(fd, call);
11987c478bd9Sstevel@tonic-gate 			clr_call(call);
11997c478bd9Sstevel@tonic-gate 			queue(Free_call_p, current);
12007c478bd9Sstevel@tonic-gate 			continue;
12017c478bd9Sstevel@tonic-gate 		}
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 		DEBUG((9, "try to accept #%d", call->sequence));
12047c478bd9Sstevel@tonic-gate 		SPLhi();
12057c478bd9Sstevel@tonic-gate 		close(Acceptfd);
12067c478bd9Sstevel@tonic-gate 		if ((Acceptfd = open_bind(NULL, 0, 0, (unsigned int *) 0, NULL)) != 0) {
12077c478bd9Sstevel@tonic-gate 			error(E_OPENBIND, CONTINUE);
12087c478bd9Sstevel@tonic-gate 			clr_call(call);
12097c478bd9Sstevel@tonic-gate 			queue(Free_call_p, current);
12107c478bd9Sstevel@tonic-gate 			continue;	/* let transport provider generate disconnect */
12117c478bd9Sstevel@tonic-gate 		}
12127c478bd9Sstevel@tonic-gate 		SPLlo();
12137c478bd9Sstevel@tonic-gate 		if (t_accept(fd, Acceptfd, call) < 0) {
12147c478bd9Sstevel@tonic-gate 			if (t_errno == TLOOK) {
12157c478bd9Sstevel@tonic-gate 				t_close(Acceptfd);
12167c478bd9Sstevel@tonic-gate 				SPLhi();
12177c478bd9Sstevel@tonic-gate 				if (dup(Passfd) != 0)
12187c478bd9Sstevel@tonic-gate 					logmessage("Trouble duping fd 0");
12197c478bd9Sstevel@tonic-gate 				SPLlo();
12207c478bd9Sstevel@tonic-gate 				logmessage("Incoming call during t_accept -- queueing current call");
12217c478bd9Sstevel@tonic-gate 				DEBUG((9, "save call #%d", call->sequence));
12227c478bd9Sstevel@tonic-gate 				pqueue(phead, current);
12237c478bd9Sstevel@tonic-gate 				return;
12247c478bd9Sstevel@tonic-gate 			}
12257c478bd9Sstevel@tonic-gate 			else {
12267c478bd9Sstevel@tonic-gate 				t_close(Acceptfd);
12277c478bd9Sstevel@tonic-gate 				SPLhi();
12287c478bd9Sstevel@tonic-gate 				if (dup(Passfd) != 0)
12297c478bd9Sstevel@tonic-gate 					logmessage("Trouble duping fd 0");
12307c478bd9Sstevel@tonic-gate 				SPLlo();
12317c478bd9Sstevel@tonic-gate 				tli_error(E_T_ACCEPT, CONTINUE);
12327c478bd9Sstevel@tonic-gate 				clr_call(call);
12337c478bd9Sstevel@tonic-gate 				queue(Free_call_p, current);
12347c478bd9Sstevel@tonic-gate 				continue;
12357c478bd9Sstevel@tonic-gate 			}
12367c478bd9Sstevel@tonic-gate 		}
12377c478bd9Sstevel@tonic-gate 
12387c478bd9Sstevel@tonic-gate 		sprintf(scratch, "Connect: fd %d, svctag %s, seq %d, type %s",
12397c478bd9Sstevel@tonic-gate 			fd, dbp->dbf_svc_code, call->sequence,
12407c478bd9Sstevel@tonic-gate 			(dbp->dbf_sflags & PFLAG) ? "passfd" : "exec");
12417c478bd9Sstevel@tonic-gate 		logmessage(scratch);
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 		DEBUG((9, "Accepted call %d", call->sequence));
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 		if (dbp->dbf_sflags & PFLAG) {
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 			close(Passfd);
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 			if (pushmod(Acceptfd, dbp->dbf_modules)) {
12507c478bd9Sstevel@tonic-gate 				sprintf(scratch, "Could not push modules: %s", dbp->dbf_modules);
12517c478bd9Sstevel@tonic-gate 				logmessage(scratch);
12527c478bd9Sstevel@tonic-gate 				goto cleanup;
12537c478bd9Sstevel@tonic-gate 			}
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 			/* doconfig needs a file descriptor, so use Passfd */
12567c478bd9Sstevel@tonic-gate 			DEBUG((9, "Running doconfig on %s", dbp->dbf_svc_code));
12577c478bd9Sstevel@tonic-gate 			if ((i = doconfig(Acceptfd, dbp->dbf_svc_code, NOASSIGN|NORUN)) != 0) {
12587c478bd9Sstevel@tonic-gate 				DEBUG((9, "doconfig exited with code %d", i));
12597c478bd9Sstevel@tonic-gate 				sprintf(scratch, "doconfig failed on line %d of script %s", i, dbp->dbf_svc_code);
12607c478bd9Sstevel@tonic-gate 				logmessage(scratch);
12617c478bd9Sstevel@tonic-gate 				goto cleanup;
12627c478bd9Sstevel@tonic-gate 			}
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate 			/* open pipe to pass fd through */
12657c478bd9Sstevel@tonic-gate 			if ((Passfd = open(dbp->dbf_cmd_line, O_WRONLY)) < 0) {
12667c478bd9Sstevel@tonic-gate 				/* bad pipe? */
12677c478bd9Sstevel@tonic-gate 				sprintf(scratch,"Open failed: %s", dbp->dbf_cmd_line);
12687c478bd9Sstevel@tonic-gate 				logmessage(scratch);
12697c478bd9Sstevel@tonic-gate 				goto cleanup;
12707c478bd9Sstevel@tonic-gate 			}
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate 			if (ioctl(Passfd, I_SENDFD, Acceptfd) < 0) {
12737c478bd9Sstevel@tonic-gate 				/* clean up call, log error */
12747c478bd9Sstevel@tonic-gate 				sprintf(scratch,"Passfd failed: %s", dbp->dbf_cmd_line);
12757c478bd9Sstevel@tonic-gate 				logmessage(scratch);
12767c478bd9Sstevel@tonic-gate 			}
12777c478bd9Sstevel@tonic-gate cleanup:
12787c478bd9Sstevel@tonic-gate 			/* clean up this call */
12797c478bd9Sstevel@tonic-gate 			clr_call(call);
12807c478bd9Sstevel@tonic-gate 			t_close(Acceptfd);
12817c478bd9Sstevel@tonic-gate 			close(Passfd);
12827c478bd9Sstevel@tonic-gate 			Acceptfd = open("/dev/null", O_RDWR);
12837c478bd9Sstevel@tonic-gate 			Passfd = dup(Acceptfd);
12847c478bd9Sstevel@tonic-gate 			queue(Free_call_p, current);
12857c478bd9Sstevel@tonic-gate 		}
12867c478bd9Sstevel@tonic-gate 		else {
12877c478bd9Sstevel@tonic-gate 			if ((pid = fork()) < 0)
12887c478bd9Sstevel@tonic-gate 				log(E_FORK_SERVICE);
12897c478bd9Sstevel@tonic-gate 			else if (!pid) {
12907c478bd9Sstevel@tonic-gate 				setpgrp();
12917c478bd9Sstevel@tonic-gate 				/* so log files are correct */
12927c478bd9Sstevel@tonic-gate 				Pid = getpid();
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate 				if (senviron(call))  {
12957c478bd9Sstevel@tonic-gate 					logmessage("Can't expand server's environment");
12967c478bd9Sstevel@tonic-gate 				}
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 				start_server(Acceptfd, dbp);
12997c478bd9Sstevel@tonic-gate #ifdef	COREDUMP
13007c478bd9Sstevel@tonic-gate 				abort();
13017c478bd9Sstevel@tonic-gate #endif
13027c478bd9Sstevel@tonic-gate 				exit(1); /* server failed, don't log */
13037c478bd9Sstevel@tonic-gate 					/* no return */
13047c478bd9Sstevel@tonic-gate 			}
13057c478bd9Sstevel@tonic-gate 			/* only parent gets here */
13067c478bd9Sstevel@tonic-gate 			clr_call(call);
13077c478bd9Sstevel@tonic-gate 			t_close(Acceptfd);
13087c478bd9Sstevel@tonic-gate 			queue(Free_call_p, current);
13097c478bd9Sstevel@tonic-gate 			SPLhi();
13107c478bd9Sstevel@tonic-gate 			if (dup(Passfd) != 0)
13117c478bd9Sstevel@tonic-gate 				logmessage("Trouble duping fd 0");
13127c478bd9Sstevel@tonic-gate 			SPLlo();
13137c478bd9Sstevel@tonic-gate 		}
13147c478bd9Sstevel@tonic-gate 	}
13157c478bd9Sstevel@tonic-gate }
13167c478bd9Sstevel@tonic-gate 
13177c478bd9Sstevel@tonic-gate /*
13187c478bd9Sstevel@tonic-gate  * common code to  start a server process (for any service)
13197c478bd9Sstevel@tonic-gate  * The first argument in argv is the full pathname of server.
13207c478bd9Sstevel@tonic-gate  * Before exec-ing the server, the caller's
13217c478bd9Sstevel@tonic-gate  * logical address, opt and udata are addded to the environment.
13227c478bd9Sstevel@tonic-gate  */
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate static char homeenv[BUFSIZ];
13257c478bd9Sstevel@tonic-gate static char pathenv[BUFSIZ];
13267c478bd9Sstevel@tonic-gate 
1327113f4232Sakaplan int
13287c478bd9Sstevel@tonic-gate start_server(netfd, dbp)
13297c478bd9Sstevel@tonic-gate int netfd;
1330113f4232Sakaplan dbf_t *dbp;
13317c478bd9Sstevel@tonic-gate {
13327c478bd9Sstevel@tonic-gate 	char	*path;
13337c478bd9Sstevel@tonic-gate 	char	**argvp;
13347c478bd9Sstevel@tonic-gate 	extern	char **environ;
13357c478bd9Sstevel@tonic-gate 	extern	char **mkdbfargv();
1336113f4232Sakaplan 	struct passwd *pwdp;
13377c478bd9Sstevel@tonic-gate 	struct	group *grpp;
13387c478bd9Sstevel@tonic-gate 	char	msgbuf[256];
13397c478bd9Sstevel@tonic-gate 	int	i;
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 	argvp = mkdbfargv(dbp);
13437c478bd9Sstevel@tonic-gate 	path = *argvp;
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 	/* set up stdout and stderr before pushing optional modules	*/
13467c478bd9Sstevel@tonic-gate 	/* this child doesn't need access to _sacpipe and _pmpipe	*/
13477c478bd9Sstevel@tonic-gate 
13487c478bd9Sstevel@tonic-gate 	(void) close(Sacpipefd);
13497c478bd9Sstevel@tonic-gate 	(void) close(Pmpipefd);
13507c478bd9Sstevel@tonic-gate 
13517c478bd9Sstevel@tonic-gate 	if (dbp->dbf_flags & DBF_UTMP) {
13527c478bd9Sstevel@tonic-gate 		pid_t	tmp;
13537c478bd9Sstevel@tonic-gate 		struct	stat	sbuf;
13547c478bd9Sstevel@tonic-gate 		char	device[20];
13557c478bd9Sstevel@tonic-gate 		char	dummy[PMTAGSIZE + 1];
13567c478bd9Sstevel@tonic-gate 		struct	utmpx utline;
13577c478bd9Sstevel@tonic-gate 
13587c478bd9Sstevel@tonic-gate 		/*
13597c478bd9Sstevel@tonic-gate 		 * create a utmpx entry --
13607c478bd9Sstevel@tonic-gate 		 * we do an extra fork here to make init this process's
13617c478bd9Sstevel@tonic-gate 		 * parent.  this lets init clean up the utmpx entry when
13627c478bd9Sstevel@tonic-gate 		 * this proc dies.
13637c478bd9Sstevel@tonic-gate 		 *
13647c478bd9Sstevel@tonic-gate 		 * the utmpx routines need a file descriptor!
13657c478bd9Sstevel@tonic-gate 		 */
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 		DEBUG((9, "Creating a utmpx entry for this service "));
13687c478bd9Sstevel@tonic-gate 		if ((tmp = fork()) < 0) {
13697c478bd9Sstevel@tonic-gate 			logmessage("Can't fork to create utmpx entry");
13707c478bd9Sstevel@tonic-gate 			exit(2);
13717c478bd9Sstevel@tonic-gate 		}
13727c478bd9Sstevel@tonic-gate 		if (tmp)
13737c478bd9Sstevel@tonic-gate 			exit(0);	/* kill parent */
13747c478bd9Sstevel@tonic-gate 
13757c478bd9Sstevel@tonic-gate 		/*
13767c478bd9Sstevel@tonic-gate 		 * child continues processing, creating utmp and exec'ing
13777c478bd9Sstevel@tonic-gate 		 * the service
13787c478bd9Sstevel@tonic-gate 		 */
13797c478bd9Sstevel@tonic-gate 
13807c478bd9Sstevel@tonic-gate 		setpgrp();
13817c478bd9Sstevel@tonic-gate 		if (fstat(0, &sbuf) < 0) {
13827c478bd9Sstevel@tonic-gate 			logmessage("Stat failed on fd 0: no line field "
13837c478bd9Sstevel@tonic-gate 			    "available for utmpx entry");
13847c478bd9Sstevel@tonic-gate 			*device = '\0';
13857c478bd9Sstevel@tonic-gate 		}
13867c478bd9Sstevel@tonic-gate 		else {
13877c478bd9Sstevel@tonic-gate 			if (minor(sbuf.st_rdev) < 100)
13887c478bd9Sstevel@tonic-gate 				sprintf(device, "%.9s%02d", Minor_prefix,
13897c478bd9Sstevel@tonic-gate 				    minor(sbuf.st_rdev));
13907c478bd9Sstevel@tonic-gate 			else
13917c478bd9Sstevel@tonic-gate 				sprintf(device, "%.8s%03d", Minor_prefix,
13927c478bd9Sstevel@tonic-gate 				    minor(sbuf.st_rdev));
13937c478bd9Sstevel@tonic-gate 			DEBUG((9, "Device: %s", device));
13947c478bd9Sstevel@tonic-gate 		}
13957c478bd9Sstevel@tonic-gate 		/*
13967c478bd9Sstevel@tonic-gate 		 * prepend a "." so this can be distinguished as a "funny"
13977c478bd9Sstevel@tonic-gate 		 * utmpx entry that may never get a DEAD_PROCESS entry in
13987c478bd9Sstevel@tonic-gate 		 * the wtmpx file.
13997c478bd9Sstevel@tonic-gate 		 */
14007c478bd9Sstevel@tonic-gate 		sprintf(dummy, ".%s", Mytag);
14017c478bd9Sstevel@tonic-gate 		/* XXX - utmp - fix login name length */
14027c478bd9Sstevel@tonic-gate 		strncpy(utline.ut_user, dummy, sizeof (utline.ut_user) - 1);
14037c478bd9Sstevel@tonic-gate 		sprintf(utline.ut_id, "ls%c%c", SC_WILDC, SC_WILDC);
14047c478bd9Sstevel@tonic-gate 		strncpy(utline.ut_line, device, sizeof (utline.ut_line) - 1);
14057c478bd9Sstevel@tonic-gate 		utline.ut_pid = getpid();
14067c478bd9Sstevel@tonic-gate 		utline.ut_type = USER_PROCESS;
14077c478bd9Sstevel@tonic-gate 		utline.ut_exit.e_termination = 0;
14087c478bd9Sstevel@tonic-gate 		utline.ut_exit.e_exit = 0;
14097c478bd9Sstevel@tonic-gate 		utline.ut_xtime = (time_t) time((time_t *)0);
14107c478bd9Sstevel@tonic-gate 		makeutx(&utline);
14117c478bd9Sstevel@tonic-gate 	}
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate 	if (dup(0) != 1 || dup(0) != 2) {
14147c478bd9Sstevel@tonic-gate 		logmessage("Dup of fd 0 failed");
14157c478bd9Sstevel@tonic-gate 		exit(2); /* server, don't log */
14167c478bd9Sstevel@tonic-gate 	}
14177c478bd9Sstevel@tonic-gate 
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate 	if (pushmod(netfd, dbp->dbf_modules)) {
14207c478bd9Sstevel@tonic-gate 		logmessage("Can't push server's modules: exit");
14217c478bd9Sstevel@tonic-gate 		exit(2); /* server, don't log */
14227c478bd9Sstevel@tonic-gate 	}
14237c478bd9Sstevel@tonic-gate 
14247c478bd9Sstevel@tonic-gate 	rst_signals();
14257c478bd9Sstevel@tonic-gate 
14267c478bd9Sstevel@tonic-gate 	DEBUG((9, "Running doconfig on %s", dbp->dbf_svc_code));
14277c478bd9Sstevel@tonic-gate 	if ((i = doconfig(Acceptfd, dbp->dbf_svc_code, 0)) != 0) {
14287c478bd9Sstevel@tonic-gate 		DEBUG((9, "doconfig exited with code %d", i));
14297c478bd9Sstevel@tonic-gate 		sprintf(msgbuf, "doconfig failed on line %d of script %s", i, dbp->dbf_svc_code);
14307c478bd9Sstevel@tonic-gate 		logmessage(msgbuf);
14317c478bd9Sstevel@tonic-gate 		exit(2);
14327c478bd9Sstevel@tonic-gate 	}
14337c478bd9Sstevel@tonic-gate 
14347c478bd9Sstevel@tonic-gate 	if ((pwdp = getpwnam(dbp->dbf_id)) == NULL)  {
14357c478bd9Sstevel@tonic-gate 		sprintf(msgbuf, "Missing or bad passwd entry for <%s>",dbp->dbf_id);
14367c478bd9Sstevel@tonic-gate 		logmessage(msgbuf);
14377c478bd9Sstevel@tonic-gate 		exit(2); /* server, don't log */
14387c478bd9Sstevel@tonic-gate 	}
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate 	if (setgid(pwdp->pw_gid)) {
14417c478bd9Sstevel@tonic-gate 		if ((grpp = getgrgid(pwdp->pw_gid)) == NULL) {
14427c478bd9Sstevel@tonic-gate 			sprintf(msgbuf, "No group entry for %ld", pwdp->pw_gid);
14437c478bd9Sstevel@tonic-gate 			logmessage(msgbuf);
14447c478bd9Sstevel@tonic-gate 			exit(2); /* server, don't log */
14457c478bd9Sstevel@tonic-gate 		}
14467c478bd9Sstevel@tonic-gate 		sprintf(msgbuf, "Cannot set group id to %s", grpp->gr_name);
14477c478bd9Sstevel@tonic-gate 		logmessage(msgbuf);
14487c478bd9Sstevel@tonic-gate 		exit(2); /* server, don't log */
14497c478bd9Sstevel@tonic-gate 	}
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	if (setuid(pwdp->pw_uid)) {
14527c478bd9Sstevel@tonic-gate 		sprintf(msgbuf, "Cannot set user id to %s", dbp->dbf_id);
14537c478bd9Sstevel@tonic-gate 		logmessage(msgbuf);
14547c478bd9Sstevel@tonic-gate 		exit(2); /* server, don't log */
14557c478bd9Sstevel@tonic-gate 	}
14567c478bd9Sstevel@tonic-gate 
14577c478bd9Sstevel@tonic-gate 	if (chdir(pwdp->pw_dir)) {
14587c478bd9Sstevel@tonic-gate                 sprintf(msgbuf, "Cannot chdir to %s", pwdp->pw_dir);
14597c478bd9Sstevel@tonic-gate                 logmessage(msgbuf);
14607c478bd9Sstevel@tonic-gate                 exit(2); /* server, don't log */
14617c478bd9Sstevel@tonic-gate         }
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 	DEBUG((9, "New uid %ld New gid %ld", getuid(), getgid()));
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 	sprintf(homeenv, "HOME=%s", pwdp->pw_dir);
14677c478bd9Sstevel@tonic-gate 	putenv(homeenv);
14687c478bd9Sstevel@tonic-gate 	if (pwdp->pw_uid)
14697c478bd9Sstevel@tonic-gate 		sprintf(pathenv, "PATH=/usr/bin:");
14707c478bd9Sstevel@tonic-gate 	else
14717c478bd9Sstevel@tonic-gate 		sprintf(pathenv, "PATH=/usr/sbin:/usr/bin");
14727c478bd9Sstevel@tonic-gate 	putenv(pathenv);
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 	endpwent();
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate 	execve(path, argvp, environ);
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate 	/* exec returns only on failure!		*/
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	logmessage("ERROR: could not exec server");
14817c478bd9Sstevel@tonic-gate 	sys_error(E_SYS_ERROR, CONTINUE);
14827c478bd9Sstevel@tonic-gate 	return(-1);
14837c478bd9Sstevel@tonic-gate }
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 
14867c478bd9Sstevel@tonic-gate /*
14877c478bd9Sstevel@tonic-gate  * senviron:	Update environment before exec-ing the server:
14887c478bd9Sstevel@tonic-gate  *		The callers logical address is placed in the
14897c478bd9Sstevel@tonic-gate  *		environment in hex/ascii character representation.
14907c478bd9Sstevel@tonic-gate  *
14917c478bd9Sstevel@tonic-gate  * Note:	no need to free the malloc'ed buffers since this process
14927c478bd9Sstevel@tonic-gate  *		will either exec or exit.
14937c478bd9Sstevel@tonic-gate  */
14947c478bd9Sstevel@tonic-gate 
14957c478bd9Sstevel@tonic-gate static char provenv[2*PATHSIZE];
14967c478bd9Sstevel@tonic-gate static char prefenv[2*PATHSIZE];
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate int
14997c478bd9Sstevel@tonic-gate senviron(call)
1500113f4232Sakaplan struct t_call *call;
15017c478bd9Sstevel@tonic-gate {
1502113f4232Sakaplan 	char *p;
15037c478bd9Sstevel@tonic-gate 	extern void nlsaddr2c();
15047c478bd9Sstevel@tonic-gate 	extern char *getenv();
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate 
15077c478bd9Sstevel@tonic-gate /*
15087c478bd9Sstevel@tonic-gate  * The following code handles the case where the listener was started with
15097c478bd9Sstevel@tonic-gate  * no environment.  If so, supply a reasonable default path.  Parent already
15107c478bd9Sstevel@tonic-gate  * set TZ on startup if it wasn't, so don't need to do it here.
15117c478bd9Sstevel@tonic-gate  */
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 	if (getenv("PATH") == NULL)
15147c478bd9Sstevel@tonic-gate 		putenv("PATH=/usr/sbin:/usr/bin");
15157c478bd9Sstevel@tonic-gate 
15167c478bd9Sstevel@tonic-gate 	if ((p = (char *)malloc(((call->addr.len)<<1) + 18)) == NULL)
15177c478bd9Sstevel@tonic-gate 		return(-1);
15187c478bd9Sstevel@tonic-gate 	strcpy(p, NLSADDR);
15197c478bd9Sstevel@tonic-gate 	strcat(p, "=");
15207c478bd9Sstevel@tonic-gate 	nlsaddr2c(p + strlen(p), call->addr.buf, (int)call->addr.len);
15217c478bd9Sstevel@tonic-gate 	DEBUG((7, "Adding %s to server's environment", p));
15227c478bd9Sstevel@tonic-gate 	putenv(p);
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate 	if ((p = (char *)malloc(((call->opt.len)<<1) + 16)) == NULL)
15257c478bd9Sstevel@tonic-gate 		return(-1);
15267c478bd9Sstevel@tonic-gate 	strcpy(p, NLSOPT);
15277c478bd9Sstevel@tonic-gate 	strcat(p, "=");
15287c478bd9Sstevel@tonic-gate 	nlsaddr2c(p + strlen(p), call->opt.buf, (int)call->opt.len);
15297c478bd9Sstevel@tonic-gate 	DEBUG((7, "Adding %s to server's environment", p));
15307c478bd9Sstevel@tonic-gate 	putenv(p);
15317c478bd9Sstevel@tonic-gate 
15327c478bd9Sstevel@tonic-gate 	p = provenv;
15337c478bd9Sstevel@tonic-gate 	strcpy(p, NLSPROVIDER);
15347c478bd9Sstevel@tonic-gate 	strcat(p, "=");
15357c478bd9Sstevel@tonic-gate 	strcat(p, Netspec);
15367c478bd9Sstevel@tonic-gate 	DEBUG((7, "Adding %s to environment", p));
15377c478bd9Sstevel@tonic-gate 	putenv(p);
15387c478bd9Sstevel@tonic-gate 
15397c478bd9Sstevel@tonic-gate 	/*
15407c478bd9Sstevel@tonic-gate 	 * MPREFIX is NEW for SVR4.0.  It tells the nlps_server what to use
15417c478bd9Sstevel@tonic-gate 	 * as a minor device prefix.  THIS SHOULD BE DOCUMENTED!
15427c478bd9Sstevel@tonic-gate 	 */
15437c478bd9Sstevel@tonic-gate 	p = prefenv;
15447c478bd9Sstevel@tonic-gate 	strcpy(p, "MPREFIX");
15457c478bd9Sstevel@tonic-gate 	strcat(p, "=");
15467c478bd9Sstevel@tonic-gate 	strcat(p, Minor_prefix);
15477c478bd9Sstevel@tonic-gate 	DEBUG((7, "Adding %s to environment", p));
15487c478bd9Sstevel@tonic-gate 	putenv(p);
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate 	if ((p = (char *)malloc(((call->udata.len)<<1) + 20)) == NULL)
15517c478bd9Sstevel@tonic-gate 		return(-1);
15527c478bd9Sstevel@tonic-gate 	strcpy(p, NLSUDATA);
15537c478bd9Sstevel@tonic-gate 	strcat(p, "=");
15547c478bd9Sstevel@tonic-gate 	if ((int)call->udata.len >= 0)
15557c478bd9Sstevel@tonic-gate 		nlsaddr2c(p + strlen(p), call->udata.buf, (int)call->udata.len);
15567c478bd9Sstevel@tonic-gate 	putenv(p);
15577c478bd9Sstevel@tonic-gate 	return (0);
15587c478bd9Sstevel@tonic-gate }
15597c478bd9Sstevel@tonic-gate 
15607c478bd9Sstevel@tonic-gate 
15617c478bd9Sstevel@tonic-gate /*
15627c478bd9Sstevel@tonic-gate  * parse:	Parse TZ= string like init does for consistency
15637c478bd9Sstevel@tonic-gate  *		Work on string in place since result will
15647c478bd9Sstevel@tonic-gate  *		either be the same or shorter.
15657c478bd9Sstevel@tonic-gate  */
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate char *
15687c478bd9Sstevel@tonic-gate parse(s)
15697c478bd9Sstevel@tonic-gate char *s;
15707c478bd9Sstevel@tonic-gate {
1571113f4232Sakaplan 	char *p;
1572113f4232Sakaplan 	char *tp;
15737c478bd9Sstevel@tonic-gate 	char scratch[BUFSIZ];
15747c478bd9Sstevel@tonic-gate 	int delim;
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate 	tp = p = s + strlen("TZ=");	/* skip TZ= in parsing */
15777c478bd9Sstevel@tonic-gate 	if ((*p == '"') || (*p == '\'')) {
15787c478bd9Sstevel@tonic-gate 		/* it is quoted */
15797c478bd9Sstevel@tonic-gate 		delim = *p++;
15807c478bd9Sstevel@tonic-gate 		for (;;) {
15817c478bd9Sstevel@tonic-gate 			if (*p == '\0') {
1582052519c2SGarrett D'Amore 				/* etc/default/init ill-formed, go without TZ */
1583052519c2SGarrett D'Amore 				sprintf(scratch, "%s ill-formed", TZFILE);
15847c478bd9Sstevel@tonic-gate 				logmessage(scratch);
15857c478bd9Sstevel@tonic-gate 				strcpy(s, "TZ=");
15867c478bd9Sstevel@tonic-gate 				return(s);
15877c478bd9Sstevel@tonic-gate 			}
15887c478bd9Sstevel@tonic-gate 			if (*p == delim) {
15897c478bd9Sstevel@tonic-gate 				*tp = '\0';
15907c478bd9Sstevel@tonic-gate 				return(s);
15917c478bd9Sstevel@tonic-gate 			}
15927c478bd9Sstevel@tonic-gate 			else {
15937c478bd9Sstevel@tonic-gate 				*tp++ = *p++;
15947c478bd9Sstevel@tonic-gate 			}
15957c478bd9Sstevel@tonic-gate 		}
15967c478bd9Sstevel@tonic-gate 	}
15977c478bd9Sstevel@tonic-gate 	else { /* look for comment or trailing whitespace */
15987c478bd9Sstevel@tonic-gate 		for ( ; *p && !isspace(*p) && *p != '#'; ++p)
15997c478bd9Sstevel@tonic-gate 			;
16007c478bd9Sstevel@tonic-gate 		/* if a comment or trailing whitespace, trash it */
16017c478bd9Sstevel@tonic-gate 		if (*p) {
16027c478bd9Sstevel@tonic-gate 			*p = '\0';
16037c478bd9Sstevel@tonic-gate 		}
16047c478bd9Sstevel@tonic-gate 		return(s);
16057c478bd9Sstevel@tonic-gate 	}
16067c478bd9Sstevel@tonic-gate }
16077c478bd9Sstevel@tonic-gate 
16087c478bd9Sstevel@tonic-gate 
16097c478bd9Sstevel@tonic-gate /*
16107c478bd9Sstevel@tonic-gate  * clr_call:	clear out a call structure
16117c478bd9Sstevel@tonic-gate  */
16127c478bd9Sstevel@tonic-gate 
1613113f4232Sakaplan static void
1614113f4232Sakaplan clr_call(struct t_call *call)
16157c478bd9Sstevel@tonic-gate {
16167c478bd9Sstevel@tonic-gate 	call->sequence = 0;
16177c478bd9Sstevel@tonic-gate 	call->addr.len = 0;
16187c478bd9Sstevel@tonic-gate 	call->opt.len = 0;
16197c478bd9Sstevel@tonic-gate 	call->udata.len = 0;
16207c478bd9Sstevel@tonic-gate 	memset(call->addr.buf, 0, (int)call->addr.maxlen);
16217c478bd9Sstevel@tonic-gate 	memset(call->opt.buf, 0, (int)call->opt.maxlen);
16227c478bd9Sstevel@tonic-gate 	memset(call->udata.buf, 0, (int)call->udata.maxlen);
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate 
16257c478bd9Sstevel@tonic-gate 
16267c478bd9Sstevel@tonic-gate /*
16277c478bd9Sstevel@tonic-gate  * pitchcall: remove call from pending list
16287c478bd9Sstevel@tonic-gate  */
16297c478bd9Sstevel@tonic-gate 
1630113f4232Sakaplan static void
1631113f4232Sakaplan pitchcall(struct call_list *pending, struct t_discon *discon)
16327c478bd9Sstevel@tonic-gate {
1633113f4232Sakaplan 	struct callsave *p, *oldp;
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate 	DEBUG((9, "pitching call, sequence # is %d", discon->sequence));
16367c478bd9Sstevel@tonic-gate 	if (EMPTYLIST(pending)) {
16377c478bd9Sstevel@tonic-gate 		discon->sequence = -1;
16387c478bd9Sstevel@tonic-gate 		return;
16397c478bd9Sstevel@tonic-gate 	}
16407c478bd9Sstevel@tonic-gate 	p = pending->cl_head;
16417c478bd9Sstevel@tonic-gate 	oldp = (struct callsave *) NULL;
16427c478bd9Sstevel@tonic-gate 	while (p) {
16437c478bd9Sstevel@tonic-gate 		if (p->c_cp->sequence == discon->sequence) {
16447c478bd9Sstevel@tonic-gate 			if (oldp == (struct callsave *) NULL) {
16457c478bd9Sstevel@tonic-gate 				pending->cl_head = p->c_np;
16467c478bd9Sstevel@tonic-gate 				if (pending->cl_head == (struct callsave *) NULL) {
16477c478bd9Sstevel@tonic-gate 					pending->cl_tail = (struct callsave *) NULL;
16487c478bd9Sstevel@tonic-gate 				}
16497c478bd9Sstevel@tonic-gate 			}
16507c478bd9Sstevel@tonic-gate 			else if (p == pending->cl_tail) {
16517c478bd9Sstevel@tonic-gate 				oldp->c_np = p->c_np;
16527c478bd9Sstevel@tonic-gate 				pending->cl_tail = oldp;
16537c478bd9Sstevel@tonic-gate 			}
16547c478bd9Sstevel@tonic-gate 			else {
16557c478bd9Sstevel@tonic-gate 				oldp->c_np = p->c_np;
16567c478bd9Sstevel@tonic-gate 			}
16577c478bd9Sstevel@tonic-gate 			clr_call(p->c_cp);
16587c478bd9Sstevel@tonic-gate 			queue(Free_call_p, p);
16597c478bd9Sstevel@tonic-gate 			discon->sequence = -1;
16607c478bd9Sstevel@tonic-gate 			return;
16617c478bd9Sstevel@tonic-gate 		}
16627c478bd9Sstevel@tonic-gate 		oldp = p;
16637c478bd9Sstevel@tonic-gate 		p = p->c_np;
16647c478bd9Sstevel@tonic-gate 	}
16657c478bd9Sstevel@tonic-gate 	logmessage("received disconnect with no pending call");
16667c478bd9Sstevel@tonic-gate 	discon->sequence = -1;
16677c478bd9Sstevel@tonic-gate 	return;
16687c478bd9Sstevel@tonic-gate }
16697c478bd9Sstevel@tonic-gate 
16707c478bd9Sstevel@tonic-gate /*
16717c478bd9Sstevel@tonic-gate  * add_prvaddr:  open and bind the private address specified in the database
16727c478bd9Sstevel@tonic-gate  *               entry passed into the routine.  Update the maxcon and fd
16737c478bd9Sstevel@tonic-gate  *               entries in the database structure
16747c478bd9Sstevel@tonic-gate  *
16757c478bd9Sstevel@tonic-gate  *	This routine is very sloppy with malloc'ed memory, but addresses
16767c478bd9Sstevel@tonic-gate  *	shouldn't ever change enough for this to matter.
16777c478bd9Sstevel@tonic-gate  */
16787c478bd9Sstevel@tonic-gate 
1679113f4232Sakaplan int
16807c478bd9Sstevel@tonic-gate add_prvaddr(dbp)
16817c478bd9Sstevel@tonic-gate dbf_t *dbp;
16827c478bd9Sstevel@tonic-gate {
16837c478bd9Sstevel@tonic-gate 	extern	char	*t_alloc();
1684113f4232Sakaplan 	int	j;
16857c478bd9Sstevel@tonic-gate 	struct	call_list *temp_pend;
1686113f4232Sakaplan 	struct	callsave *tmp;
16877c478bd9Sstevel@tonic-gate 	char	scratch[BUFSIZ];
16887c478bd9Sstevel@tonic-gate 	int	bindfd;
16897c478bd9Sstevel@tonic-gate 	extern	struct	netbuf *stoa();
16907c478bd9Sstevel@tonic-gate 	char	str[NAMEBUFSZ];
16917c478bd9Sstevel@tonic-gate 	char	*lstr = str;
16927c478bd9Sstevel@tonic-gate 	struct	netbuf	netbuf;
16937c478bd9Sstevel@tonic-gate 	int	maxcon;
16947c478bd9Sstevel@tonic-gate 	char	*ap;
16957c478bd9Sstevel@tonic-gate 	int	clen;
16967c478bd9Sstevel@tonic-gate 
16977c478bd9Sstevel@tonic-gate 	DEBUG((9,"in add_prvaddr, addr %s, svc %s",
16987c478bd9Sstevel@tonic-gate 		(dbp->dbf_sflags & DFLAG) ? "DYNAMIC" : dbp->dbf_prv_adr,
16997c478bd9Sstevel@tonic-gate 		dbp->dbf_svc_code));
17007c478bd9Sstevel@tonic-gate 	netbuf.buf = NULL;
17017c478bd9Sstevel@tonic-gate 	netbuf.maxlen = 0;
17027c478bd9Sstevel@tonic-gate 	netbuf.len = 0;
17037c478bd9Sstevel@tonic-gate 	if (!(dbp->dbf_sflags & DFLAG)) {
17047c478bd9Sstevel@tonic-gate 		strcpy(lstr, dbp->dbf_prv_adr);
17057c478bd9Sstevel@tonic-gate 
17067c478bd9Sstevel@tonic-gate 		/* call stoa - convert from rfs address to netbuf */
17077c478bd9Sstevel@tonic-gate 
17087c478bd9Sstevel@tonic-gate 		if (stoa(lstr, &netbuf) == (struct netbuf *)NULL)  {
17097c478bd9Sstevel@tonic-gate 			DEBUG((9,"stoa returned null, errno = %d\n",errno));
17107c478bd9Sstevel@tonic-gate 			error(1, E_MALLOC);
17117c478bd9Sstevel@tonic-gate 			return(-1);
17127c478bd9Sstevel@tonic-gate 		}
17137c478bd9Sstevel@tonic-gate 		clen = netbuf.len;
17147c478bd9Sstevel@tonic-gate 	}
17157c478bd9Sstevel@tonic-gate 	else {
17167c478bd9Sstevel@tonic-gate 		clen = -1;
17177c478bd9Sstevel@tonic-gate 	}
17187c478bd9Sstevel@tonic-gate 	if ((bindfd = open_bind(netbuf.buf, MAXCON, clen, &maxcon, &ap)) < 0) {
17197c478bd9Sstevel@tonic-gate 		switch (bindfd) {
17207c478bd9Sstevel@tonic-gate 		case -1:
17217c478bd9Sstevel@tonic-gate 			return(-1);
17227c478bd9Sstevel@tonic-gate 			break;
17237c478bd9Sstevel@tonic-gate 		case -2:
17247c478bd9Sstevel@tonic-gate 			sprintf(scratch, "  Service %s ignored: out of file descriptors", dbp->dbf_svc_code);
17257c478bd9Sstevel@tonic-gate 			logmessage(scratch);
17267c478bd9Sstevel@tonic-gate 			return(-1);
17277c478bd9Sstevel@tonic-gate 			break;
17287c478bd9Sstevel@tonic-gate 		case -3:
17297c478bd9Sstevel@tonic-gate 			sprintf(scratch, "  Service %s ignored: unable to bind requested address", dbp->dbf_svc_code);
17307c478bd9Sstevel@tonic-gate 			logmessage(scratch);
17317c478bd9Sstevel@tonic-gate 			return(-1);
17327c478bd9Sstevel@tonic-gate 			break;
17337c478bd9Sstevel@tonic-gate 		default:
17347c478bd9Sstevel@tonic-gate 			error(E_OPENBIND, EXIT);
17357c478bd9Sstevel@tonic-gate 		}
17367c478bd9Sstevel@tonic-gate 	}
17377c478bd9Sstevel@tonic-gate 	if (clen == -1) {
17387c478bd9Sstevel@tonic-gate 		sprintf(scratch,"Service %s: fd %d dynamic addr %s", dbp->dbf_svc_code, bindfd, ap);
17397c478bd9Sstevel@tonic-gate 		dbp->dbf_prv_adr = ap;
17407c478bd9Sstevel@tonic-gate 	}
17417c478bd9Sstevel@tonic-gate 	else {
17427c478bd9Sstevel@tonic-gate 		sprintf(scratch,"Service %s: fd %d addr %s", dbp->dbf_svc_code, bindfd, dbp->dbf_prv_adr);
17437c478bd9Sstevel@tonic-gate 	}
17447c478bd9Sstevel@tonic-gate 	logmessage(scratch);
17457c478bd9Sstevel@tonic-gate 	rpc_register(dbp);
17467c478bd9Sstevel@tonic-gate 	temp_pend = Priv_call + bindfd;
17477c478bd9Sstevel@tonic-gate 	dbp->dbf_fd = bindfd;
17487c478bd9Sstevel@tonic-gate 	dbp->dbf_maxcon = maxcon;
17497c478bd9Sstevel@tonic-gate 	temp_pend->cl_head = (struct callsave *) NULL;
17507c478bd9Sstevel@tonic-gate 	temp_pend->cl_tail = (struct callsave *) NULL;
17517c478bd9Sstevel@tonic-gate 	for (j=0; j < maxcon; ++j)  {
17527c478bd9Sstevel@tonic-gate 		if ((tmp = (struct callsave *) malloc(sizeof(struct callsave))) == NULL)  {
17537c478bd9Sstevel@tonic-gate 			error (E_MALLOC, NOCORE | EXIT);
17547c478bd9Sstevel@tonic-gate 		}
17557c478bd9Sstevel@tonic-gate 		if ((tmp->c_cp = (struct t_call *) t_alloc(bindfd, T_CALL,
17567c478bd9Sstevel@tonic-gate 				T_ALL)) == NULL) {
17577c478bd9Sstevel@tonic-gate 			tli_error(E_T_ALLOC,EXIT);
17587c478bd9Sstevel@tonic-gate 		}
17597c478bd9Sstevel@tonic-gate 		queue(Free_call_p, tmp);
17607c478bd9Sstevel@tonic-gate 	}
17617c478bd9Sstevel@tonic-gate 	return(0);
17627c478bd9Sstevel@tonic-gate }
17637c478bd9Sstevel@tonic-gate 
17647c478bd9Sstevel@tonic-gate /*
17657c478bd9Sstevel@tonic-gate  * mod_prvaddr -- after re-reading the database, take appropriate action for
17667c478bd9Sstevel@tonic-gate  *		  new, deleted, or changed addresses.
17677c478bd9Sstevel@tonic-gate  */
1768113f4232Sakaplan static void
1769113f4232Sakaplan mod_prvaddr(void)
17707c478bd9Sstevel@tonic-gate {
17717c478bd9Sstevel@tonic-gate 	dbf_t	*entry_p;
17727c478bd9Sstevel@tonic-gate 	dbf_t	*oldentry_p;
17737c478bd9Sstevel@tonic-gate 	char	scratch[BUFSIZ];
17747c478bd9Sstevel@tonic-gate 	dbf_t	*svc_code_match();
17757c478bd9Sstevel@tonic-gate 	int	bound;
17767c478bd9Sstevel@tonic-gate 	struct	pollfd	*sp;
17777c478bd9Sstevel@tonic-gate 
17787c478bd9Sstevel@tonic-gate 	DEBUG((9, "in mod_prvaddr..."));
17797c478bd9Sstevel@tonic-gate 	/*
17807c478bd9Sstevel@tonic-gate 	 * for each entry in the new table, check for a svc code match.
17817c478bd9Sstevel@tonic-gate 	 * if there is a svc code match and the address matches, all we
17827c478bd9Sstevel@tonic-gate 	 * need to do is update the new table.  if the addresses are
17837c478bd9Sstevel@tonic-gate 	 * different, we need to remove the old one and replace it.
17847c478bd9Sstevel@tonic-gate 	 */
17857c478bd9Sstevel@tonic-gate 	for (entry_p = Newdbf; entry_p && entry_p->dbf_svc_code; entry_p++) {
17867c478bd9Sstevel@tonic-gate 		if ((oldentry_p = svc_code_match(entry_p->dbf_svc_code)) != NULL) {
17877c478bd9Sstevel@tonic-gate 			/* matched svc code.  see if address matches. */
17887c478bd9Sstevel@tonic-gate 			DEBUG((9, "MATCHED service code"));
17897c478bd9Sstevel@tonic-gate 			if ((strcmp(oldentry_p->dbf_prv_adr, entry_p->dbf_prv_adr) == 0) || ((oldentry_p->dbf_sflags & DFLAG) && (entry_p->dbf_sflags & DFLAG))) {
17907c478bd9Sstevel@tonic-gate 				DEBUG((9, "SAME addresses, old %s, new %s",
17917c478bd9Sstevel@tonic-gate 				oldentry_p->dbf_prv_adr, entry_p->dbf_prv_adr));
17927c478bd9Sstevel@tonic-gate 				/* update new table with fd, set old fd to -1 */
17937c478bd9Sstevel@tonic-gate 				DEBUG((9, "Old fd %d",  oldentry_p->dbf_fd));
17947c478bd9Sstevel@tonic-gate 				entry_p->dbf_fd = oldentry_p->dbf_fd;
17957c478bd9Sstevel@tonic-gate 				entry_p->dbf_maxcon = oldentry_p->dbf_maxcon;
17967c478bd9Sstevel@tonic-gate 				oldentry_p->dbf_fd = -1;
17977c478bd9Sstevel@tonic-gate 				if ((oldentry_p->dbf_sflags & DFLAG) && (entry_p->dbf_sflags & DFLAG)) {
17987c478bd9Sstevel@tonic-gate 					entry_p->dbf_prv_adr = oldentry_p->dbf_prv_adr;
17997c478bd9Sstevel@tonic-gate 				}
18007c478bd9Sstevel@tonic-gate 				if (entry_p->dbf_fd != -1) {
18017c478bd9Sstevel@tonic-gate 					sprintf(scratch, "Service %s: fd %d addr %s",
18027c478bd9Sstevel@tonic-gate 						entry_p->dbf_svc_code, entry_p->dbf_fd,
18037c478bd9Sstevel@tonic-gate 						entry_p->dbf_prv_adr);
18047c478bd9Sstevel@tonic-gate 					logmessage(scratch);
18057c478bd9Sstevel@tonic-gate 				}
18067c478bd9Sstevel@tonic-gate 				if ((oldentry_p->dbf_version != entry_p->dbf_version) || (oldentry_p->dbf_prognum != entry_p->dbf_prognum)) {
18077c478bd9Sstevel@tonic-gate 					rpc_unregister(oldentry_p);
18087c478bd9Sstevel@tonic-gate 					rpc_register(entry_p);
18097c478bd9Sstevel@tonic-gate 				}
18107c478bd9Sstevel@tonic-gate 			}
18117c478bd9Sstevel@tonic-gate 		}
18127c478bd9Sstevel@tonic-gate 	}
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate 	/* now unbind the remaining addresses in the old table (fd != -1) */
18157c478bd9Sstevel@tonic-gate 
18167c478bd9Sstevel@tonic-gate 	for (oldentry_p = Dbfhead; oldentry_p && oldentry_p->dbf_svc_code; oldentry_p++) {
18177c478bd9Sstevel@tonic-gate 		if (oldentry_p->dbf_fd != -1) {
18187c478bd9Sstevel@tonic-gate 			DEBUG((9, "deleting %s",  oldentry_p->dbf_svc_code));
18197c478bd9Sstevel@tonic-gate 			if (del_prvaddr(oldentry_p) == 0)
18207c478bd9Sstevel@tonic-gate 				Valid_addrs--;
18217c478bd9Sstevel@tonic-gate 		}
18227c478bd9Sstevel@tonic-gate 	}
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 	/* now bind all of the new addresses (fd == -1) */
18257c478bd9Sstevel@tonic-gate 	/*
18267c478bd9Sstevel@tonic-gate 	 * this tries to bind any addresses that failed to bind successfully
18277c478bd9Sstevel@tonic-gate 	 * when the address changed.  This means that if a service is moved to
18287c478bd9Sstevel@tonic-gate 	 * an address that is being deleted, the first attempt to bind it will
18297c478bd9Sstevel@tonic-gate 	 * fail, the old address will be removed, and this bind will succeed
18307c478bd9Sstevel@tonic-gate 	 */
18317c478bd9Sstevel@tonic-gate 
18327c478bd9Sstevel@tonic-gate 	/* first the static addrs */
18337c478bd9Sstevel@tonic-gate 	for (entry_p = Newdbf; entry_p && entry_p->dbf_svc_code; entry_p++) {
18347c478bd9Sstevel@tonic-gate 		if ((entry_p->dbf_fd == -1) && (!(entry_p->dbf_sflags & DFLAG))) {
18357c478bd9Sstevel@tonic-gate 			DEBUG((9, "adding %s",  entry_p->dbf_svc_code));
18367c478bd9Sstevel@tonic-gate 			if (add_prvaddr(entry_p) == 0)
18377c478bd9Sstevel@tonic-gate 				Valid_addrs++;
18387c478bd9Sstevel@tonic-gate 		}
18397c478bd9Sstevel@tonic-gate 	}
18407c478bd9Sstevel@tonic-gate 	/* then the dynamic addrs */
18417c478bd9Sstevel@tonic-gate 	for (entry_p = Newdbf; entry_p && entry_p->dbf_svc_code; entry_p++) {
18427c478bd9Sstevel@tonic-gate 		if ((entry_p->dbf_fd == -1) && (entry_p->dbf_sflags & DFLAG)) {
18437c478bd9Sstevel@tonic-gate 			DEBUG((9, "adding %s",  entry_p->dbf_svc_code));
18447c478bd9Sstevel@tonic-gate 			if (add_prvaddr(entry_p) == 0)
18457c478bd9Sstevel@tonic-gate 				Valid_addrs++;
18467c478bd9Sstevel@tonic-gate 		}
18477c478bd9Sstevel@tonic-gate 	}
18487c478bd9Sstevel@tonic-gate 
18497c478bd9Sstevel@tonic-gate 	/* free old database, set up new pollfd table, and we're done */
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 	free(Dbfhead);
18527c478bd9Sstevel@tonic-gate 	free(Server_cmd_lines);
18537c478bd9Sstevel@tonic-gate 	Dbfhead = Newdbf;
18547c478bd9Sstevel@tonic-gate 	Newdbf = NULL;
18557c478bd9Sstevel@tonic-gate 	Server_cmd_lines = New_cmd_lines;
18567c478bd9Sstevel@tonic-gate 	sprintf(scratch, "Re-read complete, %d %s bound, %d fds free", Valid_addrs,
18577c478bd9Sstevel@tonic-gate 		(Valid_addrs == 1) ? "address" : "addresses",
18587c478bd9Sstevel@tonic-gate 		Ndesc-Valid_addrs-USEDFDS);
18597c478bd9Sstevel@tonic-gate 	logmessage(scratch);
18607c478bd9Sstevel@tonic-gate 
18617c478bd9Sstevel@tonic-gate 	/* Pollfds[0] is for _pmpipe */
18627c478bd9Sstevel@tonic-gate 	sp = &Pollfds[1];
18637c478bd9Sstevel@tonic-gate 	for (entry_p = Dbfhead; entry_p && entry_p->dbf_svc_code; entry_p++) {
18647c478bd9Sstevel@tonic-gate 		if (entry_p->dbf_fd >= 0) {
18657c478bd9Sstevel@tonic-gate 			sp->fd = entry_p->dbf_fd;
18667c478bd9Sstevel@tonic-gate 			DEBUG((9, "adding %d to poll struct", entry_p->dbf_fd));
18677c478bd9Sstevel@tonic-gate 			sp->events = POLLIN;
18687c478bd9Sstevel@tonic-gate 			sp->revents = 0;
18697c478bd9Sstevel@tonic-gate 			sp++;
18707c478bd9Sstevel@tonic-gate 		}
18717c478bd9Sstevel@tonic-gate 	}
18727c478bd9Sstevel@tonic-gate }
18737c478bd9Sstevel@tonic-gate 
18747c478bd9Sstevel@tonic-gate /*
18757c478bd9Sstevel@tonic-gate  * unbind the address, close the file descriptor, and free call structs
18767c478bd9Sstevel@tonic-gate  */
18777c478bd9Sstevel@tonic-gate 
1878113f4232Sakaplan int
18797c478bd9Sstevel@tonic-gate del_prvaddr(dbp)
18807c478bd9Sstevel@tonic-gate dbf_t	*dbp;
18817c478bd9Sstevel@tonic-gate {
18827c478bd9Sstevel@tonic-gate 	struct	callsave	*tmp;
18837c478bd9Sstevel@tonic-gate 	struct	call_list	*q;
18847c478bd9Sstevel@tonic-gate 	struct	t_call		*call;
18857c478bd9Sstevel@tonic-gate 	int	i;
18867c478bd9Sstevel@tonic-gate 	char	scratch[BUFSIZ];
18877c478bd9Sstevel@tonic-gate 
18887c478bd9Sstevel@tonic-gate 	DEBUG((9, "in del_prvaddr..."));
18897c478bd9Sstevel@tonic-gate 	rpc_unregister(dbp);
18907c478bd9Sstevel@tonic-gate 	if (dbp->dbf_fd < 0)
18917c478bd9Sstevel@tonic-gate 		return -1;
18927c478bd9Sstevel@tonic-gate 
18937c478bd9Sstevel@tonic-gate 	q = Priv_call + dbp->dbf_fd;
18947c478bd9Sstevel@tonic-gate 	i = 0;
18957c478bd9Sstevel@tonic-gate 
18967c478bd9Sstevel@tonic-gate 	/* delete pending calls */
18977c478bd9Sstevel@tonic-gate 	while ((tmp = dequeue(q)) != NULL) {
18987c478bd9Sstevel@tonic-gate 		i++;
18997c478bd9Sstevel@tonic-gate 		call = tmp->c_cp;
19007c478bd9Sstevel@tonic-gate 		t_snddis(dbp->dbf_fd, call);
19017c478bd9Sstevel@tonic-gate 		t_free((char *)call, T_CALL);
19027c478bd9Sstevel@tonic-gate 		free(tmp);
19037c478bd9Sstevel@tonic-gate 	}
19047c478bd9Sstevel@tonic-gate 
19057c478bd9Sstevel@tonic-gate 	/* delete free call structs we don't need */
19067c478bd9Sstevel@tonic-gate 	for ( ; i < dbp->dbf_maxcon; i++) {
19077c478bd9Sstevel@tonic-gate 		tmp = dequeue(Free_call_p);
19087c478bd9Sstevel@tonic-gate 		t_free((char *)tmp->c_cp, T_CALL);
19097c478bd9Sstevel@tonic-gate 		free(tmp);
19107c478bd9Sstevel@tonic-gate 	}
19117c478bd9Sstevel@tonic-gate 
19127c478bd9Sstevel@tonic-gate 	t_unbind(dbp->dbf_fd);
19137c478bd9Sstevel@tonic-gate 	t_close(dbp->dbf_fd);
19147c478bd9Sstevel@tonic-gate 	sprintf(scratch, "Unbind %s: fd %d addr %s", dbp->dbf_svc_code,
19157c478bd9Sstevel@tonic-gate 		dbp->dbf_fd, dbp->dbf_prv_adr);
19167c478bd9Sstevel@tonic-gate 	logmessage(scratch);
19177c478bd9Sstevel@tonic-gate 	dbp->dbf_fd = -1;
19187c478bd9Sstevel@tonic-gate 	return 0;
19197c478bd9Sstevel@tonic-gate }
19207c478bd9Sstevel@tonic-gate 
19217c478bd9Sstevel@tonic-gate 
19227c478bd9Sstevel@tonic-gate /*
19237c478bd9Sstevel@tonic-gate  * look through the old database file to see if this service code matches
19247c478bd9Sstevel@tonic-gate  * one already present
19257c478bd9Sstevel@tonic-gate  */
19267c478bd9Sstevel@tonic-gate 
19277c478bd9Sstevel@tonic-gate dbf_t *
19287c478bd9Sstevel@tonic-gate svc_code_match(new_code)
19297c478bd9Sstevel@tonic-gate char	*new_code;
19307c478bd9Sstevel@tonic-gate {
19317c478bd9Sstevel@tonic-gate 	dbf_t	*dbp;
19327c478bd9Sstevel@tonic-gate 
19337c478bd9Sstevel@tonic-gate 	for (dbp = Dbfhead; dbp && dbp->dbf_svc_code; dbp++) {
19347c478bd9Sstevel@tonic-gate 		if (strcmp(dbp->dbf_svc_code, new_code) == 0)
19357c478bd9Sstevel@tonic-gate 			return(dbp);
19367c478bd9Sstevel@tonic-gate 	}
19377c478bd9Sstevel@tonic-gate 	return((dbf_t *)NULL);
19387c478bd9Sstevel@tonic-gate }
19397c478bd9Sstevel@tonic-gate 
19407c478bd9Sstevel@tonic-gate 
19417c478bd9Sstevel@tonic-gate /*
19427c478bd9Sstevel@tonic-gate  * register an rpc service with rpcbind
19437c478bd9Sstevel@tonic-gate  */
19447c478bd9Sstevel@tonic-gate 
19457c478bd9Sstevel@tonic-gate void
19467c478bd9Sstevel@tonic-gate rpc_register(dbp)
1947113f4232Sakaplan dbf_t *dbp;
19487c478bd9Sstevel@tonic-gate {
19497c478bd9Sstevel@tonic-gate 	char	str[NAMEBUFSZ];
19507c478bd9Sstevel@tonic-gate 	char	scratch[BUFSIZ];
19517c478bd9Sstevel@tonic-gate 	char	*lstr = str;
19527c478bd9Sstevel@tonic-gate 	struct	netbuf	netbuf;
19537c478bd9Sstevel@tonic-gate 	extern	struct	netbuf *stoa();
19547c478bd9Sstevel@tonic-gate 	extern	int	errno;
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate 	DEBUG((9, "in rpc_register"));
19577c478bd9Sstevel@tonic-gate 	if (dbp->dbf_prognum == -1 || dbp->dbf_version == -1)
19587c478bd9Sstevel@tonic-gate 		/* not an rpc service */
19597c478bd9Sstevel@tonic-gate 		return;
19607c478bd9Sstevel@tonic-gate 
19617c478bd9Sstevel@tonic-gate 	rpc_unregister(dbp);
19627c478bd9Sstevel@tonic-gate 	netbuf.buf = NULL;
19637c478bd9Sstevel@tonic-gate 	netbuf.maxlen = 0;
19647c478bd9Sstevel@tonic-gate 	netbuf.len = 0;
19657c478bd9Sstevel@tonic-gate 	strcpy(lstr, dbp->dbf_prv_adr);
19667c478bd9Sstevel@tonic-gate 	if (stoa(lstr, &netbuf) == (struct netbuf *)NULL)  {
19677c478bd9Sstevel@tonic-gate 		DEBUG((9,"stoa returned null, errno = %d\n",errno));
19687c478bd9Sstevel@tonic-gate 		error(1, E_MALLOC);
19697c478bd9Sstevel@tonic-gate 		return;
19707c478bd9Sstevel@tonic-gate 	}
19717c478bd9Sstevel@tonic-gate 	if (rpcb_set(dbp->dbf_prognum, dbp->dbf_version, Netconf, &netbuf)) {
19727c478bd9Sstevel@tonic-gate 		sprintf(scratch,"  registered with rpcbind, prognum %d version %d", dbp->dbf_prognum, dbp->dbf_version);
19737c478bd9Sstevel@tonic-gate 		logmessage(scratch);
19747c478bd9Sstevel@tonic-gate 	}
19757c478bd9Sstevel@tonic-gate 	else {
19767c478bd9Sstevel@tonic-gate 		logmessage("rpcb_set failed, service not registered with rpcbind");
19777c478bd9Sstevel@tonic-gate 	}
19787c478bd9Sstevel@tonic-gate 	return;
19797c478bd9Sstevel@tonic-gate }
19807c478bd9Sstevel@tonic-gate 
19817c478bd9Sstevel@tonic-gate 
19827c478bd9Sstevel@tonic-gate /*
19837c478bd9Sstevel@tonic-gate  * unregister an rpc service with rpcbind
19847c478bd9Sstevel@tonic-gate  */
19857c478bd9Sstevel@tonic-gate 
19867c478bd9Sstevel@tonic-gate void
19877c478bd9Sstevel@tonic-gate rpc_unregister(dbp)
1988113f4232Sakaplan dbf_t *dbp;
19897c478bd9Sstevel@tonic-gate {
19907c478bd9Sstevel@tonic-gate 	DEBUG((9, "in rpc_unregister"));
19917c478bd9Sstevel@tonic-gate 	if (dbp->dbf_prognum == -1 || dbp->dbf_version == -1)
19927c478bd9Sstevel@tonic-gate 		/* not an rpc service */
19937c478bd9Sstevel@tonic-gate 		return;
19947c478bd9Sstevel@tonic-gate 	(void) rpcb_unset(dbp->dbf_prognum, dbp->dbf_version, Netconf);
19957c478bd9Sstevel@tonic-gate }
1996