int main(int argc, char **argv) { char *modp; /* ptr to module name */ int i; /* loop var & junk (what else?) */ boolean_t mod_present; /* B_TRUE if -m module */ boolean_t topmost; /* B_TRUE if -t */ struct str_mlist mlist[NMODULES]; /* modlist for strlist */ struct str_list strlist; /* mods on stream */ /* * init */ Cmd_namep = argv[0]; mod_present = topmost = B_FALSE; strlist.sl_nmods = NMODULES; strlist.sl_modlist = mlist; /* * parse args */ if (argc > 1) { while ((i = getopt(argc, argv, OPTLIST)) != -1) { switch (i) { case 'm': /* module present ? */ modp = optarg; mod_present = B_TRUE; break; case 't': /* list topmost */ topmost = B_TRUE; break; default: (void) fprintf(stderr, USAGE, Cmd_namep); return (ERR_USAGE); } } if (optind < argc) { (void) fprintf(stderr, USAGE, Cmd_namep); return (ERR_USAGE); } } if (topmost && mod_present) { (void) fprintf(stderr, "%s: [-t] and [-m] options cannot be used together\n", Cmd_namep); (void) fprintf(stderr, USAGE, Cmd_namep); return (ERR_USAGE); } /* * get number of modules on stream * allocate more room if needed */ if ((i = ioctl(STDIN_FILENO, I_LIST, NULL)) < 0) { perror("I_LIST"); (void) fprintf(stderr, "%s: I_LIST ioctl failed\n", Cmd_namep); return (ERR_STDIN); } if (i > strlist.sl_nmods) if (more_modules(&strlist, i) != SUCCESS) return (ERR_MEM); /* * get list of modules on stream */ strlist.sl_nmods = i; if (ioctl(STDIN_FILENO, I_LIST, &strlist) < 0) { perror("I_LIST"); (void) fprintf(stderr, "%s: I_LIST ioctl failed\n", Cmd_namep); return (ERR_STDIN); } /* * list topmost module */ if (topmost) { if (strlist.sl_nmods >= 2) { (void) puts(strlist.sl_modlist[0].l_name); return (SUCCESS); } return (ERR_MODULE); } /* * check if module is present */ if (mod_present) { for (i = 0; i < strlist.sl_nmods; i++) { if (strncmp(modp, strlist.sl_modlist[i].l_name, FMNAMESZ) == 0) { (void) puts("yes"); return (SUCCESS); } } (void) puts("no"); return (ERR_MODULE); } /* * print names of all modules and topmost driver on stream */ for (i = 0; i < strlist.sl_nmods; i++) (void) puts(strlist.sl_modlist[i].l_name); return (SUCCESS); }
int main(int argc, char **argv) { char buf[BUFSIZ]; /* input buffer */ char *file_namep; /* file from -f opt */ char *modnamep; /* mods from -h or -u opt */ char *modp; /* for walking thru modnamep */ FILE *fp; /* file pointer for -f file */ int i; /* loop index and junk var */ int j; /* loop index and junk var */ int euid; /* effective uid */ short error; /* TRUE if usage error */ short fromfile; /* TRUE if -f file */ short is_a_tty; /* TRUE if TCGETA succeeds */ short pop; /* TRUE if -p */ short popall; /* TRUE if -p -a */ short popupto; /* TRUE if -p -u module */ short push; /* TRUE if -h mod1[,mod2 ...] */ struct str_mlist newmods[NMODULES]; /* mod list for new list */ struct stat stats; /* stream stats */ struct str_list newlist; /* modules to be pushed */ struct termio termio; /* save state of tty */ /* * init */ Cmd_namep = argv[0]; error = fromfile = is_a_tty = pop = popall = popupto = push = FALSE; Oldlist.sl_modlist = Oldmods; Oldlist.sl_nmods = NMODULES; newlist.sl_modlist = newmods; newlist.sl_nmods = NMODULES; /* * only owner and root can change stream configuration */ if ((euid = geteuid()) != 0) { if (fstat(0, &stats) < 0) { perror("fstat"); (void) fprintf(stderr, "%s: fstat of stdin failed\n", Cmd_namep); return (ERR_STDIN); } if (euid != stats.st_uid) { (void) fprintf(stderr, "%s: not owner of stdin\n", Cmd_namep); return (ERR_PERM); } } /* * parse args */ if (argc == 1) { (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); return (ERR_USAGE); } while (!error && (i = getopt(argc, argv, OPTLIST)) != -1) { switch (i) { case 'a': /* pop All */ if (fromfile || popupto || push) error = TRUE; else popall = TRUE; break; case 'f': /* read from File */ if (pop || push) error = TRUE; else { fromfile = TRUE; file_namep = optarg; } break; case 'h': /* pusH */ if (fromfile || pop) error = TRUE; else { push = TRUE; modnamep = optarg; } break; case 'p': /* poP */ if (fromfile || push) error = TRUE; else pop = TRUE; break; case 'u': /* pop Upto */ if (fromfile || popall || push) error = TRUE; else { popupto = TRUE; modnamep = optarg; } break; default: (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); return (ERR_USAGE); /*NOTREACHED*/ } } if (error || optind < argc) { (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); return (ERR_USAGE); } if (!pop && (popall || popupto)) { (void) fprintf(stderr, "%s: -p option must be used with -a or -u to pop modules\n", Cmd_namep); (void) fprintf(stderr, USAGE, Cmd_namep, Cmd_namep, Cmd_namep); return (ERR_USAGE); } /* * Save state so can restore if something goes wrong * (If are only going to push modules, don't need to * save original module list for restore.) */ if (fromfile || pop) { /* * get number of modules on stream * allocate more room if needed */ if ((i = ioctl(STDIN, I_LIST, NULL)) < 0) { perror("I_LIST"); (void) fprintf(stderr, "%s: I_LIST ioctl failed\n", Cmd_namep); return (ERR_STDIN); } if (i > Oldlist.sl_nmods && more_modules(&Oldlist, i) != SUCCESS) return (ERR_MEM); /* * get list of modules on stream */ Oldlist.sl_nmods = i; if (ioctl(STDIN, I_LIST, &Oldlist) < 0) { perror("I_LIST"); (void) fprintf(stderr, "%s: I_LIST ioctl failed\n", Cmd_namep); return (ERR_STDIN); } /* * The following attempts to avoid leaving a * terminal line that does not respond to anything * if the strchg -h or -f options failed due to * specifying invalid module names for pushing */ if (ioctl(STDIN, TCGETA, &termio) >= 0) is_a_tty = TRUE; } /* * push modules on stream */ if (push) { /* * pull mod names out of comma-separated list */ for (i = 0, modp = strtok(modnamep, ","); modp != NULL; ++i, modp = strtok(NULL, ",")) { if (push_module(modp) == FAILURE) { /* pop the 'i' modules we just added */ restore(i, 0); return (ERR_STDIN); } } return (SUCCESS); } /* * read configuration from a file */ if (fromfile) { if ((fp = fopen(file_namep, "r")) == NULL) { perror("fopen"); (void) fprintf(stderr, "%s: could not open file '%s'\n", Cmd_namep, file_namep); return (ERR_OPEN); } /* * read file and construct a new strlist */ i = 0; while (fgets(buf, BUFSIZ, fp) != NULL) { if (buf[0] == '#') continue; /* skip comments */ /* * skip trailing newline, trailing and leading * whitespace */ if ((modp = strtok(buf, " \t\n")) == NULL) continue; /* blank line */ (void) strncpy(newlist.sl_modlist[i].l_name, modp, FMNAMESZ); ++i; if ((modp = strtok(NULL, " \t\n")) != NULL) { /* * bad format * should only be one name per line */ (void) fprintf(stderr, "%s: error on line %d in file %s: " "multiple module names??\n", Cmd_namep, i, file_namep); return (ERR_MODULE); } if (i > newlist.sl_nmods) if (more_modules(&newlist, i) != SUCCESS) return (ERR_MEM); } newlist.sl_nmods = i; /* * If an empty file, exit silently */ if (i == 0) return (SUCCESS); /* * Pop all modules currently on the stream. */ if ((i = pop_modules(Oldlist.sl_nmods - 1)) != (Oldlist.sl_nmods - 1)) { /* put back whatever we've popped */ restore(0, i); return (ERR_STDIN); } /* * Push new modules */ for (i = newlist.sl_nmods - 1; i >= 0; --i) { if (push_module(newlist.sl_modlist[i].l_name) == FAILURE) { /* * pop whatever new modules we've pushed * then push old module list back on */ restore((newlist.sl_nmods - 1 - i), (Oldlist.sl_nmods - 1)); /* * If the stream is a tty line, at least try * to set the state to what it was before. */ if (is_a_tty && ioctl(STDIN, TCSETA, &termio) < 0) { perror("TCSETA"); (void) fprintf(stderr, "%s: WARNING: Could not restore " "the states of the terminal line " "discipline\n", Cmd_namep); } return (ERR_STDIN); } } return (SUCCESS); } /* end if-fromfile */ /* * pop all modules (except driver) */ if (popall) { if (Oldlist.sl_nmods > 1) { if ((i = pop_modules(Oldlist.sl_nmods - 1)) != (Oldlist.sl_nmods - 1)) { restore(0, i); return (ERR_STDIN); } } return (SUCCESS); } /* * pop up to (but not including) a module */ if (popupto) { /* * check that the module is in fact on the stream */ for (i = 0; i < Oldlist.sl_nmods; ++i) if (strncmp(Oldlist.sl_modlist[i].l_name, modnamep, FMNAMESZ) == 0) break; if (i == Oldlist.sl_nmods) { /* no match found */ (void) fprintf(stderr, "%s: %s not found on stream\n", Cmd_namep, modnamep); return (ERR_MODULE); } if ((j = pop_modules(i)) != i) { /* put back whatever we've popped */ restore(0, j); return (ERR_STDIN); } return (SUCCESS); } /* * pop the topmost module */ if (pop) { if (Oldlist.sl_nmods > 1) if (pop_modules(1) != 1) /* no need to restore */ return (ERR_STDIN); return (SUCCESS); } return (SUCCESS); }