10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 22*515Smeem 23*515Smeem /* 24*515Smeem * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25*515Smeem * Use is subject to license terms. 26*515Smeem */ 27*515Smeem 280Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 290Sstevel@tonic-gate /* All Rights Reserved */ 300Sstevel@tonic-gate 31*515Smeem #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */ 320Sstevel@tonic-gate 33*515Smeem /* 340Sstevel@tonic-gate * Streams Command strchg: change the configuration of the 350Sstevel@tonic-gate * stream associated with stdin. 360Sstevel@tonic-gate * 370Sstevel@tonic-gate * USAGE: strchg -h module1[,module2,module3 ...] 380Sstevel@tonic-gate * or: strchg -p 390Sstevel@tonic-gate * or: strchg -p -a 400Sstevel@tonic-gate * or: strchg -p -u module 410Sstevel@tonic-gate * or: strchg -f file 420Sstevel@tonic-gate * 430Sstevel@tonic-gate * -h pusHes the named module(s) onto the stdin stream 440Sstevel@tonic-gate * -p poPs the topmost module from the stdin stream 450Sstevel@tonic-gate * -p -a poPs All modules 460Sstevel@tonic-gate * -p -u module poPs all modules Up to, but not including, the named module 470Sstevel@tonic-gate * -f file reads a list of modules from the named File, pops all modules, 480Sstevel@tonic-gate * then pushes the list of modules 490Sstevel@tonic-gate * 500Sstevel@tonic-gate * RETURNS: 510Sstevel@tonic-gate * 0 SUCCESS it worked 520Sstevel@tonic-gate * 1 ERR_USAGE bad invocation 530Sstevel@tonic-gate * 2 ERR_MODULE bad module name(s) 540Sstevel@tonic-gate * 3 ERR_STDIN an ioctl or stat on the stdin stream failed 550Sstevel@tonic-gate * 4 ERR_MEM couldn't allocate memory 560Sstevel@tonic-gate * 5 ERR_OPEN couldn't open file in -f opt 570Sstevel@tonic-gate * 6 ERR_PERM not owner or superuser 580Sstevel@tonic-gate * 590Sstevel@tonic-gate */ 600Sstevel@tonic-gate 610Sstevel@tonic-gate 62*515Smeem #include <stdio.h> 63*515Smeem #include <sys/stropts.h> 64*515Smeem #include <sys/termio.h> 65*515Smeem #include <sys/types.h> 66*515Smeem #include <sys/stat.h> 67*515Smeem #include <string.h> 68*515Smeem #include <stdlib.h> 69*515Smeem #include <unistd.h> 700Sstevel@tonic-gate 71*515Smeem #define FALSE 0 720Sstevel@tonic-gate #define TRUE 1 730Sstevel@tonic-gate 74*515Smeem #define SUCCESS 0 75*515Smeem #define FAILURE 1 760Sstevel@tonic-gate 770Sstevel@tonic-gate #define NMODULES 16 /* "reasonable" # of modules to push */ 780Sstevel@tonic-gate /* (can push more if you like) */ 790Sstevel@tonic-gate #define MAXMODULES 2048 /* max # of modules to push */ 800Sstevel@tonic-gate 810Sstevel@tonic-gate #define OPTLIST "af:h:pu:" 82*515Smeem #define USAGE "Usage:\t%s -h module1[,module2 ... ]\n\t%s -f file"\ 83*515Smeem "\n\t%s -p [-a | -u module ]\n" 840Sstevel@tonic-gate 850Sstevel@tonic-gate #define ERR_USAGE 1 /* bad invocation */ 860Sstevel@tonic-gate #define ERR_MODULE 2 /* bad module name(s) or too many modules */ 870Sstevel@tonic-gate #define ERR_STDIN 3 /* an ioctl or stat on stdin failed */ 880Sstevel@tonic-gate #define ERR_MEM 4 /* couldn't allocate memory */ 890Sstevel@tonic-gate #define ERR_OPEN 5 /* couldn't open file in -f opt */ 900Sstevel@tonic-gate #define ERR_PERM 6 /* not owner or superuser */ 910Sstevel@tonic-gate 920Sstevel@tonic-gate #define STDIN 0 930Sstevel@tonic-gate 94*515Smeem static char *Cmd_namep; /* how was it invoked? */ 950Sstevel@tonic-gate static struct str_mlist Oldmods[NMODULES]; /* modlist for Oldlist */ 960Sstevel@tonic-gate static struct str_list Oldlist; /* original modules */ 970Sstevel@tonic-gate 98*515Smeem static int pop_modules(int); 99*515Smeem static int push_module(const char *); 100*515Smeem static int more_modules(struct str_list *, int); 101*515Smeem static void restore(int, int); 1020Sstevel@tonic-gate 103*515Smeem int 104*515Smeem main(int argc, char **argv) 1050Sstevel@tonic-gate { 1060Sstevel@tonic-gate char buf[BUFSIZ]; /* input buffer */ 1070Sstevel@tonic-gate char *file_namep; /* file from -f opt */ 1080Sstevel@tonic-gate char *modnamep; /* mods from -h or -u opt */ 1090Sstevel@tonic-gate char *modp; /* for walking thru modnamep */ 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate FILE *fp; /* file pointer for -f file */ 1120Sstevel@tonic-gate 113*515Smeem int i; /* loop index and junk var */ 114*515Smeem int j; /* loop index and junk var */ 1150Sstevel@tonic-gate int euid; /* effective uid */ 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate short error; /* TRUE if usage error */ 1180Sstevel@tonic-gate short fromfile; /* TRUE if -f file */ 1190Sstevel@tonic-gate short is_a_tty; /* TRUE if TCGETA succeeds */ 1200Sstevel@tonic-gate short pop; /* TRUE if -p */ 1210Sstevel@tonic-gate short popall; /* TRUE if -p -a */ 1220Sstevel@tonic-gate short popupto; /* TRUE if -p -u module */ 1230Sstevel@tonic-gate short push; /* TRUE if -h mod1[,mod2 ...] */ 1240Sstevel@tonic-gate 125*515Smeem struct str_mlist newmods[NMODULES]; /* mod list for new list */ 1260Sstevel@tonic-gate struct stat stats; /* stream stats */ 1270Sstevel@tonic-gate struct str_list newlist; /* modules to be pushed */ 1280Sstevel@tonic-gate struct termio termio; /* save state of tty */ 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate /* 1310Sstevel@tonic-gate * init 1320Sstevel@tonic-gate */ 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate Cmd_namep = argv[0]; 1350Sstevel@tonic-gate error = fromfile = is_a_tty = pop = popall = popupto = push = FALSE; 1360Sstevel@tonic-gate Oldlist.sl_modlist = Oldmods; 1370Sstevel@tonic-gate Oldlist.sl_nmods = NMODULES; 1380Sstevel@tonic-gate newlist.sl_modlist = newmods; 1390Sstevel@tonic-gate newlist.sl_nmods = NMODULES; 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate /* 1420Sstevel@tonic-gate * only owner and root can change stream configuration 1430Sstevel@tonic-gate */ 144*515Smeem if ((euid = geteuid()) != 0) { 145*515Smeem if (fstat(0, &stats) < 0) { 1460Sstevel@tonic-gate perror("fstat"); 1470Sstevel@tonic-gate (void) fprintf(stderr, "%s: fstat of stdin failed\n", 1480Sstevel@tonic-gate Cmd_namep); 149*515Smeem return (ERR_STDIN); 1500Sstevel@tonic-gate } 151*515Smeem if (euid != stats.st_uid) { 1520Sstevel@tonic-gate (void) fprintf(stderr, 1530Sstevel@tonic-gate "%s: not owner of stdin\n", Cmd_namep); 154*515Smeem return (ERR_PERM); 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate } 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate /* 1600Sstevel@tonic-gate * parse args 1610Sstevel@tonic-gate */ 1620Sstevel@tonic-gate 163*515Smeem if (argc == 1) { 1640Sstevel@tonic-gate (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 165*515Smeem return (ERR_USAGE); 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate 168*515Smeem while (!error && (i = getopt(argc, argv, OPTLIST)) != -1) { 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate switch (i) { 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate case 'a': /* pop All */ 173*515Smeem if (fromfile || popupto || push) 1740Sstevel@tonic-gate error = TRUE; 1750Sstevel@tonic-gate else 1760Sstevel@tonic-gate popall = TRUE; 1770Sstevel@tonic-gate break; 1780Sstevel@tonic-gate 179*515Smeem case 'f': /* read from File */ 180*515Smeem if (pop || push) 1810Sstevel@tonic-gate error = TRUE; 1820Sstevel@tonic-gate else { 1830Sstevel@tonic-gate fromfile = TRUE; 1840Sstevel@tonic-gate file_namep = optarg; 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate break; 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate case 'h': /* pusH */ 189*515Smeem if (fromfile || pop) 1900Sstevel@tonic-gate error = TRUE; 1910Sstevel@tonic-gate else { 1920Sstevel@tonic-gate push = TRUE; 1930Sstevel@tonic-gate modnamep = optarg; 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate break; 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate case 'p': /* poP */ 198*515Smeem if (fromfile || push) 1990Sstevel@tonic-gate error = TRUE; 2000Sstevel@tonic-gate else 2010Sstevel@tonic-gate pop = TRUE; 2020Sstevel@tonic-gate break; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate case 'u': /* pop Upto */ 205*515Smeem if (fromfile || popall || push) 2060Sstevel@tonic-gate error = TRUE; 2070Sstevel@tonic-gate else { 2080Sstevel@tonic-gate popupto = TRUE; 2090Sstevel@tonic-gate modnamep = optarg; 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate break; 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate default: 2140Sstevel@tonic-gate (void) fprintf(stderr, 2150Sstevel@tonic-gate USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 216*515Smeem return (ERR_USAGE); 2170Sstevel@tonic-gate /*NOTREACHED*/ 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate } 2200Sstevel@tonic-gate 221*515Smeem if (error || optind < argc) { 2220Sstevel@tonic-gate (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 223*515Smeem return (ERR_USAGE); 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate 226*515Smeem if (!pop && (popall || popupto)) { 2270Sstevel@tonic-gate (void) fprintf(stderr, 228*515Smeem "%s: -p option must be used with -a or -u to pop modules\n", 229*515Smeem Cmd_namep); 2300Sstevel@tonic-gate (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 231*515Smeem return (ERR_USAGE); 2320Sstevel@tonic-gate } 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate /* 2360Sstevel@tonic-gate * Save state so can restore if something goes wrong 237*515Smeem * (If are only going to push modules, don't need to 2380Sstevel@tonic-gate * save original module list for restore.) 2390Sstevel@tonic-gate */ 240*515Smeem if (fromfile || pop) { 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate /* 2430Sstevel@tonic-gate * get number of modules on stream 2440Sstevel@tonic-gate * allocate more room if needed 2450Sstevel@tonic-gate */ 246*515Smeem if ((i = ioctl(STDIN, I_LIST, NULL)) < 0) { 2470Sstevel@tonic-gate perror("I_LIST"); 2480Sstevel@tonic-gate (void) fprintf(stderr, 2490Sstevel@tonic-gate "%s: I_LIST ioctl failed\n", Cmd_namep); 250*515Smeem return (ERR_STDIN); 2510Sstevel@tonic-gate } 252*515Smeem if (i > Oldlist.sl_nmods && 253*515Smeem more_modules(&Oldlist, i) != SUCCESS) 254*515Smeem return (ERR_MEM); 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate /* 2570Sstevel@tonic-gate * get list of modules on stream 2580Sstevel@tonic-gate */ 2590Sstevel@tonic-gate Oldlist.sl_nmods = i; 260*515Smeem if (ioctl(STDIN, I_LIST, &Oldlist) < 0) { 2610Sstevel@tonic-gate perror("I_LIST"); 2620Sstevel@tonic-gate (void) fprintf(stderr, 2630Sstevel@tonic-gate "%s: I_LIST ioctl failed\n", Cmd_namep); 264*515Smeem return (ERR_STDIN); 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate /* 2680Sstevel@tonic-gate * The following attempts to avoid leaving a 2690Sstevel@tonic-gate * terminal line that does not respond to anything 2700Sstevel@tonic-gate * if the strchg -h or -f options failed due to 2710Sstevel@tonic-gate * specifying invalid module names for pushing 2720Sstevel@tonic-gate */ 273*515Smeem if (ioctl(STDIN, TCGETA, &termio) >= 0) 2740Sstevel@tonic-gate is_a_tty = TRUE; 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate /* 2790Sstevel@tonic-gate * push modules on stream 2800Sstevel@tonic-gate */ 281*515Smeem if (push) { 2820Sstevel@tonic-gate /* 2830Sstevel@tonic-gate * pull mod names out of comma-separated list 2840Sstevel@tonic-gate */ 285*515Smeem for (i = 0, modp = strtok(modnamep, ","); 286*515Smeem modp != NULL; ++i, modp = strtok(NULL, ",")) { 287*515Smeem if (push_module(modp) == FAILURE) { 2880Sstevel@tonic-gate /* pop the 'i' modules we just added */ 2890Sstevel@tonic-gate restore(i, 0); 290*515Smeem return (ERR_STDIN); 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate } 293*515Smeem return (SUCCESS); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate /* 2970Sstevel@tonic-gate * read configuration from a file 2980Sstevel@tonic-gate */ 299*515Smeem if (fromfile) { 3000Sstevel@tonic-gate 301*515Smeem if ((fp = fopen(file_namep, "r")) == NULL) { 3020Sstevel@tonic-gate perror("fopen"); 3030Sstevel@tonic-gate (void) fprintf(stderr, 3040Sstevel@tonic-gate "%s: could not open file '%s'\n", 3050Sstevel@tonic-gate Cmd_namep, file_namep); 306*515Smeem return (ERR_OPEN); 3070Sstevel@tonic-gate } 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate /* 3100Sstevel@tonic-gate * read file and construct a new strlist 3110Sstevel@tonic-gate */ 3120Sstevel@tonic-gate i = 0; 313*515Smeem while (fgets(buf, BUFSIZ, fp) != NULL) { 3140Sstevel@tonic-gate 315*515Smeem if (buf[0] == '#') 3160Sstevel@tonic-gate continue; /* skip comments */ 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate /* 3190Sstevel@tonic-gate * skip trailing newline, trailing and leading 3200Sstevel@tonic-gate * whitespace 3210Sstevel@tonic-gate */ 322*515Smeem if ((modp = strtok(buf, " \t\n")) == NULL) 3230Sstevel@tonic-gate continue; /* blank line */ 3240Sstevel@tonic-gate 325*515Smeem (void) strncpy(newlist.sl_modlist[i].l_name, 326*515Smeem modp, FMNAMESZ); 3270Sstevel@tonic-gate ++i; 328*515Smeem if ((modp = strtok(NULL, " \t\n")) != NULL) { 3290Sstevel@tonic-gate /* 330*515Smeem * bad format 3310Sstevel@tonic-gate * should only be one name per line 3320Sstevel@tonic-gate */ 3330Sstevel@tonic-gate (void) fprintf(stderr, 334*515Smeem "%s: error on line %d in file %s: " 335*515Smeem "multiple module names??\n", 336*515Smeem Cmd_namep, i, file_namep); 337*515Smeem return (ERR_MODULE); 3380Sstevel@tonic-gate } 339*515Smeem if (i > newlist.sl_nmods) 340*515Smeem if (more_modules(&newlist, i) != SUCCESS) 341*515Smeem return (ERR_MEM); 3420Sstevel@tonic-gate } 3430Sstevel@tonic-gate newlist.sl_nmods = i; 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate /* 3460Sstevel@tonic-gate * If an empty file, exit silently 3470Sstevel@tonic-gate */ 348*515Smeem if (i == 0) 349*515Smeem return (SUCCESS); 3500Sstevel@tonic-gate 351*515Smeem /* 3520Sstevel@tonic-gate * Pop all modules currently on the stream. 3530Sstevel@tonic-gate */ 354*515Smeem if ((i = pop_modules(Oldlist.sl_nmods - 1)) 355*515Smeem != (Oldlist.sl_nmods - 1)) { 3560Sstevel@tonic-gate /* put back whatever we've popped */ 3570Sstevel@tonic-gate restore(0, i); 358*515Smeem return (ERR_STDIN); 3590Sstevel@tonic-gate } 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate /* 3620Sstevel@tonic-gate * Push new modules 3630Sstevel@tonic-gate */ 364*515Smeem for (i = newlist.sl_nmods - 1; i >= 0; --i) { 365*515Smeem if (push_module(newlist.sl_modlist[i].l_name) == 366*515Smeem FAILURE) { 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate /* 3690Sstevel@tonic-gate * pop whatever new modules we've pushed 3700Sstevel@tonic-gate * then push old module list back on 3710Sstevel@tonic-gate */ 3720Sstevel@tonic-gate restore((newlist.sl_nmods - 1 - i), 373*515Smeem (Oldlist.sl_nmods - 1)); 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate /* 3760Sstevel@tonic-gate * If the stream is a tty line, at least try 3770Sstevel@tonic-gate * to set the state to what it was before. 3780Sstevel@tonic-gate */ 379*515Smeem if (is_a_tty && 380*515Smeem ioctl(STDIN, TCSETA, &termio) < 0) { 381*515Smeem perror("TCSETA"); 382*515Smeem (void) fprintf(stderr, 383*515Smeem "%s: WARNING: Could not restore " 384*515Smeem "the states of the terminal line " 385*515Smeem "discipline\n", Cmd_namep); 3860Sstevel@tonic-gate } 387*515Smeem return (ERR_STDIN); 3880Sstevel@tonic-gate } 389*515Smeem } 390*515Smeem return (SUCCESS); 3910Sstevel@tonic-gate } /* end if-fromfile */ 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate /* 3950Sstevel@tonic-gate * pop all modules (except driver) 3960Sstevel@tonic-gate */ 397*515Smeem if (popall) { 398*515Smeem if (Oldlist.sl_nmods > 1) { 399*515Smeem if ((i = pop_modules(Oldlist.sl_nmods - 1)) != 400*515Smeem (Oldlist.sl_nmods - 1)) { 4010Sstevel@tonic-gate restore(0, i); 402*515Smeem return (ERR_STDIN); 4030Sstevel@tonic-gate } 4040Sstevel@tonic-gate } 405*515Smeem return (SUCCESS); 4060Sstevel@tonic-gate } 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate /* 4090Sstevel@tonic-gate * pop up to (but not including) a module 4100Sstevel@tonic-gate */ 411*515Smeem if (popupto) { 4120Sstevel@tonic-gate /* 4130Sstevel@tonic-gate * check that the module is in fact on the stream 4140Sstevel@tonic-gate */ 415*515Smeem for (i = 0; i < Oldlist.sl_nmods; ++i) 416*515Smeem if (strncmp(Oldlist.sl_modlist[i].l_name, modnamep, 417*515Smeem FMNAMESZ) == 0) 4180Sstevel@tonic-gate break; 419*515Smeem if (i == Oldlist.sl_nmods) { 4200Sstevel@tonic-gate /* no match found */ 4210Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s not found on stream\n", 4220Sstevel@tonic-gate Cmd_namep, modnamep); 423*515Smeem return (ERR_MODULE); 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate 426*515Smeem if ((j = pop_modules(i)) != i) { 4270Sstevel@tonic-gate /* put back whatever we've popped */ 4280Sstevel@tonic-gate restore(0, j); 429*515Smeem return (ERR_STDIN); 4300Sstevel@tonic-gate } 431*515Smeem return (SUCCESS); 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate /* 4350Sstevel@tonic-gate * pop the topmost module 4360Sstevel@tonic-gate */ 437*515Smeem if (pop) { 438*515Smeem if (Oldlist.sl_nmods > 1) 439*515Smeem if (pop_modules(1) != 1) 4400Sstevel@tonic-gate /* no need to restore */ 441*515Smeem return (ERR_STDIN); 442*515Smeem return (SUCCESS); 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate 445*515Smeem return (SUCCESS); 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate 448*515Smeem /* 4490Sstevel@tonic-gate * pop_module(n) pop 'n' modules from stream 4500Sstevel@tonic-gate * 4510Sstevel@tonic-gate * returns # of modules popped 4520Sstevel@tonic-gate */ 4530Sstevel@tonic-gate static int 454*515Smeem pop_modules(int num_modules) 4550Sstevel@tonic-gate { 456*515Smeem int i; 4570Sstevel@tonic-gate 458*515Smeem for (i = 0; i < num_modules; i++) { 459*515Smeem if (ioctl(STDIN, I_POP, 0) < 0) { 4600Sstevel@tonic-gate perror("I_POP"); 4610Sstevel@tonic-gate (void) fprintf(stderr, 462*515Smeem "%s: I_POP ioctl failed\n", Cmd_namep); 463*515Smeem return (i); 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate } 466*515Smeem return (i); 4670Sstevel@tonic-gate } 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate /* 4700Sstevel@tonic-gate * push_module(modnamep) pushes 'modnamep' module on stream 4710Sstevel@tonic-gate * 4720Sstevel@tonic-gate * returns SUCCESS or FAILURE 4730Sstevel@tonic-gate */ 4740Sstevel@tonic-gate static int 475*515Smeem push_module(const char *modnamep) 4760Sstevel@tonic-gate { 477*515Smeem if (ioctl(STDIN, I_PUSH, modnamep) < 0) { 4780Sstevel@tonic-gate perror("I_PUSH"); 4790Sstevel@tonic-gate (void) fprintf(stderr, 480*515Smeem "%s: I_PUSH ioctl of %s failed\n", Cmd_namep, modnamep); 481*515Smeem return (FAILURE); 4820Sstevel@tonic-gate } 4830Sstevel@tonic-gate return (SUCCESS); 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate /* 4880Sstevel@tonic-gate * restore(npop, npush) restore original state of stream 4890Sstevel@tonic-gate * 4900Sstevel@tonic-gate * pops 'npop' modules, then pushes the topmost 'npush' modules from 4910Sstevel@tonic-gate * Oldlist 4920Sstevel@tonic-gate * 4930Sstevel@tonic-gate */ 4940Sstevel@tonic-gate static void 495*515Smeem restore(int npop, int npush) 4960Sstevel@tonic-gate { 497*515Smeem int i; 4980Sstevel@tonic-gate 499*515Smeem if ((i = pop_modules(npop)) != npop) { 5000Sstevel@tonic-gate (void) fprintf(stderr, 501*515Smeem "%s: WARNING: could not restore state of stream\n", 502*515Smeem Cmd_namep); 5030Sstevel@tonic-gate return; 5040Sstevel@tonic-gate } 505*515Smeem 506*515Smeem if (npush >= Oldlist.sl_nmods) { /* "cannot" happen */ 5070Sstevel@tonic-gate (void) fprintf(stderr, 508*515Smeem "%s: internal logic error in restore\n", Cmd_namep); 5090Sstevel@tonic-gate (void) fprintf(stderr, 510*515Smeem "%s: WARNING: could not restore state of stream\n", 511*515Smeem Cmd_namep); 5120Sstevel@tonic-gate return; 5130Sstevel@tonic-gate } 514*515Smeem 515*515Smeem for (i = npush - 1; i >= 0; --i) { 516*515Smeem if (push_module(Oldlist.sl_modlist[i].l_name) == FAILURE) { 5170Sstevel@tonic-gate (void) fprintf(stderr, 518*515Smeem "%s: WARNING: could not restore state of stream\n", 519*515Smeem Cmd_namep); 5200Sstevel@tonic-gate return; 5210Sstevel@tonic-gate } 5220Sstevel@tonic-gate } 5230Sstevel@tonic-gate } 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate /* 5260Sstevel@tonic-gate * more_modules(listp, n) allocate space for 'n' modules in 'listp' 5270Sstevel@tonic-gate * 5280Sstevel@tonic-gate * returns: SUCCESS or FAILURE 5290Sstevel@tonic-gate */ 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate static int 532*515Smeem more_modules(struct str_list *listp, int n) 5330Sstevel@tonic-gate { 534*515Smeem int i; 535*515Smeem struct str_mlist *modp; 5360Sstevel@tonic-gate 537*515Smeem if (n > MAXMODULES) { 5380Sstevel@tonic-gate (void) fprintf(stderr, 539*515Smeem "%s: too many modules (%d) -- max is %d\n", 540*515Smeem Cmd_namep, n, MAXMODULES); 541*515Smeem return (FAILURE); 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate 544*515Smeem if ((modp = calloc(n, sizeof (struct str_mlist))) == NULL) { 5450Sstevel@tonic-gate perror("calloc"); 5460Sstevel@tonic-gate (void) fprintf(stderr, 547*515Smeem "%s: failed to allocate space for module list\n", 548*515Smeem Cmd_namep); 549*515Smeem return (FAILURE); 5500Sstevel@tonic-gate } 5510Sstevel@tonic-gate 552*515Smeem for (i = 0; i < listp->sl_nmods; ++i) 5530Sstevel@tonic-gate (void) strncpy(modp[i].l_name, listp->sl_modlist[i].l_name, 554*515Smeem FMNAMESZ); 5550Sstevel@tonic-gate listp->sl_nmods = n; 5560Sstevel@tonic-gate listp->sl_modlist = modp; 557*515Smeem return (SUCCESS); 5580Sstevel@tonic-gate } 559