17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 22*4b908718Smeem 23*4b908718Smeem /* 24*4b908718Smeem * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25*4b908718Smeem * Use is subject to license terms. 26*4b908718Smeem */ 27*4b908718Smeem 287c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 297c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 307c478bd9Sstevel@tonic-gate 31*4b908718Smeem #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate /* 347c478bd9Sstevel@tonic-gate * Streams Command strchg: change the configuration of the 357c478bd9Sstevel@tonic-gate * stream associated with stdin. 367c478bd9Sstevel@tonic-gate * 377c478bd9Sstevel@tonic-gate * USAGE: strchg -h module1[,module2,module3 ...] 387c478bd9Sstevel@tonic-gate * or: strchg -p 397c478bd9Sstevel@tonic-gate * or: strchg -p -a 407c478bd9Sstevel@tonic-gate * or: strchg -p -u module 417c478bd9Sstevel@tonic-gate * or: strchg -f file 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate * -h pusHes the named module(s) onto the stdin stream 447c478bd9Sstevel@tonic-gate * -p poPs the topmost module from the stdin stream 457c478bd9Sstevel@tonic-gate * -p -a poPs All modules 467c478bd9Sstevel@tonic-gate * -p -u module poPs all modules Up to, but not including, the named module 477c478bd9Sstevel@tonic-gate * -f file reads a list of modules from the named File, pops all modules, 487c478bd9Sstevel@tonic-gate * then pushes the list of modules 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * RETURNS: 517c478bd9Sstevel@tonic-gate * 0 SUCCESS it worked 527c478bd9Sstevel@tonic-gate * 1 ERR_USAGE bad invocation 537c478bd9Sstevel@tonic-gate * 2 ERR_MODULE bad module name(s) 547c478bd9Sstevel@tonic-gate * 3 ERR_STDIN an ioctl or stat on the stdin stream failed 557c478bd9Sstevel@tonic-gate * 4 ERR_MEM couldn't allocate memory 567c478bd9Sstevel@tonic-gate * 5 ERR_OPEN couldn't open file in -f opt 577c478bd9Sstevel@tonic-gate * 6 ERR_PERM not owner or superuser 587c478bd9Sstevel@tonic-gate * 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #include <stdio.h> 637c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 647c478bd9Sstevel@tonic-gate #include <sys/termio.h> 657c478bd9Sstevel@tonic-gate #include <sys/types.h> 667c478bd9Sstevel@tonic-gate #include <sys/stat.h> 67*4b908718Smeem #include <string.h> 68*4b908718Smeem #include <stdlib.h> 69*4b908718Smeem #include <unistd.h> 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate #define FALSE 0 727c478bd9Sstevel@tonic-gate #define TRUE 1 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate #define SUCCESS 0 757c478bd9Sstevel@tonic-gate #define FAILURE 1 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate #define NMODULES 16 /* "reasonable" # of modules to push */ 787c478bd9Sstevel@tonic-gate /* (can push more if you like) */ 797c478bd9Sstevel@tonic-gate #define MAXMODULES 2048 /* max # of modules to push */ 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate #define OPTLIST "af:h:pu:" 82*4b908718Smeem #define USAGE "Usage:\t%s -h module1[,module2 ... ]\n\t%s -f file"\ 83*4b908718Smeem "\n\t%s -p [-a | -u module ]\n" 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate #define ERR_USAGE 1 /* bad invocation */ 867c478bd9Sstevel@tonic-gate #define ERR_MODULE 2 /* bad module name(s) or too many modules */ 877c478bd9Sstevel@tonic-gate #define ERR_STDIN 3 /* an ioctl or stat on stdin failed */ 887c478bd9Sstevel@tonic-gate #define ERR_MEM 4 /* couldn't allocate memory */ 897c478bd9Sstevel@tonic-gate #define ERR_OPEN 5 /* couldn't open file in -f opt */ 907c478bd9Sstevel@tonic-gate #define ERR_PERM 6 /* not owner or superuser */ 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate #define STDIN 0 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate static char *Cmd_namep; /* how was it invoked? */ 957c478bd9Sstevel@tonic-gate static struct str_mlist Oldmods[NMODULES]; /* modlist for Oldlist */ 967c478bd9Sstevel@tonic-gate static struct str_list Oldlist; /* original modules */ 977c478bd9Sstevel@tonic-gate 98*4b908718Smeem static int pop_modules(int); 99*4b908718Smeem static int push_module(const char *); 100*4b908718Smeem static int more_modules(struct str_list *, int); 101*4b908718Smeem static void restore(int, int); 1027c478bd9Sstevel@tonic-gate 103*4b908718Smeem int 104*4b908718Smeem main(int argc, char **argv) 1057c478bd9Sstevel@tonic-gate { 1067c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; /* input buffer */ 1077c478bd9Sstevel@tonic-gate char *file_namep; /* file from -f opt */ 1087c478bd9Sstevel@tonic-gate char *modnamep; /* mods from -h or -u opt */ 1097c478bd9Sstevel@tonic-gate char *modp; /* for walking thru modnamep */ 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate FILE *fp; /* file pointer for -f file */ 1127c478bd9Sstevel@tonic-gate 113*4b908718Smeem int i; /* loop index and junk var */ 114*4b908718Smeem int j; /* loop index and junk var */ 1157c478bd9Sstevel@tonic-gate int euid; /* effective uid */ 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate short error; /* TRUE if usage error */ 1187c478bd9Sstevel@tonic-gate short fromfile; /* TRUE if -f file */ 1197c478bd9Sstevel@tonic-gate short is_a_tty; /* TRUE if TCGETA succeeds */ 1207c478bd9Sstevel@tonic-gate short pop; /* TRUE if -p */ 1217c478bd9Sstevel@tonic-gate short popall; /* TRUE if -p -a */ 1227c478bd9Sstevel@tonic-gate short popupto; /* TRUE if -p -u module */ 1237c478bd9Sstevel@tonic-gate short push; /* TRUE if -h mod1[,mod2 ...] */ 1247c478bd9Sstevel@tonic-gate 125*4b908718Smeem struct str_mlist newmods[NMODULES]; /* mod list for new list */ 1267c478bd9Sstevel@tonic-gate struct stat stats; /* stream stats */ 1277c478bd9Sstevel@tonic-gate struct str_list newlist; /* modules to be pushed */ 1287c478bd9Sstevel@tonic-gate struct termio termio; /* save state of tty */ 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* 1317c478bd9Sstevel@tonic-gate * init 1327c478bd9Sstevel@tonic-gate */ 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate Cmd_namep = argv[0]; 1357c478bd9Sstevel@tonic-gate error = fromfile = is_a_tty = pop = popall = popupto = push = FALSE; 1367c478bd9Sstevel@tonic-gate Oldlist.sl_modlist = Oldmods; 1377c478bd9Sstevel@tonic-gate Oldlist.sl_nmods = NMODULES; 1387c478bd9Sstevel@tonic-gate newlist.sl_modlist = newmods; 1397c478bd9Sstevel@tonic-gate newlist.sl_nmods = NMODULES; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate /* 1427c478bd9Sstevel@tonic-gate * only owner and root can change stream configuration 1437c478bd9Sstevel@tonic-gate */ 1447c478bd9Sstevel@tonic-gate if ((euid = geteuid()) != 0) { 1457c478bd9Sstevel@tonic-gate if (fstat(0, &stats) < 0) { 1467c478bd9Sstevel@tonic-gate perror("fstat"); 1477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: fstat of stdin failed\n", 1487c478bd9Sstevel@tonic-gate Cmd_namep); 1497c478bd9Sstevel@tonic-gate return (ERR_STDIN); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate if (euid != stats.st_uid) { 1527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1537c478bd9Sstevel@tonic-gate "%s: not owner of stdin\n", Cmd_namep); 1547c478bd9Sstevel@tonic-gate return (ERR_PERM); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* 1607c478bd9Sstevel@tonic-gate * parse args 1617c478bd9Sstevel@tonic-gate */ 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate if (argc == 1) { 1647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 1657c478bd9Sstevel@tonic-gate return (ERR_USAGE); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate while (!error && (i = getopt(argc, argv, OPTLIST)) != -1) { 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate switch (i) { 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate case 'a': /* pop All */ 1737c478bd9Sstevel@tonic-gate if (fromfile || popupto || push) 1747c478bd9Sstevel@tonic-gate error = TRUE; 1757c478bd9Sstevel@tonic-gate else 1767c478bd9Sstevel@tonic-gate popall = TRUE; 1777c478bd9Sstevel@tonic-gate break; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate case 'f': /* read from File */ 1807c478bd9Sstevel@tonic-gate if (pop || push) 1817c478bd9Sstevel@tonic-gate error = TRUE; 1827c478bd9Sstevel@tonic-gate else { 1837c478bd9Sstevel@tonic-gate fromfile = TRUE; 1847c478bd9Sstevel@tonic-gate file_namep = optarg; 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate break; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate case 'h': /* pusH */ 1897c478bd9Sstevel@tonic-gate if (fromfile || pop) 1907c478bd9Sstevel@tonic-gate error = TRUE; 1917c478bd9Sstevel@tonic-gate else { 1927c478bd9Sstevel@tonic-gate push = TRUE; 1937c478bd9Sstevel@tonic-gate modnamep = optarg; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate break; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate case 'p': /* poP */ 1987c478bd9Sstevel@tonic-gate if (fromfile || push) 1997c478bd9Sstevel@tonic-gate error = TRUE; 2007c478bd9Sstevel@tonic-gate else 2017c478bd9Sstevel@tonic-gate pop = TRUE; 2027c478bd9Sstevel@tonic-gate break; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate case 'u': /* pop Upto */ 2057c478bd9Sstevel@tonic-gate if (fromfile || popall || push) 2067c478bd9Sstevel@tonic-gate error = TRUE; 2077c478bd9Sstevel@tonic-gate else { 2087c478bd9Sstevel@tonic-gate popupto = TRUE; 2097c478bd9Sstevel@tonic-gate modnamep = optarg; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate break; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate default: 2147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2157c478bd9Sstevel@tonic-gate USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 2167c478bd9Sstevel@tonic-gate return (ERR_USAGE); 2177c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (error || optind < argc) { 2227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 2237c478bd9Sstevel@tonic-gate return (ERR_USAGE); 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate if (!pop && (popall || popupto)) { 2277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2287c478bd9Sstevel@tonic-gate "%s: -p option must be used with -a or -u to pop modules\n", 2297c478bd9Sstevel@tonic-gate Cmd_namep); 2307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); 2317c478bd9Sstevel@tonic-gate return (ERR_USAGE); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate /* 2367c478bd9Sstevel@tonic-gate * Save state so can restore if something goes wrong 2377c478bd9Sstevel@tonic-gate * (If are only going to push modules, don't need to 2387c478bd9Sstevel@tonic-gate * save original module list for restore.) 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate if (fromfile || pop) { 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * get number of modules on stream 2447c478bd9Sstevel@tonic-gate * allocate more room if needed 2457c478bd9Sstevel@tonic-gate */ 246*4b908718Smeem if ((i = ioctl(STDIN, I_LIST, NULL)) < 0) { 2477c478bd9Sstevel@tonic-gate perror("I_LIST"); 2487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2497c478bd9Sstevel@tonic-gate "%s: I_LIST ioctl failed\n", Cmd_namep); 2507c478bd9Sstevel@tonic-gate return (ERR_STDIN); 2517c478bd9Sstevel@tonic-gate } 252*4b908718Smeem if (i > Oldlist.sl_nmods && 253*4b908718Smeem more_modules(&Oldlist, i) != SUCCESS) 2547c478bd9Sstevel@tonic-gate return (ERR_MEM); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * get list of modules on stream 2587c478bd9Sstevel@tonic-gate */ 2597c478bd9Sstevel@tonic-gate Oldlist.sl_nmods = i; 2607c478bd9Sstevel@tonic-gate if (ioctl(STDIN, I_LIST, &Oldlist) < 0) { 2617c478bd9Sstevel@tonic-gate perror("I_LIST"); 2627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2637c478bd9Sstevel@tonic-gate "%s: I_LIST ioctl failed\n", Cmd_namep); 2647c478bd9Sstevel@tonic-gate return (ERR_STDIN); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * The following attempts to avoid leaving a 2697c478bd9Sstevel@tonic-gate * terminal line that does not respond to anything 2707c478bd9Sstevel@tonic-gate * if the strchg -h or -f options failed due to 2717c478bd9Sstevel@tonic-gate * specifying invalid module names for pushing 2727c478bd9Sstevel@tonic-gate */ 2737c478bd9Sstevel@tonic-gate if (ioctl(STDIN, TCGETA, &termio) >= 0) 2747c478bd9Sstevel@tonic-gate is_a_tty = TRUE; 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * push modules on stream 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate if (push) { 2827c478bd9Sstevel@tonic-gate /* 2837c478bd9Sstevel@tonic-gate * pull mod names out of comma-separated list 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate for (i = 0, modp = strtok(modnamep, ","); 286*4b908718Smeem modp != NULL; ++i, modp = strtok(NULL, ",")) { 2877c478bd9Sstevel@tonic-gate if (push_module(modp) == FAILURE) { 2887c478bd9Sstevel@tonic-gate /* pop the 'i' modules we just added */ 2897c478bd9Sstevel@tonic-gate restore(i, 0); 2907c478bd9Sstevel@tonic-gate return (ERR_STDIN); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate return (SUCCESS); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* 2977c478bd9Sstevel@tonic-gate * read configuration from a file 2987c478bd9Sstevel@tonic-gate */ 2997c478bd9Sstevel@tonic-gate if (fromfile) { 3007c478bd9Sstevel@tonic-gate 301*4b908718Smeem if ((fp = fopen(file_namep, "r")) == NULL) { 3027c478bd9Sstevel@tonic-gate perror("fopen"); 3037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3047c478bd9Sstevel@tonic-gate "%s: could not open file '%s'\n", 3057c478bd9Sstevel@tonic-gate Cmd_namep, file_namep); 3067c478bd9Sstevel@tonic-gate return (ERR_OPEN); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * read file and construct a new strlist 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate i = 0; 313*4b908718Smeem while (fgets(buf, BUFSIZ, fp) != NULL) { 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate if (buf[0] == '#') 3167c478bd9Sstevel@tonic-gate continue; /* skip comments */ 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate /* 3197c478bd9Sstevel@tonic-gate * skip trailing newline, trailing and leading 3207c478bd9Sstevel@tonic-gate * whitespace 3217c478bd9Sstevel@tonic-gate */ 322*4b908718Smeem if ((modp = strtok(buf, " \t\n")) == NULL) 3237c478bd9Sstevel@tonic-gate continue; /* blank line */ 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate (void) strncpy(newlist.sl_modlist[i].l_name, 3267c478bd9Sstevel@tonic-gate modp, FMNAMESZ); 3277c478bd9Sstevel@tonic-gate ++i; 328*4b908718Smeem if ((modp = strtok(NULL, " \t\n")) != NULL) { 3297c478bd9Sstevel@tonic-gate /* 3307c478bd9Sstevel@tonic-gate * bad format 3317c478bd9Sstevel@tonic-gate * should only be one name per line 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 334*4b908718Smeem "%s: error on line %d in file %s: " 335*4b908718Smeem "multiple module names??\n", 3367c478bd9Sstevel@tonic-gate Cmd_namep, i, file_namep); 3377c478bd9Sstevel@tonic-gate return (ERR_MODULE); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate if (i > newlist.sl_nmods) 3407c478bd9Sstevel@tonic-gate if (more_modules(&newlist, i) != SUCCESS) 3417c478bd9Sstevel@tonic-gate return (ERR_MEM); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate newlist.sl_nmods = i; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate /* 3467c478bd9Sstevel@tonic-gate * If an empty file, exit silently 3477c478bd9Sstevel@tonic-gate */ 3487c478bd9Sstevel@tonic-gate if (i == 0) 3497c478bd9Sstevel@tonic-gate return (SUCCESS); 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate /* 3527c478bd9Sstevel@tonic-gate * Pop all modules currently on the stream. 3537c478bd9Sstevel@tonic-gate */ 3547c478bd9Sstevel@tonic-gate if ((i = pop_modules(Oldlist.sl_nmods - 1)) 3557c478bd9Sstevel@tonic-gate != (Oldlist.sl_nmods - 1)) { 3567c478bd9Sstevel@tonic-gate /* put back whatever we've popped */ 3577c478bd9Sstevel@tonic-gate restore(0, i); 3587c478bd9Sstevel@tonic-gate return (ERR_STDIN); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate /* 3627c478bd9Sstevel@tonic-gate * Push new modules 3637c478bd9Sstevel@tonic-gate */ 3647c478bd9Sstevel@tonic-gate for (i = newlist.sl_nmods - 1; i >= 0; --i) { 365*4b908718Smeem if (push_module(newlist.sl_modlist[i].l_name) == 366*4b908718Smeem FAILURE) { 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate /* 3697c478bd9Sstevel@tonic-gate * pop whatever new modules we've pushed 3707c478bd9Sstevel@tonic-gate * then push old module list back on 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate restore((newlist.sl_nmods - 1 - i), 3737c478bd9Sstevel@tonic-gate (Oldlist.sl_nmods - 1)); 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate /* 3767c478bd9Sstevel@tonic-gate * If the stream is a tty line, at least try 3777c478bd9Sstevel@tonic-gate * to set the state to what it was before. 3787c478bd9Sstevel@tonic-gate */ 379*4b908718Smeem if (is_a_tty && 380*4b908718Smeem ioctl(STDIN, TCSETA, &termio) < 0) { 3817c478bd9Sstevel@tonic-gate perror("TCSETA"); 3827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 383*4b908718Smeem "%s: WARNING: Could not restore " 384*4b908718Smeem "the states of the terminal line " 385*4b908718Smeem "discipline\n", Cmd_namep); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate return (ERR_STDIN); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate return (SUCCESS); 3917c478bd9Sstevel@tonic-gate } /* end if-fromfile */ 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* 3957c478bd9Sstevel@tonic-gate * pop all modules (except driver) 3967c478bd9Sstevel@tonic-gate */ 3977c478bd9Sstevel@tonic-gate if (popall) { 3987c478bd9Sstevel@tonic-gate if (Oldlist.sl_nmods > 1) { 399*4b908718Smeem if ((i = pop_modules(Oldlist.sl_nmods - 1)) != 400*4b908718Smeem (Oldlist.sl_nmods - 1)) { 4017c478bd9Sstevel@tonic-gate restore(0, i); 4027c478bd9Sstevel@tonic-gate return (ERR_STDIN); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate return (SUCCESS); 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * pop up to (but not including) a module 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate if (popupto) { 4127c478bd9Sstevel@tonic-gate /* 4137c478bd9Sstevel@tonic-gate * check that the module is in fact on the stream 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate for (i = 0; i < Oldlist.sl_nmods; ++i) 4167c478bd9Sstevel@tonic-gate if (strncmp(Oldlist.sl_modlist[i].l_name, modnamep, 417*4b908718Smeem FMNAMESZ) == 0) 4187c478bd9Sstevel@tonic-gate break; 4197c478bd9Sstevel@tonic-gate if (i == Oldlist.sl_nmods) { 4207c478bd9Sstevel@tonic-gate /* no match found */ 4217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s not found on stream\n", 4227c478bd9Sstevel@tonic-gate Cmd_namep, modnamep); 4237c478bd9Sstevel@tonic-gate return (ERR_MODULE); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate if ((j = pop_modules(i)) != i) { 4277c478bd9Sstevel@tonic-gate /* put back whatever we've popped */ 4287c478bd9Sstevel@tonic-gate restore(0, j); 4297c478bd9Sstevel@tonic-gate return (ERR_STDIN); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate return (SUCCESS); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate /* 4357c478bd9Sstevel@tonic-gate * pop the topmost module 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate if (pop) { 4387c478bd9Sstevel@tonic-gate if (Oldlist.sl_nmods > 1) 4397c478bd9Sstevel@tonic-gate if (pop_modules(1) != 1) 4407c478bd9Sstevel@tonic-gate /* no need to restore */ 4417c478bd9Sstevel@tonic-gate return (ERR_STDIN); 4427c478bd9Sstevel@tonic-gate return (SUCCESS); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 445*4b908718Smeem return (SUCCESS); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* 4497c478bd9Sstevel@tonic-gate * pop_module(n) pop 'n' modules from stream 4507c478bd9Sstevel@tonic-gate * 4517c478bd9Sstevel@tonic-gate * returns # of modules popped 4527c478bd9Sstevel@tonic-gate */ 4537c478bd9Sstevel@tonic-gate static int 454*4b908718Smeem pop_modules(int num_modules) 4557c478bd9Sstevel@tonic-gate { 456*4b908718Smeem int i; 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate for (i = 0; i < num_modules; i++) { 4597c478bd9Sstevel@tonic-gate if (ioctl(STDIN, I_POP, 0) < 0) { 4607c478bd9Sstevel@tonic-gate perror("I_POP"); 4617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4627c478bd9Sstevel@tonic-gate "%s: I_POP ioctl failed\n", Cmd_namep); 4637c478bd9Sstevel@tonic-gate return (i); 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate return (i); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * push_module(modnamep) pushes 'modnamep' module on stream 4717c478bd9Sstevel@tonic-gate * 4727c478bd9Sstevel@tonic-gate * returns SUCCESS or FAILURE 4737c478bd9Sstevel@tonic-gate */ 4747c478bd9Sstevel@tonic-gate static int 475*4b908718Smeem push_module(const char *modnamep) 4767c478bd9Sstevel@tonic-gate { 4777c478bd9Sstevel@tonic-gate if (ioctl(STDIN, I_PUSH, modnamep) < 0) { 4787c478bd9Sstevel@tonic-gate perror("I_PUSH"); 4797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4807c478bd9Sstevel@tonic-gate "%s: I_PUSH ioctl of %s failed\n", Cmd_namep, modnamep); 4817c478bd9Sstevel@tonic-gate return (FAILURE); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate return (SUCCESS); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* 4887c478bd9Sstevel@tonic-gate * restore(npop, npush) restore original state of stream 4897c478bd9Sstevel@tonic-gate * 4907c478bd9Sstevel@tonic-gate * pops 'npop' modules, then pushes the topmost 'npush' modules from 4917c478bd9Sstevel@tonic-gate * Oldlist 4927c478bd9Sstevel@tonic-gate * 4937c478bd9Sstevel@tonic-gate */ 4947c478bd9Sstevel@tonic-gate static void 495*4b908718Smeem restore(int npop, int npush) 4967c478bd9Sstevel@tonic-gate { 497*4b908718Smeem int i; 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate if ((i = pop_modules(npop)) != npop) { 5007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 501*4b908718Smeem "%s: WARNING: could not restore state of stream\n", 502*4b908718Smeem Cmd_namep); 5037c478bd9Sstevel@tonic-gate return; 5047c478bd9Sstevel@tonic-gate } 505*4b908718Smeem 5067c478bd9Sstevel@tonic-gate if (npush >= Oldlist.sl_nmods) { /* "cannot" happen */ 5077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5087c478bd9Sstevel@tonic-gate "%s: internal logic error in restore\n", Cmd_namep); 5097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 510*4b908718Smeem "%s: WARNING: could not restore state of stream\n", 511*4b908718Smeem Cmd_namep); 5127c478bd9Sstevel@tonic-gate return; 5137c478bd9Sstevel@tonic-gate } 514*4b908718Smeem 5157c478bd9Sstevel@tonic-gate for (i = npush - 1; i >= 0; --i) { 5167c478bd9Sstevel@tonic-gate if (push_module(Oldlist.sl_modlist[i].l_name) == FAILURE) { 5177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5187c478bd9Sstevel@tonic-gate "%s: WARNING: could not restore state of stream\n", 5197c478bd9Sstevel@tonic-gate Cmd_namep); 5207c478bd9Sstevel@tonic-gate return; 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* 5267c478bd9Sstevel@tonic-gate * more_modules(listp, n) allocate space for 'n' modules in 'listp' 5277c478bd9Sstevel@tonic-gate * 5287c478bd9Sstevel@tonic-gate * returns: SUCCESS or FAILURE 5297c478bd9Sstevel@tonic-gate */ 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate static int 532*4b908718Smeem more_modules(struct str_list *listp, int n) 5337c478bd9Sstevel@tonic-gate { 534*4b908718Smeem int i; 535*4b908718Smeem struct str_mlist *modp; 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate if (n > MAXMODULES) { 5387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5397c478bd9Sstevel@tonic-gate "%s: too many modules (%d) -- max is %d\n", 5407c478bd9Sstevel@tonic-gate Cmd_namep, n, MAXMODULES); 5417c478bd9Sstevel@tonic-gate return (FAILURE); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 544*4b908718Smeem if ((modp = calloc(n, sizeof (struct str_mlist))) == NULL) { 5457c478bd9Sstevel@tonic-gate perror("calloc"); 5467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5477c478bd9Sstevel@tonic-gate "%s: failed to allocate space for module list\n", 5487c478bd9Sstevel@tonic-gate Cmd_namep); 5497c478bd9Sstevel@tonic-gate return (FAILURE); 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate for (i = 0; i < listp->sl_nmods; ++i) 5537c478bd9Sstevel@tonic-gate (void) strncpy(modp[i].l_name, listp->sl_modlist[i].l_name, 5547c478bd9Sstevel@tonic-gate FMNAMESZ); 5557c478bd9Sstevel@tonic-gate listp->sl_nmods = n; 5567c478bd9Sstevel@tonic-gate listp->sl_modlist = modp; 5577c478bd9Sstevel@tonic-gate return (SUCCESS); 5587c478bd9Sstevel@tonic-gate } 559