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