xref: /onnv-gate/usr/src/cmd/nlsadmin/nlsadmin.c (revision 640:acd8cb5618b4)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*640Sbasabi  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate 
330Sstevel@tonic-gate /*
340Sstevel@tonic-gate  * nlsadmin.c -- control program for the network listener service
350Sstevel@tonic-gate  *
360Sstevel@tonic-gate  * This program replaces a previous version of nlsadmin.
370Sstevel@tonic-gate  *
380Sstevel@tonic-gate  * This version of nlsadmin works with the service access facility to
390Sstevel@tonic-gate  * control the network listener.  The functionality of the SVR3.2 nlsadmin
400Sstevel@tonic-gate  * command is supported through calls to the more general sacadm and pmadm
410Sstevel@tonic-gate  * commands available through SAF.  Users should migrate away from nlsadmin
420Sstevel@tonic-gate  * to sacadm and pmadm for these functions.
430Sstevel@tonic-gate  *
440Sstevel@tonic-gate  * The -m option of the SVR3.2 nlsadmin command is now ignored.
450Sstevel@tonic-gate  *
460Sstevel@tonic-gate  * The -t option associates an address with service code 1 (same as in SVR3.2).
470Sstevel@tonic-gate  * The -l option associates an address with service code 0.
480Sstevel@tonic-gate  *
490Sstevel@tonic-gate  * nlsadmin also contains new functionality -- the ability to format a
500Sstevel@tonic-gate  * "listener-specific" string to put in the _pmtab database.  This
510Sstevel@tonic-gate  * functionality is required by SAF.
520Sstevel@tonic-gate  */
530Sstevel@tonic-gate 
540Sstevel@tonic-gate #include <sys/types.h>
550Sstevel@tonic-gate #include <sys/stat.h>
560Sstevel@tonic-gate #include <stdio.h>
57*640Sbasabi #include <stdlib.h>
580Sstevel@tonic-gate #include <ctype.h>
590Sstevel@tonic-gate #include <errno.h>
600Sstevel@tonic-gate #include <string.h>
610Sstevel@tonic-gate #include <sac.h>
620Sstevel@tonic-gate #include "nlsadmin.h"
630Sstevel@tonic-gate 
640Sstevel@tonic-gate #define OPTIONS	"a:c:d:e:ikl:mo:p:qr:st:vw:xy:z:A:N:VDR:"
650Sstevel@tonic-gate #ifndef FALSE
660Sstevel@tonic-gate #define TRUE	1
670Sstevel@tonic-gate #define FALSE	0
680Sstevel@tonic-gate #endif
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate  * defines for -q exit codes: QZERO is used for conditions that the
710Sstevel@tonic-gate  * man page documents as returning 0, QONE for those that return 1
720Sstevel@tonic-gate  */
730Sstevel@tonic-gate #define QZERO	0
740Sstevel@tonic-gate #define QONE	1
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * defines for simulated standard error format code
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate #define MM_NOSEV        0
800Sstevel@tonic-gate #define MM_HALT         1
810Sstevel@tonic-gate #define MM_ERROR        2
820Sstevel@tonic-gate #define MM_WARNING      3
830Sstevel@tonic-gate #define MM_INFO         4
840Sstevel@tonic-gate 
850Sstevel@tonic-gate char	*Nlsname;		/* set to argv[0]			*/
860Sstevel@tonic-gate char	Label[25];		/* label component for fmtmsg		*/
870Sstevel@tonic-gate int	Quietflag = FALSE;	/* set to TRUE when -q used		*/
880Sstevel@tonic-gate 
890Sstevel@tonic-gate extern	int errno;
900Sstevel@tonic-gate void	nlsmesg();
910Sstevel@tonic-gate uid_t	geteuid();
920Sstevel@tonic-gate char	*nexttok();
930Sstevel@tonic-gate char	*pflags();
940Sstevel@tonic-gate char	*gencmdstr();
950Sstevel@tonic-gate 
960Sstevel@tonic-gate struct	svcfields {
970Sstevel@tonic-gate 	char	*pmtag;
980Sstevel@tonic-gate 	char	*pmtype;
990Sstevel@tonic-gate 	char	*svc_code;
1000Sstevel@tonic-gate 	char	*flags;
1010Sstevel@tonic-gate 	char	*id;
1020Sstevel@tonic-gate 	char	*res1;
1030Sstevel@tonic-gate 	char	*res2;
1040Sstevel@tonic-gate 	char	*res3;
1050Sstevel@tonic-gate 	char	*addr;
1060Sstevel@tonic-gate 	char	*rpc;
1070Sstevel@tonic-gate 	char	*lflags;
1080Sstevel@tonic-gate 	char	*modules;
1090Sstevel@tonic-gate 	char	*command;
1100Sstevel@tonic-gate 	char	*comment;
1110Sstevel@tonic-gate };
1120Sstevel@tonic-gate 
113*640Sbasabi void no_permission(void) __NORETURN;
114*640Sbasabi void usage(int flag);
1150Sstevel@tonic-gate 
116*640Sbasabi int
main(int argc,char ** argv)117*640Sbasabi main(int argc, char **argv)
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate 	extern	char *optarg;
1200Sstevel@tonic-gate 	extern	int optind;
1210Sstevel@tonic-gate 	int	c;			/* used for return from getopt  */
1220Sstevel@tonic-gate 	char	*addrptr = NULL;	/* set when -A address is used	*/
1230Sstevel@tonic-gate 	char	*rpcptr = NULL;		/* set when -R rpcinfo is used	*/
1240Sstevel@tonic-gate 	char	*cmdptr = NULL;		/* set with -c command		*/
1250Sstevel@tonic-gate 	char	*comptr = NULL;		/* set with -y comment (old)	*/
1260Sstevel@tonic-gate 	char	*idptr = NULL;		/* set with -w id (old)		*/
1270Sstevel@tonic-gate 	char	*lptr = NULL;		/* set with -l addr (old)	*/
1280Sstevel@tonic-gate 	char	*moduleptr = NULL;	/* set with -m modules		*/
1290Sstevel@tonic-gate 	char	*pipeptr = NULL;	/* set with -o pipe		*/
1300Sstevel@tonic-gate 	char	*svcptr = NULL;		/* set when service code used (old) */
1310Sstevel@tonic-gate 	char	*tptr = NULL;		/* set when -t addr used (old)	*/
1320Sstevel@tonic-gate 	char	*netspec = NULL;	/* set to the network specification */
1330Sstevel@tonic-gate 	int	flag = 0;		/* bit flag of type of command	*/
1340Sstevel@tonic-gate 	int	exitcode = 0;		/* exit status of this command	*/
1350Sstevel@tonic-gate 	int	lflags = 0;		/* listener flags		*/
1360Sstevel@tonic-gate 	char	buf[BUFSIZ];		/* temp buffer #1		*/
1370Sstevel@tonic-gate 	char	mesg[BUFSIZ];		/* temp buffer #2		*/
1380Sstevel@tonic-gate 	FILE	*fp;			/* used for checking netspec	*/
1390Sstevel@tonic-gate 	char	*ptr;			/* temp pointer			*/
1400Sstevel@tonic-gate 	char	*ptr2;			/* temp pointer			*/
1410Sstevel@tonic-gate 	int	sawsep = 0;		/* flag for RPC separator	*/
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	Nlsname = argv[0];
1440Sstevel@tonic-gate 	sprintf(Label, "UX:%.14s", argv[0]);	/* for standard message fmt */
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	while ((c = getopt(argc, argv, OPTIONS)) != -1) {
1470Sstevel@tonic-gate 		switch (c) {
1480Sstevel@tonic-gate 		case 'a':
1490Sstevel@tonic-gate 			if ( (flag && (flag != CMDFLAG)) || svcptr || Quietflag
1500Sstevel@tonic-gate 			      || addrptr || rpcptr || lflags)
1510Sstevel@tonic-gate 				usage(INCONSISTENT);
1520Sstevel@tonic-gate 			svcptr = optarg;
1530Sstevel@tonic-gate 			break;
1540Sstevel@tonic-gate 		case 'c':
1550Sstevel@tonic-gate 			if ( (flag && (flag != CMDFLAG)) || cmdptr || Quietflag )
1560Sstevel@tonic-gate 				usage(INCONSISTENT);
1570Sstevel@tonic-gate 			cmdptr = optarg;
1580Sstevel@tonic-gate 			flag |= CMDFLAG;
1590Sstevel@tonic-gate 			break;
1600Sstevel@tonic-gate 		case 'd':
1610Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || comptr || addrptr
1620Sstevel@tonic-gate 			     || rpcptr || cmdptr || idptr || lflags )
1630Sstevel@tonic-gate 				usage(INCONSISTENT);
1640Sstevel@tonic-gate 			svcptr = optarg;
1650Sstevel@tonic-gate 			flag |= DISFLAG;
1660Sstevel@tonic-gate 			break;
1670Sstevel@tonic-gate 		case 'e':
1680Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || comptr || addrptr
1690Sstevel@tonic-gate 			     || rpcptr || cmdptr || idptr || lflags )
1700Sstevel@tonic-gate 				usage(INCONSISTENT);
1710Sstevel@tonic-gate 			svcptr = optarg;
1720Sstevel@tonic-gate 			flag |= ENAFLAG;
1730Sstevel@tonic-gate 			break;
1740Sstevel@tonic-gate 		case 'i':
1750Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || comptr || addrptr
1760Sstevel@tonic-gate 			     || rpcptr || cmdptr || idptr || lflags )
1770Sstevel@tonic-gate 				usage(INCONSISTENT);
1780Sstevel@tonic-gate 			flag |= INIFLAG;
1790Sstevel@tonic-gate 			break;
1800Sstevel@tonic-gate 		case 'k':
1810Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || comptr || addrptr
1820Sstevel@tonic-gate 			     || rpcptr || cmdptr || idptr || lflags )
1830Sstevel@tonic-gate 				usage(INCONSISTENT);
1840Sstevel@tonic-gate 			flag |= KILFLAG;
1850Sstevel@tonic-gate 			break;
1860Sstevel@tonic-gate 		case 'l':
1870Sstevel@tonic-gate 			if ( ( flag && (flag != ADRFLAG)) || svcptr || lptr
1880Sstevel@tonic-gate 			      || Quietflag || comptr || addrptr || rpcptr
1890Sstevel@tonic-gate 			      || cmdptr || idptr || lflags )
1900Sstevel@tonic-gate 				usage(INCONSISTENT);
1910Sstevel@tonic-gate 			lptr = optarg;
1920Sstevel@tonic-gate 			flag |= ADRFLAG;
1930Sstevel@tonic-gate 			break;
1940Sstevel@tonic-gate 		case 'm':
1950Sstevel@tonic-gate 			if ( (flag && (flag != CMDFLAG)) || Quietflag || rpcptr || lflags )
1960Sstevel@tonic-gate 				usage(INCONSISTENT);
1970Sstevel@tonic-gate 			flag |= CMDFLAG;
1980Sstevel@tonic-gate 			break;
1990Sstevel@tonic-gate 		case 'o':
2000Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || comptr || idptr || netspec )
2010Sstevel@tonic-gate 				usage(INCONSISTENT);
2020Sstevel@tonic-gate 			pipeptr = optarg;
2030Sstevel@tonic-gate 			flag |= PIPFLAG;
2040Sstevel@tonic-gate 			break;
2050Sstevel@tonic-gate 		case 'p':
2060Sstevel@tonic-gate 			if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG)) || Quietflag )
2070Sstevel@tonic-gate 				usage(INCONSISTENT);
2080Sstevel@tonic-gate 			moduleptr = optarg;
2090Sstevel@tonic-gate 			break;
2100Sstevel@tonic-gate 		case 'q':
2110Sstevel@tonic-gate 			if ( (flag && (flag != ZZZFLAG)) || Quietflag || comptr
2120Sstevel@tonic-gate 			     || rpcptr || lflags || idptr )
2130Sstevel@tonic-gate 				usage(INCONSISTENT);
2140Sstevel@tonic-gate 			Quietflag = TRUE;
2150Sstevel@tonic-gate 			break;
2160Sstevel@tonic-gate 		case 'r':
2170Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || comptr || addrptr
2180Sstevel@tonic-gate 			     || rpcptr || cmdptr || idptr || lflags )
2190Sstevel@tonic-gate 				usage(INCONSISTENT);
2200Sstevel@tonic-gate 			flag |= REMFLAG;
2210Sstevel@tonic-gate 			svcptr = optarg;
2220Sstevel@tonic-gate 			break;
2230Sstevel@tonic-gate 		case 's':
2240Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || comptr || addrptr
2250Sstevel@tonic-gate 			     || rpcptr || cmdptr || idptr || lflags )
2260Sstevel@tonic-gate 				usage(INCONSISTENT);
2270Sstevel@tonic-gate 			flag |= STAFLAG;
2280Sstevel@tonic-gate 			break;
2290Sstevel@tonic-gate 		case 't':
2300Sstevel@tonic-gate 			if ( (flag && (flag != ADRFLAG)) || svcptr || tptr
2310Sstevel@tonic-gate 			      || Quietflag || comptr || addrptr || rpcptr
2320Sstevel@tonic-gate 			      || cmdptr || idptr || lflags )
2330Sstevel@tonic-gate 				usage(INCONSISTENT);
2340Sstevel@tonic-gate 			tptr = optarg;
2350Sstevel@tonic-gate 			flag |= ADRFLAG;
2360Sstevel@tonic-gate 			break;
2370Sstevel@tonic-gate 		case 'v':
2380Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || comptr || rpcptr
2390Sstevel@tonic-gate 			     || addrptr || idptr || lflags )
2400Sstevel@tonic-gate 				usage(INCONSISTENT);
2410Sstevel@tonic-gate 			flag |= VBSFLAG;
2420Sstevel@tonic-gate 			break;
2430Sstevel@tonic-gate 		case 'w':
2440Sstevel@tonic-gate 			if ( (flag && (flag != CMDFLAG)) || Quietflag || idptr
2450Sstevel@tonic-gate 			     || rpcptr || addrptr || lflags )
2460Sstevel@tonic-gate 				usage(INCONSISTENT);
2470Sstevel@tonic-gate 			idptr = optarg;
2480Sstevel@tonic-gate 			break;
2490Sstevel@tonic-gate 		case 'x':
2500Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || netspec || comptr
2510Sstevel@tonic-gate 			     || rpcptr || addrptr || lflags || idptr )
2520Sstevel@tonic-gate 				usage(INCONSISTENT);
2530Sstevel@tonic-gate 			flag |= NETFLAG;
2540Sstevel@tonic-gate 			break;
2550Sstevel@tonic-gate 		case 'y':
2560Sstevel@tonic-gate 			if ( (flag && (flag != CMDFLAG)) || Quietflag || comptr
2570Sstevel@tonic-gate 			     || rpcptr || addrptr || lflags )
2580Sstevel@tonic-gate 				usage(INCONSISTENT);
2590Sstevel@tonic-gate 			comptr = optarg;
2600Sstevel@tonic-gate 			break;
2610Sstevel@tonic-gate 		case 'z':
2620Sstevel@tonic-gate 			if ( flag || svcptr || comptr || addrptr || rpcptr
2630Sstevel@tonic-gate 			     || idptr || lflags )
2640Sstevel@tonic-gate 				usage(INCONSISTENT);
2650Sstevel@tonic-gate 			flag |= ZZZFLAG;
2660Sstevel@tonic-gate 			svcptr = optarg;
2670Sstevel@tonic-gate 			break;
2680Sstevel@tonic-gate 		case 'A':
2690Sstevel@tonic-gate 			if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG))
2700Sstevel@tonic-gate 			     || netspec || svcptr || idptr || comptr )
2710Sstevel@tonic-gate 				usage(INCONSISTENT);
2720Sstevel@tonic-gate 			addrptr = optarg;
2730Sstevel@tonic-gate 			break;
2740Sstevel@tonic-gate 		case 'D':
2750Sstevel@tonic-gate 			if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG))
2760Sstevel@tonic-gate 			     || netspec || svcptr || idptr || comptr || addrptr
2770Sstevel@tonic-gate 			     || lflags )
2780Sstevel@tonic-gate 				usage(INCONSISTENT);
2790Sstevel@tonic-gate 			lflags |= DFLAG;
2800Sstevel@tonic-gate 			break;
2810Sstevel@tonic-gate 		case 'N':
2820Sstevel@tonic-gate 			if ( netspec )
2830Sstevel@tonic-gate 				usage(INCONSISTENT);
2840Sstevel@tonic-gate 			netspec = optarg;
2850Sstevel@tonic-gate 			break;
2860Sstevel@tonic-gate 		case 'R':
2870Sstevel@tonic-gate 			if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG))
2880Sstevel@tonic-gate 			     || netspec || svcptr || idptr || comptr )
2890Sstevel@tonic-gate 				usage(INCONSISTENT);
2900Sstevel@tonic-gate 			for (ptr = optarg; *ptr; ++ptr) {
2910Sstevel@tonic-gate 				if ((*ptr == ':') && !sawsep) {
2920Sstevel@tonic-gate 					/*
2930Sstevel@tonic-gate 					 * skip separator - note that if
2940Sstevel@tonic-gate 					 * separator has been seen, it's not
2950Sstevel@tonic-gate 					 * a digit so it will generate a usage
2960Sstevel@tonic-gate 					 * message below like we want
2970Sstevel@tonic-gate 					 */
2980Sstevel@tonic-gate 					sawsep++;
2990Sstevel@tonic-gate 					continue;
3000Sstevel@tonic-gate 				}
3010Sstevel@tonic-gate 				if (!isdigit(*ptr))
3020Sstevel@tonic-gate 					usage(USAGE);
3030Sstevel@tonic-gate 			}
3040Sstevel@tonic-gate 			ptr = strchr(optarg, ':');
3050Sstevel@tonic-gate 			if (ptr)
3060Sstevel@tonic-gate 				/* change the ':' to a ',' */
3070Sstevel@tonic-gate 				*ptr = ',';
3080Sstevel@tonic-gate 			else
3090Sstevel@tonic-gate 				usage(USAGE);
3100Sstevel@tonic-gate 			rpcptr = optarg;
3110Sstevel@tonic-gate 			break;
3120Sstevel@tonic-gate 		case 'V':
3130Sstevel@tonic-gate 			if ( flag || svcptr || Quietflag || comptr || netspec
3140Sstevel@tonic-gate 			     || rpcptr || addrptr || idptr || lflags )
3150Sstevel@tonic-gate 				usage(INCONSISTENT);
3160Sstevel@tonic-gate 			flag |= VERFLAG;
3170Sstevel@tonic-gate 			break;
3180Sstevel@tonic-gate 		case '?':
3190Sstevel@tonic-gate 			usage(USAGE);
3200Sstevel@tonic-gate 		}
321*640Sbasabi 		/* NOTREACHED */
3220Sstevel@tonic-gate 	}
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	if ((optind < argc) && ! netspec)
3250Sstevel@tonic-gate 		netspec = argv[optind++];
3260Sstevel@tonic-gate 	if (optind < argc)
3270Sstevel@tonic-gate 		usage(USAGE);
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	/* determine if this command requires a netspec */
3310Sstevel@tonic-gate 	if (flag != CMDFLAG) {
3320Sstevel@tonic-gate 		/* if flag is CMDFLAG, more complicated checking of netspec
3330Sstevel@tonic-gate 		 * is done below in switch
3340Sstevel@tonic-gate 		 */
3350Sstevel@tonic-gate 		if ((flag == PIPFLAG || flag == VERFLAG || flag == NETFLAG)) {
3360Sstevel@tonic-gate 			if (netspec)
3370Sstevel@tonic-gate 				usage(USAGE);
3380Sstevel@tonic-gate 		}
3390Sstevel@tonic-gate 		else if (!netspec)
3400Sstevel@tonic-gate 			usage(USAGE);
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	if (netspec && (flag != INIFLAG)) {
3440Sstevel@tonic-gate 		sprintf(buf, SAC_LSPM, netspec);
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 		if ((fp = popen(buf, "r")) == NULL) {
3470Sstevel@tonic-gate 			nlsmesg(MM_ERROR, "System error");
3480Sstevel@tonic-gate 			exit(NLS_SYSERR);
3490Sstevel@tonic-gate 		}
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 		if (fgets(buf, BUFSIZ, fp) == NULL) {
3520Sstevel@tonic-gate 			nlsmesg(MM_ERROR, "Invalid network specification");
3530Sstevel@tonic-gate 			exit(NLS_BADPM);
3540Sstevel@tonic-gate 		}
3550Sstevel@tonic-gate 		else {
3560Sstevel@tonic-gate 			ptr = strchr(buf, ':');
3570Sstevel@tonic-gate 			ptr++;
3580Sstevel@tonic-gate 			ptr2 = strchr(ptr, ':');
3590Sstevel@tonic-gate 			*ptr2 = NULL;
3600Sstevel@tonic-gate 			if (strcmp(ptr, LISTENTYPE) != 0) {
3610Sstevel@tonic-gate 				sprintf(mesg, "Network specification \"%s\" is not of type %s", netspec, LISTENTYPE);
3620Sstevel@tonic-gate 				nlsmesg(MM_ERROR, mesg);
3630Sstevel@tonic-gate 				exit(NLS_BADPM);
3640Sstevel@tonic-gate 			}
3650Sstevel@tonic-gate 		}
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 		pclose(fp);
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	if (svcptr) {
3710Sstevel@tonic-gate 		/* check to see if service code is "correct" -- right range
3720Sstevel@tonic-gate 		 * and format.  The -m flag is ignored, so no check for
3730Sstevel@tonic-gate 		 * "administrative" service codes (0-100) is done.
3740Sstevel@tonic-gate 		 */
3750Sstevel@tonic-gate 		c = strlen(svcptr);
3760Sstevel@tonic-gate 		if ((c == 0) || (c >= SVC_CODE_SZ)) {
3770Sstevel@tonic-gate 			sprintf(mesg, "Service code contains more than %d characters", SVC_CODE_SZ);
3780Sstevel@tonic-gate 			nlsmesg(MM_ERROR, mesg);
3790Sstevel@tonic-gate 			exit(NLS_SERV);
3800Sstevel@tonic-gate 		}
3810Sstevel@tonic-gate 	}
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	switch (flag) {
3840Sstevel@tonic-gate 	default:
3850Sstevel@tonic-gate 		usage(USAGE);
3860Sstevel@tonic-gate 		break;
3870Sstevel@tonic-gate 	case NONE:
3880Sstevel@tonic-gate 		if ( svcptr || comptr || rpcptr || lflags || idptr )
3890Sstevel@tonic-gate 			usage(INCONSISTENT);
3900Sstevel@tonic-gate 		exitcode = prt_nets(netspec);
3910Sstevel@tonic-gate 		break;
3920Sstevel@tonic-gate 	case INIFLAG:
3930Sstevel@tonic-gate 		if (geteuid() != ROOT)
3940Sstevel@tonic-gate 			no_permission();
3950Sstevel@tonic-gate 		exitcode = add_pm(netspec);
3960Sstevel@tonic-gate 		break;
3970Sstevel@tonic-gate 	case CMDFLAG:
3980Sstevel@tonic-gate 		if ( svcptr || comptr || idptr || netspec ) {
3990Sstevel@tonic-gate 			if (geteuid() != ROOT)
4000Sstevel@tonic-gate 				no_permission();
4010Sstevel@tonic-gate 			if ((exitcode = old_addsvc(svcptr, "", cmdptr, comptr, moduleptr, idptr, NULL, netspec)) != NLS_OK)
4020Sstevel@tonic-gate 				switch (exitcode) {
4030Sstevel@tonic-gate 				case NLS_SERV:
4040Sstevel@tonic-gate 					nlsmesg(MM_ERROR, "Service code already exists");
4050Sstevel@tonic-gate 					break;
4060Sstevel@tonic-gate 				default:
4070Sstevel@tonic-gate 					nlsmesg(MM_ERROR, "Could not add service");
4080Sstevel@tonic-gate 					break;
4090Sstevel@tonic-gate 				}
4100Sstevel@tonic-gate 		}
4110Sstevel@tonic-gate 		else {
4120Sstevel@tonic-gate 			if (netspec)
4130Sstevel@tonic-gate 				usage(INCONSISTENT);
4140Sstevel@tonic-gate 			exitcode = prt_cmd(cmdptr, CFLAG | lflags, moduleptr, addrptr, rpcptr);
4150Sstevel@tonic-gate 		}
4160Sstevel@tonic-gate 		break;
4170Sstevel@tonic-gate 	case PIPFLAG:
4180Sstevel@tonic-gate 		if (geteuid() != ROOT)
4190Sstevel@tonic-gate 			no_permission();
4200Sstevel@tonic-gate 		exitcode = prt_cmd(pipeptr, PFLAG | lflags, moduleptr, addrptr, rpcptr);
4210Sstevel@tonic-gate 		break;
4220Sstevel@tonic-gate 	case VERFLAG:
4230Sstevel@tonic-gate 		printf("%d\n", VERSION);
4240Sstevel@tonic-gate 		exit(NLS_OK);
4250Sstevel@tonic-gate 		break;
4260Sstevel@tonic-gate 	case DISFLAG:
4270Sstevel@tonic-gate 		if (geteuid() != ROOT)
4280Sstevel@tonic-gate 			no_permission();
4290Sstevel@tonic-gate 		exitcode = disable_svc(svcptr, netspec);
4300Sstevel@tonic-gate 		break;
4310Sstevel@tonic-gate 	case ENAFLAG:
4320Sstevel@tonic-gate 		if (geteuid() != ROOT)
4330Sstevel@tonic-gate 			no_permission();
4340Sstevel@tonic-gate 		exitcode = enable_svc(svcptr, netspec);
4350Sstevel@tonic-gate 		break;
4360Sstevel@tonic-gate 	case KILFLAG:
4370Sstevel@tonic-gate 		if (geteuid() != ROOT)
4380Sstevel@tonic-gate 			no_permission();
4390Sstevel@tonic-gate 		exitcode = kill_listener(netspec);
4400Sstevel@tonic-gate 		break;
4410Sstevel@tonic-gate 	case ADRFLAG:
4420Sstevel@tonic-gate 		/* check for root permissions in setup_addr */
4430Sstevel@tonic-gate 		exitcode = setup_addr(lptr, tptr, netspec);
4440Sstevel@tonic-gate 		break;
4450Sstevel@tonic-gate 	case REMFLAG:
4460Sstevel@tonic-gate 		if (geteuid() != ROOT)
4470Sstevel@tonic-gate 			no_permission();
4480Sstevel@tonic-gate 		exitcode = remove_svc(svcptr, netspec, TRUE);
4490Sstevel@tonic-gate 		break;
4500Sstevel@tonic-gate 	case STAFLAG:
4510Sstevel@tonic-gate 		if (geteuid() != ROOT)
4520Sstevel@tonic-gate 			no_permission();
4530Sstevel@tonic-gate 		exitcode = start_listener(netspec);
4540Sstevel@tonic-gate 		break;
4550Sstevel@tonic-gate 	case VBSFLAG:
4560Sstevel@tonic-gate 		exitcode = prt_svcs(NULL, netspec);
4570Sstevel@tonic-gate 		break;
4580Sstevel@tonic-gate 	case NETFLAG:
4590Sstevel@tonic-gate 		exitcode = prt_nets(NULL);
4600Sstevel@tonic-gate 		break;
4610Sstevel@tonic-gate 	case ZZZFLAG:
4620Sstevel@tonic-gate 		exitcode = prt_svcs(svcptr, netspec);
4630Sstevel@tonic-gate 		break;
4640Sstevel@tonic-gate 	}
4650Sstevel@tonic-gate 	if (exitcode == NLS_SYSERR)
4660Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "System error in SAC command");
467*640Sbasabi 	return (exitcode);
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate static char umsg[] = "usage: %s -x\n\
4720Sstevel@tonic-gate        %s [ options ] netspec\n\
4730Sstevel@tonic-gate        %s [ options ] -N port_monitor_tag\n\
4740Sstevel@tonic-gate        %s -V\n\
4750Sstevel@tonic-gate        %s -c cmd | -o pipename [ -p modules ] [ -A addr | -D ] \\\n\
4760Sstevel@tonic-gate           [ -R prognum:versnum ]\n\
4770Sstevel@tonic-gate \n\
4780Sstevel@tonic-gate        [ options ] are:\n\
4790Sstevel@tonic-gate        [ -a svc_code -c \"cmd\" -y \"cmt\" [-p modules] [-w id] ]\n\
4800Sstevel@tonic-gate        [-q] | [-v] | [-s] | [-k] | [-i] |\n\
4810Sstevel@tonic-gate        [-e svc_code] | [-d svc_code] | [-r svc_code] | [[-q] -z svc_code]\n\
4820Sstevel@tonic-gate        [[-l addr | -] [-t addr | -]] |\n\
4830Sstevel@tonic-gate ";
4840Sstevel@tonic-gate 
485*640Sbasabi void
usage(int flag)486*640Sbasabi usage(int flag)
4870Sstevel@tonic-gate {
4880Sstevel@tonic-gate 	switch (flag) {
4890Sstevel@tonic-gate 	case INCONSISTENT:
4900Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Inconsistent options");
4910Sstevel@tonic-gate 		break;
4920Sstevel@tonic-gate 	case MISSINGARG:
4930Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Missing argument");
4940Sstevel@tonic-gate 		break;
4950Sstevel@tonic-gate 	case USAGE:
4960Sstevel@tonic-gate 		break;
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 	fprintf(stderr, umsg, Nlsname, Nlsname, Nlsname, Nlsname, Nlsname);
4990Sstevel@tonic-gate 	exit(NLS_CMD);
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate /*
5040Sstevel@tonic-gate  * no_permission:  print out error message and exit when the user needs to
5050Sstevel@tonic-gate  *                 needs to be root and isn't.
5060Sstevel@tonic-gate  */
5070Sstevel@tonic-gate 
508*640Sbasabi void
no_permission(void)509*640Sbasabi no_permission(void)
5100Sstevel@tonic-gate {
5110Sstevel@tonic-gate 	nlsmesg(MM_ERROR, "Must be super user");
5120Sstevel@tonic-gate 	exit(NLS_PERM);
5130Sstevel@tonic-gate }
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate /*
5160Sstevel@tonic-gate  * nlsmesg:  print out either an error or a warning message.  severity must
5170Sstevel@tonic-gate  *           be either MM_ERROR or MM_WARNING.  this routine will be converted
5180Sstevel@tonic-gate  *           to use the standard message format later.
5190Sstevel@tonic-gate  */
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate void
nlsmesg(int severity,char * text)522*640Sbasabi nlsmesg(int severity, char *text)
5230Sstevel@tonic-gate {
5240Sstevel@tonic-gate 	int	class;
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	if (severity == MM_ERROR)
5270Sstevel@tonic-gate 		fprintf(stderr, "%s: error: %s\n", Nlsname, text);
5280Sstevel@tonic-gate 	else
5290Sstevel@tonic-gate 		fprintf(stderr, "%s: warning: %s\n", Nlsname, text);
5300Sstevel@tonic-gate 	return;
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate /*
5340Sstevel@tonic-gate  * prt_cmd:  print out the listener-dependent string for sacadm.
5350Sstevel@tonic-gate  */
5360Sstevel@tonic-gate 
537*640Sbasabi int
prt_cmd(char * path,long flags,char * modules,char * addr,char * rpcp)538*640Sbasabi prt_cmd(char *path, long flags, char *modules, char *addr, char *rpcp)
539*640Sbasabi 	/* path: full path of command or pipe	*/
540*640Sbasabi 	/* flags: listener flags		*/
541*640Sbasabi 	/* PFLAG for pipe			*/
542*640Sbasabi 	/* CFLAG for command			*/
543*640Sbasabi 	/* DFLAG for dynamic addr		*/
544*640Sbasabi  	/* modules: STREAMS modules to push	*/
545*640Sbasabi 	/* addr: private address		*/
546*640Sbasabi 	/* rpcp: RPC prog and ver #		*/
5470Sstevel@tonic-gate {
5480Sstevel@tonic-gate 	struct	stat	sbuf;
5490Sstevel@tonic-gate 	char	mesgbuf[BUFSIZ];
5500Sstevel@tonic-gate 	char	*tmp;
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 	if (*path != '/') {
5530Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Must specify full path name");
5540Sstevel@tonic-gate 		return(NLS_CMD);
5550Sstevel@tonic-gate 	}
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 	if ((tmp = strchr(path, ' ')) != NULL)
5580Sstevel@tonic-gate 		*tmp = NULL;
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 	if (stat(path, &sbuf) < 0) {
5610Sstevel@tonic-gate 		if (errno != EFAULT) {
5620Sstevel@tonic-gate 			sprintf(mesgbuf, "%s does not exist", path);
5630Sstevel@tonic-gate 			nlsmesg(MM_WARNING, mesgbuf);
5640Sstevel@tonic-gate 		}
5650Sstevel@tonic-gate 		else
5660Sstevel@tonic-gate 			return(NLS_SYSERR);
5670Sstevel@tonic-gate 	}
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 	if (tmp)
5700Sstevel@tonic-gate 		*tmp = ' ';
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	printf("%s:%s:%s:%s:%s\n", (addr ? addr : ""), (rpcp ? rpcp : ""),
5730Sstevel@tonic-gate 		pflags(flags), (modules ? modules : ""), path);
5740Sstevel@tonic-gate 	return(NLS_OK);
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate /*
5780Sstevel@tonic-gate  * old_addsvc:  use pmadm to add a service code to the listener.  this will
5790Sstevel@tonic-gate  *              not allow specification of a private address -- use pmadm!
5800Sstevel@tonic-gate  */
5810Sstevel@tonic-gate 
582*640Sbasabi int
old_addsvc(char * svc,char * addr,char * cmd,char * com,char * module,char * id,char * flags,char * netspec)583*640Sbasabi old_addsvc(char *svc, char *addr, char *cmd, char *com, char *module,
584*640Sbasabi     char *id, char *flags, char *netspec)
5850Sstevel@tonic-gate {
5860Sstevel@tonic-gate 	char	buf[BUFSIZ];
5870Sstevel@tonic-gate 	char	mesgbuf[BUFSIZ];
5880Sstevel@tonic-gate 	int	rtn;
5890Sstevel@tonic-gate 	struct	stat	sbuf;
5900Sstevel@tonic-gate 	char	*tmp;
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 	if (!svc || !cmd || !com || !netspec)
5930Sstevel@tonic-gate 		usage(MISSINGARG);
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	/* create "port-monitor specific" info in the same way as prt_cmd */
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	if (*cmd != '/') {
5980Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Must specify full path name");
5990Sstevel@tonic-gate 		return(NLS_CMD);
6000Sstevel@tonic-gate 	}
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	if ((tmp = strchr(cmd, ' ')) != NULL)
6030Sstevel@tonic-gate 		*tmp = NULL;
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	if (stat(cmd, &sbuf) < 0) {
6060Sstevel@tonic-gate 		if (errno != EFAULT) {
6070Sstevel@tonic-gate 			sprintf(mesgbuf, "%s does not exist", cmd);
6080Sstevel@tonic-gate 			nlsmesg(MM_WARNING, mesgbuf);
6090Sstevel@tonic-gate 		}
6100Sstevel@tonic-gate 		else
6110Sstevel@tonic-gate 			return(NLS_SYSERR);
6120Sstevel@tonic-gate 	}
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 	if (tmp)
6150Sstevel@tonic-gate 		*tmp = ' ';
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 	if (addr)
6180Sstevel@tonic-gate 		sprintf(mesgbuf, "'%s::c:%s:%s'", addr, module ? module : "" , cmd);
6190Sstevel@tonic-gate 	else
6200Sstevel@tonic-gate 		sprintf(mesgbuf, "'::c:%s:%s'", module ? module : "" , cmd);
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	if (flags && *flags)
6230Sstevel@tonic-gate 		sprintf(buf, PM_ADDSVCF, netspec, svc, (id)?id:DEFAULTID, flags, mesgbuf, VERSION, com ? com : "");
6240Sstevel@tonic-gate 	else
6250Sstevel@tonic-gate 		sprintf(buf, PM_ADDSVC, netspec, svc, (id)?id:DEFAULTID, mesgbuf, VERSION, com ? com : "");
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	if ((rtn = system(buf)) < 0) {
6280Sstevel@tonic-gate 		return(NLS_SYSERR);
6290Sstevel@tonic-gate 	}
6300Sstevel@tonic-gate 	rtn = (rtn>>8) & 0xff;	/* get child return value out of exit word */
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	switch (rtn) {
6330Sstevel@tonic-gate 	case 0:
6340Sstevel@tonic-gate 		return(NLS_OK);
6350Sstevel@tonic-gate 		break;
6360Sstevel@tonic-gate 	case E_BADARGS:
6370Sstevel@tonic-gate 	case E_SAFERR:
6380Sstevel@tonic-gate 	case E_SYSERR:
6390Sstevel@tonic-gate 	case E_NOEXIST:
6400Sstevel@tonic-gate 	case E_PMRUN:
6410Sstevel@tonic-gate 	case E_PMNOTRUN:
6420Sstevel@tonic-gate 	case E_RECOVER:
6430Sstevel@tonic-gate 	case E_SACNOTRUN:
6440Sstevel@tonic-gate 	default:
6450Sstevel@tonic-gate 		return(NLS_SYSERR);
6460Sstevel@tonic-gate 		break;
6470Sstevel@tonic-gate 	case E_DUP:
6480Sstevel@tonic-gate 		return(NLS_SERV);
6490Sstevel@tonic-gate 		break;
6500Sstevel@tonic-gate 	case E_NOPRIV:
6510Sstevel@tonic-gate 		no_permission();
6520Sstevel@tonic-gate 		break;
6530Sstevel@tonic-gate 	}
654*640Sbasabi 	/* NOTREACHED */
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate /*
6580Sstevel@tonic-gate  * prt_nets:  print the status of one network, or all nets if netspec
6590Sstevel@tonic-gate  *            is NULL
6600Sstevel@tonic-gate  */
661*640Sbasabi int
prt_nets(char * netspec)662*640Sbasabi prt_nets(char *netspec)
6630Sstevel@tonic-gate {
6640Sstevel@tonic-gate 	char	buf[BUFSIZ];
6650Sstevel@tonic-gate 	FILE	*fp;
6660Sstevel@tonic-gate 	char	*name;
6670Sstevel@tonic-gate 	char	*state;
6680Sstevel@tonic-gate 	char	*type;
6690Sstevel@tonic-gate 	int	found = FALSE;
6700Sstevel@tonic-gate 	int	rtn = NLS_OK;
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 	if (netspec == NULL)
6730Sstevel@tonic-gate 		sprintf(buf, SAC_LSTY, LISTENTYPE);
6740Sstevel@tonic-gate 	else
6750Sstevel@tonic-gate 		sprintf(buf, SAC_LSPM, netspec);
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 	if ((fp = popen(buf, "r")) == NULL)
6780Sstevel@tonic-gate 		return(NLS_SYSERR);
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate 	while (fgets(buf, BUFSIZ, fp) != NULL) {
6810Sstevel@tonic-gate 		if ((name = nexttok(buf, ":")) == NULL)
6820Sstevel@tonic-gate 			return(NLS_SYSERR);
6830Sstevel@tonic-gate 		if ((type = nexttok(NULL, ":")) == NULL)
6840Sstevel@tonic-gate 			return(NLS_SYSERR);
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 		if (strcmp(type, LISTENTYPE) != 0)
6870Sstevel@tonic-gate 			continue;  /* ignore other types of port monitors */
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 		found = TRUE;
6900Sstevel@tonic-gate 		if (nexttok(NULL, ":") == NULL)
6910Sstevel@tonic-gate 			return(NLS_SYSERR);
6920Sstevel@tonic-gate 		if (nexttok(NULL, ":") == NULL)
6930Sstevel@tonic-gate 			return(NLS_SYSERR);
6940Sstevel@tonic-gate 		if ((state = nexttok(NULL, ":")) == NULL)
6950Sstevel@tonic-gate 			return(NLS_SYSERR);
6960Sstevel@tonic-gate 		if (strcmp(state, "ENABLED") == NULL ||
6970Sstevel@tonic-gate 		    strcmp(state, "STARTING") == NULL) {
6980Sstevel@tonic-gate 			rtn = QZERO;
6990Sstevel@tonic-gate 			if (!Quietflag)
7000Sstevel@tonic-gate 				printf("%s\t%s\n", name, "ACTIVE");
7010Sstevel@tonic-gate 		}
7020Sstevel@tonic-gate 		else {
7030Sstevel@tonic-gate 			rtn = QONE;
7040Sstevel@tonic-gate 			if (!Quietflag)
7050Sstevel@tonic-gate 				printf("%s\t%s\n", name, "INACTIVE");
7060Sstevel@tonic-gate 		}
7070Sstevel@tonic-gate 	}
7080Sstevel@tonic-gate 	pclose(fp);
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate 	if (netspec && !found) {
7110Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Invalid network specification");
7120Sstevel@tonic-gate 		return(NLS_BADPM);
7130Sstevel@tonic-gate 	}
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	if (netspec)
7160Sstevel@tonic-gate 		return(rtn);
7170Sstevel@tonic-gate 	else
7180Sstevel@tonic-gate 		return(NLS_OK);
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate }
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate /*
7240Sstevel@tonic-gate  * print info about service on netspec, or all services on netspec
7250Sstevel@tonic-gate  * if svc is NULL
7260Sstevel@tonic-gate  */
7270Sstevel@tonic-gate 
728*640Sbasabi int
prt_svcs(char * svc,char * netspec)729*640Sbasabi prt_svcs(char *svc, char *netspec)
7300Sstevel@tonic-gate {
7310Sstevel@tonic-gate 	char	buf[BUFSIZ];
7320Sstevel@tonic-gate 	char	mesg[BUFSIZ];
7330Sstevel@tonic-gate 	FILE	*fp;
7340Sstevel@tonic-gate 	struct	svcfields entry;
7350Sstevel@tonic-gate 	int	rtn;
7360Sstevel@tonic-gate 	int	found = FALSE;
7370Sstevel@tonic-gate 	char	*p;
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate 	if (svc == NULL)
7400Sstevel@tonic-gate 		sprintf(buf, PM_LSALL, netspec);
7410Sstevel@tonic-gate 	else
7420Sstevel@tonic-gate 		sprintf(buf, PM_LSONE, netspec, svc);
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	if ((fp = popen(buf, "r")) == NULL)
7450Sstevel@tonic-gate 		return(NLS_SYSERR);
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate 	while (fgets(buf, BUFSIZ, fp) != NULL) {
7480Sstevel@tonic-gate 		if ((rtn = svc_format(buf, &entry)) != 0) {
7490Sstevel@tonic-gate 			switch (rtn) {
7500Sstevel@tonic-gate 			case NOTLISTEN:
7510Sstevel@tonic-gate 				continue;
7520Sstevel@tonic-gate 				break;
7530Sstevel@tonic-gate 			case BADPMFMT:
7540Sstevel@tonic-gate 				return(NLS_SYSERR);
7550Sstevel@tonic-gate 				break;
7560Sstevel@tonic-gate 			case BADLISFMT:
7570Sstevel@tonic-gate 				sprintf(mesg, "Entry for code \"%s\" has incorrect format", entry.svc_code);
7580Sstevel@tonic-gate 				nlsmesg(MM_WARNING, mesg);
7590Sstevel@tonic-gate 				continue;
7600Sstevel@tonic-gate 				break;
7610Sstevel@tonic-gate 			}
7620Sstevel@tonic-gate 		}
7630Sstevel@tonic-gate 		found = TRUE;
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 		if (!Quietflag) {
7660Sstevel@tonic-gate 			printf("%s\t", entry.svc_code);
7670Sstevel@tonic-gate 			if (*entry.addr)
7680Sstevel@tonic-gate 				printf("%s\t", entry.addr);
7690Sstevel@tonic-gate 			else if (strchr(entry.lflags, 'd'))
7700Sstevel@tonic-gate 				printf("DYNAMIC\t");
7710Sstevel@tonic-gate 			else
7720Sstevel@tonic-gate 				printf("NOADDR\t");
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate 			if (strchr(entry.flags, 'x') == NULL)
7750Sstevel@tonic-gate 				printf("ENABLED \t");
7760Sstevel@tonic-gate 			else
7770Sstevel@tonic-gate 				printf("DISABLED\t");
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 			printf("%s\t%s\t%s\t%s\t# %s",
7810Sstevel@tonic-gate 				(*entry.rpc)?entry.rpc:"NORPC", entry.id,
7820Sstevel@tonic-gate 				(*entry.modules)?entry.modules:"NOMODULES",
7830Sstevel@tonic-gate 				entry.command, (*entry.comment)?entry.comment:"");
7840Sstevel@tonic-gate 		}
7850Sstevel@tonic-gate 		else {
7860Sstevel@tonic-gate 			if (strchr(entry.flags, 'x') == NULL)
7870Sstevel@tonic-gate 				return(QZERO);
7880Sstevel@tonic-gate 			else
7890Sstevel@tonic-gate 				return(QONE);
7900Sstevel@tonic-gate 		}
7910Sstevel@tonic-gate 	}
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	pclose(fp);
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	if (rtn == NOTLISTEN) { /* check last return to see if error */
7960Sstevel@tonic-gate 		sprintf(mesg, "Network specification \"%s\" is not of type %s", netspec, LISTENTYPE);
7970Sstevel@tonic-gate 		nlsmesg(MM_ERROR, mesg);
7980Sstevel@tonic-gate 		return(NLS_BADPM);
7990Sstevel@tonic-gate 	}
8000Sstevel@tonic-gate 	if (svc && !found) {
8010Sstevel@tonic-gate 		if (!Quietflag) {
8020Sstevel@tonic-gate 			sprintf(mesg, "Service \"%s\" unknown", svc);
8030Sstevel@tonic-gate 			nlsmesg(MM_ERROR, mesg);
8040Sstevel@tonic-gate 		}
8050Sstevel@tonic-gate 		return(NLS_SERV);
8060Sstevel@tonic-gate 	}
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	return(NLS_OK);
8090Sstevel@tonic-gate }
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate /*
8120Sstevel@tonic-gate  * disable_svc:  use pmadm to disable a service
8130Sstevel@tonic-gate  */
8140Sstevel@tonic-gate 
815*640Sbasabi int
disable_svc(char * svc,char * netspec)816*640Sbasabi disable_svc(char *svc, char *netspec)
8170Sstevel@tonic-gate {
8180Sstevel@tonic-gate 	char	buf[BUFSIZ];
8190Sstevel@tonic-gate 	int	rtn;
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 	sprintf(buf, PM_DISABLE, netspec, svc);
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 	if ((rtn = system(buf)) < 0) {
8240Sstevel@tonic-gate 		return(NLS_SYSERR);
8250Sstevel@tonic-gate 	}
8260Sstevel@tonic-gate 	rtn = (rtn>>8) & 0xff;	/* get child return value out of exit word */
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 	switch (rtn) {
8290Sstevel@tonic-gate 	case 0:
8300Sstevel@tonic-gate 		return(NLS_OK);
8310Sstevel@tonic-gate 		break;
8320Sstevel@tonic-gate 	case E_BADARGS:
8330Sstevel@tonic-gate 	case E_SAFERR:
8340Sstevel@tonic-gate 	case E_SYSERR:
8350Sstevel@tonic-gate 	case E_PMRUN:
8360Sstevel@tonic-gate 	case E_PMNOTRUN:
8370Sstevel@tonic-gate 	case E_RECOVER:
8380Sstevel@tonic-gate 	case E_SACNOTRUN:
8390Sstevel@tonic-gate 	default:
8400Sstevel@tonic-gate 		return(NLS_SYSERR);
8410Sstevel@tonic-gate 		break;
8420Sstevel@tonic-gate 	case E_NOEXIST:
8430Sstevel@tonic-gate 	case E_DUP:
8440Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Non-existent service.");
8450Sstevel@tonic-gate 		return(NLS_SERV);
8460Sstevel@tonic-gate 		break;
8470Sstevel@tonic-gate 	case E_NOPRIV:
8480Sstevel@tonic-gate 		no_permission();
8490Sstevel@tonic-gate 		break;
8500Sstevel@tonic-gate 	}
851*640Sbasabi 	/* NOTREACHED */
8520Sstevel@tonic-gate }
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 
855*640Sbasabi int
enable_svc(char * svc,char * netspec)856*640Sbasabi enable_svc(char *svc, char *netspec)
8570Sstevel@tonic-gate {
8580Sstevel@tonic-gate 	char	buf[BUFSIZ];
8590Sstevel@tonic-gate 	int	rtn;
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate 	sprintf(buf, PM_ENABLE, netspec, svc);
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 	if ((rtn = system(buf)) < 0) {
8640Sstevel@tonic-gate 		return(NLS_SYSERR);
8650Sstevel@tonic-gate 	}
8660Sstevel@tonic-gate 	rtn = (rtn>>8) & 0xff;	/* get child return value out of exit word */
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	switch (rtn) {
8690Sstevel@tonic-gate 	case 0:
8700Sstevel@tonic-gate 		return(NLS_OK);
8710Sstevel@tonic-gate 		break;
8720Sstevel@tonic-gate 	case E_BADARGS:
8730Sstevel@tonic-gate 	case E_SAFERR:
8740Sstevel@tonic-gate 	case E_SYSERR:
8750Sstevel@tonic-gate 	case E_PMRUN:
8760Sstevel@tonic-gate 	case E_PMNOTRUN:
8770Sstevel@tonic-gate 	case E_RECOVER:
8780Sstevel@tonic-gate 	case E_SACNOTRUN:
8790Sstevel@tonic-gate 	default:
8800Sstevel@tonic-gate 		return(NLS_SYSERR);
8810Sstevel@tonic-gate 		break;
8820Sstevel@tonic-gate 	case E_NOEXIST:
8830Sstevel@tonic-gate 	case E_DUP:
8840Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Non-existent service.");
8850Sstevel@tonic-gate 		return(NLS_SERV);
8860Sstevel@tonic-gate 		break;
8870Sstevel@tonic-gate 	case E_NOPRIV:
8880Sstevel@tonic-gate 		no_permission();
8890Sstevel@tonic-gate 		break;
8900Sstevel@tonic-gate 	}
891*640Sbasabi 	/* NOTREACHED */
8920Sstevel@tonic-gate }
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 
895*640Sbasabi int
remove_svc(char * svc,char * netspec,int printerrors)896*640Sbasabi remove_svc(char *svc, char *netspec, int printerrors)
8970Sstevel@tonic-gate {
8980Sstevel@tonic-gate 	char	buf[BUFSIZ];
8990Sstevel@tonic-gate 	int	rtn;
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 	sprintf(buf, PM_REMSVC, netspec, svc);
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 	if ((rtn = system(buf)) < 0) {
9040Sstevel@tonic-gate 		return(NLS_SYSERR);
9050Sstevel@tonic-gate 	}
9060Sstevel@tonic-gate 	rtn = (rtn>>8) & 0xff;	/* get child return value out of exit word */
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	switch (rtn) {
9090Sstevel@tonic-gate 	case 0:
9100Sstevel@tonic-gate 		return(NLS_OK);
9110Sstevel@tonic-gate 		break;
9120Sstevel@tonic-gate 	case E_BADARGS:
9130Sstevel@tonic-gate 	case E_SAFERR:
9140Sstevel@tonic-gate 	case E_SYSERR:
9150Sstevel@tonic-gate 	case E_PMRUN:
9160Sstevel@tonic-gate 	case E_PMNOTRUN:
9170Sstevel@tonic-gate 	case E_RECOVER:
9180Sstevel@tonic-gate 	case E_SACNOTRUN:
9190Sstevel@tonic-gate 	default:
9200Sstevel@tonic-gate 		return(NLS_SYSERR);
9210Sstevel@tonic-gate 		break;
9220Sstevel@tonic-gate 	case E_NOEXIST:
9230Sstevel@tonic-gate 	case E_DUP:
9240Sstevel@tonic-gate 		if (printerrors)
9250Sstevel@tonic-gate 			nlsmesg(MM_ERROR, "Non-existent service.");
9260Sstevel@tonic-gate 		return(NLS_SERV);
9270Sstevel@tonic-gate 		break;
9280Sstevel@tonic-gate 	case E_NOPRIV:
9290Sstevel@tonic-gate 		no_permission();
9300Sstevel@tonic-gate 		break;
9310Sstevel@tonic-gate 	}
932*640Sbasabi 	/* NOTREACHED */
9330Sstevel@tonic-gate }
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 
936*640Sbasabi int
kill_listener(char * netspec)937*640Sbasabi kill_listener(char *netspec)
9380Sstevel@tonic-gate {
9390Sstevel@tonic-gate 	char	buf[BUFSIZ];
9400Sstevel@tonic-gate 	char	mesg[BUFSIZ];
9410Sstevel@tonic-gate 	int	rtn;
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	sprintf(buf, SAC_KILLPM, netspec);
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 	if ((rtn = system(buf)) < 0) {
9460Sstevel@tonic-gate 		return(NLS_SYSERR);
9470Sstevel@tonic-gate 	}
9480Sstevel@tonic-gate 	rtn = (rtn>>8) & 0xff;	/* get child return value out of exit word */
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	switch (rtn) {
9510Sstevel@tonic-gate 	case 0:
9520Sstevel@tonic-gate 		return(NLS_OK);
9530Sstevel@tonic-gate 		break;
9540Sstevel@tonic-gate 	case E_BADARGS:
9550Sstevel@tonic-gate 	case E_DUP:
9560Sstevel@tonic-gate 	case E_SAFERR:
9570Sstevel@tonic-gate 	case E_SYSERR:
9580Sstevel@tonic-gate 	case E_PMRUN:
9590Sstevel@tonic-gate 	case E_RECOVER:
9600Sstevel@tonic-gate 	case E_SACNOTRUN:
9610Sstevel@tonic-gate 	default:
9620Sstevel@tonic-gate 		return(NLS_SYSERR);
9630Sstevel@tonic-gate 		break;
9640Sstevel@tonic-gate 	case E_PMNOTRUN:
9650Sstevel@tonic-gate 		sprintf(mesg, "No listener active on network \"%s\"", netspec);
9660Sstevel@tonic-gate 		nlsmesg(MM_ERROR, mesg);
9670Sstevel@tonic-gate 		return(NLS_FAILED);
9680Sstevel@tonic-gate 	case E_NOEXIST:
9690Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Non-existent port monitor.");
9700Sstevel@tonic-gate 		return(NLS_SERV);
9710Sstevel@tonic-gate 		break;
9720Sstevel@tonic-gate 	case E_NOPRIV:
9730Sstevel@tonic-gate 		no_permission();
9740Sstevel@tonic-gate 		break;
9750Sstevel@tonic-gate 	}
976*640Sbasabi 	/* NOTREACHED */
9770Sstevel@tonic-gate }
9780Sstevel@tonic-gate 
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate /*
9810Sstevel@tonic-gate  * add_pm:  add a port monitor (initialize directories) using sacadm
9820Sstevel@tonic-gate  */
9830Sstevel@tonic-gate 
984*640Sbasabi int
add_pm(char * netspec)985*640Sbasabi add_pm(char *netspec)
9860Sstevel@tonic-gate {
9870Sstevel@tonic-gate 	char	buf[BUFSIZ];
9880Sstevel@tonic-gate 	char	mesg[BUFSIZ];
9890Sstevel@tonic-gate 	int	rtn;
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate 	sprintf(buf, SAC_ADDPM, netspec, LISTENTYPE, gencmdstr(netspec), VERSION);
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 	if ((rtn = system(buf)) < 0) {
9940Sstevel@tonic-gate 		return(NLS_SYSERR);
9950Sstevel@tonic-gate 	}
9960Sstevel@tonic-gate 	rtn = (rtn>>8) & 0xff;	/* get child return value out of exit word */
9970Sstevel@tonic-gate 
9980Sstevel@tonic-gate 	switch (rtn) {
9990Sstevel@tonic-gate 	case 0:
10000Sstevel@tonic-gate 		old_addsvc(NLPSSVCCODE, NULL, NLPSSRV, "NLPS server", "", "root", NULL, netspec);
10010Sstevel@tonic-gate 		return(NLS_OK);
10020Sstevel@tonic-gate 		break;
10030Sstevel@tonic-gate 	case E_BADARGS:
10040Sstevel@tonic-gate 	case E_SAFERR:
10050Sstevel@tonic-gate 	case E_SYSERR:
10060Sstevel@tonic-gate 	case E_RECOVER:
10070Sstevel@tonic-gate 	case E_NOEXIST:
10080Sstevel@tonic-gate 	case E_PMNOTRUN:
10090Sstevel@tonic-gate 	case E_SACNOTRUN:
10100Sstevel@tonic-gate 	default:
10110Sstevel@tonic-gate 		return(NLS_SYSERR);
10120Sstevel@tonic-gate 		break;
10130Sstevel@tonic-gate 	case E_DUP:
10140Sstevel@tonic-gate 	case E_PMRUN:
10150Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Listener already initialized");
10160Sstevel@tonic-gate 		return(NLS_FAILED);
10170Sstevel@tonic-gate 		break;
10180Sstevel@tonic-gate 	case E_NOPRIV:
10190Sstevel@tonic-gate 		no_permission();
10200Sstevel@tonic-gate 		break;
10210Sstevel@tonic-gate 	}
1022*640Sbasabi 	/* NOTREACHED */
10230Sstevel@tonic-gate }
10240Sstevel@tonic-gate 
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate /*
10270Sstevel@tonic-gate  * gencmdstr:  generate the correct string to invoke the listener (starlan
10280Sstevel@tonic-gate  *             requires special handling)
10290Sstevel@tonic-gate  */
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate char *
gencmdstr(char * netspec)1032*640Sbasabi gencmdstr(char *netspec)
10330Sstevel@tonic-gate {
10340Sstevel@tonic-gate 	static char buf[BUFSIZ];
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 	(void) strcpy(buf, LISTENCMD);
10370Sstevel@tonic-gate 	if (!strcmp(netspec, "starlan"))
10380Sstevel@tonic-gate 		(void) strcat(buf, " -m slan");
10390Sstevel@tonic-gate 	(void) strcat(buf, " ");
10400Sstevel@tonic-gate 	(void) strcat(buf, netspec);
10410Sstevel@tonic-gate 	return(buf);
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate 
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate /*
10460Sstevel@tonic-gate  * start_listener: start the listener
10470Sstevel@tonic-gate  */
10480Sstevel@tonic-gate 
1049*640Sbasabi int
start_listener(char * netspec)1050*640Sbasabi start_listener(char *netspec)
10510Sstevel@tonic-gate {
10520Sstevel@tonic-gate 	char	buf[BUFSIZ];
10530Sstevel@tonic-gate 	char	scratch[BUFSIZ];
10540Sstevel@tonic-gate 	int	rtn;
10550Sstevel@tonic-gate 
10560Sstevel@tonic-gate 	sprintf(buf, SAC_STARTPM, netspec);
10570Sstevel@tonic-gate 
10580Sstevel@tonic-gate 	if ((rtn = system(buf)) < 0)
10590Sstevel@tonic-gate 		return(NLS_SYSERR);
10600Sstevel@tonic-gate 	rtn = (rtn>>8) & 0xff;
10610Sstevel@tonic-gate 	switch (rtn) {
10620Sstevel@tonic-gate 	case 0:
10630Sstevel@tonic-gate 		break;
10640Sstevel@tonic-gate 	case E_BADARGS:
10650Sstevel@tonic-gate 	case E_SAFERR:
10660Sstevel@tonic-gate 	case E_SYSERR:
10670Sstevel@tonic-gate 	case E_RECOVER:
10680Sstevel@tonic-gate 	case E_PMNOTRUN:
10690Sstevel@tonic-gate 	case E_SACNOTRUN:
10700Sstevel@tonic-gate 	default:
10710Sstevel@tonic-gate 		return(NLS_SYSERR);
10720Sstevel@tonic-gate 		break;
10730Sstevel@tonic-gate 	case E_NOEXIST:
10740Sstevel@tonic-gate 	case E_DUP:
10750Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Non-existent port monitor.");
10760Sstevel@tonic-gate 		return(NLS_BADPM);
10770Sstevel@tonic-gate 		break;
10780Sstevel@tonic-gate 	case E_PMRUN:
10790Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Listener already running");
10800Sstevel@tonic-gate 		return(NLS_FAILED);
10810Sstevel@tonic-gate 	case E_NOPRIV:
10820Sstevel@tonic-gate 		no_permission();
10830Sstevel@tonic-gate 		break;
10840Sstevel@tonic-gate 	}
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 	sprintf(buf, SAC_ENABLPM, netspec);
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate 	if ((rtn = system(buf)) < 0) {
10890Sstevel@tonic-gate 		return(NLS_SYSERR);
10900Sstevel@tonic-gate 	}
10910Sstevel@tonic-gate 	rtn = (rtn>>8) & 0xff;
10920Sstevel@tonic-gate 	switch (rtn) {
10930Sstevel@tonic-gate 	case 0:
10940Sstevel@tonic-gate 		return(NLS_OK);
10950Sstevel@tonic-gate 		break;
10960Sstevel@tonic-gate 	case E_BADARGS:
10970Sstevel@tonic-gate 	case E_SAFERR:
10980Sstevel@tonic-gate 	case E_SYSERR:
10990Sstevel@tonic-gate 	case E_RECOVER:
11000Sstevel@tonic-gate 	case E_SACNOTRUN:
11010Sstevel@tonic-gate 	default:
11020Sstevel@tonic-gate 		return(NLS_SYSERR);
11030Sstevel@tonic-gate 		break;
11040Sstevel@tonic-gate 	case E_NOEXIST:
11050Sstevel@tonic-gate 	case E_DUP:
11060Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Non-existent port monitor.");
11070Sstevel@tonic-gate 		return(NLS_BADPM);
11080Sstevel@tonic-gate 		break;
11090Sstevel@tonic-gate 	case E_PMRUN:
11100Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Listener already running");
11110Sstevel@tonic-gate 		return(NLS_FAILED);
11120Sstevel@tonic-gate 	case E_PMNOTRUN:
11130Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Listener start failed");
11140Sstevel@tonic-gate 		return(NLS_FAILED);
11150Sstevel@tonic-gate 	case E_NOPRIV:
11160Sstevel@tonic-gate 		no_permission();
11170Sstevel@tonic-gate 		break;
11180Sstevel@tonic-gate 	}
1119*640Sbasabi 	/* NOTREACHED */
11200Sstevel@tonic-gate }
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate 
11230Sstevel@tonic-gate /*
11240Sstevel@tonic-gate  * setup_addr:  setup the -l and -t addresses.
11250Sstevel@tonic-gate  */
11260Sstevel@tonic-gate 
1127*640Sbasabi int
setup_addr(char * laddr,char * taddr,char * netspec)1128*640Sbasabi setup_addr(char *laddr, char *taddr, char *netspec)
11290Sstevel@tonic-gate {
11300Sstevel@tonic-gate 	char	buf[BUFSIZ];
11310Sstevel@tonic-gate 	char	mesg[BUFSIZ];
11320Sstevel@tonic-gate 	char	*p;
11330Sstevel@tonic-gate 	int	rtn;
11340Sstevel@tonic-gate 	int	qlisten = FALSE;
11350Sstevel@tonic-gate 	int	qtty = FALSE;
11360Sstevel@tonic-gate 	FILE	*fp;
11370Sstevel@tonic-gate 	struct	svcfields entry;
11380Sstevel@tonic-gate 
11390Sstevel@tonic-gate 	if (laddr && *laddr == '-')
11400Sstevel@tonic-gate 		qlisten = TRUE;
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	if (taddr && *taddr == '-')
11430Sstevel@tonic-gate 		qtty = TRUE;
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate 	if (laddr) {
11460Sstevel@tonic-gate 		sprintf(buf, PM_LSONE, netspec, NLPSSVCCODE);
11470Sstevel@tonic-gate 
11480Sstevel@tonic-gate 		if ((fp = popen(buf, "r")) == NULL) {
11490Sstevel@tonic-gate 			return(NLS_SYSERR);
11500Sstevel@tonic-gate 		}
11510Sstevel@tonic-gate 
11520Sstevel@tonic-gate 		if (fgets(buf, BUFSIZ, fp) != NULL) {
11530Sstevel@tonic-gate 			if ((rtn = svc_format(buf, &entry)) != 0) {
11540Sstevel@tonic-gate 				switch (rtn) {
11550Sstevel@tonic-gate 				case NOTLISTEN:
11560Sstevel@tonic-gate 					nlsmesg(MM_ERROR, "Incorrect port monitor type.  Must be of type listen");
11570Sstevel@tonic-gate 					return(NLS_FAILED);
11580Sstevel@tonic-gate 					break;
11590Sstevel@tonic-gate 				case BADPMFMT:
11600Sstevel@tonic-gate 					return(NLS_SYSERR);
11610Sstevel@tonic-gate 					break;
11620Sstevel@tonic-gate 				case BADLISFMT:
11630Sstevel@tonic-gate 					sprintf(mesg, "Entry for code \"%s\" has incorrect format", entry.svc_code);
11640Sstevel@tonic-gate 					nlsmesg(MM_WARNING, mesg);
11650Sstevel@tonic-gate 					break;
11660Sstevel@tonic-gate 				}
11670Sstevel@tonic-gate 			}
11680Sstevel@tonic-gate 			else {
11690Sstevel@tonic-gate 				if (qlisten)
11700Sstevel@tonic-gate 					printf("%s\n", entry.addr);
11710Sstevel@tonic-gate 				else {
11720Sstevel@tonic-gate 					if (geteuid() != ROOT)
11730Sstevel@tonic-gate 						no_permission();
11740Sstevel@tonic-gate 					/* add address */
11750Sstevel@tonic-gate 					remove_svc(NLPSSVCCODE, netspec, FALSE);
11760Sstevel@tonic-gate 					p = strchr(entry.comment, '\n');
11770Sstevel@tonic-gate 					if (p)
11780Sstevel@tonic-gate 						*p = '\0';
11790Sstevel@tonic-gate 					old_addsvc(NLPSSVCCODE, laddr, entry.command, entry.comment, entry.modules, entry.id, entry.flags, netspec);
11800Sstevel@tonic-gate 				}
11810Sstevel@tonic-gate 			}
11820Sstevel@tonic-gate 			pclose(fp);
11830Sstevel@tonic-gate 		}
11840Sstevel@tonic-gate 		else if (!qlisten)
11850Sstevel@tonic-gate 			nlsmesg(MM_WARNING, "NLPS service not defined");
11860Sstevel@tonic-gate 	}
11870Sstevel@tonic-gate 	if (taddr) {
11880Sstevel@tonic-gate 		sprintf(buf, PM_LSONE, netspec, TTYSVCCODE);
11890Sstevel@tonic-gate 
11900Sstevel@tonic-gate 		if ((fp = popen(buf, "r")) == NULL) {
11910Sstevel@tonic-gate 			return(NLS_SYSERR);
11920Sstevel@tonic-gate 		}
11930Sstevel@tonic-gate 
11940Sstevel@tonic-gate 		if (fgets(buf, BUFSIZ, fp) != NULL) {
11950Sstevel@tonic-gate 			if ((rtn = svc_format(buf, &entry)) != 0) {
11960Sstevel@tonic-gate 				switch (rtn) {
11970Sstevel@tonic-gate 				case NOTLISTEN:
11980Sstevel@tonic-gate 					nlsmesg(MM_ERROR, "Incorrect port monitor type.  Must be of type listen");
11990Sstevel@tonic-gate 					return(NLS_FAILED);
12000Sstevel@tonic-gate 					break;
12010Sstevel@tonic-gate 				case BADPMFMT:
12020Sstevel@tonic-gate 					return(NLS_SYSERR);
12030Sstevel@tonic-gate 					break;
12040Sstevel@tonic-gate 				case BADLISFMT:
12050Sstevel@tonic-gate 					sprintf(mesg, "Entry for code \"%s\" has incorrect format", entry.svc_code);
12060Sstevel@tonic-gate 					nlsmesg(MM_WARNING, mesg);
12070Sstevel@tonic-gate 					break;
12080Sstevel@tonic-gate 				}
12090Sstevel@tonic-gate 			}
12100Sstevel@tonic-gate 			else {
12110Sstevel@tonic-gate 				if (qtty)
12120Sstevel@tonic-gate 					printf("%s\n", entry.addr);
12130Sstevel@tonic-gate 				else {
12140Sstevel@tonic-gate 					if (geteuid() != ROOT)
12150Sstevel@tonic-gate 						no_permission();
12160Sstevel@tonic-gate 					/* add address */
12170Sstevel@tonic-gate 					remove_svc(TTYSVCCODE, netspec, FALSE);
12180Sstevel@tonic-gate 					p = strchr(entry.comment, '\n');
12190Sstevel@tonic-gate 					if (p)
12200Sstevel@tonic-gate 						*p = '\0';
12210Sstevel@tonic-gate 					old_addsvc(TTYSVCCODE, taddr, entry.command, entry.comment, entry.modules, entry.id, entry.flags, netspec);
12220Sstevel@tonic-gate 				}
12230Sstevel@tonic-gate 			}
12240Sstevel@tonic-gate 			pclose(fp);
12250Sstevel@tonic-gate 		}
12260Sstevel@tonic-gate 		else if (!qtty)
12270Sstevel@tonic-gate 			nlsmesg(MM_WARNING, "remote login service not defined");
12280Sstevel@tonic-gate 	}
12290Sstevel@tonic-gate 	return(NLS_OK);
12300Sstevel@tonic-gate }
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate 
12330Sstevel@tonic-gate /*
12340Sstevel@tonic-gate  * svc_format:  scan a line of output from pmadm to separate it into fields.
12350Sstevel@tonic-gate  *              returns BADPMFMT for missing fields or incorrect syntax.
12360Sstevel@tonic-gate  *                      NOTLISTEN is the port monitor type is not listen.
12370Sstevel@tonic-gate  *                      BADLISFMT if the listener-specific data is incorrect.
12380Sstevel@tonic-gate  *                      NLS_OK if everything checked out and data is broken
12390Sstevel@tonic-gate  *                             into the structure.
12400Sstevel@tonic-gate  */
12410Sstevel@tonic-gate 
1242*640Sbasabi int
svc_format(char * buf,struct svcfields * entry)1243*640Sbasabi svc_format(char *buf, struct svcfields *entry)
12440Sstevel@tonic-gate {
12450Sstevel@tonic-gate 	char	*ptr;		/* temporary pointer into buffer	*/
12460Sstevel@tonic-gate 	char	*tmp;		/* temporary pointer into buffer	*/
12470Sstevel@tonic-gate 
12480Sstevel@tonic-gate 	entry->pmtag = buf;
12490Sstevel@tonic-gate 	if ((ptr = strchr(buf, ':')) == NULL)
12500Sstevel@tonic-gate 		return(BADPMFMT);
12510Sstevel@tonic-gate 	*ptr++ = NULL;
12520Sstevel@tonic-gate 	entry->pmtype = ptr;
12530Sstevel@tonic-gate 	if ((ptr = strchr(entry->pmtype, ':')) == NULL)
12540Sstevel@tonic-gate 		return(BADPMFMT);
12550Sstevel@tonic-gate 	*ptr++ = NULL;
12560Sstevel@tonic-gate 	entry->svc_code = ptr;
12570Sstevel@tonic-gate 
12580Sstevel@tonic-gate 	if (strcmp(entry->pmtype, LISTENTYPE) != 0)
12590Sstevel@tonic-gate 		return(NOTLISTEN);
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate 	if ((ptr = strchr(entry->svc_code, ':')) == NULL)
12620Sstevel@tonic-gate 		return(BADPMFMT);
12630Sstevel@tonic-gate 	*ptr++ = NULL;
12640Sstevel@tonic-gate 	entry->flags = ptr;
12650Sstevel@tonic-gate 	if ((ptr = strchr(entry->flags, ':')) == NULL)
12660Sstevel@tonic-gate 		return(BADPMFMT);
12670Sstevel@tonic-gate 	*ptr++ = NULL;
12680Sstevel@tonic-gate 	entry->id = ptr;
12690Sstevel@tonic-gate 	if ((ptr = strchr(entry->id, ':')) == NULL)
12700Sstevel@tonic-gate 		return(BADPMFMT);
12710Sstevel@tonic-gate 	*ptr++ = NULL;
12720Sstevel@tonic-gate 	entry->res1 = ptr;
12730Sstevel@tonic-gate 	if ((ptr = strchr(entry->res1, ':')) == NULL)
12740Sstevel@tonic-gate 		return(BADPMFMT);
12750Sstevel@tonic-gate 	*ptr++ = NULL;
12760Sstevel@tonic-gate 	entry->res2 = ptr;
12770Sstevel@tonic-gate 	if ((ptr = strchr(entry->res2, ':')) == NULL)
12780Sstevel@tonic-gate 		return(BADPMFMT);
12790Sstevel@tonic-gate 	*ptr++ = NULL;
12800Sstevel@tonic-gate 	entry->res3 = ptr;
12810Sstevel@tonic-gate 	if ((ptr = strchr(entry->res3, ':')) == NULL)
12820Sstevel@tonic-gate 		return(BADPMFMT);
12830Sstevel@tonic-gate 	*ptr++ = NULL;
12840Sstevel@tonic-gate 	entry->addr = ptr;
12850Sstevel@tonic-gate 	if ((ptr = strchr(entry->addr, ':')) == NULL)
12860Sstevel@tonic-gate 		return(BADLISFMT);
12870Sstevel@tonic-gate 	*ptr++ = NULL;
12880Sstevel@tonic-gate 	entry->rpc = ptr;
12890Sstevel@tonic-gate 	if ((ptr = strchr(entry->rpc, ':')) == NULL)
12900Sstevel@tonic-gate 		return(BADLISFMT);
12910Sstevel@tonic-gate 	*ptr++ = NULL;
12920Sstevel@tonic-gate 	if (*entry->rpc) {
12930Sstevel@tonic-gate 		if ((tmp = strchr(entry->rpc, ',')) == NULL)
12940Sstevel@tonic-gate 			return(BADLISFMT);
12950Sstevel@tonic-gate 		*tmp = ':';
12960Sstevel@tonic-gate 	}
12970Sstevel@tonic-gate 	entry->lflags = ptr;
12980Sstevel@tonic-gate 	if ((ptr = strchr(entry->lflags, ':')) == NULL)
12990Sstevel@tonic-gate 		return(BADLISFMT);
13000Sstevel@tonic-gate 	*ptr++ = NULL;
13010Sstevel@tonic-gate 	entry->modules = ptr;
13020Sstevel@tonic-gate 	if ((ptr = strchr(entry->modules, ':')) == NULL)
13030Sstevel@tonic-gate 		return(BADLISFMT);
13040Sstevel@tonic-gate 	*ptr++ = NULL;
13050Sstevel@tonic-gate 	entry->command = ptr;
13060Sstevel@tonic-gate 	if ((ptr = strchr(entry->command, '#')) == NULL)
13070Sstevel@tonic-gate 		return(BADLISFMT);
13080Sstevel@tonic-gate 	*ptr++ = NULL;
13090Sstevel@tonic-gate 	entry->comment = ptr;
13100Sstevel@tonic-gate 	return(NLS_OK);
13110Sstevel@tonic-gate }
13120Sstevel@tonic-gate 
13130Sstevel@tonic-gate 
13140Sstevel@tonic-gate /*
13150Sstevel@tonic-gate  * nexttok - return next token, essentially a strtok, but it can
13160Sstevel@tonic-gate  *	deal with null fields and strtok can not
13170Sstevel@tonic-gate  *
13180Sstevel@tonic-gate  *	args:	str - the string to be examined, NULL if we should
13190Sstevel@tonic-gate  *		      examine the remembered string
13200Sstevel@tonic-gate  *		delim - the list of valid delimiters
13210Sstevel@tonic-gate  */
13220Sstevel@tonic-gate 
13230Sstevel@tonic-gate 
13240Sstevel@tonic-gate char *
nexttok(char * str,char * delim)1325*640Sbasabi nexttok(char *str, char *delim)
13260Sstevel@tonic-gate {
13270Sstevel@tonic-gate 	static char *savep;	/* the remembered string */
13280Sstevel@tonic-gate 	register char *p;	/* pointer to start of token */
13290Sstevel@tonic-gate 	register char *ep;	/* pointer to end of token */
13300Sstevel@tonic-gate 
13310Sstevel@tonic-gate 	p = (str == NULL) ? savep : str ;
13320Sstevel@tonic-gate 	if (p == NULL)
13330Sstevel@tonic-gate 		return(NULL);
13340Sstevel@tonic-gate 	ep = strpbrk(p, delim);
13350Sstevel@tonic-gate 	if (ep == NULL) {
13360Sstevel@tonic-gate 		savep = NULL;
13370Sstevel@tonic-gate 		return(p);
13380Sstevel@tonic-gate 	}
13390Sstevel@tonic-gate 	savep = ep + 1;
13400Sstevel@tonic-gate 	*ep = '\0';
13410Sstevel@tonic-gate 	return(p);
13420Sstevel@tonic-gate }
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate /*
13460Sstevel@tonic-gate  * pflags - put flags into intelligible form for output
13470Sstevel@tonic-gate  *
13480Sstevel@tonic-gate  *	args:	flags - binary representation of flags
13490Sstevel@tonic-gate  */
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate char *
pflags(long flags)1352*640Sbasabi pflags(long flags)
13530Sstevel@tonic-gate {
13540Sstevel@tonic-gate 	register int i;			/* scratch counter */
13550Sstevel@tonic-gate 	static char buf[BUFSIZ];	/* formatted flags */
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate 	if (flags == 0)
13580Sstevel@tonic-gate 		return("");
13590Sstevel@tonic-gate 	i = 0;
13600Sstevel@tonic-gate 	if (flags & CFLAG) {
13610Sstevel@tonic-gate 		buf[i++] = 'c';
13620Sstevel@tonic-gate 		flags &= ~CFLAG;
13630Sstevel@tonic-gate 	}
13640Sstevel@tonic-gate 	if (flags & DFLAG) {
13650Sstevel@tonic-gate 		buf[i++] = 'd';
13660Sstevel@tonic-gate 		flags &= ~DFLAG;
13670Sstevel@tonic-gate 	}
13680Sstevel@tonic-gate 	if (flags & PFLAG) {
13690Sstevel@tonic-gate 		buf[i++] = 'p';
13700Sstevel@tonic-gate 		flags &= ~PFLAG;
13710Sstevel@tonic-gate 	}
13720Sstevel@tonic-gate 	if (flags) {
13730Sstevel@tonic-gate 		nlsmesg(MM_ERROR, "Internal error in pflags");
13740Sstevel@tonic-gate 		exit(NLS_FAILED);
13750Sstevel@tonic-gate 	}
13760Sstevel@tonic-gate 	buf[i] = '\0';
13770Sstevel@tonic-gate 	return(buf);
13780Sstevel@tonic-gate }
1379