diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/nlsadmin | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/nlsadmin')
| -rw-r--r-- | usr/src/cmd/nlsadmin/Makefile | 46 | ||||
| -rw-r--r-- | usr/src/cmd/nlsadmin/nlsadmin.c | 1386 | ||||
| -rw-r--r-- | usr/src/cmd/nlsadmin/nlsadmin.h | 112 |
3 files changed, 1544 insertions, 0 deletions
diff --git a/usr/src/cmd/nlsadmin/Makefile b/usr/src/cmd/nlsadmin/Makefile new file mode 100644 index 0000000000..cee25ee83b --- /dev/null +++ b/usr/src/cmd/nlsadmin/Makefile @@ -0,0 +1,46 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1989 by Sun Microsystems, Inc. +# + +PROG= nlsadmin + +include ../Makefile.cmd + +OWNER= root +GROUP= adm +FILEMODE= 0755 + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTUSRSBINPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/nlsadmin/nlsadmin.c b/usr/src/cmd/nlsadmin/nlsadmin.c new file mode 100644 index 0000000000..5ace867cc1 --- /dev/null +++ b/usr/src/cmd/nlsadmin/nlsadmin.c @@ -0,0 +1,1386 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1998 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * nlsadmin.c -- control program for the network listener service + * + * This program replaces a previous version of nlsadmin. + * + * This version of nlsadmin works with the service access facility to + * control the network listener. The functionality of the SVR3.2 nlsadmin + * command is supported through calls to the more general sacadm and pmadm + * commands available through SAF. Users should migrate away from nlsadmin + * to sacadm and pmadm for these functions. + * + * The -m option of the SVR3.2 nlsadmin command is now ignored. + * + * The -t option associates an address with service code 1 (same as in SVR3.2). + * The -l option associates an address with service code 0. + * + * nlsadmin also contains new functionality -- the ability to format a + * "listener-specific" string to put in the _pmtab database. This + * functionality is required by SAF. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <sac.h> +#include "nlsadmin.h" + +#define OPTIONS "a:c:d:e:ikl:mo:p:qr:st:vw:xy:z:A:N:VDR:" +#ifndef FALSE +#define TRUE 1 +#define FALSE 0 +#endif +/* + * defines for -q exit codes: QZERO is used for conditions that the + * man page documents as returning 0, QONE for those that return 1 + */ +#define QZERO 0 +#define QONE 1 + +/* + * defines for simulated standard error format code + */ +#define MM_NOSEV 0 +#define MM_HALT 1 +#define MM_ERROR 2 +#define MM_WARNING 3 +#define MM_INFO 4 + +char *Nlsname; /* set to argv[0] */ +char Label[25]; /* label component for fmtmsg */ +int Quietflag = FALSE; /* set to TRUE when -q used */ + +extern int errno; +void nlsmesg(); +uid_t geteuid(); +char *nexttok(); +char *pflags(); +char *gencmdstr(); + +struct svcfields { + char *pmtag; + char *pmtype; + char *svc_code; + char *flags; + char *id; + char *res1; + char *res2; + char *res3; + char *addr; + char *rpc; + char *lflags; + char *modules; + char *command; + char *comment; +}; + + +main(argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int c; /* used for return from getopt */ + char *addrptr = NULL; /* set when -A address is used */ + char *rpcptr = NULL; /* set when -R rpcinfo is used */ + char *cmdptr = NULL; /* set with -c command */ + char *comptr = NULL; /* set with -y comment (old) */ + char *idptr = NULL; /* set with -w id (old) */ + char *lptr = NULL; /* set with -l addr (old) */ + char *moduleptr = NULL; /* set with -m modules */ + char *pipeptr = NULL; /* set with -o pipe */ + char *svcptr = NULL; /* set when service code used (old) */ + char *tptr = NULL; /* set when -t addr used (old) */ + char *netspec = NULL; /* set to the network specification */ + int flag = 0; /* bit flag of type of command */ + int exitcode = 0; /* exit status of this command */ + int lflags = 0; /* listener flags */ + char buf[BUFSIZ]; /* temp buffer #1 */ + char mesg[BUFSIZ]; /* temp buffer #2 */ + FILE *fp; /* used for checking netspec */ + char *ptr; /* temp pointer */ + char *ptr2; /* temp pointer */ + int sawsep = 0; /* flag for RPC separator */ + + Nlsname = argv[0]; + sprintf(Label, "UX:%.14s", argv[0]); /* for standard message fmt */ + + while ((c = getopt(argc, argv, OPTIONS)) != -1) { + switch (c) { + case 'a': + if ( (flag && (flag != CMDFLAG)) || svcptr || Quietflag + || addrptr || rpcptr || lflags) + usage(INCONSISTENT); + svcptr = optarg; + break; + case 'c': + if ( (flag && (flag != CMDFLAG)) || cmdptr || Quietflag ) + usage(INCONSISTENT); + cmdptr = optarg; + flag |= CMDFLAG; + break; + case 'd': + if ( flag || svcptr || Quietflag || comptr || addrptr + || rpcptr || cmdptr || idptr || lflags ) + usage(INCONSISTENT); + svcptr = optarg; + flag |= DISFLAG; + break; + case 'e': + if ( flag || svcptr || Quietflag || comptr || addrptr + || rpcptr || cmdptr || idptr || lflags ) + usage(INCONSISTENT); + svcptr = optarg; + flag |= ENAFLAG; + break; + case 'i': + if ( flag || svcptr || Quietflag || comptr || addrptr + || rpcptr || cmdptr || idptr || lflags ) + usage(INCONSISTENT); + flag |= INIFLAG; + break; + case 'k': + if ( flag || svcptr || Quietflag || comptr || addrptr + || rpcptr || cmdptr || idptr || lflags ) + usage(INCONSISTENT); + flag |= KILFLAG; + break; + case 'l': + if ( ( flag && (flag != ADRFLAG)) || svcptr || lptr + || Quietflag || comptr || addrptr || rpcptr + || cmdptr || idptr || lflags ) + usage(INCONSISTENT); + lptr = optarg; + flag |= ADRFLAG; + break; + case 'm': + if ( (flag && (flag != CMDFLAG)) || Quietflag || rpcptr || lflags ) + usage(INCONSISTENT); + flag |= CMDFLAG; + break; + case 'o': + if ( flag || svcptr || Quietflag || comptr || idptr || netspec ) + usage(INCONSISTENT); + pipeptr = optarg; + flag |= PIPFLAG; + break; + case 'p': + if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG)) || Quietflag ) + usage(INCONSISTENT); + moduleptr = optarg; + break; + case 'q': + if ( (flag && (flag != ZZZFLAG)) || Quietflag || comptr + || rpcptr || lflags || idptr ) + usage(INCONSISTENT); + Quietflag = TRUE; + break; + case 'r': + if ( flag || svcptr || Quietflag || comptr || addrptr + || rpcptr || cmdptr || idptr || lflags ) + usage(INCONSISTENT); + flag |= REMFLAG; + svcptr = optarg; + break; + case 's': + if ( flag || svcptr || Quietflag || comptr || addrptr + || rpcptr || cmdptr || idptr || lflags ) + usage(INCONSISTENT); + flag |= STAFLAG; + break; + case 't': + if ( (flag && (flag != ADRFLAG)) || svcptr || tptr + || Quietflag || comptr || addrptr || rpcptr + || cmdptr || idptr || lflags ) + usage(INCONSISTENT); + tptr = optarg; + flag |= ADRFLAG; + break; + case 'v': + if ( flag || svcptr || Quietflag || comptr || rpcptr + || addrptr || idptr || lflags ) + usage(INCONSISTENT); + flag |= VBSFLAG; + break; + case 'w': + if ( (flag && (flag != CMDFLAG)) || Quietflag || idptr + || rpcptr || addrptr || lflags ) + usage(INCONSISTENT); + idptr = optarg; + break; + case 'x': + if ( flag || svcptr || Quietflag || netspec || comptr + || rpcptr || addrptr || lflags || idptr ) + usage(INCONSISTENT); + flag |= NETFLAG; + break; + case 'y': + if ( (flag && (flag != CMDFLAG)) || Quietflag || comptr + || rpcptr || addrptr || lflags ) + usage(INCONSISTENT); + comptr = optarg; + break; + case 'z': + if ( flag || svcptr || comptr || addrptr || rpcptr + || idptr || lflags ) + usage(INCONSISTENT); + flag |= ZZZFLAG; + svcptr = optarg; + break; + case 'A': + if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG)) + || netspec || svcptr || idptr || comptr ) + usage(INCONSISTENT); + addrptr = optarg; + break; + case 'D': + if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG)) + || netspec || svcptr || idptr || comptr || addrptr + || lflags ) + usage(INCONSISTENT); + lflags |= DFLAG; + break; + case 'N': + if ( netspec ) + usage(INCONSISTENT); + netspec = optarg; + break; + case 'R': + if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG)) + || netspec || svcptr || idptr || comptr ) + usage(INCONSISTENT); + for (ptr = optarg; *ptr; ++ptr) { + if ((*ptr == ':') && !sawsep) { + /* + * skip separator - note that if + * separator has been seen, it's not + * a digit so it will generate a usage + * message below like we want + */ + sawsep++; + continue; + } + if (!isdigit(*ptr)) + usage(USAGE); + } + ptr = strchr(optarg, ':'); + if (ptr) + /* change the ':' to a ',' */ + *ptr = ','; + else + usage(USAGE); + rpcptr = optarg; + break; + case 'V': + if ( flag || svcptr || Quietflag || comptr || netspec + || rpcptr || addrptr || idptr || lflags ) + usage(INCONSISTENT); + flag |= VERFLAG; + break; + case '?': + usage(USAGE); + } + } + + if ((optind < argc) && ! netspec) + netspec = argv[optind++]; + if (optind < argc) + usage(USAGE); + + + /* determine if this command requires a netspec */ + if (flag != CMDFLAG) { + /* if flag is CMDFLAG, more complicated checking of netspec + * is done below in switch + */ + if ((flag == PIPFLAG || flag == VERFLAG || flag == NETFLAG)) { + if (netspec) + usage(USAGE); + } + else if (!netspec) + usage(USAGE); + } + + if (netspec && (flag != INIFLAG)) { + sprintf(buf, SAC_LSPM, netspec); + + if ((fp = popen(buf, "r")) == NULL) { + nlsmesg(MM_ERROR, "System error"); + exit(NLS_SYSERR); + } + + if (fgets(buf, BUFSIZ, fp) == NULL) { + nlsmesg(MM_ERROR, "Invalid network specification"); + exit(NLS_BADPM); + } + else { + ptr = strchr(buf, ':'); + ptr++; + ptr2 = strchr(ptr, ':'); + *ptr2 = NULL; + if (strcmp(ptr, LISTENTYPE) != 0) { + sprintf(mesg, "Network specification \"%s\" is not of type %s", netspec, LISTENTYPE); + nlsmesg(MM_ERROR, mesg); + exit(NLS_BADPM); + } + } + + pclose(fp); + } + + if (svcptr) { + /* check to see if service code is "correct" -- right range + * and format. The -m flag is ignored, so no check for + * "administrative" service codes (0-100) is done. + */ + c = strlen(svcptr); + if ((c == 0) || (c >= SVC_CODE_SZ)) { + sprintf(mesg, "Service code contains more than %d characters", SVC_CODE_SZ); + nlsmesg(MM_ERROR, mesg); + exit(NLS_SERV); + } + } + + switch (flag) { + default: + usage(USAGE); + break; + case NONE: + if ( svcptr || comptr || rpcptr || lflags || idptr ) + usage(INCONSISTENT); + exitcode = prt_nets(netspec); + break; + case INIFLAG: + if (geteuid() != ROOT) + no_permission(); + exitcode = add_pm(netspec); + break; + case CMDFLAG: + if ( svcptr || comptr || idptr || netspec ) { + if (geteuid() != ROOT) + no_permission(); + if ((exitcode = old_addsvc(svcptr, "", cmdptr, comptr, moduleptr, idptr, NULL, netspec)) != NLS_OK) + switch (exitcode) { + case NLS_SERV: + nlsmesg(MM_ERROR, "Service code already exists"); + break; + default: + nlsmesg(MM_ERROR, "Could not add service"); + break; + } + } + else { + if (netspec) + usage(INCONSISTENT); + exitcode = prt_cmd(cmdptr, CFLAG | lflags, moduleptr, addrptr, rpcptr); + } + break; + case PIPFLAG: + if (geteuid() != ROOT) + no_permission(); + exitcode = prt_cmd(pipeptr, PFLAG | lflags, moduleptr, addrptr, rpcptr); + break; + case VERFLAG: + printf("%d\n", VERSION); + exit(NLS_OK); + break; + case DISFLAG: + if (geteuid() != ROOT) + no_permission(); + exitcode = disable_svc(svcptr, netspec); + break; + case ENAFLAG: + if (geteuid() != ROOT) + no_permission(); + exitcode = enable_svc(svcptr, netspec); + break; + case KILFLAG: + if (geteuid() != ROOT) + no_permission(); + exitcode = kill_listener(netspec); + break; + case ADRFLAG: + /* check for root permissions in setup_addr */ + exitcode = setup_addr(lptr, tptr, netspec); + break; + case REMFLAG: + if (geteuid() != ROOT) + no_permission(); + exitcode = remove_svc(svcptr, netspec, TRUE); + break; + case STAFLAG: + if (geteuid() != ROOT) + no_permission(); + exitcode = start_listener(netspec); + break; + case VBSFLAG: + exitcode = prt_svcs(NULL, netspec); + break; + case NETFLAG: + exitcode = prt_nets(NULL); + break; + case ZZZFLAG: + exitcode = prt_svcs(svcptr, netspec); + break; + } + if (exitcode == NLS_SYSERR) + nlsmesg(MM_ERROR, "System error in SAC command"); + exit(exitcode); +} + + +static char umsg[] = "usage: %s -x\n\ + %s [ options ] netspec\n\ + %s [ options ] -N port_monitor_tag\n\ + %s -V\n\ + %s -c cmd | -o pipename [ -p modules ] [ -A addr | -D ] \\\n\ + [ -R prognum:versnum ]\n\ +\n\ + [ options ] are:\n\ + [ -a svc_code -c \"cmd\" -y \"cmt\" [-p modules] [-w id] ]\n\ + [-q] | [-v] | [-s] | [-k] | [-i] |\n\ + [-e svc_code] | [-d svc_code] | [-r svc_code] | [[-q] -z svc_code]\n\ + [[-l addr | -] [-t addr | -]] |\n\ +"; + +usage(flag) +int flag; +{ + switch (flag) { + case INCONSISTENT: + nlsmesg(MM_ERROR, "Inconsistent options"); + break; + case MISSINGARG: + nlsmesg(MM_ERROR, "Missing argument"); + break; + case USAGE: + break; + } + fprintf(stderr, umsg, Nlsname, Nlsname, Nlsname, Nlsname, Nlsname); + exit(NLS_CMD); +} + + +/* + * no_permission: print out error message and exit when the user needs to + * needs to be root and isn't. + */ + +no_permission() +{ + nlsmesg(MM_ERROR, "Must be super user"); + exit(NLS_PERM); +} + +/* + * nlsmesg: print out either an error or a warning message. severity must + * be either MM_ERROR or MM_WARNING. this routine will be converted + * to use the standard message format later. + */ + +void +nlsmesg(severity, text) +int severity; +char *text; +{ + int class; + + if (severity == MM_ERROR) + fprintf(stderr, "%s: error: %s\n", Nlsname, text); + else + fprintf(stderr, "%s: warning: %s\n", Nlsname, text); + return; +} + +/* + * prt_cmd: print out the listener-dependent string for sacadm. + */ + +prt_cmd(path, flags, modules, addr, rpcp) +char *path; /* full path of command or pipe */ +long flags; /* listener flags */ + /* PFLAG for pipe */ + /* CFLAG for command */ + /* DFLAG for dynamic addr */ +char *modules; /* STREAMS modules to push */ +char *addr; /* private address */ +char *rpcp; /* RPC prog and ver # */ +{ + struct stat sbuf; + char mesgbuf[BUFSIZ]; + char *tmp; + + if (*path != '/') { + nlsmesg(MM_ERROR, "Must specify full path name"); + return(NLS_CMD); + } + + if ((tmp = strchr(path, ' ')) != NULL) + *tmp = NULL; + + if (stat(path, &sbuf) < 0) { + if (errno != EFAULT) { + sprintf(mesgbuf, "%s does not exist", path); + nlsmesg(MM_WARNING, mesgbuf); + } + else + return(NLS_SYSERR); + } + + if (tmp) + *tmp = ' '; + + printf("%s:%s:%s:%s:%s\n", (addr ? addr : ""), (rpcp ? rpcp : ""), + pflags(flags), (modules ? modules : ""), path); + return(NLS_OK); +} + +/* + * old_addsvc: use pmadm to add a service code to the listener. this will + * not allow specification of a private address -- use pmadm! + */ + +old_addsvc(svc, addr, cmd, com, module, id, flags, netspec) +char *svc; +char *addr; +char *cmd; +char *com; +char *module; +char *id; +char *flags; +char *netspec; +{ + char buf[BUFSIZ]; + char mesgbuf[BUFSIZ]; + int rtn; + struct stat sbuf; + char *tmp; + + if (!svc || !cmd || !com || !netspec) + usage(MISSINGARG); + + /* create "port-monitor specific" info in the same way as prt_cmd */ + + if (*cmd != '/') { + nlsmesg(MM_ERROR, "Must specify full path name"); + return(NLS_CMD); + } + + if ((tmp = strchr(cmd, ' ')) != NULL) + *tmp = NULL; + + if (stat(cmd, &sbuf) < 0) { + if (errno != EFAULT) { + sprintf(mesgbuf, "%s does not exist", cmd); + nlsmesg(MM_WARNING, mesgbuf); + } + else + return(NLS_SYSERR); + } + + if (tmp) + *tmp = ' '; + + if (addr) + sprintf(mesgbuf, "'%s::c:%s:%s'", addr, module ? module : "" , cmd); + else + sprintf(mesgbuf, "'::c:%s:%s'", module ? module : "" , cmd); + + if (flags && *flags) + sprintf(buf, PM_ADDSVCF, netspec, svc, (id)?id:DEFAULTID, flags, mesgbuf, VERSION, com ? com : ""); + else + sprintf(buf, PM_ADDSVC, netspec, svc, (id)?id:DEFAULTID, mesgbuf, VERSION, com ? com : ""); + + if ((rtn = system(buf)) < 0) { + return(NLS_SYSERR); + } + rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ + + switch (rtn) { + case 0: + return(NLS_OK); + break; + case E_BADARGS: + case E_SAFERR: + case E_SYSERR: + case E_NOEXIST: + case E_PMRUN: + case E_PMNOTRUN: + case E_RECOVER: + case E_SACNOTRUN: + default: + return(NLS_SYSERR); + break; + case E_DUP: + return(NLS_SERV); + break; + case E_NOPRIV: + no_permission(); + break; + } +} + +/* + * prt_nets: print the status of one network, or all nets if netspec + * is NULL + */ +prt_nets(netspec) +char *netspec; +{ + char buf[BUFSIZ]; + FILE *fp; + char *name; + char *state; + char *type; + int found = FALSE; + int rtn = NLS_OK; + + if (netspec == NULL) + sprintf(buf, SAC_LSTY, LISTENTYPE); + else + sprintf(buf, SAC_LSPM, netspec); + + if ((fp = popen(buf, "r")) == NULL) + return(NLS_SYSERR); + + while (fgets(buf, BUFSIZ, fp) != NULL) { + if ((name = nexttok(buf, ":")) == NULL) + return(NLS_SYSERR); + if ((type = nexttok(NULL, ":")) == NULL) + return(NLS_SYSERR); + + if (strcmp(type, LISTENTYPE) != 0) + continue; /* ignore other types of port monitors */ + + found = TRUE; + if (nexttok(NULL, ":") == NULL) + return(NLS_SYSERR); + if (nexttok(NULL, ":") == NULL) + return(NLS_SYSERR); + if ((state = nexttok(NULL, ":")) == NULL) + return(NLS_SYSERR); + if (strcmp(state, "ENABLED") == NULL || + strcmp(state, "STARTING") == NULL) { + rtn = QZERO; + if (!Quietflag) + printf("%s\t%s\n", name, "ACTIVE"); + } + else { + rtn = QONE; + if (!Quietflag) + printf("%s\t%s\n", name, "INACTIVE"); + } + } + pclose(fp); + + if (netspec && !found) { + nlsmesg(MM_ERROR, "Invalid network specification"); + return(NLS_BADPM); + } + + if (netspec) + return(rtn); + else + return(NLS_OK); + +} + + +/* + * print info about service on netspec, or all services on netspec + * if svc is NULL + */ + +prt_svcs(svc, netspec) +char *svc; +char *netspec; +{ + char buf[BUFSIZ]; + char mesg[BUFSIZ]; + FILE *fp; + struct svcfields entry; + int rtn; + int found = FALSE; + char *p; + + if (svc == NULL) + sprintf(buf, PM_LSALL, netspec); + else + sprintf(buf, PM_LSONE, netspec, svc); + + if ((fp = popen(buf, "r")) == NULL) + return(NLS_SYSERR); + + while (fgets(buf, BUFSIZ, fp) != NULL) { + if ((rtn = svc_format(buf, &entry)) != 0) { + switch (rtn) { + case NOTLISTEN: + continue; + break; + case BADPMFMT: + return(NLS_SYSERR); + break; + case BADLISFMT: + sprintf(mesg, "Entry for code \"%s\" has incorrect format", entry.svc_code); + nlsmesg(MM_WARNING, mesg); + continue; + break; + } + } + found = TRUE; + + if (!Quietflag) { + printf("%s\t", entry.svc_code); + if (*entry.addr) + printf("%s\t", entry.addr); + else if (strchr(entry.lflags, 'd')) + printf("DYNAMIC\t"); + else + printf("NOADDR\t"); + + if (strchr(entry.flags, 'x') == NULL) + printf("ENABLED \t"); + else + printf("DISABLED\t"); + + + printf("%s\t%s\t%s\t%s\t# %s", + (*entry.rpc)?entry.rpc:"NORPC", entry.id, + (*entry.modules)?entry.modules:"NOMODULES", + entry.command, (*entry.comment)?entry.comment:""); + } + else { + if (strchr(entry.flags, 'x') == NULL) + return(QZERO); + else + return(QONE); + } + } + + pclose(fp); + + if (rtn == NOTLISTEN) { /* check last return to see if error */ + sprintf(mesg, "Network specification \"%s\" is not of type %s", netspec, LISTENTYPE); + nlsmesg(MM_ERROR, mesg); + return(NLS_BADPM); + } + if (svc && !found) { + if (!Quietflag) { + sprintf(mesg, "Service \"%s\" unknown", svc); + nlsmesg(MM_ERROR, mesg); + } + return(NLS_SERV); + } + + return(NLS_OK); +} + +/* + * disable_svc: use pmadm to disable a service + */ + +disable_svc(svc, netspec) +char *svc; +char *netspec; +{ + char buf[BUFSIZ]; + int rtn; + + sprintf(buf, PM_DISABLE, netspec, svc); + + if ((rtn = system(buf)) < 0) { + return(NLS_SYSERR); + } + rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ + + switch (rtn) { + case 0: + return(NLS_OK); + break; + case E_BADARGS: + case E_SAFERR: + case E_SYSERR: + case E_PMRUN: + case E_PMNOTRUN: + case E_RECOVER: + case E_SACNOTRUN: + default: + return(NLS_SYSERR); + break; + case E_NOEXIST: + case E_DUP: + nlsmesg(MM_ERROR, "Non-existent service."); + return(NLS_SERV); + break; + case E_NOPRIV: + no_permission(); + break; + } +} + + +enable_svc(svc, netspec) +char *svc; +char *netspec; +{ + char buf[BUFSIZ]; + int rtn; + + sprintf(buf, PM_ENABLE, netspec, svc); + + if ((rtn = system(buf)) < 0) { + return(NLS_SYSERR); + } + rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ + + switch (rtn) { + case 0: + return(NLS_OK); + break; + case E_BADARGS: + case E_SAFERR: + case E_SYSERR: + case E_PMRUN: + case E_PMNOTRUN: + case E_RECOVER: + case E_SACNOTRUN: + default: + return(NLS_SYSERR); + break; + case E_NOEXIST: + case E_DUP: + nlsmesg(MM_ERROR, "Non-existent service."); + return(NLS_SERV); + break; + case E_NOPRIV: + no_permission(); + break; + } +} + + +remove_svc(svc, netspec, printerrors) +char *svc; +char *netspec; +int printerrors; +{ + char buf[BUFSIZ]; + int rtn; + + sprintf(buf, PM_REMSVC, netspec, svc); + + if ((rtn = system(buf)) < 0) { + return(NLS_SYSERR); + } + rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ + + switch (rtn) { + case 0: + return(NLS_OK); + break; + case E_BADARGS: + case E_SAFERR: + case E_SYSERR: + case E_PMRUN: + case E_PMNOTRUN: + case E_RECOVER: + case E_SACNOTRUN: + default: + return(NLS_SYSERR); + break; + case E_NOEXIST: + case E_DUP: + if (printerrors) + nlsmesg(MM_ERROR, "Non-existent service."); + return(NLS_SERV); + break; + case E_NOPRIV: + no_permission(); + break; + } +} + + +kill_listener(netspec) +char *netspec; +{ + char buf[BUFSIZ]; + char mesg[BUFSIZ]; + int rtn; + + sprintf(buf, SAC_KILLPM, netspec); + + if ((rtn = system(buf)) < 0) { + return(NLS_SYSERR); + } + rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ + + switch (rtn) { + case 0: + return(NLS_OK); + break; + case E_BADARGS: + case E_DUP: + case E_SAFERR: + case E_SYSERR: + case E_PMRUN: + case E_RECOVER: + case E_SACNOTRUN: + default: + return(NLS_SYSERR); + break; + case E_PMNOTRUN: + sprintf(mesg, "No listener active on network \"%s\"", netspec); + nlsmesg(MM_ERROR, mesg); + return(NLS_FAILED); + case E_NOEXIST: + nlsmesg(MM_ERROR, "Non-existent port monitor."); + return(NLS_SERV); + break; + case E_NOPRIV: + no_permission(); + break; + } +} + + +/* + * add_pm: add a port monitor (initialize directories) using sacadm + */ + +add_pm(netspec) +char *netspec; +{ + char buf[BUFSIZ]; + char mesg[BUFSIZ]; + int rtn; + + sprintf(buf, SAC_ADDPM, netspec, LISTENTYPE, gencmdstr(netspec), VERSION); + + if ((rtn = system(buf)) < 0) { + return(NLS_SYSERR); + } + rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ + + switch (rtn) { + case 0: + old_addsvc(NLPSSVCCODE, NULL, NLPSSRV, "NLPS server", "", "root", NULL, netspec); + return(NLS_OK); + break; + case E_BADARGS: + case E_SAFERR: + case E_SYSERR: + case E_RECOVER: + case E_NOEXIST: + case E_PMNOTRUN: + case E_SACNOTRUN: + default: + return(NLS_SYSERR); + break; + case E_DUP: + case E_PMRUN: + nlsmesg(MM_ERROR, "Listener already initialized"); + return(NLS_FAILED); + break; + case E_NOPRIV: + no_permission(); + break; + } +} + + +/* + * gencmdstr: generate the correct string to invoke the listener (starlan + * requires special handling) + */ + +char * +gencmdstr(netspec) +char *netspec; +{ + static char buf[BUFSIZ]; + + (void) strcpy(buf, LISTENCMD); + if (!strcmp(netspec, "starlan")) + (void) strcat(buf, " -m slan"); + (void) strcat(buf, " "); + (void) strcat(buf, netspec); + return(buf); +} + + +/* + * start_listener: start the listener + */ + +start_listener(netspec) +char *netspec; +{ + char buf[BUFSIZ]; + char scratch[BUFSIZ]; + int rtn; + + sprintf(buf, SAC_STARTPM, netspec); + + if ((rtn = system(buf)) < 0) + return(NLS_SYSERR); + rtn = (rtn>>8) & 0xff; + switch (rtn) { + case 0: + break; + case E_BADARGS: + case E_SAFERR: + case E_SYSERR: + case E_RECOVER: + case E_PMNOTRUN: + case E_SACNOTRUN: + default: + return(NLS_SYSERR); + break; + case E_NOEXIST: + case E_DUP: + nlsmesg(MM_ERROR, "Non-existent port monitor."); + return(NLS_BADPM); + break; + case E_PMRUN: + nlsmesg(MM_ERROR, "Listener already running"); + return(NLS_FAILED); + case E_NOPRIV: + no_permission(); + break; + } + + sprintf(buf, SAC_ENABLPM, netspec); + + if ((rtn = system(buf)) < 0) { + return(NLS_SYSERR); + } + rtn = (rtn>>8) & 0xff; + switch (rtn) { + case 0: + return(NLS_OK); + break; + case E_BADARGS: + case E_SAFERR: + case E_SYSERR: + case E_RECOVER: + case E_SACNOTRUN: + default: + return(NLS_SYSERR); + break; + case E_NOEXIST: + case E_DUP: + nlsmesg(MM_ERROR, "Non-existent port monitor."); + return(NLS_BADPM); + break; + case E_PMRUN: + nlsmesg(MM_ERROR, "Listener already running"); + return(NLS_FAILED); + case E_PMNOTRUN: + nlsmesg(MM_ERROR, "Listener start failed"); + return(NLS_FAILED); + case E_NOPRIV: + no_permission(); + break; + } +} + + +/* + * setup_addr: setup the -l and -t addresses. + */ + +setup_addr(laddr, taddr, netspec) +char *laddr; +char *taddr; +char *netspec; +{ + char buf[BUFSIZ]; + char mesg[BUFSIZ]; + char *p; + int rtn; + int qlisten = FALSE; + int qtty = FALSE; + FILE *fp; + struct svcfields entry; + + if (laddr && *laddr == '-') + qlisten = TRUE; + + if (taddr && *taddr == '-') + qtty = TRUE; + + if (laddr) { + sprintf(buf, PM_LSONE, netspec, NLPSSVCCODE); + + if ((fp = popen(buf, "r")) == NULL) { + return(NLS_SYSERR); + } + + if (fgets(buf, BUFSIZ, fp) != NULL) { + if ((rtn = svc_format(buf, &entry)) != 0) { + switch (rtn) { + case NOTLISTEN: + nlsmesg(MM_ERROR, "Incorrect port monitor type. Must be of type listen"); + return(NLS_FAILED); + break; + case BADPMFMT: + return(NLS_SYSERR); + break; + case BADLISFMT: + sprintf(mesg, "Entry for code \"%s\" has incorrect format", entry.svc_code); + nlsmesg(MM_WARNING, mesg); + break; + } + } + else { + if (qlisten) + printf("%s\n", entry.addr); + else { + if (geteuid() != ROOT) + no_permission(); + /* add address */ + remove_svc(NLPSSVCCODE, netspec, FALSE); + p = strchr(entry.comment, '\n'); + if (p) + *p = '\0'; + old_addsvc(NLPSSVCCODE, laddr, entry.command, entry.comment, entry.modules, entry.id, entry.flags, netspec); + } + } + pclose(fp); + } + else if (!qlisten) + nlsmesg(MM_WARNING, "NLPS service not defined"); + } + if (taddr) { + sprintf(buf, PM_LSONE, netspec, TTYSVCCODE); + + if ((fp = popen(buf, "r")) == NULL) { + return(NLS_SYSERR); + } + + if (fgets(buf, BUFSIZ, fp) != NULL) { + if ((rtn = svc_format(buf, &entry)) != 0) { + switch (rtn) { + case NOTLISTEN: + nlsmesg(MM_ERROR, "Incorrect port monitor type. Must be of type listen"); + return(NLS_FAILED); + break; + case BADPMFMT: + return(NLS_SYSERR); + break; + case BADLISFMT: + sprintf(mesg, "Entry for code \"%s\" has incorrect format", entry.svc_code); + nlsmesg(MM_WARNING, mesg); + break; + } + } + else { + if (qtty) + printf("%s\n", entry.addr); + else { + if (geteuid() != ROOT) + no_permission(); + /* add address */ + remove_svc(TTYSVCCODE, netspec, FALSE); + p = strchr(entry.comment, '\n'); + if (p) + *p = '\0'; + old_addsvc(TTYSVCCODE, taddr, entry.command, entry.comment, entry.modules, entry.id, entry.flags, netspec); + } + } + pclose(fp); + } + else if (!qtty) + nlsmesg(MM_WARNING, "remote login service not defined"); + } + return(NLS_OK); +} + + +/* + * svc_format: scan a line of output from pmadm to separate it into fields. + * returns BADPMFMT for missing fields or incorrect syntax. + * NOTLISTEN is the port monitor type is not listen. + * BADLISFMT if the listener-specific data is incorrect. + * NLS_OK if everything checked out and data is broken + * into the structure. + */ + +svc_format(buf, entry) +char *buf; +struct svcfields *entry; +{ + char *ptr; /* temporary pointer into buffer */ + char *tmp; /* temporary pointer into buffer */ + + entry->pmtag = buf; + if ((ptr = strchr(buf, ':')) == NULL) + return(BADPMFMT); + *ptr++ = NULL; + entry->pmtype = ptr; + if ((ptr = strchr(entry->pmtype, ':')) == NULL) + return(BADPMFMT); + *ptr++ = NULL; + entry->svc_code = ptr; + + if (strcmp(entry->pmtype, LISTENTYPE) != 0) + return(NOTLISTEN); + + if ((ptr = strchr(entry->svc_code, ':')) == NULL) + return(BADPMFMT); + *ptr++ = NULL; + entry->flags = ptr; + if ((ptr = strchr(entry->flags, ':')) == NULL) + return(BADPMFMT); + *ptr++ = NULL; + entry->id = ptr; + if ((ptr = strchr(entry->id, ':')) == NULL) + return(BADPMFMT); + *ptr++ = NULL; + entry->res1 = ptr; + if ((ptr = strchr(entry->res1, ':')) == NULL) + return(BADPMFMT); + *ptr++ = NULL; + entry->res2 = ptr; + if ((ptr = strchr(entry->res2, ':')) == NULL) + return(BADPMFMT); + *ptr++ = NULL; + entry->res3 = ptr; + if ((ptr = strchr(entry->res3, ':')) == NULL) + return(BADPMFMT); + *ptr++ = NULL; + entry->addr = ptr; + if ((ptr = strchr(entry->addr, ':')) == NULL) + return(BADLISFMT); + *ptr++ = NULL; + entry->rpc = ptr; + if ((ptr = strchr(entry->rpc, ':')) == NULL) + return(BADLISFMT); + *ptr++ = NULL; + if (*entry->rpc) { + if ((tmp = strchr(entry->rpc, ',')) == NULL) + return(BADLISFMT); + *tmp = ':'; + } + entry->lflags = ptr; + if ((ptr = strchr(entry->lflags, ':')) == NULL) + return(BADLISFMT); + *ptr++ = NULL; + entry->modules = ptr; + if ((ptr = strchr(entry->modules, ':')) == NULL) + return(BADLISFMT); + *ptr++ = NULL; + entry->command = ptr; + if ((ptr = strchr(entry->command, '#')) == NULL) + return(BADLISFMT); + *ptr++ = NULL; + entry->comment = ptr; + return(NLS_OK); +} + + +/* + * nexttok - return next token, essentially a strtok, but it can + * deal with null fields and strtok can not + * + * args: str - the string to be examined, NULL if we should + * examine the remembered string + * delim - the list of valid delimiters + */ + + +char * +nexttok(str, delim) +char *str; +register char *delim; +{ + static char *savep; /* the remembered string */ + register char *p; /* pointer to start of token */ + register char *ep; /* pointer to end of token */ + + p = (str == NULL) ? savep : str ; + if (p == NULL) + return(NULL); + ep = strpbrk(p, delim); + if (ep == NULL) { + savep = NULL; + return(p); + } + savep = ep + 1; + *ep = '\0'; + return(p); +} + + +/* + * pflags - put flags into intelligible form for output + * + * args: flags - binary representation of flags + */ + +char * +pflags(flags) +long flags; +{ + register int i; /* scratch counter */ + static char buf[BUFSIZ]; /* formatted flags */ + + if (flags == 0) + return(""); + i = 0; + if (flags & CFLAG) { + buf[i++] = 'c'; + flags &= ~CFLAG; + } + if (flags & DFLAG) { + buf[i++] = 'd'; + flags &= ~DFLAG; + } + if (flags & PFLAG) { + buf[i++] = 'p'; + flags &= ~PFLAG; + } + if (flags) { + nlsmesg(MM_ERROR, "Internal error in pflags"); + exit(NLS_FAILED); + } + buf[i] = '\0'; + return(buf); +} diff --git a/usr/src/cmd/nlsadmin/nlsadmin.h b/usr/src/cmd/nlsadmin/nlsadmin.h new file mode 100644 index 0000000000..8aed200103 --- /dev/null +++ b/usr/src/cmd/nlsadmin/nlsadmin.h @@ -0,0 +1,112 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.15.1.3 */ + +/* + * nlsadmin.h: nlsadmin defines and structs + */ + +#define VERSION 4 /* current database version */ +#define MAXNAMESZ 15 +#define SVC_CODE_SZ 14 +#define DEFAULTID "listen" /* default id for servers */ +#define LISTENTYPE "listen" /* pm type for listener service */ +#define ROOT (uid_t) 0 + +#define NLPSSRV "/usr/lib/saf/nlps_server" /* full path of nlps server */ +#define LISTENCMD "/usr/lib/saf/listen" /* full path of the listener */ +#define NLPSSVCCODE "0" /* (string!) protoserv service code */ +#define TTYSVCCODE "1" /* (string!) ttyserv service code */ + +/* + * bit flags for argument processing + */ + +#define NONE 0x0000 +#define CMDFLAG 0x0001 +#define PIPFLAG 0x0002 +#define VERFLAG 0x0004 +#define DISFLAG 0x0008 +#define ENAFLAG 0x0010 +#define KILFLAG 0x0020 +#define ADRFLAG 0x0040 +#define REMFLAG 0x0080 +#define STAFLAG 0x0100 +#define VBSFLAG 0x0200 +#define NETFLAG 0x0400 +#define ZZZFLAG 0x0800 +#define INIFLAG 0x1000 + +/* + * other misc defines + */ + +#define INCONSISTENT 1 +#define MISSINGARG 2 +#define USAGE 3 + +#define NOTLISTEN 1 +#define BADPMFMT 2 +#define BADLISFMT 3 + +#define CFLAG 0x1 +#define PFLAG 0x2 +#define DFLAG 0x4 + +extern char *optarg; +extern int optind; +extern int errno; + +/* + * error returns from nlsadmin (1 is reserved for passing non-error + * information (-q)) + */ + +#define NLS_OK 0 /* no error */ +#define NLS_FAILED 2 /* failure in command */ +#define NLS_PERM 3 /* must be root */ +#define NLS_SERV 4 /* error in service code */ +#define NLS_CMD 5 /* command line error */ +#define NLS_SYSERR 6 /* system error during cmd */ +#define NLS_BADPM 7 /* bad port monitor */ + +/* + * command lines for SAC functions + */ + +#define SAC_LSPM "/usr/sbin/sacadm -L -p %s 2>/dev/null" +#define SAC_LSTY "/usr/sbin/sacadm -L -t %s 2>/dev/null" +#define SAC_KILLPM "/usr/sbin/sacadm -k -p %s 2>/dev/null" +#define SAC_STARTPM "/usr/sbin/sacadm -s -p %s 2>/dev/null" +#define SAC_ENABLPM "/usr/sbin/sacadm -e -p %s 2>/dev/null" +#define SAC_ADDPM "/usr/sbin/sacadm -a -p %s -t %s -c \"%s\" -v %d 2>/dev/null" +#define PM_DISABLE "/usr/sbin/pmadm -d -p %s -s %s 2>/dev/null" +#define PM_ENABLE "/usr/sbin/pmadm -e -p %s -s %s 2>/dev/null" +#define PM_LSALL "/usr/sbin/pmadm -L -p %s 2>/dev/null" +#define PM_LSONE "/usr/sbin/pmadm -L -p %s -s %s 2>/dev/null" +#define PM_REMSVC "/usr/sbin/pmadm -r -p %s -s %s 2>/dev/null" +#define PM_ADDSVC "/usr/sbin/pmadm -a -p %s -s %s -i %s -m %s -v %d -y \"%s\" 2>/dev/null" +#define PM_ADDSVCF "/usr/sbin/pmadm -a -p %s -s %s -i %s -f %s -m %s -v %d -y \"%s\" 2>/dev/null" |
