/* * 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 #include #include #include #include #include #include #include #include #include #include "ttymon.h" #include "tmstruct.h" #include "tmextern.h" #include "stty.h" static void insert_def(); static void zero(); int check_flags(); void mkargv(); extern struct Gdef Gdef[]; extern int Ndefs; char *strsave(); /* * read_ttydefs - read in the /etc/ttydefs and store in Gdef array * - if id is not NULL, only get entry with that id * - if check is TRUE, print out the entries */ void read_ttydefs(id,check) char *id; int check; { FILE *fp; static struct Gdef def; register struct Gdef *gptr; static char line[BUFSIZ]; static char dbuf[BUFSIZ]; register char *ptr; int len; int input,state,size,rawc,field; char oldc; static char d_id[MAXID+1], d_nextid[MAXID+1], d_autobaud[MAXID+1], d_if[BUFSIZ], d_ff[BUFSIZ]; static char *states[] = { "","tty label","Initial flags","Final flags","Autobaud","Next label" }; extern char *getword(); if ((fp = fopen(TTYDEFS,"r")) == NULL) { log("can't open \"%s\".\n", TTYDEFS); return; } if (check) { for (len = 0; len < (size_t)(BUFSIZ - 1); len++) dbuf[len] = '-'; dbuf[len] = '\0'; } /* Start searching for the line with the proper "id". */ input = ACTIVE; do { 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 (check && rawc != '#') log("Entry too long."); 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; /* Now we have the complete line */ /* Initialize "def" and "gptr". */ gptr = &def; zero((char *)gptr, sizeof(struct Gdef)); ptr = line; state = T_TTYLABEL; (void)strncpy(d_id,getword(ptr,&size,0),MAXID); gptr->g_id = d_id; ptr += size; if (*ptr != ':') { field = state; state = FAILURE; } else { ptr++; /* Skip the ':' */ state++ ; } /* If "id" != NULL, and it does not match, go to next entry */ if ((id != NULL) && (strcmp(id,gptr->g_id) != 0)) continue; if (check) { len = strlen(line); dbuf[len] = '\0'; log("\n%s", dbuf); log("%s", line); log("%s\n", dbuf); dbuf[len] = '-'; } for (; state != FAILURE && state != SUCCESS;) { switch(state) { case T_IFLAGS: (void)strncpy(d_if,getword(ptr,&size,1),BUFSIZ); gptr->g_iflags = d_if; ptr += size; if ((*ptr != ':') || (check_flags(d_if) != 0)) { field = state; state = FAILURE; } else { ptr++; state++ ; } break; case T_FFLAGS: (void)strncpy(d_ff,getword(ptr,&size,1),BUFSIZ); gptr->g_fflags = d_ff; ptr += size; if ((*ptr != ':') || (check_flags(d_ff) != 0)) { field = state; state = FAILURE; } else { ptr++; state++ ; } break; case T_AUTOBAUD: (void)strncpy(d_autobaud,getword(ptr,&size,0),MAXID); if (size > 1) { ptr += size; field = state; state = FAILURE; break; } if (size == 1) { if (*d_autobaud == 'A') gptr->g_autobaud |= A_FLAG; else { ptr += size; field = state; state = FAILURE; break; } } ptr += size; if (*ptr != ':') { field = state; state = FAILURE; } else { ptr++; /* Skip the ':' */ state++ ; } break; case T_NEXTLABEL: (void)strncpy(d_nextid,getword(ptr,&size,0),MAXID); gptr->g_nextid = d_nextid; ptr += size; if (*ptr != '\0') { field = state; state = FAILURE; } else state = SUCCESS; break; } /* end switch */ } /* end for loop */ if (state == SUCCESS) { if (check) { log("ttylabel:\t%s", gptr->g_id); log("initial flags:\t%s", gptr->g_iflags); log("final flags:\t%s", gptr->g_fflags); if (gptr->g_autobaud & A_FLAG) log("autobaud:\tyes"); else log("autobaud:\tno"); log("nextlabel:\t%s", gptr->g_nextid); } if (Ndefs < MAXDEFS) insert_def(gptr); else { log("can't add more entries to ttydefs table, " " Maximum entries = %d", MAXDEFS); (void)fclose(fp); return; } if (id != NULL) { return; } } else { *++ptr = '\0'; log("Parsing failure in the \"%s\" field\n" "%s<--error detected here\n", states[field],line); } } while (input == ACTIVE); (void)fclose(fp); return; } /* * zero - zero out the buffer */ static void zero(adr,size) register char *adr; register int size; { if (adr != NULL) while (size--) *adr++ = '\0'; } /* * find_def(ttylabel) * - scan Gdef table for an entry with requested "ttylabel". * - return a Gdef ptr if entry with "ttylabel" is found * - return NULL if no entry with matching "ttylabel" */ struct Gdef * find_def(ttylabel) char *ttylabel; { int i; struct Gdef *tp; tp = &Gdef[0]; for (i = 0; i < Ndefs; i++,tp++) { if (strcmp(ttylabel, tp->g_id) == 0) { return(tp); } } return(NULL); } /* * check_flags - check to see if the flags contains options that are * recognizable by stty * - return 0 if no error. Otherwise return -1 */ int check_flags(flags) char *flags; { struct termio termio; struct termios termios; struct termiox termiox; struct winsize winsize; int term; int cnt = 1; char *argvp[MAXARGS]; /* stty args */ static char *binstty = "/usr/bin/stty"; static char buf[BUFSIZ]; extern char *sttyparse(); char *s_arg; /* this will point to invalid option */ /* put flags into buf, because strtok will break up buffer */ (void)strcpy(buf,flags); argvp[0] = binstty; /* just a place holder */ mkargv(buf,&argvp[1],&cnt,MAXARGS-1); argvp[cnt] = (char *)0; /* * because we don't know what type of terminal we have now, * just set term = everything, so all possible stty options * are accepted */ term = ASYNC|TERMIOS|FLOW; if ((s_arg = sttyparse(cnt, argvp, term, &termio, &termios, &termiox, &winsize)) != NULL) { log("invalid mode: %s", s_arg); return(-1); } return(0); } /* * insert_def - insert one entry into Gdef table */ static void insert_def(gptr) struct Gdef *gptr; { struct Gdef *tp; extern struct Gdef *find_def(); if (find_def(gptr->g_id) != NULL) { log("Warning -- duplicate entry <%s>, ignored", gptr->g_id); return; } tp = &Gdef[Ndefs]; tp->g_id = strsave(gptr->g_id); tp->g_iflags = strsave(gptr->g_iflags); tp->g_fflags = strsave(gptr->g_fflags); tp->g_autobaud = gptr->g_autobaud; tp->g_nextid = strsave(gptr->g_nextid); Ndefs++; return; } /* * mkargv - parse the string into args, starting from args[cnt] */ void mkargv(string,args,cnt,maxargs) char *string, **args; int *cnt, maxargs; { register char *ptrin,*ptrout; register int i; int qsize; extern char quoted(); for (i=0; i < maxargs; i++) args[i] = (char *)NULL; for (ptrin = ptrout = string,i=0; *ptrin != '\0' && i < maxargs; i++) { /* Skip excess white spaces between arguments. */ while(*ptrin == ' ' || *ptrin == '\t') { ptrin++; ptrout++; } /* Save the address of argument if there is something there. */ if (*ptrin == '\0') break; else args[i] = ptrout; /* Span the argument itself. The '\' character causes quoting */ /* of the next character to take place (except for '\0'). */ while (*ptrin != '\0') { if (*ptrin == '\\') { *ptrout++ = quoted(ptrin,&qsize); ptrin += qsize; /* Is this the end of the argument? If so quit loop. */ } else if (*ptrin == ' ' || *ptrin == '\t') { ptrin++; break; /* If this is a normal letter of the argument, save it, advancing */ /* the pointers at the same time. */ } else *ptrout++ = *ptrin++; } /* Null terminate the string. */ *ptrout++ = '\0'; } (*cnt) += i; } #ifdef DEBUG /* * dump_ttydefs - dump Gdef table to log file */ void dump_ttydefs() { int i; struct Gdef *gptr; gptr = &Gdef[0]; log("********** dumping ttydefs table **********"); log("Ndefs = %d", Ndefs); log(" "); for (i = 0; i < Ndefs; i++,gptr++) { log("----------------------------------------"); log("ttylabel:\t%s", gptr->g_id); log("initial flags:\t%s", gptr->g_iflags); log("final flags:\t%s", gptr->g_fflags); if (gptr->g_autobaud & A_FLAG) log("autobaud:\tyes"); else log("Autobaud:\tno"); log("nextlabel:\t%s", gptr->g_nextid); log(" "); } log("********** end dumping ttydefs table **********"); return; } #endif /* * this is copies from uucp/strsave.c * and is modified that if malloc fails, it will exit */ char * strsave(str) register char *str; { register char *rval; if (str == NULL) { if ((rval = (char *)malloc(1)) == NULL) { log("strsave: malloc failed"); exit(1); } *rval = '\0'; } else { if ((rval = (char *)malloc(strlen(str) + 1)) == NULL) { log("strsave: malloc failed"); exit(1); } (void)strcpy(rval, str); } return(rval); }