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
main(int argc,char ** argv)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
pop_modules(int num_modules)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
push_module(const char * modnamep)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
restore(int npop,int npush)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
more_modules(struct str_list * listp,int n)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