/*
* 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"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include "extern.h"
#include "misc.h"
#include <sac.h>
#include "structs.h"
/*
* functions
*/
char *pflags();
char *pspec();
void usage();
void parseline();
void add_svc();
void rem_svc();
void ed_svc();
void list_svcs();
void doconf();
/*
* format of a _pmtab entry - used to hold parsed info
*/
struct pmtab {
};
/*
* format of a tag list, which is a list of port monitor tags of
* a designated type
*/
struct taglist {
};
/*
* common error messages
*/
/*
* main - scan args for pmadm and call appropriate handling code
*/
int
{
int c; /* option letter */
register char *p; /* scratch pointer */
if (argc == 1)
switch (c) {
case 'a':
sawaflag = 1;
break;
case 'd':
break;
case 'e':
break;
case 'f':
while (*optarg) {
switch (*optarg++) {
case 'u':
break;
case 'x':
break;
default:
break;
}
}
/* null terminate just in case anything is there */
break;
case 'g':
break;
case 'i':
}
break;
case 'L':
break;
case 'l':
break;
case 'm':
}
if (*optarg == '\0') {
/* this will generate a usage message below */
errflg++;
break;
}
break;
case 'p':
}
}
for (p = pmtag; *p; p++) {
if (!isalnum(*p)) {
error("port monitor tag must be alphanumeric");
}
}
break;
case 'r':
break;
case 's':
}
}
for (p = svctag; *p; p++) {
if (!isalnum(*p)) {
error("service tag must be alphanumeric");
}
}
break;
case 't':
}
}
for (p = type; *p; p++) {
if (!isalnum(*p)) {
error("port monitor type must be alphanumeric");
}
}
break;
case 'v':
if (version < 0) {
error("version number can not be negative");
}
break;
case 'y':
}
break;
case 'z':
}
break;
case '?':
errflg++;
}
}
if (badcnt) {
/* bad flags were given to -f */
}
/*
* don't do anything if _sactab isn't the version we understand
*/
error("_sactab version number is incorrect");
}
else if (ret == 2) {
}
else if (ret == 3) {
}
switch (flag) {
case ADD:
if (uid) {
}
if (!sawaflag || (pmtag && type) || (!pmtag && !type) || !svctag || !id || !pmspec || (version < 0))
break;
case REMOVE:
if (uid) {
}
break;
case ENABLE:
if (uid) {
}
break;
case DISABLE:
if (uid) {
}
break;
case LIST:
conflag = 1;
/* fall through */
case PLIST:
break;
case CONFIG:
}
break;
default:
/* we only get here if more than one flag bit was set */
/* NOTREACHED */
}
quit();
/* NOTREACHED */
}
/*
* usage - print out a usage message
*
* args: cmdname - the name command was invoked with
*/
void
char *cmdname;
{
(void) fprintf(stderr, "Usage:\t%s -a [ -p pmtag | -t type ] -s svctag -i id -m \"pmspecific\"\n", cmdname);
quit();
}
/*
* add_svc - add a service entry
*
* args: tag - port monitor's tag (may be null)
* type - port monitor's type (may be null)
* svctag - service's tag
* id - identity under which service should run
* pmspec - uninterpreted port monitor-specific info
* flags - service flags
* version - version number of port monitor's pmtab
* comment - comment describing service
* script - service's configuration script
*/
void
char *tag;
char *type;
char *svctag;
char *id;
char *pmspec;
long flags;
int version;
char *comment;
char *script;
{
error("Could not open _sactab");
}
}
}
if (tag) {
/*
* treat the case of 1 PM as a degenerate case of a list of PMs from a
* type specification. Build the 'list' here.
*/
}
added = 0;
while (tp) {
}
else if (ret == 2) {
}
else if (ret == 3) {
}
}
if (tag) {
/* special case of tag only */
}
else {
continue;
}
}
/*
* put in the config script, if specified
*/
if (script) {
/* do_config put out any messages */
continue;
}
}
/*
* add the line
*/
}
added++;
/*
* tell the SAC to to tell PM to read _pmtab
*/
}
if (added == 0) {
error("No services added");
}
return;
}
/*
* rem_svc - remove a service
*
* args: pmtag - tag of port monitor responsible for the service
* svctag - tag of the service to be removed
*/
void
char *pmtag;
char *svctag;
{
error("Could not open _sactab");
}
}
}
}
if (line != 1) {
error("error accessing temp file");
}
}
error("error accessing temp file");
}
error("error closing tempfile");
}
/* note - replace only returns if successful */
/*
* tell the SAC to to tell PM to read _pmtab
*/
/*
* if we got rid of the service, try to remove the config script too.
* Don't check return status since it may not have existed anyhow.
*/
return;
}
}
/*
* ed_svc - enable or disable a particular service
*
* args: pmtag - tag of port monitor responsible for the service
* svctag - tag of service to be enabled or disabled
* flag - operation to perform (ENABLE or DISABLE)
*/
void
char *pmtag;
char *svctag;
int flag;
{
char *p; /* scratch pointer */
error("Could not open _sactab");
}
}
}
}
if (line != 1) {
error("error accessing temp file");
}
}
/*
* Note: find_svc above has already read and parsed this entry, thus
* we know it to be well-formed, so just change the flags as appropriate
*/
error("error accessing temp file");
}
/*
* copy initial portion of entry
*/
for ( ; from <= p; )
/*
* isolate and fix the flags
*/
for ( ; from < p; ) {
if (*from == 'x') {
from++;
continue;
}
}
/*
* above we removed x flag, if this was a disable operation, stick it in
* and also copy the field delimiter
*/
*to++ = 'x';
/*
* copy the rest of the line
*/
/*** *to = '\0'; BUG: Don't uncomment it ****/
error("error accessing temp file");
}
error("error closing tempfile");
}
/* note - replace only returns if successful */
/*
* tell the SAC to to tell PM to read _pmtab
*/
}
/*
* doconf - take a config script and have it put where it belongs or
* output an existing one
*
* args: script - name of file containing script (if NULL, means
* output existing one instead)
* tag - tag of port monitor that is responsible for the
* designated service (may be null)
* type - type of port monitor that is responsible for the
* designated service (may be null)
* svctag - tag of service whose config script we're operating on
*/
void
char *script;
char *tag;
char *type;
char *svctag;
{
error("Could not open _sactab");
}
}
}
if (tag) {
/*
* treat the case of 1 PM as a degenerate case of a list of PMs from a
* type specification. Build the 'list' here.
*/
}
added = 0;
while (tp) {
}
if (tag) {
/* special case of tag only */
}
else {
continue;
}
}
/*
* do_config does all the real work (keep track if any errors occurred)
*/
added++;
}
if (added == 0) {
error("No configuration scripts installed");
}
return;
}
/*
* tell_sac - use sacadm to tell the sac to tell a port monitor to read
* its _pmtab. Return TRUE on success, FALSE on failure.
*
* args: tag - tag of port monitor to be notified
*/
int
{
(void) fprintf(stderr, "warning - fork failed - could not notify <%s> about modified table\n", tag);
return(FALSE);
}
else if (pid) {
/* parent */
if (status) {
return (FALSE);
}
} else {
}
"warning - could not notify <%s> about modified"
" table\n", tag);
" \"sacadm -x -p %s\"\n", tag);
return(FALSE);
}
else {
return(TRUE);
}
}
else {
/* set IFS for security */
(void) putenv("IFS=\" \"");
/* muffle sacadm warning messages */
/*
* if we got here, it didn't work, exit status will clue in parent to
* put out the warning
*/
exit(1);
}
/* NOTREACHED */
}
/*
* list_svcs - list information about services
*
* args: pmtag - tag of port monitor responsible for the service
* (may be null)
* type - type of port monitor responsible for the service
* (may be null)
* svctag - tag of service to be listed (may be null)
* oflag - true if output should be easily parseable
*/
void
char *pmtag;
char *type;
char *svctag;
{
register char *p; /* working pointer */
error("Could not open _sactab");
}
}
if (type) {
}
}
else
while (tp) {
/* not interested in this port monitor */
continue;
}
}
if (*p == '\0')
continue;
if (oflag) {
(void) printf("%s:%s:%s:%s:%s:%s:%s:%s:%s#%s\n",
}
else {
if (nprint == 0) {
(void) printf("PMTAG PMTYPE SVCTAG FLGS ID <PMSPECIFIC>\n");
}
}
nprint++;
}
}
}
else {
}
}
/* if we didn't find any valid ones, indicate an error */
if (nprint == 0) {
if (svctag)
else
}
return;
}
/*
* find_svc - find an entry in _pmtab for a particular service tag
*
* args: fp - file pointer for _pmtab
* tag - port monitor tag (for error reporting)
* svctag - tag of service we're looking for
*/
int
{
register char *p; /* working pointer */
line++;
if (*p == '\0')
continue;
return(line);
}
/* NOTREACHED */
return (0);
} else
return (0);
}
/*
* parseline - parse a line from _pmtab. This routine will return if the
* parse wa successful, otherwise it will output an error and
* exit.
*
* args: p - pointer to the data read from the file (note - this is
* a static data region, so we can point into it)
* pp - pointer to a structure in which the separated fields
* are placed
* tag - port monitor tag (for error reporting)
*
* A line in the file has the following format:
*
* tag:flags:identity:reserved:reserved:reserved:PM_spec_info # comment
*/
void
register char *p;
char *tag;
{
/*
* get the service tag
*/
if (p == NULL) {
}
p[PMTAGSIZE] = '\0';
}
/*
* get the flags
*/
if (p == NULL) {
}
while (*p) {
switch (*p++) {
case 'u':
break;
case 'x':
break;
default:
break;
}
}
/*
* get the identity
*/
if (p == NULL) {
}
/*
* get the first reserved field
*/
if (p == NULL) {
}
/*
* get the second reserved field
*/
if (p == NULL) {
}
/*
* get the third reserved field
*/
if (p == NULL) {
}
/*
* the rest is the port monitor specific info
*/
if (p == NULL) {
}
return;
}
/*
* pspec - format port monitor specific information
*
* args: spec - port monitor specific info, separated by
* field separater character (may be escaped by \)
*/
char *
char *spec;
{
newflag = 1;
while (*from) {
switch (*from) {
case ':':
if (newflag) {
*to++ = '-';
}
*to++ = ' ';
from++;
newflag = 1;
break;
case '\\':
*to++ = ':';
/* skip over \: */
from += 2;
}
else
newflag = 0;
break;
default:
newflag = 0;
}
}
*to = '\0';
return(buf);
}
/*
* pflags - put service flags into intelligible form for output
*
* args: flags - binary representation of flags
* dflag - true if a "-" should be returned if no flags
*/
char *
long flags;
int dflag;
{
register int i; /* scratch counter */
if (flags == 0) {
if (dflag)
return("-");
else
return("");
}
i = 0;
buf[i++] = 'u';
}
buf[i++] = 'x';
}
if (flags) {
error("Internal error in pflags");
}
buf[i] = '\0';
return(buf);
}
/*
* find_type - find entries in _sactab for a particular port monitor type
*
* args: fp - file pointer for _sactab
* type - type of port monitor we're looking for (if type is
* null, it means find all PMs)
*/
struct taglist *
char *type;
{
register char *p; /* working pointer */
if (*p == '\0')
continue;
error("malloc failed");
}
}
}
error("error reading _sactab");
/* NOTREACHED */
return (0);
} else
}