1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate /* 29*7c478bd9Sstevel@tonic-gate * Streams Command strchg: change the configuration of the 30*7c478bd9Sstevel@tonic-gate * stream associated with stdin. 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate * USAGE: strchg -h module1[,module2,module3 ...] 33*7c478bd9Sstevel@tonic-gate * or: strchg -p 34*7c478bd9Sstevel@tonic-gate * or: strchg -p -a 35*7c478bd9Sstevel@tonic-gate * or: strchg -p -u module 36*7c478bd9Sstevel@tonic-gate * or: strchg -f file 37*7c478bd9Sstevel@tonic-gate * 38*7c478bd9Sstevel@tonic-gate * -h pusHes the named module(s) onto the stdin stream 39*7c478bd9Sstevel@tonic-gate * -p poPs the topmost module from the stdin stream 40*7c478bd9Sstevel@tonic-gate * -p -a poPs All modules 41*7c478bd9Sstevel@tonic-gate * -p -u module poPs all modules Up to, but not including, the named module 42*7c478bd9Sstevel@tonic-gate * -f file reads a list of modules from the named File, pops all modules, 43*7c478bd9Sstevel@tonic-gate * then pushes the list of modules 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * RETURNS: 46*7c478bd9Sstevel@tonic-gate * 0 SUCCESS it worked 47*7c478bd9Sstevel@tonic-gate * 1 ERR_USAGE bad invocation 48*7c478bd9Sstevel@tonic-gate * 2 ERR_MODULE bad module name(s) 49*7c478bd9Sstevel@tonic-gate * 3 ERR_STDIN an ioctl or stat on the stdin stream failed 50*7c478bd9Sstevel@tonic-gate * 4 ERR_MEM couldn't allocate memory 51*7c478bd9Sstevel@tonic-gate * 5 ERR_OPEN couldn't open file in -f opt 52*7c478bd9Sstevel@tonic-gate * 6 ERR_PERM not owner or superuser 53*7c478bd9Sstevel@tonic-gate * 54*7c478bd9Sstevel@tonic-gate */ 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate #include <stdio.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/termio.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #define FALSE 0 64*7c478bd9Sstevel@tonic-gate #define TRUE 1 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #define SUCCESS 0 67*7c478bd9Sstevel@tonic-gate #define FAILURE 1 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #define NMODULES 16 /* "reasonable" # of modules to push */ 70*7c478bd9Sstevel@tonic-gate /* (can push more if you like) */ 71*7c478bd9Sstevel@tonic-gate #define MAXMODULES 2048 /* max # of modules to push */ 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate #define OPTLIST "af:h:pu:" 74*7c478bd9Sstevel@tonic-gate #define USAGE "Usage:\t%s -h module1[,module2 ... ]\n\t%s -f file\n\t%s -p [-a | -u module ]\n" 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate #define ERR_USAGE 1 /* bad invocation */ 77*7c478bd9Sstevel@tonic-gate #define ERR_MODULE 2 /* bad module name(s) or too many modules */ 78*7c478bd9Sstevel@tonic-gate #define ERR_STDIN 3 /* an ioctl or stat on stdin failed */ 79*7c478bd9Sstevel@tonic-gate #define ERR_MEM 4 /* couldn't allocate memory */ 80*7c478bd9Sstevel@tonic-gate #define ERR_OPEN 5 /* couldn't open file in -f opt */ 81*7c478bd9Sstevel@tonic-gate #define ERR_PERM 6 /* not owner or superuser */ 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate #define STDIN 0 84*7c478bd9Sstevel@tonic-gate #define CNULL (char *)NULL 85*7c478bd9Sstevel@tonic-gate #define SAME 0 /* return from str[n]cmp if match */ 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate static char *Cmd_namep; /* how was it invoked? */ 88*7c478bd9Sstevel@tonic-gate static struct str_mlist Oldmods[NMODULES]; /* modlist for Oldlist */ 89*7c478bd9Sstevel@tonic-gate static struct str_list Oldlist; /* original modules */ 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate extern char *strncpy(); 92*7c478bd9Sstevel@tonic-gate extern char *strtok(); 93*7c478bd9Sstevel@tonic-gate extern int getopt(); 94*7c478bd9Sstevel@tonic-gate extern unsigned short geteuid(); 95*7c478bd9Sstevel@tonic-gate extern int ioctl(); 96*7c478bd9Sstevel@tonic-gate extern int strncmp(); 97*7c478bd9Sstevel@tonic-gate extern void perror(); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate static int pop_modules(); /* pop 'n' modules */ 100*7c478bd9Sstevel@tonic-gate static int push_module(); /* push a module */ 101*7c478bd9Sstevel@tonic-gate static int more_modules(); /* increase size of mod lists */ 102*7c478bd9Sstevel@tonic-gate static void restore(); /* restore state of stdin */ 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate main( argc, argv) 105*7c478bd9Sstevel@tonic-gate int argc; 106*7c478bd9Sstevel@tonic-gate char *argv[]; 107*7c478bd9Sstevel@tonic-gate { 108*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; /* input buffer */ 109*7c478bd9Sstevel@tonic-gate char *file_namep; /* file from -f opt */ 110*7c478bd9Sstevel@tonic-gate char *modnamep; /* mods from -h or -u opt */ 111*7c478bd9Sstevel@tonic-gate char *modp; /* for walking thru modnamep */ 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate FILE *fp; /* file pointer for -f file */ 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate register int i; /* loop index and junk var */ 116*7c478bd9Sstevel@tonic-gate register int j; /* loop index and junk var */ 117*7c478bd9Sstevel@tonic-gate int euid; /* effective uid */ 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate short error; /* TRUE if usage error */ 120*7c478bd9Sstevel@tonic-gate short fromfile; /* TRUE if -f file */ 121*7c478bd9Sstevel@tonic-gate short is_a_tty; /* TRUE if TCGETA succeeds */ 122*7c478bd9Sstevel@tonic-gate short pop; /* TRUE if -p */ 123*7c478bd9Sstevel@tonic-gate short popall; /* TRUE if -p -a */ 124*7c478bd9Sstevel@tonic-gate short popupto; /* TRUE if -p -u module */ 125*7c478bd9Sstevel@tonic-gate short push; /* TRUE if -h mod1[,mod2 ...] */ 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate struct str_mlist 128*7c478bd9Sstevel@tonic-gate newmods[NMODULES];/* mod list for new list */ 129*7c478bd9Sstevel@tonic-gate struct stat stats; /* stream stats */ 130*7c478bd9Sstevel@tonic-gate struct str_list newlist; /* modules to be pushed */ 131*7c478bd9Sstevel@tonic-gate struct termio termio; /* save state of tty */ 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate extern char *optarg; /* for getopt() */ 134*7c478bd9Sstevel@tonic-gate extern int optind; /* for getopt() */ 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* 137*7c478bd9Sstevel@tonic-gate * init 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate Cmd_namep = argv[0]; 141*7c478bd9Sstevel@tonic-gate error = fromfile = is_a_tty = pop = popall = popupto = push = FALSE; 142*7c478bd9Sstevel@tonic-gate Oldlist.sl_modlist = Oldmods; 143*7c478bd9Sstevel@tonic-gate Oldlist.sl_nmods = NMODULES; 144*7c478bd9Sstevel@tonic-gate newlist.sl_modlist = newmods; 145*7c478bd9Sstevel@tonic-gate newlist.sl_nmods = NMODULES; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate /* 148*7c478bd9Sstevel@tonic-gate * only owner and root can change stream configuration 149*7c478bd9Sstevel@tonic-gate */ 150*7c478bd9Sstevel@tonic-gate if ( (euid = geteuid()) != 0 ) { 151*7c478bd9Sstevel@tonic-gate if ( fstat(0, &stats) < 0 ) { 152*7c478bd9Sstevel@tonic-gate perror("fstat"); 153*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: fstat of stdin failed\n", 154*7c478bd9Sstevel@tonic-gate Cmd_namep); 155*7c478bd9Sstevel@tonic-gate return(ERR_STDIN); 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate if ( euid != stats.st_uid ) { 158*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 159*7c478bd9Sstevel@tonic-gate "%s: not owner of stdin\n", Cmd_namep); 160*7c478bd9Sstevel@tonic-gate return(ERR_PERM); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * parse args 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate if ( argc == 1 ) { 170*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 171*7c478bd9Sstevel@tonic-gate return(ERR_USAGE); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate while ( !error && (i = getopt( argc, argv, OPTLIST)) != -1 ) { 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate switch (i) { 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate case 'a': /* pop All */ 179*7c478bd9Sstevel@tonic-gate if ( fromfile || popupto || push ) 180*7c478bd9Sstevel@tonic-gate error = TRUE; 181*7c478bd9Sstevel@tonic-gate else 182*7c478bd9Sstevel@tonic-gate popall = TRUE; 183*7c478bd9Sstevel@tonic-gate break; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate case 'f': /* read from File*/ 186*7c478bd9Sstevel@tonic-gate if ( pop || push ) 187*7c478bd9Sstevel@tonic-gate error = TRUE; 188*7c478bd9Sstevel@tonic-gate else { 189*7c478bd9Sstevel@tonic-gate fromfile = TRUE; 190*7c478bd9Sstevel@tonic-gate file_namep = optarg; 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate break; 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate case 'h': /* pusH */ 195*7c478bd9Sstevel@tonic-gate if ( fromfile || pop ) 196*7c478bd9Sstevel@tonic-gate error = TRUE; 197*7c478bd9Sstevel@tonic-gate else { 198*7c478bd9Sstevel@tonic-gate push = TRUE; 199*7c478bd9Sstevel@tonic-gate modnamep = optarg; 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate break; 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate case 'p': /* poP */ 204*7c478bd9Sstevel@tonic-gate if ( fromfile || push ) 205*7c478bd9Sstevel@tonic-gate error = TRUE; 206*7c478bd9Sstevel@tonic-gate else 207*7c478bd9Sstevel@tonic-gate pop = TRUE; 208*7c478bd9Sstevel@tonic-gate break; 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate case 'u': /* pop Upto */ 211*7c478bd9Sstevel@tonic-gate if ( fromfile || popall || push ) 212*7c478bd9Sstevel@tonic-gate error = TRUE; 213*7c478bd9Sstevel@tonic-gate else { 214*7c478bd9Sstevel@tonic-gate popupto = TRUE; 215*7c478bd9Sstevel@tonic-gate modnamep = optarg; 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate break; 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate default: 220*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 221*7c478bd9Sstevel@tonic-gate USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 222*7c478bd9Sstevel@tonic-gate return(ERR_USAGE); 223*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate if ( error || optind < argc ) { 228*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 229*7c478bd9Sstevel@tonic-gate return(ERR_USAGE); 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate if ( !pop && ( popall || popupto ) ) { 233*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 234*7c478bd9Sstevel@tonic-gate "%s: -p option must be used with -a or -u to pop modules\n", 235*7c478bd9Sstevel@tonic-gate Cmd_namep); 236*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 237*7c478bd9Sstevel@tonic-gate return(ERR_USAGE); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /* 242*7c478bd9Sstevel@tonic-gate * Save state so can restore if something goes wrong 243*7c478bd9Sstevel@tonic-gate * (If are only going to push modules, don't need to 244*7c478bd9Sstevel@tonic-gate * save original module list for restore.) 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate if ( fromfile || pop ) { 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate /* 249*7c478bd9Sstevel@tonic-gate * get number of modules on stream 250*7c478bd9Sstevel@tonic-gate * allocate more room if needed 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate if ( (i = ioctl(STDIN, I_LIST, (struct str_list *)NULL)) 253*7c478bd9Sstevel@tonic-gate < 0 ) { 254*7c478bd9Sstevel@tonic-gate perror("I_LIST"); 255*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 256*7c478bd9Sstevel@tonic-gate "%s: I_LIST ioctl failed\n", Cmd_namep); 257*7c478bd9Sstevel@tonic-gate return(ERR_STDIN); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate if ( i > Oldlist.sl_nmods ) 260*7c478bd9Sstevel@tonic-gate if ( more_modules(&Oldlist, i) != SUCCESS ) 261*7c478bd9Sstevel@tonic-gate return(ERR_MEM); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate /* 264*7c478bd9Sstevel@tonic-gate * get list of modules on stream 265*7c478bd9Sstevel@tonic-gate */ 266*7c478bd9Sstevel@tonic-gate Oldlist.sl_nmods = i; 267*7c478bd9Sstevel@tonic-gate if ( ioctl(STDIN, I_LIST, &Oldlist) < 0 ) { 268*7c478bd9Sstevel@tonic-gate perror("I_LIST"); 269*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 270*7c478bd9Sstevel@tonic-gate "%s: I_LIST ioctl failed\n", Cmd_namep); 271*7c478bd9Sstevel@tonic-gate return(ERR_STDIN); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate /* 275*7c478bd9Sstevel@tonic-gate * The following attempts to avoid leaving a 276*7c478bd9Sstevel@tonic-gate * terminal line that does not respond to anything 277*7c478bd9Sstevel@tonic-gate * if the strchg -h or -f options failed due to 278*7c478bd9Sstevel@tonic-gate * specifying invalid module names for pushing 279*7c478bd9Sstevel@tonic-gate */ 280*7c478bd9Sstevel@tonic-gate if (ioctl(STDIN, TCGETA, &termio) >= 0 ) 281*7c478bd9Sstevel@tonic-gate is_a_tty = TRUE; 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* 286*7c478bd9Sstevel@tonic-gate * push modules on stream 287*7c478bd9Sstevel@tonic-gate */ 288*7c478bd9Sstevel@tonic-gate if ( push ) { 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * pull mod names out of comma-separated list 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate for ( i = 0, modp = strtok(modnamep, ","); 293*7c478bd9Sstevel@tonic-gate modp != CNULL; ++i, modp = strtok(CNULL, ",") ) { 294*7c478bd9Sstevel@tonic-gate if ( push_module(modp) == FAILURE) { 295*7c478bd9Sstevel@tonic-gate /* pop the 'i' modules we just added */ 296*7c478bd9Sstevel@tonic-gate restore(i, 0); 297*7c478bd9Sstevel@tonic-gate return(ERR_STDIN); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate return(SUCCESS); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate /* 304*7c478bd9Sstevel@tonic-gate * read configuration from a file 305*7c478bd9Sstevel@tonic-gate */ 306*7c478bd9Sstevel@tonic-gate if ( fromfile ) { 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate if ( (fp = fopen(file_namep, "r")) == (FILE *)NULL ) { 309*7c478bd9Sstevel@tonic-gate perror("fopen"); 310*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 311*7c478bd9Sstevel@tonic-gate "%s: could not open file '%s'\n", 312*7c478bd9Sstevel@tonic-gate Cmd_namep, file_namep); 313*7c478bd9Sstevel@tonic-gate return(ERR_OPEN); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* 317*7c478bd9Sstevel@tonic-gate * read file and construct a new strlist 318*7c478bd9Sstevel@tonic-gate */ 319*7c478bd9Sstevel@tonic-gate i = 0; 320*7c478bd9Sstevel@tonic-gate while ( fgets(buf, BUFSIZ, fp) != CNULL ) { 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate if ( buf[0] == '#' ) 323*7c478bd9Sstevel@tonic-gate continue; /* skip comments */ 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* 326*7c478bd9Sstevel@tonic-gate * skip trailing newline, trailing and leading 327*7c478bd9Sstevel@tonic-gate * whitespace 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate if ( (modp = strtok(buf, " \t\n")) == CNULL ) 330*7c478bd9Sstevel@tonic-gate continue; /* blank line */ 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate (void)strncpy(newlist.sl_modlist[i].l_name, 333*7c478bd9Sstevel@tonic-gate modp, FMNAMESZ); 334*7c478bd9Sstevel@tonic-gate ++i; 335*7c478bd9Sstevel@tonic-gate if ( (modp = strtok(CNULL, " \t\n")) != CNULL ) { 336*7c478bd9Sstevel@tonic-gate /* 337*7c478bd9Sstevel@tonic-gate * bad format 338*7c478bd9Sstevel@tonic-gate * should only be one name per line 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 341*7c478bd9Sstevel@tonic-gate "%s: error on line %d in file %s: multiple module names??\n", 342*7c478bd9Sstevel@tonic-gate Cmd_namep, i, file_namep); 343*7c478bd9Sstevel@tonic-gate return(ERR_MODULE); 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate if ( i > newlist.sl_nmods ) 346*7c478bd9Sstevel@tonic-gate if ( more_modules(&newlist, i) != SUCCESS ) 347*7c478bd9Sstevel@tonic-gate return(ERR_MEM); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate newlist.sl_nmods = i; 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate /* 352*7c478bd9Sstevel@tonic-gate * If an empty file, exit silently 353*7c478bd9Sstevel@tonic-gate */ 354*7c478bd9Sstevel@tonic-gate if ( i == 0 ) 355*7c478bd9Sstevel@tonic-gate return(SUCCESS); 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /* 358*7c478bd9Sstevel@tonic-gate * Pop all modules currently on the stream. 359*7c478bd9Sstevel@tonic-gate */ 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate if ( (i = pop_modules(Oldlist.sl_nmods - 1)) 362*7c478bd9Sstevel@tonic-gate != (Oldlist.sl_nmods - 1) ) { 363*7c478bd9Sstevel@tonic-gate /* put back whatever we've popped */ 364*7c478bd9Sstevel@tonic-gate restore(0, i); 365*7c478bd9Sstevel@tonic-gate return(ERR_STDIN); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate /* 369*7c478bd9Sstevel@tonic-gate * Push new modules 370*7c478bd9Sstevel@tonic-gate */ 371*7c478bd9Sstevel@tonic-gate for ( i = newlist.sl_nmods - 1; i >= 0; --i ) { 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate if ( push_module(newlist.sl_modlist[i].l_name) 374*7c478bd9Sstevel@tonic-gate == FAILURE ) { 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* 377*7c478bd9Sstevel@tonic-gate * pop whatever new modules we've pushed 378*7c478bd9Sstevel@tonic-gate * then push old module list back on 379*7c478bd9Sstevel@tonic-gate */ 380*7c478bd9Sstevel@tonic-gate restore((newlist.sl_nmods - 1 - i), 381*7c478bd9Sstevel@tonic-gate (Oldlist.sl_nmods - 1)); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate /* 384*7c478bd9Sstevel@tonic-gate * If the stream is a tty line, at least try 385*7c478bd9Sstevel@tonic-gate * to set the state to what it was before. 386*7c478bd9Sstevel@tonic-gate */ 387*7c478bd9Sstevel@tonic-gate if ( is_a_tty ) { 388*7c478bd9Sstevel@tonic-gate if ( ioctl(STDIN, TCSETA, &termio) < 0 ) { 389*7c478bd9Sstevel@tonic-gate perror("TCSETA"); 390*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 391*7c478bd9Sstevel@tonic-gate "%s: WARNING: Could not restore the states of the terminal line discipline\n", 392*7c478bd9Sstevel@tonic-gate Cmd_namep); 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate return(ERR_STDIN); 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate return(SUCCESS); 399*7c478bd9Sstevel@tonic-gate } /* end if-fromfile */ 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate /* 403*7c478bd9Sstevel@tonic-gate * pop all modules (except driver) 404*7c478bd9Sstevel@tonic-gate */ 405*7c478bd9Sstevel@tonic-gate if ( popall ) { 406*7c478bd9Sstevel@tonic-gate if ( Oldlist.sl_nmods > 1 ) { 407*7c478bd9Sstevel@tonic-gate if ( (i = pop_modules(Oldlist.sl_nmods - 1)) 408*7c478bd9Sstevel@tonic-gate != (Oldlist.sl_nmods - 1) ) { 409*7c478bd9Sstevel@tonic-gate restore(0, i); 410*7c478bd9Sstevel@tonic-gate return(ERR_STDIN); 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate return(SUCCESS); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /* 417*7c478bd9Sstevel@tonic-gate * pop up to (but not including) a module 418*7c478bd9Sstevel@tonic-gate */ 419*7c478bd9Sstevel@tonic-gate if ( popupto ) { 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate * check that the module is in fact on the stream 422*7c478bd9Sstevel@tonic-gate */ 423*7c478bd9Sstevel@tonic-gate for ( i = 0; i < Oldlist.sl_nmods; ++i ) 424*7c478bd9Sstevel@tonic-gate if ( strncmp(Oldlist.sl_modlist[i].l_name, modnamep, 425*7c478bd9Sstevel@tonic-gate FMNAMESZ) == SAME ) 426*7c478bd9Sstevel@tonic-gate break; 427*7c478bd9Sstevel@tonic-gate if ( i == Oldlist.sl_nmods ) { 428*7c478bd9Sstevel@tonic-gate /* no match found */ 429*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s not found on stream\n", 430*7c478bd9Sstevel@tonic-gate Cmd_namep, modnamep); 431*7c478bd9Sstevel@tonic-gate return(ERR_MODULE); 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate if ( (j = pop_modules(i)) != i ) { 435*7c478bd9Sstevel@tonic-gate /* put back whatever we've popped */ 436*7c478bd9Sstevel@tonic-gate restore(0, j); 437*7c478bd9Sstevel@tonic-gate return(ERR_STDIN); 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate return(SUCCESS); 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate /* 443*7c478bd9Sstevel@tonic-gate * pop the topmost module 444*7c478bd9Sstevel@tonic-gate */ 445*7c478bd9Sstevel@tonic-gate if ( pop ) { 446*7c478bd9Sstevel@tonic-gate if ( Oldlist.sl_nmods > 1 ) 447*7c478bd9Sstevel@tonic-gate if ( pop_modules(1) != 1 ) 448*7c478bd9Sstevel@tonic-gate /* no need to restore */ 449*7c478bd9Sstevel@tonic-gate return(ERR_STDIN); 450*7c478bd9Sstevel@tonic-gate return(SUCCESS); 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate /* 457*7c478bd9Sstevel@tonic-gate * pop_module(n) pop 'n' modules from stream 458*7c478bd9Sstevel@tonic-gate * 459*7c478bd9Sstevel@tonic-gate * returns # of modules popped 460*7c478bd9Sstevel@tonic-gate */ 461*7c478bd9Sstevel@tonic-gate static int 462*7c478bd9Sstevel@tonic-gate pop_modules(num_modules) 463*7c478bd9Sstevel@tonic-gate int num_modules; 464*7c478bd9Sstevel@tonic-gate { 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate register short i; /* the ubiquitous loop variable */ 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate for ( i = 0; i < num_modules; i++ ) { 469*7c478bd9Sstevel@tonic-gate if ( ioctl(STDIN, I_POP, 0) < 0 ) { 470*7c478bd9Sstevel@tonic-gate perror("I_POP"); 471*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 472*7c478bd9Sstevel@tonic-gate "%s: I_POP ioctl failed\n", Cmd_namep); 473*7c478bd9Sstevel@tonic-gate return(i); 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate return(i); 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate /* 480*7c478bd9Sstevel@tonic-gate * push_module(modnamep) pushes 'modnamep' module on stream 481*7c478bd9Sstevel@tonic-gate * 482*7c478bd9Sstevel@tonic-gate * returns SUCCESS or FAILURE 483*7c478bd9Sstevel@tonic-gate */ 484*7c478bd9Sstevel@tonic-gate static int 485*7c478bd9Sstevel@tonic-gate push_module(modnamep) 486*7c478bd9Sstevel@tonic-gate char *modnamep; 487*7c478bd9Sstevel@tonic-gate { 488*7c478bd9Sstevel@tonic-gate if ( ioctl(STDIN, I_PUSH, modnamep) < 0 ) { 489*7c478bd9Sstevel@tonic-gate perror("I_PUSH"); 490*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 491*7c478bd9Sstevel@tonic-gate "%s: I_PUSH ioctl of %s failed\n", Cmd_namep, modnamep); 492*7c478bd9Sstevel@tonic-gate return(FAILURE); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate return (SUCCESS); 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate /* 499*7c478bd9Sstevel@tonic-gate * restore(npop, npush) restore original state of stream 500*7c478bd9Sstevel@tonic-gate * 501*7c478bd9Sstevel@tonic-gate * pops 'npop' modules, then pushes the topmost 'npush' modules from 502*7c478bd9Sstevel@tonic-gate * Oldlist 503*7c478bd9Sstevel@tonic-gate * 504*7c478bd9Sstevel@tonic-gate */ 505*7c478bd9Sstevel@tonic-gate static void 506*7c478bd9Sstevel@tonic-gate restore(npop, npush) 507*7c478bd9Sstevel@tonic-gate int npop; 508*7c478bd9Sstevel@tonic-gate int npush; 509*7c478bd9Sstevel@tonic-gate { 510*7c478bd9Sstevel@tonic-gate register int i; 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate if ( (i = pop_modules(npop)) != npop ) { 513*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 514*7c478bd9Sstevel@tonic-gate "%s: WARNING: could not restore state of stream\n", Cmd_namep); 515*7c478bd9Sstevel@tonic-gate return; 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate if ( npush >= Oldlist.sl_nmods ) { /* "cannot" happen */ 518*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 519*7c478bd9Sstevel@tonic-gate "%s: internal logic error in restore\n", Cmd_namep); 520*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 521*7c478bd9Sstevel@tonic-gate "%s: WARNING: could not restore state of stream\n", Cmd_namep); 522*7c478bd9Sstevel@tonic-gate return; 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate for ( i = npush - 1; i >= 0; --i ) { 525*7c478bd9Sstevel@tonic-gate if ( push_module(Oldlist.sl_modlist[i].l_name) == FAILURE ) { 526*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 527*7c478bd9Sstevel@tonic-gate "%s: WARNING: could not restore state of stream\n", 528*7c478bd9Sstevel@tonic-gate Cmd_namep); 529*7c478bd9Sstevel@tonic-gate return; 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate return; 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate /* 536*7c478bd9Sstevel@tonic-gate * more_modules(listp, n) allocate space for 'n' modules in 'listp' 537*7c478bd9Sstevel@tonic-gate * 538*7c478bd9Sstevel@tonic-gate * returns: SUCCESS or FAILURE 539*7c478bd9Sstevel@tonic-gate */ 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate static int 542*7c478bd9Sstevel@tonic-gate more_modules(listp, n) 543*7c478bd9Sstevel@tonic-gate struct str_list *listp; /* streams module list */ 544*7c478bd9Sstevel@tonic-gate int n; /* # of modules */ 545*7c478bd9Sstevel@tonic-gate { 546*7c478bd9Sstevel@tonic-gate register int i; 547*7c478bd9Sstevel@tonic-gate register struct str_mlist *modp; 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate extern char *calloc(); 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate if ( n > MAXMODULES ) { 552*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 553*7c478bd9Sstevel@tonic-gate "%s: too many modules (%d) -- max is %d\n", 554*7c478bd9Sstevel@tonic-gate Cmd_namep, n, MAXMODULES); 555*7c478bd9Sstevel@tonic-gate return(FAILURE); 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate if ( (modp = (struct str_mlist *)calloc((unsigned)n, 559*7c478bd9Sstevel@tonic-gate (unsigned)sizeof(struct str_mlist))) == (struct str_mlist *)NULL ) { 560*7c478bd9Sstevel@tonic-gate perror("calloc"); 561*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 562*7c478bd9Sstevel@tonic-gate "%s: failed to allocate space for module list\n", 563*7c478bd9Sstevel@tonic-gate Cmd_namep); 564*7c478bd9Sstevel@tonic-gate return(FAILURE); 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate for ( i = 0; i < listp->sl_nmods; ++i ) 568*7c478bd9Sstevel@tonic-gate (void) strncpy(modp[i].l_name, listp->sl_modlist[i].l_name, 569*7c478bd9Sstevel@tonic-gate FMNAMESZ); 570*7c478bd9Sstevel@tonic-gate listp->sl_nmods = n; 571*7c478bd9Sstevel@tonic-gate listp->sl_modlist = modp; 572*7c478bd9Sstevel@tonic-gate return(SUCCESS); 573*7c478bd9Sstevel@tonic-gate } 574