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