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/ttymon/tmpmtab.c | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/ttymon/tmpmtab.c')
-rw-r--r-- | usr/src/cmd/ttymon/tmpmtab.c | 849 |
1 files changed, 849 insertions, 0 deletions
diff --git a/usr/src/cmd/ttymon/tmpmtab.c b/usr/src/cmd/ttymon/tmpmtab.c new file mode 100644 index 0000000000..80a1f4a6cd --- /dev/null +++ b/usr/src/cmd/ttymon/tmpmtab.c @@ -0,0 +1,849 @@ +/* + * 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 2004 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 <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <ctype.h> +#include <string.h> +#include <pwd.h> +#include <grp.h> +#include <signal.h> +#include "ttymon.h" +#include "tmstruct.h" +#include "tmextern.h" + +extern char *strsave(); +extern void set_softcar(); +extern int vml(); +void purge(); +static int get_flags(); +static int get_ttyflags(); +static int same_entry(); +static int check_pmtab(); +static void insert_pmtab(); +static void free_pmtab(); +static char *expand(); + +int check_identity(); + +int strcheck(); + +/* + * read_pmtab() + * - read and parse pmtab + * - store table in linked list pointed by global variable "PMtab" + * - exit if file does not exist or error detected. + */ +void +read_pmtab() +{ + register struct pmtab *gptr; + register char *ptr, *wptr; + FILE *fp; + int input, state, size, rawc, field, linenum; + char oldc; + char line[BUFSIZ]; + char wbuf[BUFSIZ]; + static char *states[] = { + "","tag","flags","identity","reserved1","reserved2","reserved3", + "device","ttyflags","count","service", "timeout","ttylabel", + "modules","prompt","disable msg","terminal type","soft-carrier" + }; + +# ifdef DEBUG + debug("in read_pmtab"); +# endif + + if ((fp = fopen(PMTABFILE,"r")) == NULL) { + fatal("open pmtab (%s) failed", PMTABFILE); + } + + Nentries = 0; + if (check_version(PMTAB_VERS, PMTABFILE) != 0) + fatal("check pmtab version failed"); + + for (gptr = PMtab; gptr; gptr = gptr->p_next) { + if ((gptr->p_status == SESSION) || + (gptr->p_status == LOCKED) || + (gptr->p_status == UNACCESS)) { + if (gptr->p_fd > 0) { + (void)close(gptr->p_fd); + gptr->p_fd = 0; + } + gptr->p_inservice = gptr->p_status; + } + gptr->p_status = NOTVALID; + } + + wptr = wbuf; + input = ACTIVE; + linenum = 0; + do { + linenum++; + line[0] = '\0'; + for (ptr= line,oldc = '\0'; ptr < &line[sizeof(line)-1] && + (rawc=getc(fp))!= '\n' && rawc != EOF; ptr++,oldc=(char)rawc){ + if ((rawc == '#') && (oldc != '\\')) + break; + *ptr = (char)rawc; + } + *ptr = '\0'; + + /* skip rest of the line */ + if (rawc != EOF && rawc != '\n') { + if (rawc != '#') + log("Entry too long.\n"); + while ((rawc = getc(fp)) != EOF && rawc != '\n') + ; + } + + if (rawc == EOF) { + if (ptr == line) break; + else input = FINISHED; + } + + /* if empty line, skip */ + for (ptr=line; *ptr != '\0' && isspace(*ptr); ptr++) + ; + if (*ptr == '\0') continue; + +#ifdef DEBUG + debug("**** Next Entry ****\n%s", line); +#endif + log("Processing pmtab line #%d", linenum); + + /* Now we have the complete line */ + + if ((gptr = ALLOC_PMTAB) == PNULL) + fatal("memory allocation failed"); + + /* set hangup flag, this is the default */ + gptr->p_ttyflags |= H_FLAG; + + /* + * For compatibility reasons, we cannot rely on these + * having values assigned from pmtab. + */ + gptr->p_termtype = ""; + gptr->p_softcar = ""; + + for (state=P_TAG,ptr=line;state !=FAILURE && state !=SUCCESS;) { + switch(state) { + case P_TAG: + gptr->p_tag = strsave(getword(ptr,&size,0)); + break; + case P_FLAGS: + (void)strcpy(wptr, getword(ptr,&size,0)); + if ((get_flags(wptr, &gptr->p_flags)) != 0) { + field = state; + state = FAILURE; + } + break; + case P_IDENTITY: + gptr->p_identity=strsave(getword(ptr,&size,0)); + break; + case P_RES1: + gptr->p_res1=strsave(getword(ptr,&size,0)); + break; + case P_RES2: + gptr->p_res2=strsave(getword(ptr,&size,0)); + break; + case P_RES3: + gptr->p_res3=strsave(getword(ptr,&size,0)); + break; + case P_DEVICE: + gptr->p_device = strsave(getword(ptr,&size,0)); + break; + case P_TTYFLAGS: + (void)strcpy(wptr, getword(ptr,&size,0)); + if ((get_ttyflags(wptr,&gptr->p_ttyflags))!=0) { + field = state; + state = FAILURE; + } + break; + case P_COUNT: + (void)strcpy(wptr, getword(ptr,&size,0)); + if (strcheck(wptr, NUM) != 0) { + log("wait_read count must be a positive number"); + field = state; + state = FAILURE; + } + else + gptr->p_count = atoi(wptr); + break; + case P_SERVER: + gptr->p_server = + strsave(expand(getword(ptr,&size,1), + gptr->p_device)); + break; + case P_TIMEOUT: + (void)strcpy(wptr, getword(ptr,&size,0)); + if (strcheck(wptr, NUM) != 0) { + log("timeout value must be a positive number"); + field = state; + state = FAILURE; + } + else + gptr->p_timeout = atoi(wptr); + break; + case P_TTYLABEL: + gptr->p_ttylabel=strsave(getword(ptr,&size,0)); + break; + case P_MODULES: + gptr->p_modules = strsave(getword(ptr,&size,0)); + if (vml(gptr->p_modules) != 0) { + field = state; + state = FAILURE; + } + break; + case P_PROMPT: + gptr->p_prompt = strsave(getword(ptr,&size,TRUE)); + break; + case P_DMSG: + gptr->p_dmsg = strsave(getword(ptr,&size,TRUE)); + break; + + case P_TERMTYPE: + gptr->p_termtype = strsave(getword(ptr,&size,TRUE)); + break; + + case P_SOFTCAR: + gptr->p_softcar = strsave(getword(ptr,&size,TRUE)); + break; + + } /* end switch */ + ptr += size; + if (state == FAILURE) + break; + if (*ptr == ':') { + ptr++; /* Skip the ':' */ + state++ ; + } else if (*ptr != '\0') { + field = state; + state = FAILURE; + } + if (*ptr == '\0') { + /* + * Maintain compatibility with older ttymon + * pmtab files. If Sun-added fields are + * missing, this should not be an error. + */ + if (state > P_DMSG) { + state = SUCCESS; + } else { + field = state; + state = FAILURE; + } + } + } /* end for loop */ + + if (state == SUCCESS) { + if (check_pmtab(gptr) == 0) { + if (Nentries < Maxfds) + insert_pmtab(gptr); + else { + log("can't add more entries to " + "pmtab, Maxfds = %d", Maxfds); + free_pmtab(gptr); + (void)fclose(fp); + return; + } + } + else { + log("Parsing failure for entry: \n%s", line); + log("-------------------------------------------"); + free_pmtab(gptr); + } + } else { + *++ptr = '\0'; + log("Parsing failure in the \"%s\" field,\n%s" + "<--error detected here", states[field], line); + log("-------------------------------------------"); + free_pmtab(gptr); + } + } while (input == ACTIVE); + + (void)fclose(fp); + return; +} + +/* + * get_flags - scan flags field to set U_FLAG and X_FLAG + */ +static int +get_flags(wptr, flags) +char *wptr; /* pointer to the input string */ +long *flags; /* pointer to the flag to set */ +{ + register char *p; + for (p = wptr; *p; p++) { + switch (*p) { + case 'x': + *flags |= X_FLAG; + break; + case 'u': + *flags |= U_FLAG; + break; + default: + log("Invalid flag -- %c", *p); + return(-1); + } + } + return(0); +} + +/* + * get_ttyflags - scan ttyflags field to set corresponding flags + */ +static int +get_ttyflags(wptr, ttyflags) +char *wptr; /* pointer to the input string */ +long *ttyflags; /* pointer to the flag to be set*/ +{ + register char *p; + for (p = wptr; *p; p++) { + switch (*p) { + case 'c': + *ttyflags |= C_FLAG; + break; + case 'h': /* h means don't hangup */ + *ttyflags &= ~H_FLAG; + break; + case 'b': + *ttyflags |= B_FLAG; + break; + case 'r': + *ttyflags |= R_FLAG; + break; + case 'I': + *ttyflags |= I_FLAG; + break; + default: + log("Invalid ttyflag -- %c", *p); + return(-1); + } + } + return(0); +} + +# ifdef DEBUG +/* + * pflags - put service flags into intelligible form for output + */ + +char * +pflags(flags) +long flags; /* binary representation of the flags */ +{ + register int i; /* scratch counter */ + static char buf[BUFSIZ]; /* formatted flags */ + + if (flags == 0) + return("-"); + i = 0; + if (flags & U_FLAG) { + buf[i++] = 'u'; + flags &= ~U_FLAG; + } + if (flags & X_FLAG) { + buf[i++] = 'x'; + flags &= ~X_FLAG; + } + if (flags) + log("Internal error in pflags"); + buf[i] = '\0'; + return(buf); +} + +/* + * pttyflags - put ttyflags into intelligible form for output + */ + +char * +pttyflags(flags) +long flags; /* binary representation of ttyflags */ +{ + register int i; /* scratch counter */ + static char buf[BUFSIZ]; /* formatted flags */ + + if (flags == 0) + return("h"); + i = 0; + if (flags & C_FLAG) { + buf[i++] = 'c'; + flags &= ~C_FLAG; + } + if (flags & H_FLAG) + flags &= ~H_FLAG; + else + buf[i++] = 'h'; + if (flags & B_FLAG) { + buf[i++] = 'b'; + flags &= ~B_FLAG; + } + if (flags & R_FLAG) { + buf[i++] = 'r'; + flags &= ~B_FLAG; + } + if (flags & I_FLAG) { + buf[i++] = 'I'; + flags &= ~I_FLAG; + } + if (flags) + log("Internal error in p_ttyflags"); + buf[i] = '\0'; + return(buf); +} + +void +dump_pmtab() +{ + struct pmtab *gptr; + + debug("in dump_pmtab"); + log("********** dumping pmtab **********"); + log(" "); + for (gptr=PMtab; gptr; gptr = gptr->p_next) { + log("-------------------------------------------"); + log("tag:\t\t%s", gptr->p_tag); + log("flags:\t\t%s",pflags(gptr->p_flags)); + log("identity:\t%s", gptr->p_identity); + log("reserved1:\t%s", gptr->p_res1); + log("reserved2:\t%s", gptr->p_res2); + log("reserved3:\t%s", gptr->p_res3); + log("device:\t%s", gptr->p_device); + log("ttyflags:\t%s",pttyflags(gptr->p_ttyflags)); + log("count:\t\t%d", gptr->p_count); + log("server:\t%s", gptr->p_server); + log("timeout:\t%d", gptr->p_timeout); + log("ttylabel:\t%s", gptr->p_ttylabel); + log("modules:\t%s", gptr->p_modules); + log("prompt:\t%s", gptr->p_prompt); + log("disable msg:\t%s", gptr->p_dmsg); + log("terminal type:\t%s", gptr->p_termtype); + log("soft-carrier:\t%s", gptr->p_softcar); + log("status:\t\t%d", gptr->p_status); + log("inservice:\t%d", gptr->p_inservice); + log("fd:\t\t%d", gptr->p_fd); + log("pid:\t\t%ld", gptr->p_pid); + log("uid:\t\t%ld", gptr->p_uid); + log("gid:\t\t%ld", gptr->p_gid); + log("dir:\t%s", gptr->p_dir); + log(" "); + } + log("********** end dumping pmtab **********"); +} +# endif + +/* + * same_entry(e1,e2) - compare 2 entries of pmtab + * if the fields are different, copy e2 to e1 + * return 1 if same, return 0 if different + */ +static int +same_entry(e1,e2) +struct pmtab *e1,*e2; +{ + + if (strcmp(e1->p_identity, e2->p_identity) != 0) + return(0); + if (strcmp(e1->p_res1, e2->p_res1) != 0) + return(0); + if (strcmp(e1->p_res2, e2->p_res2) != 0) + return(0); + if (strcmp(e1->p_res3, e2->p_res3) != 0) + return(0); + if (strcmp(e1->p_device, e2->p_device) != 0) + return(0); + if (strcmp(e1->p_server, e2->p_server) != 0) + return(0); + if (strcmp(e1->p_ttylabel, e2->p_ttylabel) != 0) + return(0); + if (strcmp(e1->p_modules, e2->p_modules) != 0) + return(0); + if (strcmp(e1->p_prompt, e2->p_prompt) != 0) + return(0); + if (strcmp(e1->p_dmsg, e2->p_dmsg) != 0) + return(0); + if (strcmp(e1->p_termtype, e2->p_termtype) != 0) + return(0); + if (strcmp(e1->p_softcar, e2->p_softcar) != 0) + return(0); + if (e1->p_flags != e2->p_flags) + return(0); + /* + * compare lowest 4 bits only, + * because A_FLAG is not part of original ttyflags + */ + if ((e1->p_ttyflags & ~A_FLAG) != (e2->p_ttyflags & ~A_FLAG)) + return(0); + if (e1->p_count != e2->p_count) + return(0); + if (e1->p_timeout != e2->p_timeout) + return(0); + if (e1->p_uid != e2->p_uid) + return(0); + if (e1->p_gid != e2->p_gid) + return(0); + if (strcmp(e1->p_dir, e2->p_dir) != 0) + return(0); + return(1); +} + + +/* + * insert_pmtab - insert a pmtab entry into the linked list + */ + +static void +insert_pmtab(sp) +register struct pmtab *sp; /* ptr to entry to be inserted */ +{ + register struct pmtab *tsp, *savtsp; /* scratch pointers */ + int ret; /* strcmp return value */ + +# ifdef DEBUG + debug("in insert_pmtab"); +# endif + savtsp = tsp = PMtab; + +/* + * find the correct place to insert this element + */ + + while (tsp) { + ret = strcmp(sp->p_tag, tsp->p_tag); + if (ret > 0) { + /* keep on looking */ + savtsp = tsp; + tsp = tsp->p_next; + continue; + } + else if (ret == 0) { + if (tsp->p_status) { + /* this is a duplicate entry, ignore it */ + log("Ignoring duplicate entry for <%s>", + tsp->p_tag); + } + else { + if (same_entry(tsp,sp)) { /* same entry */ + tsp->p_status = VALID; + } + else { /* entry changed */ + if ((sp->p_flags & X_FLAG) && + ((sp->p_dmsg == NULL) || + (*(sp->p_dmsg) == '\0'))) { + /* disabled entry */ + tsp->p_status = NOTVALID; + } + else { +# ifdef DEBUG + debug("replacing <%s>", sp->p_tag); +# endif + /* replace old entry */ + sp->p_next = tsp->p_next; + if (tsp == PMtab) { + PMtab = sp; + } + else { + savtsp->p_next = sp; + } + sp->p_status = CHANGED; + sp->p_fd = tsp->p_fd; + sp->p_pid = tsp->p_pid; + sp->p_inservice = + tsp->p_inservice; + sp = tsp; + } + } + Nentries++; + } + free_pmtab(sp); + return; + } + else { + if ((sp->p_flags & X_FLAG) && + ((sp->p_dmsg == NULL) || + (*(sp->p_dmsg) == '\0'))) { /* disabled entry */ + free_pmtab(sp); + return; + } + /* + * Set the state of soft-carrier. + * Since this is a one-time only operation, + * we do it when this service is added to + * the enabled list. + */ + if (*sp->p_softcar != '\0') + set_softcar(sp); + + /* insert it here */ + if (tsp == PMtab) { + sp->p_next = PMtab; + PMtab = sp; + } + else { + sp->p_next = savtsp->p_next; + savtsp->p_next = sp; + } +# ifdef DEBUG + debug("adding <%s>", sp->p_tag); +# endif + Nentries++; + /* this entry is "current" */ + sp->p_status = VALID; + return; + } + } + +/* + * either an empty list or should put element at end of list + */ + + if ((sp->p_flags & X_FLAG) && + ((sp->p_dmsg == NULL) || + (*(sp->p_dmsg) == '\0'))) { /* disabled entry */ + free_pmtab(sp); /* do not poll this entry */ + return; + } + /* + * Set the state of soft-carrier. + * Since this is a one-time only operation, + * we do it when this service is added to + * the enabled list. + */ + if (*sp->p_softcar != '\0') + set_softcar(sp); + sp->p_next = NULL; + if (PMtab == NULL) + PMtab = sp; + else + savtsp->p_next = sp; +# ifdef DEBUG + debug("adding <%s>", sp->p_tag); +# endif + ++Nentries; + /* this entry is "current" */ + sp->p_status = VALID; +} + + +/* + * purge - purge linked list of "old" entries + */ + + +void +purge() +{ + register struct pmtab *sp; /* working pointer */ + register struct pmtab *savesp, *tsp; /* scratch pointers */ + +# ifdef DEBUG + debug("in purge"); +# endif + sp = savesp = PMtab; + while (sp) { + if (sp->p_status) { +# ifdef DEBUG + debug("p_status not 0"); +# endif + savesp = sp; + sp = sp->p_next; + } + else { + tsp = sp; + if (tsp == PMtab) { + PMtab = sp->p_next; + savesp = PMtab; + } + else + savesp->p_next = sp->p_next; +# ifdef DEBUG + debug("purging <%s>", sp->p_tag); +# endif + sp = sp->p_next; + free_pmtab(tsp); + } + } +} + +/* + * free_pmtab - free one pmtab entry + */ +static void +free_pmtab(p) +struct pmtab *p; +{ +#ifdef DEBUG + debug("in free_pmtab"); +#endif + free(p->p_tag); + free(p->p_identity); + free(p->p_res1); + free(p->p_res2); + free(p->p_res3); + free(p->p_device); + free(p->p_server); + free(p->p_ttylabel); + free(p->p_modules); + free(p->p_prompt); + free(p->p_dmsg); + free(p->p_termtype); + free(p->p_softcar); + if (p->p_dir) + free(p->p_dir); + free(p); +} + +/* + * check_pmtab - check the fields to make sure things are correct + * - return 0 if everything is ok + * - return -1 if something is wrong + */ + +static int +check_pmtab(p) +struct pmtab *p; +{ + if (p == NULL) { + log("pmtab ptr is NULL"); + return(-1); + } + + /* check service tag */ + if ((p->p_tag == NULL) || (*(p->p_tag) == '\0')) { + log("port/service tag is missing"); + return(-1); + } + if (strlen(p->p_tag) > (size_t)(MAXID - 1)) { + log("port/service tag <%s> is longer than %d", p->p_tag, + MAXID-1); + return(-1); + } + if (strcheck(p->p_tag, ALNUM) != 0) { + log("port/service tag <%s> is not alphanumeric", p->p_tag); + return(-1); + } + if (check_identity(p) != 0) { + return(-1); + } + + if (check_device(p->p_device) != 0) + return(-1); + + if (check_cmd(p->p_server) != 0) + return(-1); + return(0); +} + +extern struct passwd *getpwnam(); +extern void endpwent(); +extern struct group *getgrgid(); +extern void endgrent(); + +/* + * check_identity - check to see if the identity is a valid user + * - log name in the passwd file, + * - and if its group id is a valid one + * - return 0 if everything is ok. Otherwise, return -1 + */ + +int +check_identity(p) +struct pmtab *p; +{ + register struct passwd *pwdp; + + if ((p->p_identity == NULL) || (*(p->p_identity) == '\0')) { + log("identity field is missing"); + return(-1); + } + if ((pwdp = getpwnam(p->p_identity)) == NULL) { + log("missing or bad passwd entry for <%s>", p->p_identity); + endpwent(); + return(-1); + } + if (getgrgid(pwdp->pw_gid) == NULL) { + log("no group entry for %ld", pwdp->pw_gid); + endgrent(); + endpwent(); + return(-1); + } + p->p_uid = pwdp->pw_uid; + p->p_gid = pwdp->pw_gid; + p->p_dir = strsave(pwdp->pw_dir); + endgrent(); + endpwent(); + return(0); +} + +/* + * expand(cmdp, devp) - expand %d to device name and %% to %, + * - any other characters are untouched. + * - return the expanded string + */ +static char * +expand(cmdp,devp) +char *cmdp; /* ptr to cmd string */ +char *devp; /* ptr to device name */ +{ + register char *cp, *dp, *np; + static char buf[BUFSIZ]; + cp = cmdp; + np = buf; + dp = devp; + while (*cp) { + if (*cp != '%') { + *np++ = *cp++; + continue; + } + switch (*++cp) { + case 'd': + while (*dp) { + *np++ = *dp++; + } + cp++; + break; + case '%': + *np++ = *cp++; + break; + default: + *np++ = *cp++; + break; + } + } + *np = '\0'; + return(buf); +} + |