/*
* 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
* 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 2005 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 <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <sac.h>
#include "nlsadmin.h"
#ifndef FALSE
#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
/*
* defines for simulated standard error format code
*/
#define MM_NOSEV 0
extern int errno;
void nlsmesg();
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;
};
void no_permission(void) __NORETURN;
int
{
extern char *optarg;
extern int optind;
int c; /* used for return from getopt */
switch (c) {
case 'a':
break;
case 'c':
break;
case 'd':
break;
case 'e':
break;
case 'i':
break;
case 'k':
break;
case 'l':
break;
case 'm':
break;
case 'o':
break;
case 'p':
break;
case 'q':
break;
case 'r':
break;
case 's':
break;
case 't':
break;
case 'v':
break;
case 'w':
break;
case 'x':
break;
case 'y':
break;
case 'z':
break;
case 'A':
break;
case 'D':
|| lflags )
break;
case 'N':
if ( netspec )
break;
case 'R':
/*
* 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 (ptr)
/* change the ':' to a ',' */
*ptr = ',';
else
break;
case 'V':
break;
case '?':
}
/* NOTREACHED */
}
/* determine if this command requires a netspec */
/* if flag is CMDFLAG, more complicated checking of netspec
* is done below in switch
*/
if (netspec)
}
else if (!netspec)
}
}
}
else {
ptr++;
}
}
}
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.
*/
if ((c == 0) || (c >= SVC_CODE_SZ)) {
}
}
switch (flag) {
default:
break;
case NONE:
break;
case INIFLAG:
break;
case CMDFLAG:
switch (exitcode) {
case NLS_SERV:
break;
default:
break;
}
}
else {
if (netspec)
}
break;
case PIPFLAG:
break;
case VERFLAG:
break;
case DISFLAG:
break;
case ENAFLAG:
break;
case KILFLAG:
break;
case ADRFLAG:
/* check for root permissions in setup_addr */
break;
case REMFLAG:
break;
case STAFLAG:
break;
case VBSFLAG:
break;
case NETFLAG:
break;
case ZZZFLAG:
break;
}
if (exitcode == NLS_SYSERR)
return (exitcode);
}
%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\
";
void
{
switch (flag) {
case INCONSISTENT:
break;
case MISSINGARG:
break;
case USAGE:
break;
}
}
/*
* no_permission: print out error message and exit when the user needs to
* needs to be root and isn't.
*/
void
no_permission(void)
{
}
/*
* 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
{
int class;
else
return;
}
/*
* prt_cmd: print out the listener-dependent string for sacadm.
*/
int
/* path: full path of command or pipe */
/* flags: listener flags */
/* PFLAG for pipe */
/* CFLAG for command */
/* DFLAG for dynamic addr */
/* modules: STREAMS modules to push */
/* addr: private address */
/* rpcp: RPC prog and ver # */
{
char *tmp;
if (*path != '/') {
return(NLS_CMD);
}
}
else
return(NLS_SYSERR);
}
if (tmp)
*tmp = ' ';
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!
*/
int
{
int rtn;
char *tmp;
/* create "port-monitor specific" info in the same way as prt_cmd */
if (*cmd != '/') {
return(NLS_CMD);
}
}
else
return(NLS_SYSERR);
}
if (tmp)
*tmp = ' ';
if (addr)
else
else
return(NLS_SYSERR);
}
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:
break;
}
/* NOTREACHED */
}
/*
* prt_nets: print the status of one network, or all nets if netspec
* is NULL
*/
int
{
char *name;
char *state;
char *type;
else
return(NLS_SYSERR);
return(NLS_SYSERR);
return(NLS_SYSERR);
continue; /* ignore other types of port monitors */
return(NLS_SYSERR);
return(NLS_SYSERR);
return(NLS_SYSERR);
if (!Quietflag)
}
else {
if (!Quietflag)
}
}
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
*/
int
{
int rtn;
char *p;
else
return(NLS_SYSERR);
switch (rtn) {
case NOTLISTEN:
continue;
break;
case BADPMFMT:
return(NLS_SYSERR);
break;
case BADLISFMT:
continue;
break;
}
}
if (!Quietflag) {
printf("DYNAMIC\t");
else
printf("NOADDR\t");
printf("ENABLED \t");
else
printf("DISABLED\t");
printf("%s\t%s\t%s\t%s\t# %s",
}
else {
return(QZERO);
else
return(QONE);
}
}
return(NLS_BADPM);
}
if (!Quietflag) {
}
return(NLS_SERV);
}
return(NLS_OK);
}
/*
* disable_svc: use pmadm to disable a service
*/
int
{
int rtn;
return(NLS_SYSERR);
}
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:
return(NLS_SERV);
break;
case E_NOPRIV:
break;
}
/* NOTREACHED */
}
int
{
int rtn;
return(NLS_SYSERR);
}
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:
return(NLS_SERV);
break;
case E_NOPRIV:
break;
}
/* NOTREACHED */
}
int
{
int rtn;
return(NLS_SYSERR);
}
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)
return(NLS_SERV);
break;
case E_NOPRIV:
break;
}
/* NOTREACHED */
}
int
{
int rtn;
return(NLS_SYSERR);
}
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:
return(NLS_FAILED);
case E_NOEXIST:
return(NLS_SERV);
break;
case E_NOPRIV:
break;
}
/* NOTREACHED */
}
/*
* add_pm: add a port monitor (initialize directories) using sacadm
*/
int
{
int rtn;
return(NLS_SYSERR);
}
switch (rtn) {
case 0:
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:
return(NLS_FAILED);
break;
case E_NOPRIV:
break;
}
/* NOTREACHED */
}
/*
* gencmdstr: generate the correct string to invoke the listener (starlan
* requires special handling)
*/
char *
{
return(buf);
}
/*
* start_listener: start the listener
*/
int
{
int rtn;
return(NLS_SYSERR);
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:
return(NLS_BADPM);
break;
case E_PMRUN:
return(NLS_FAILED);
case E_NOPRIV:
break;
}
return(NLS_SYSERR);
}
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:
return(NLS_BADPM);
break;
case E_PMRUN:
return(NLS_FAILED);
case E_PMNOTRUN:
return(NLS_FAILED);
case E_NOPRIV:
break;
}
/* NOTREACHED */
}
/*
* setup_addr: setup the -l and -t addresses.
*/
int
{
char *p;
int rtn;
if (laddr) {
return(NLS_SYSERR);
}
switch (rtn) {
case NOTLISTEN:
return(NLS_FAILED);
break;
case BADPMFMT:
return(NLS_SYSERR);
break;
case BADLISFMT:
break;
}
}
else {
if (qlisten)
else {
/* add address */
if (p)
*p = '\0';
old_addsvc(NLPSSVCCODE, laddr, entry.command, entry.comment, entry.modules, entry.id, entry.flags, netspec);
}
}
}
else if (!qlisten)
}
if (taddr) {
return(NLS_SYSERR);
}
switch (rtn) {
case NOTLISTEN:
return(NLS_FAILED);
break;
case BADPMFMT:
return(NLS_SYSERR);
break;
case BADLISFMT:
break;
}
}
else {
if (qtty)
else {
/* add address */
if (p)
*p = '\0';
old_addsvc(TTYSVCCODE, taddr, entry.command, entry.comment, entry.modules, entry.id, entry.flags, netspec);
}
}
}
else if (!qtty)
}
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.
*/
int
{
return(BADPMFMT);
return(BADPMFMT);
return(NOTLISTEN);
return(BADPMFMT);
return(BADPMFMT);
return(BADPMFMT);
return(BADPMFMT);
return(BADPMFMT);
return(BADPMFMT);
return(BADLISFMT);
return(BADLISFMT);
return(BADLISFMT);
*tmp = ':';
}
return(BADLISFMT);
return(BADLISFMT);
return(BADLISFMT);
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 *
{
register char *p; /* pointer to start of token */
if (p == NULL)
return(NULL);
return(p);
}
*ep = '\0';
return(p);
}
/*
* pflags - put flags into intelligible form for output
*
* args: flags - binary representation of flags
*/
char *
{
register int i; /* scratch counter */
if (flags == 0)
return("");
i = 0;
buf[i++] = 'c';
}
buf[i++] = 'd';
}
buf[i++] = 'p';
}
if (flags) {
}
buf[i] = '\0';
return(buf);
}