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 5*17e9b2b7SDhanaraj M * Common Development and Distribution License (the "License"). 6*17e9b2b7SDhanaraj M * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*17e9b2b7SDhanaraj M * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * autopush(1) is the command interface to the STREAMS autopush 327c478bd9Sstevel@tonic-gate * mechanism. The autopush command can be used to configure autopush 337c478bd9Sstevel@tonic-gate * information about a STREAMS driver, remove autopush information, 347c478bd9Sstevel@tonic-gate * and report on current configuration information. Its use is as 357c478bd9Sstevel@tonic-gate * follows: 367c478bd9Sstevel@tonic-gate * 377c478bd9Sstevel@tonic-gate * autopush -f file 387c478bd9Sstevel@tonic-gate * autopush -r -M major -m minor 397c478bd9Sstevel@tonic-gate * autopush -g -M major -m minor 407c478bd9Sstevel@tonic-gate * 417c478bd9Sstevel@tonic-gate * The -f option allows autopush information to be set from a file. The 427c478bd9Sstevel@tonic-gate * format of the file is as follows: 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * # Comment lines begin with a # in column one. 457c478bd9Sstevel@tonic-gate * # The fields are separated by white space and are: 467c478bd9Sstevel@tonic-gate * # major minor lastminor module1 module2 ... module8 477c478bd9Sstevel@tonic-gate * 487c478bd9Sstevel@tonic-gate * "lastminor" is used to configure ranges of minor devices, from "minor" 497c478bd9Sstevel@tonic-gate * to "lastminor" inclusive. It should be set to zero when not in use. 507c478bd9Sstevel@tonic-gate * The -r option allows autopush information to be removed for the given 517c478bd9Sstevel@tonic-gate * major/minor pair. The -g option allows the configuration information 527c478bd9Sstevel@tonic-gate * to be printed. The format of printing is the same as for the file. 537c478bd9Sstevel@tonic-gate */ 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* 567c478bd9Sstevel@tonic-gate * Use autopush version 1; keep before #include <sys/sad.h>. 577c478bd9Sstevel@tonic-gate * See <sys/sad.h> for details. 587c478bd9Sstevel@tonic-gate */ 597c478bd9Sstevel@tonic-gate #define AP_VERSION 1 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #include <sys/types.h> 627c478bd9Sstevel@tonic-gate #include <sys/conf.h> 637c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 647c478bd9Sstevel@tonic-gate #include <sys/sad.h> 657c478bd9Sstevel@tonic-gate #include <stdio.h> 667c478bd9Sstevel@tonic-gate #include <fcntl.h> 677c478bd9Sstevel@tonic-gate #include <errno.h> 687c478bd9Sstevel@tonic-gate #include <ctype.h> 697c478bd9Sstevel@tonic-gate #include <stdlib.h> 707c478bd9Sstevel@tonic-gate #include <unistd.h> 717c478bd9Sstevel@tonic-gate #include <string.h> 727c478bd9Sstevel@tonic-gate #include <locale.h> 737c478bd9Sstevel@tonic-gate #include <sys/stat.h> 74*17e9b2b7SDhanaraj M #include <zone.h> 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate #define OPTIONS "M:f:gm:r" /* command line options for getopt(3C) */ 777c478bd9Sstevel@tonic-gate #define COMMENT '#' 787c478bd9Sstevel@tonic-gate #define MINUS '-' 797c478bd9Sstevel@tonic-gate #define SLASH '/' 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * Output format. 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate #define OHEADER " Major Minor Lastminor\tModules\n" 857c478bd9Sstevel@tonic-gate #define OFORMAT1_ONE "%10ld %10ld - \t" 867c478bd9Sstevel@tonic-gate #define OFORMAT1_RANGE "%10ld %10ld %10ld\t" 877c478bd9Sstevel@tonic-gate #define OFORMAT1_ALL "%10ld ALL - \t" 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate #define AP_ANCHOR "[anchor]" 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate #define Openerr gettext("%s: ERROR: Could not open %s: ") 927c478bd9Sstevel@tonic-gate #define Digiterr gettext("%s: ERROR: argument to %s option must be " \ 937c478bd9Sstevel@tonic-gate "numeric\n") 947c478bd9Sstevel@tonic-gate #define Badline gettext("%s: WARNING: File %s: bad input line %d " \ 957c478bd9Sstevel@tonic-gate "ignored\n") 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate static void usage(); 987c478bd9Sstevel@tonic-gate static int rem_info(), get_info(), set_info(); 997c478bd9Sstevel@tonic-gate static int is_white_space(), parse_line(); 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate static char *Cmdp; /* command name */ 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * main(): 1057c478bd9Sstevel@tonic-gate * process command line arguments. 1067c478bd9Sstevel@tonic-gate */ 1077c478bd9Sstevel@tonic-gate int 1087c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 1097c478bd9Sstevel@tonic-gate { 1107c478bd9Sstevel@tonic-gate int c; /* character read by getopt(3C) */ 1117c478bd9Sstevel@tonic-gate char *filenamep; /* name of configuration file */ 1127c478bd9Sstevel@tonic-gate major_t major; /* major device number */ 1137c478bd9Sstevel@tonic-gate minor_t minor; /* minor device number */ 1147c478bd9Sstevel@tonic-gate char *cp; 1157c478bd9Sstevel@tonic-gate int exitcode; 1167c478bd9Sstevel@tonic-gate ushort_t minflag = 0; /* -m option used */ 1177c478bd9Sstevel@tonic-gate ushort_t majflag = 0; /* -M option used */ 1187c478bd9Sstevel@tonic-gate ushort_t fflag = 0; /* -f option used */ 1197c478bd9Sstevel@tonic-gate ushort_t rflag = 0; /* -r option used */ 1207c478bd9Sstevel@tonic-gate ushort_t gflag = 0; /* -g option used */ 1217c478bd9Sstevel@tonic-gate ushort_t errflag = 0; /* options usage error */ 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1247c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 1257c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 1267c478bd9Sstevel@tonic-gate #endif 1277c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate * Get command name. 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate Cmdp = argv[0]; 1337c478bd9Sstevel@tonic-gate for (filenamep = argv[0]; *filenamep; filenamep++) 1347c478bd9Sstevel@tonic-gate if (*filenamep == SLASH) 1357c478bd9Sstevel@tonic-gate Cmdp = filenamep + 1; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * Get options. 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate while (!errflag && ((c = getopt(argc, argv, OPTIONS)) != -1)) { 1417c478bd9Sstevel@tonic-gate switch (c) { 1427c478bd9Sstevel@tonic-gate case 'M': 1437c478bd9Sstevel@tonic-gate if (fflag|majflag) 1447c478bd9Sstevel@tonic-gate errflag++; 1457c478bd9Sstevel@tonic-gate else { 1467c478bd9Sstevel@tonic-gate majflag++; 1477c478bd9Sstevel@tonic-gate for (cp = optarg; *cp; cp++) 1487c478bd9Sstevel@tonic-gate if (!isdigit(*cp)) { 1497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1507c478bd9Sstevel@tonic-gate Digiterr, Cmdp, "-M"); 1517c478bd9Sstevel@tonic-gate exit(1); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate major = (major_t)atol(optarg); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate break; 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate case 'm': 1587c478bd9Sstevel@tonic-gate if (fflag|minflag) 1597c478bd9Sstevel@tonic-gate errflag++; 1607c478bd9Sstevel@tonic-gate else { 1617c478bd9Sstevel@tonic-gate minflag++; 1627c478bd9Sstevel@tonic-gate for (cp = optarg; *cp; cp++) 1637c478bd9Sstevel@tonic-gate if (!isdigit(*cp)) { 1647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1657c478bd9Sstevel@tonic-gate Digiterr, Cmdp, "-m"); 1667c478bd9Sstevel@tonic-gate exit(1); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate minor = (minor_t)atol(optarg); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate break; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate case 'f': 1737c478bd9Sstevel@tonic-gate if (fflag|gflag|rflag|majflag|minflag) 1747c478bd9Sstevel@tonic-gate errflag++; 1757c478bd9Sstevel@tonic-gate else { 1767c478bd9Sstevel@tonic-gate fflag++; 1777c478bd9Sstevel@tonic-gate filenamep = optarg; 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate break; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate case 'r': 1827c478bd9Sstevel@tonic-gate if (fflag|gflag|rflag) 1837c478bd9Sstevel@tonic-gate errflag++; 1847c478bd9Sstevel@tonic-gate else 1857c478bd9Sstevel@tonic-gate rflag++; 1867c478bd9Sstevel@tonic-gate break; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate case 'g': 1897c478bd9Sstevel@tonic-gate if (fflag|gflag|rflag) 1907c478bd9Sstevel@tonic-gate errflag++; 1917c478bd9Sstevel@tonic-gate else 1927c478bd9Sstevel@tonic-gate gflag++; 1937c478bd9Sstevel@tonic-gate break; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate default: 1967c478bd9Sstevel@tonic-gate errflag++; 1977c478bd9Sstevel@tonic-gate break; 1987c478bd9Sstevel@tonic-gate } /* switch */ 1997c478bd9Sstevel@tonic-gate if (errflag) { 2007c478bd9Sstevel@tonic-gate usage(); 2017c478bd9Sstevel@tonic-gate exit(1); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate } /* while */ 2047c478bd9Sstevel@tonic-gate if (((gflag || rflag) && (!majflag || !minflag)) || (optind != argc)) { 2057c478bd9Sstevel@tonic-gate usage(); 2067c478bd9Sstevel@tonic-gate exit(1); 2077c478bd9Sstevel@tonic-gate } 208*17e9b2b7SDhanaraj M 209*17e9b2b7SDhanaraj M if (getzoneid() != GLOBAL_ZONEID) { 210*17e9b2b7SDhanaraj M (void) fprintf(stderr, gettext("autopush " 211*17e9b2b7SDhanaraj M "can only be run from the global zone.\n")); 212*17e9b2b7SDhanaraj M exit(1); 213*17e9b2b7SDhanaraj M } 214*17e9b2b7SDhanaraj M 2157c478bd9Sstevel@tonic-gate if (fflag) 2167c478bd9Sstevel@tonic-gate exitcode = set_info(filenamep); 2177c478bd9Sstevel@tonic-gate else if (rflag) 2187c478bd9Sstevel@tonic-gate exitcode = rem_info(major, minor); 2197c478bd9Sstevel@tonic-gate else if (gflag) 2207c478bd9Sstevel@tonic-gate exitcode = get_info(major, minor); 2217c478bd9Sstevel@tonic-gate else { 2227c478bd9Sstevel@tonic-gate usage(); 2237c478bd9Sstevel@tonic-gate exit(1); 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate return (exitcode); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate * usage(): 2317c478bd9Sstevel@tonic-gate * print out usage statement. 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate static void 2347c478bd9Sstevel@tonic-gate usage() 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: USAGE:\n\t%s -f filename\n" 2377c478bd9Sstevel@tonic-gate "\t%s -r -M major -m minor\n" 2387c478bd9Sstevel@tonic-gate "\t%s -g -M major -m minor\n"), Cmdp, Cmdp, Cmdp, Cmdp); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * set_info(): 2437c478bd9Sstevel@tonic-gate * set autopush configuration information. 2447c478bd9Sstevel@tonic-gate * namep: autopush configuration filename 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate static int 2477c478bd9Sstevel@tonic-gate set_info(char *namep) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate int line; /* line number of file */ 2507c478bd9Sstevel@tonic-gate FILE *fp; /* file pointer of config file */ 2517c478bd9Sstevel@tonic-gate char buf[256]; /* input buffer */ 2527c478bd9Sstevel@tonic-gate struct strapush push; /* configuration information */ 2537c478bd9Sstevel@tonic-gate int sadfd; /* file descriptor to SAD driver */ 2547c478bd9Sstevel@tonic-gate int retcode = 0; /* return code */ 2557c478bd9Sstevel@tonic-gate int parsecode; /* return value from parse function */ 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate if ((sadfd = open(ADMINDEV, O_RDWR)) < 0) { 2587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Openerr, Cmdp, ADMINDEV); 2597c478bd9Sstevel@tonic-gate perror(""); 2607c478bd9Sstevel@tonic-gate return (1); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate if ((fp = fopen(namep, "r")) == NULL) { 2637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Openerr, Cmdp, namep); 2647c478bd9Sstevel@tonic-gate perror(""); 2657c478bd9Sstevel@tonic-gate return (1); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate line = 0; 2687c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof (buf), fp) != NULL) { 2697c478bd9Sstevel@tonic-gate line++; 2707c478bd9Sstevel@tonic-gate if ((buf[0] == COMMENT) || is_white_space(buf)) 2717c478bd9Sstevel@tonic-gate continue; 2727c478bd9Sstevel@tonic-gate (void) memset(&push, 0, sizeof (struct strapush)); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate parsecode = parse_line(buf, line, namep, &push); 2757c478bd9Sstevel@tonic-gate if (parsecode != 0) { 2767c478bd9Sstevel@tonic-gate retcode = parsecode; 2777c478bd9Sstevel@tonic-gate continue; 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate if (push.sap_minor == (minor_t)-1) 2817c478bd9Sstevel@tonic-gate push.sap_cmd = SAP_ALL; 2827c478bd9Sstevel@tonic-gate else if (push.sap_lastminor == 0) 2837c478bd9Sstevel@tonic-gate push.sap_cmd = SAP_ONE; 2847c478bd9Sstevel@tonic-gate else 2857c478bd9Sstevel@tonic-gate push.sap_cmd = SAP_RANGE; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate if (ioctl(sadfd, SAD_SAP, &push) < 0) { 2887c478bd9Sstevel@tonic-gate int error = errno; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate retcode = 1; 2917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2927c478bd9Sstevel@tonic-gate gettext("%s: ERROR: File %s: could not configure " 2937c478bd9Sstevel@tonic-gate "autopush for line %d\n"), Cmdp, namep, line); 2947c478bd9Sstevel@tonic-gate switch (error) { 2957c478bd9Sstevel@tonic-gate case EPERM: 2967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: " 2977c478bd9Sstevel@tonic-gate "You don't have permission to set autopush " 2987c478bd9Sstevel@tonic-gate "information\n"), Cmdp); 2997c478bd9Sstevel@tonic-gate break; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate case EINVAL: 3027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: " 3037c478bd9Sstevel@tonic-gate "Invalid major device number or invalid " 3047c478bd9Sstevel@tonic-gate "module name or too many modules\n"), Cmdp); 3057c478bd9Sstevel@tonic-gate break; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate case ENOSTR: 3087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: " 3097c478bd9Sstevel@tonic-gate "Major device is not a STREAMS " 3107c478bd9Sstevel@tonic-gate "driver\n"), Cmdp); 3117c478bd9Sstevel@tonic-gate break; 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate case EEXIST: 3147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: " 3157c478bd9Sstevel@tonic-gate "Major/minor already configured\n"), Cmdp); 3167c478bd9Sstevel@tonic-gate break; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate case ENOSR: 3197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: Ran " 3207c478bd9Sstevel@tonic-gate "out of autopush structures\n"), Cmdp); 3217c478bd9Sstevel@tonic-gate break; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate case ERANGE: 3247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: " 3257c478bd9Sstevel@tonic-gate "lastminor must be greater than minor\n"), 3267c478bd9Sstevel@tonic-gate Cmdp); 3277c478bd9Sstevel@tonic-gate break; 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate default: 3307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: "), 3317c478bd9Sstevel@tonic-gate Cmdp); 3327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", strerror(error)); 3337c478bd9Sstevel@tonic-gate break; 3347c478bd9Sstevel@tonic-gate } /* switch */ 3357c478bd9Sstevel@tonic-gate } /* if */ 3367c478bd9Sstevel@tonic-gate } /* while */ 3377c478bd9Sstevel@tonic-gate return (retcode); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate /* 3417c478bd9Sstevel@tonic-gate * rem_info(): 3427c478bd9Sstevel@tonic-gate * remove autopush configuration information. 3437c478bd9Sstevel@tonic-gate */ 3447c478bd9Sstevel@tonic-gate static int 3457c478bd9Sstevel@tonic-gate rem_info(major_t maj, minor_t min) 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate struct strapush push; /* configuration information */ 3487c478bd9Sstevel@tonic-gate int sadfd; /* file descriptor to SAD driver */ 3497c478bd9Sstevel@tonic-gate int retcode = 0; /* return code */ 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate if ((sadfd = open(ADMINDEV, O_RDWR)) < 0) { 3527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Openerr, Cmdp, ADMINDEV); 3537c478bd9Sstevel@tonic-gate perror(""); 3547c478bd9Sstevel@tonic-gate return (1); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate push.sap_cmd = SAP_CLEAR; 3577c478bd9Sstevel@tonic-gate push.sap_minor = min; 3587c478bd9Sstevel@tonic-gate push.sap_major = maj; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (ioctl(sadfd, SAD_SAP, &push) < 0) { 3617c478bd9Sstevel@tonic-gate int error = errno; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate retcode = 1; 3647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: Could not remove " 3657c478bd9Sstevel@tonic-gate "autopush information\n"), Cmdp); 3667c478bd9Sstevel@tonic-gate switch (error) { 3677c478bd9Sstevel@tonic-gate case EPERM: 3687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: You don't " 3697c478bd9Sstevel@tonic-gate "have permission to remove autopush " 3707c478bd9Sstevel@tonic-gate "information\n"), Cmdp); 3717c478bd9Sstevel@tonic-gate break; 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate case EINVAL: 3747c478bd9Sstevel@tonic-gate if ((min != 0) && (ioctl(sadfd, SAD_GAP, &push) == 0) && 3757c478bd9Sstevel@tonic-gate (push.sap_cmd == SAP_ALL)) 3767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: " 3777c478bd9Sstevel@tonic-gate "When removing an entry for ALL minors, " 3787c478bd9Sstevel@tonic-gate "minor must be set to 0\n"), Cmdp); 3797c478bd9Sstevel@tonic-gate else 3807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: " 3817c478bd9Sstevel@tonic-gate "Invalid major device number\n"), Cmdp); 3827c478bd9Sstevel@tonic-gate break; 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate case ENODEV: 3857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: Major/minor " 3867c478bd9Sstevel@tonic-gate "not configured for autopush\n"), Cmdp); 3877c478bd9Sstevel@tonic-gate break; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate case ERANGE: 3907c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: minor must " 3917c478bd9Sstevel@tonic-gate "be set to begining of range when clearing\n"), 3927c478bd9Sstevel@tonic-gate Cmdp); 3937c478bd9Sstevel@tonic-gate break; 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate default: 3967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: "), Cmdp); 3977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", strerror(error)); 3987c478bd9Sstevel@tonic-gate break; 3997c478bd9Sstevel@tonic-gate } /* switch */ 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate return (retcode); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate /* 4057c478bd9Sstevel@tonic-gate * get_info(): 4067c478bd9Sstevel@tonic-gate * get autopush configuration information. 4077c478bd9Sstevel@tonic-gate */ 4087c478bd9Sstevel@tonic-gate static int 4097c478bd9Sstevel@tonic-gate get_info(major_t maj, minor_t min) 4107c478bd9Sstevel@tonic-gate { 4117c478bd9Sstevel@tonic-gate struct strapush push; /* configuration information */ 4127c478bd9Sstevel@tonic-gate int i; /* counter */ 4137c478bd9Sstevel@tonic-gate int sadfd; /* file descriptor to SAD driver */ 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if ((sadfd = open(USERDEV, O_RDWR)) < 0) { 4167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Openerr, Cmdp, USERDEV); 4177c478bd9Sstevel@tonic-gate perror(""); 4187c478bd9Sstevel@tonic-gate return (1); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate push.sap_major = maj; 4217c478bd9Sstevel@tonic-gate push.sap_minor = min; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (ioctl(sadfd, SAD_GAP, &push) < 0) { 4247c478bd9Sstevel@tonic-gate int error = errno; 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: Could not get " 4277c478bd9Sstevel@tonic-gate "autopush information\n"), Cmdp); 4287c478bd9Sstevel@tonic-gate switch (error) { 4297c478bd9Sstevel@tonic-gate case EINVAL: 4307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: Invalid " 4317c478bd9Sstevel@tonic-gate "major device number\n"), Cmdp); 4327c478bd9Sstevel@tonic-gate break; 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate case ENOSTR: 4357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: Major " 4367c478bd9Sstevel@tonic-gate "device is not a STREAMS driver\n"), Cmdp); 4377c478bd9Sstevel@tonic-gate break; 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate case ENODEV: 4407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: Major/minor " 4417c478bd9Sstevel@tonic-gate "not configured for autopush\n"), Cmdp); 4427c478bd9Sstevel@tonic-gate break; 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate default: 4457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: "), Cmdp); 4467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", strerror(error)); 4477c478bd9Sstevel@tonic-gate break; 4487c478bd9Sstevel@tonic-gate } /* switch */ 4497c478bd9Sstevel@tonic-gate return (1); 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate (void) printf(OHEADER); 4527c478bd9Sstevel@tonic-gate switch (push.sap_cmd) { 4537c478bd9Sstevel@tonic-gate case SAP_ONE: 4547c478bd9Sstevel@tonic-gate (void) printf(OFORMAT1_ONE, push.sap_major, push.sap_minor); 4557c478bd9Sstevel@tonic-gate break; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate case SAP_RANGE: 4587c478bd9Sstevel@tonic-gate (void) printf(OFORMAT1_RANGE, push.sap_major, push.sap_minor, 4597c478bd9Sstevel@tonic-gate push.sap_lastminor); 4607c478bd9Sstevel@tonic-gate break; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate case SAP_ALL: 4637c478bd9Sstevel@tonic-gate (void) printf(OFORMAT1_ALL, push.sap_major); 4647c478bd9Sstevel@tonic-gate break; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate default: 4677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4687c478bd9Sstevel@tonic-gate gettext("%s: ERROR: Unknown configuration type\n"), Cmdp); 4697c478bd9Sstevel@tonic-gate return (1); 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate for (i = 0; i < push.sap_npush; i++) { 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate (void) printf("%s", push.sap_list[i]); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate if (push.sap_anchor == (i + 1)) 4777c478bd9Sstevel@tonic-gate (void) printf(" %s", AP_ANCHOR); 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate if (i < push.sap_npush - 1) 4807c478bd9Sstevel@tonic-gate (void) printf(" "); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate (void) printf("\n"); 4857c478bd9Sstevel@tonic-gate return (0); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate /* 4897c478bd9Sstevel@tonic-gate * is_white_space(): 4907c478bd9Sstevel@tonic-gate * Return 1 if buffer is all white space. 4917c478bd9Sstevel@tonic-gate * Return 0 otherwise. 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate static int 4947c478bd9Sstevel@tonic-gate is_white_space(char *bufp) 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate while (*bufp) { 4977c478bd9Sstevel@tonic-gate if (!isspace(*bufp)) 4987c478bd9Sstevel@tonic-gate return (0); 4997c478bd9Sstevel@tonic-gate bufp++; 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate return (1); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* 5057c478bd9Sstevel@tonic-gate * parse_line(): 5067c478bd9Sstevel@tonic-gate * Parse input line from file and report any errors found. Fill 5077c478bd9Sstevel@tonic-gate * strapush structure along the way. Returns 1 if the line has 5087c478bd9Sstevel@tonic-gate * errors and 0 if the line is well-formed. Another hidden 5097c478bd9Sstevel@tonic-gate * dependency on MAXAPUSH. `linep' is the input buffer, `lineno' 5107c478bd9Sstevel@tonic-gate * is the current line number, and `namep' is the filename. 5117c478bd9Sstevel@tonic-gate */ 5127c478bd9Sstevel@tonic-gate static int 5137c478bd9Sstevel@tonic-gate parse_line(char *linep, int lineno, char *namep, struct strapush *pushp) 5147c478bd9Sstevel@tonic-gate { 5157c478bd9Sstevel@tonic-gate char *wp; /* word pointer */ 5167c478bd9Sstevel@tonic-gate char *cp; /* character pointer */ 5177c478bd9Sstevel@tonic-gate int midx; /* module index */ 5187c478bd9Sstevel@tonic-gate int npush; /* number of modules to push */ 5197c478bd9Sstevel@tonic-gate char c; 5207c478bd9Sstevel@tonic-gate major_t major_num; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate pushp->sap_anchor = 0; /* by default, no anchor */ 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate /* 5257c478bd9Sstevel@tonic-gate * Find the major device number. 5267c478bd9Sstevel@tonic-gate */ 5277c478bd9Sstevel@tonic-gate for (wp = linep; isspace(*wp); wp++) 5287c478bd9Sstevel@tonic-gate ; 5297c478bd9Sstevel@tonic-gate for (cp = wp; !isspace(*cp); cp++) 5307c478bd9Sstevel@tonic-gate ; 5317c478bd9Sstevel@tonic-gate if (!isspace(*cp)) { 5327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Badline, Cmdp, namep, lineno); 5337c478bd9Sstevel@tonic-gate return (1); 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate c = *cp; 5367c478bd9Sstevel@tonic-gate *cp = '\0'; 5377c478bd9Sstevel@tonic-gate if (modctl(MODGETMAJBIND, wp, strlen(wp) + 1, &major_num) != 0) { 5387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Badline, Cmdp, namep, lineno); 5397c478bd9Sstevel@tonic-gate return (1); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate *cp = c; 5427c478bd9Sstevel@tonic-gate pushp->sap_major = major_num; 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* 5457c478bd9Sstevel@tonic-gate * Find the minor device number. Must handle negative values here. 5467c478bd9Sstevel@tonic-gate */ 5477c478bd9Sstevel@tonic-gate for (wp = cp; isspace(*wp); wp++) 5487c478bd9Sstevel@tonic-gate ; 5497c478bd9Sstevel@tonic-gate for (cp = wp; (isdigit(*cp) || (*cp == MINUS)); cp++) 5507c478bd9Sstevel@tonic-gate ; 5517c478bd9Sstevel@tonic-gate if (!isspace(*cp)) { 5527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Badline, Cmdp, namep, lineno); 5537c478bd9Sstevel@tonic-gate return (1); 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate pushp->sap_minor = (minor_t)atol(wp); 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate /* 5587c478bd9Sstevel@tonic-gate * Find the lastminor. 5597c478bd9Sstevel@tonic-gate */ 5607c478bd9Sstevel@tonic-gate for (wp = cp; isspace(*wp); wp++) 5617c478bd9Sstevel@tonic-gate ; 5627c478bd9Sstevel@tonic-gate for (cp = wp; isdigit(*cp); cp++) 5637c478bd9Sstevel@tonic-gate ; 5647c478bd9Sstevel@tonic-gate if (!isspace(*cp)) { 5657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Badline, Cmdp, namep, lineno); 5667c478bd9Sstevel@tonic-gate return (1); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate pushp->sap_lastminor = (minor_t)atol(wp); 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate /* 5717c478bd9Sstevel@tonic-gate * Read the list of module names. 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate npush = 0; 5747c478bd9Sstevel@tonic-gate while ((npush < MAXAPUSH) && (*cp)) { 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate while (isspace(*cp)) 5777c478bd9Sstevel@tonic-gate cp++; 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate if (strncasecmp(cp, AP_ANCHOR, sizeof (AP_ANCHOR) - 1) == 0) { 5807c478bd9Sstevel@tonic-gate if (pushp->sap_anchor != 0) { 5817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5827c478bd9Sstevel@tonic-gate gettext("%s: ERROR: File %s: more than " 5837c478bd9Sstevel@tonic-gate "one anchor in line, line %d ignored\n"), 5847c478bd9Sstevel@tonic-gate Cmdp, namep, lineno); 5857c478bd9Sstevel@tonic-gate return (1); 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate if (npush == 0) 5887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5897c478bd9Sstevel@tonic-gate gettext("%s: WARNING: File %s: anchor at " 5907c478bd9Sstevel@tonic-gate "beginning of stream on line %d ignored\n"), 5917c478bd9Sstevel@tonic-gate Cmdp, namep, lineno); 5927c478bd9Sstevel@tonic-gate pushp->sap_anchor = npush; 5937c478bd9Sstevel@tonic-gate cp += sizeof (AP_ANCHOR) - 1; 5947c478bd9Sstevel@tonic-gate continue; 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate for (midx = 0; !isspace(*cp) && *cp; midx++) { 5987c478bd9Sstevel@tonic-gate if (midx == FMNAMESZ) { 5997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: ERROR: " 6007c478bd9Sstevel@tonic-gate "File %s: module name too long, line %d " 6017c478bd9Sstevel@tonic-gate "ignored\n"), Cmdp, namep, lineno); 6027c478bd9Sstevel@tonic-gate return (1); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate pushp->sap_list[npush][midx] = *cp++; 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate if (midx > 0) { 6087c478bd9Sstevel@tonic-gate pushp->sap_list[npush][midx] = '\0'; 6097c478bd9Sstevel@tonic-gate npush++; 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate pushp->sap_npush = npush; 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate /* 6157c478bd9Sstevel@tonic-gate * We have everything we want from the line. 6167c478bd9Sstevel@tonic-gate * Now make sure there is no extra garbage on the line. 6177c478bd9Sstevel@tonic-gate */ 6187c478bd9Sstevel@tonic-gate while (isspace(*cp)) 6197c478bd9Sstevel@tonic-gate cp++; 6207c478bd9Sstevel@tonic-gate if (*cp) { 6217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6227c478bd9Sstevel@tonic-gate gettext("%s: ERROR: File %s: too many modules, line %d " 6237c478bd9Sstevel@tonic-gate "ignored\n"), Cmdp, namep, lineno); 6247c478bd9Sstevel@tonic-gate return (1); 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate return (0); 6277c478bd9Sstevel@tonic-gate } 628