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 */ 227c478bd9Sstevel@tonic-gate /* 23*113f4232Sakaplan * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <sys/param.h> 357c478bd9Sstevel@tonic-gate #include <stdio.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <stdlib.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <fmtmsg.h> 407c478bd9Sstevel@tonic-gate #include <devmgmt.h> 417c478bd9Sstevel@tonic-gate #include <devtab.h> 427c478bd9Sstevel@tonic-gate #include <values.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* 467c478bd9Sstevel@tonic-gate * Local definitions 477c478bd9Sstevel@tonic-gate * TRUE Boolean TRUE value 487c478bd9Sstevel@tonic-gate * FALSE Boolean FALSE value 497c478bd9Sstevel@tonic-gate * TOKDELIMS Char string of delimiters for lists 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #ifndef TRUE 537c478bd9Sstevel@tonic-gate #define TRUE ('t') 547c478bd9Sstevel@tonic-gate #endif 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #ifndef FALSE 577c478bd9Sstevel@tonic-gate #define FALSE 0 587c478bd9Sstevel@tonic-gate #endif 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #define TOKDELIMS ", \t\n" 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate /* 647c478bd9Sstevel@tonic-gate * Exit codes: 657c478bd9Sstevel@tonic-gate * EX_OK Exit code for all went well 667c478bd9Sstevel@tonic-gate * EX_ERROR Exit code for something failed 677c478bd9Sstevel@tonic-gate * EX_TABLES A table couldn't be accessed 687c478bd9Sstevel@tonic-gate * EX_NOALLOC Exit code for allocation failed 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate #define EX_OK 0 727c478bd9Sstevel@tonic-gate #define EX_ERROR 1 737c478bd9Sstevel@tonic-gate #define EX_TABLES 2 747c478bd9Sstevel@tonic-gate #define EX_NOALLOC 3 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* 777c478bd9Sstevel@tonic-gate * Messages: 787c478bd9Sstevel@tonic-gate * M_USAGE Usage error 797c478bd9Sstevel@tonic-gate * M_INVKEY Invalid key specified 807c478bd9Sstevel@tonic-gate * M_ERROR Some strange error 817c478bd9Sstevel@tonic-gate * M_UNABLE A list of devices is unavailable 827c478bd9Sstevel@tonic-gate * M_DEVTAB Can't access device table (for reading) 837c478bd9Sstevel@tonic-gate * M_RSVTAB Can't access device reservation table (for r/w) 847c478bd9Sstevel@tonic-gate * M_NODEV A list of devices is invalid 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #define M_USAGE "usage: devreserv [key [devicelist [...]]]" 887c478bd9Sstevel@tonic-gate #define M_INVKEY "Invalid key: %s" 897c478bd9Sstevel@tonic-gate #define M_ERROR "Internal error, errno=%d" 907c478bd9Sstevel@tonic-gate #define M_UNABLE "Cannot reserve devices" 917c478bd9Sstevel@tonic-gate #define M_DEVTAB "Cannot open the device table: %s" 927c478bd9Sstevel@tonic-gate #define M_RSVTAB "Cannot open the device-reservation table: %s" 937c478bd9Sstevel@tonic-gate #define M_NODEV M_UNABLE 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate /* 977c478bd9Sstevel@tonic-gate * Local functions and static data 987c478bd9Sstevel@tonic-gate * 997c478bd9Sstevel@tonic-gate * buildreqlist() Builds the list of requested devices for devreserv() 1007c478bd9Sstevel@tonic-gate * freereqlist() Free space allocated to the list of requested devices 1017c478bd9Sstevel@tonic-gate * ndevsin() Get number of elements in a list 1027c478bd9Sstevel@tonic-gate * stdmsg(r,l,s,m) Standard message generation 1037c478bd9Sstevel@tonic-gate * r Recoverability flag 1047c478bd9Sstevel@tonic-gate * l Label 1057c478bd9Sstevel@tonic-gate * s Severity 1067c478bd9Sstevel@tonic-gate * m Message 1077c478bd9Sstevel@tonic-gate * 1087c478bd9Sstevel@tonic-gate * lbl Buffer for the label-component of a message 1097c478bd9Sstevel@tonic-gate * txt Buffer for the text-component of a message 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate static char ***buildreqlist(); 1137c478bd9Sstevel@tonic-gate static void freereqlist(); 1147c478bd9Sstevel@tonic-gate static int ndevsin(); 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate #define stdmsg(r,l,s,m) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,m,MM_NULLACT,MM_NULLTAG) 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate static char lbl[MM_MXLABELLN+1]; 1197c478bd9Sstevel@tonic-gate static char txt[MM_MXTXTLN+1]; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* 1227c478bd9Sstevel@tonic-gate * devreserv [key [devlist [devlist [...]]]] 1237c478bd9Sstevel@tonic-gate * 1247c478bd9Sstevel@tonic-gate * This command reserves sets of devices known to the OA&M device 1257c478bd9Sstevel@tonic-gate * management system. It reserves a device from each of the device 1267c478bd9Sstevel@tonic-gate * lists presented to it, reserving them on the key (<key>). If no 1277c478bd9Sstevel@tonic-gate * device-lists are provided, the command lists those devices reserved 1287c478bd9Sstevel@tonic-gate * on the given key (<key>). If no key (<key>) is provided, the 1297c478bd9Sstevel@tonic-gate * command lists all devices currently reserved. 1307c478bd9Sstevel@tonic-gate * 1317c478bd9Sstevel@tonic-gate * Options: None 1327c478bd9Sstevel@tonic-gate * 1337c478bd9Sstevel@tonic-gate * Arguments: 1347c478bd9Sstevel@tonic-gate * key Key to lock the devices on 1357c478bd9Sstevel@tonic-gate * devlist A comma-, space-, or tab-list containing devices 1367c478bd9Sstevel@tonic-gate * (pathnames or aliases). For typical shells, space- 1377c478bd9Sstevel@tonic-gate * and tab-lists should be quoted or the separator should 1387c478bd9Sstevel@tonic-gate * be somehow escaped. 1397c478bd9Sstevel@tonic-gate * 1407c478bd9Sstevel@tonic-gate * Command Values: 1417c478bd9Sstevel@tonic-gate * EX_OK 0 Device(s) successfully allocated 1427c478bd9Sstevel@tonic-gate * EX_ERROR 1 A syntax or other error occurred 1437c478bd9Sstevel@tonic-gate * EX_TABLES 2 Either the device-table or the device- 1447c478bd9Sstevel@tonic-gate * reservation table couldn't be opened as needed 1457c478bd9Sstevel@tonic-gate * EX_NOALLOC 3 The device-reservation request couldn't be 1467c478bd9Sstevel@tonic-gate * fulfilled. 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate 149*113f4232Sakaplan int 150*113f4232Sakaplan main(int argc, char *argv[]) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* Automatics */ 1547c478bd9Sstevel@tonic-gate char ***reqlist; /* * to list of lists */ 1557c478bd9Sstevel@tonic-gate char **argp; /* Ptr to current argument */ 1567c478bd9Sstevel@tonic-gate char **alloclist; /* List of allocated devices */ 1577c478bd9Sstevel@tonic-gate char **pp; /* Temp ptr to char ptrs */ 1587c478bd9Sstevel@tonic-gate struct reservdev **rsvd; /* Ptr to list of rsvd devs */ 1597c478bd9Sstevel@tonic-gate struct reservdev **plk; /* Running ptr to locks */ 1607c478bd9Sstevel@tonic-gate char *p; /* Temp char ptr */ 1617c478bd9Sstevel@tonic-gate char *devtab; /* Device table pathname */ 1627c478bd9Sstevel@tonic-gate char *rsvtab; /* Dev-rsv tbl pathname */ 1637c478bd9Sstevel@tonic-gate int argcount; /* Number of args on cmd */ 1647c478bd9Sstevel@tonic-gate long lkey; /* Key for locking (long) */ 1657c478bd9Sstevel@tonic-gate int key; /* Key for locking */ 1667c478bd9Sstevel@tonic-gate int exitcode; /* Value to return */ 1677c478bd9Sstevel@tonic-gate int sev; /* Message severity */ 1687c478bd9Sstevel@tonic-gate int syntaxerr; /* Flag, TRUE if syntax error */ 1697c478bd9Sstevel@tonic-gate int c; /* Option character */ 1707c478bd9Sstevel@tonic-gate int i; /* Temp counter */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* 1747c478bd9Sstevel@tonic-gate * Initializations 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* Build a message label */ 1787c478bd9Sstevel@tonic-gate if (p = strrchr(argv[0], '/')) p++; 1797c478bd9Sstevel@tonic-gate else p = argv[0]; 1807c478bd9Sstevel@tonic-gate (void) strlcat(strcpy(lbl, "UX:"), p, sizeof(lbl)); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* 1847c478bd9Sstevel@tonic-gate * Allow only the text component of messages to be written 1857c478bd9Sstevel@tonic-gate * (this will probably go away in SVR4.1) 1867c478bd9Sstevel@tonic-gate */ 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate (void) putenv("MSGVERB=text"); 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * Parse the options from the command line 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate opterr = 0; 1967c478bd9Sstevel@tonic-gate syntaxerr = FALSE; 1977c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "")) != EOF) switch(c) { 1987c478bd9Sstevel@tonic-gate default: 1997c478bd9Sstevel@tonic-gate syntaxerr = FALSE; 2007c478bd9Sstevel@tonic-gate break; 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* If there's (an obvious) syntax error, write a message and quit */ 2047c478bd9Sstevel@tonic-gate if (syntaxerr) { 2057c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE); 2067c478bd9Sstevel@tonic-gate exit(EX_ERROR); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate /* Argument initializations */ 2107c478bd9Sstevel@tonic-gate argcount = argc - optind; 2117c478bd9Sstevel@tonic-gate argp = &argv[optind]; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * devreserv 2167c478bd9Sstevel@tonic-gate * 2177c478bd9Sstevel@tonic-gate * If euid == 0, write a list of all currently allocated devices. 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate if (argcount == 0) { 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* Get the list of reserved devices */ 2237c478bd9Sstevel@tonic-gate if (rsvd = reservdev()) { 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* Write the list of reserved devices with the key 2267c478bd9Sstevel@tonic-gate * that the device was locked on. The key should go 2277c478bd9Sstevel@tonic-gate * in column 16, but separate it from the alias with at 2287c478bd9Sstevel@tonic-gate * least one space */ 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate exitcode = EX_OK; 2317c478bd9Sstevel@tonic-gate for (plk = rsvd ; *plk ; plk++) { 2327c478bd9Sstevel@tonic-gate if ((i = fputs((*plk)->devname, stdout)) >= 0) do 2337c478bd9Sstevel@tonic-gate (void) fputc(' ', stdout); 2347c478bd9Sstevel@tonic-gate while (++i < 16); 2357c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%ld\n", (*plk)->key); 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate } else { 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* Problems getting the list of reserved devices */ 2417c478bd9Sstevel@tonic-gate if (((errno == EINVAL) || (errno == EACCES)) && (rsvtab = _rsvtabpath())) { 2427c478bd9Sstevel@tonic-gate (void) snprintf(txt, sizeof(txt), M_RSVTAB, rsvtab); 2437c478bd9Sstevel@tonic-gate exitcode = EX_TABLES; 2447c478bd9Sstevel@tonic-gate sev = MM_ERROR; 2457c478bd9Sstevel@tonic-gate } else { 2467c478bd9Sstevel@tonic-gate (void) sprintf(txt, M_ERROR, errno); 2477c478bd9Sstevel@tonic-gate exitcode = EX_ERROR; 2487c478bd9Sstevel@tonic-gate sev = MM_HALT; 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, sev, txt); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* Finished */ 2547c478bd9Sstevel@tonic-gate exit(exitcode); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 2597c478bd9Sstevel@tonic-gate * devreserv key 2607c478bd9Sstevel@tonic-gate * 2617c478bd9Sstevel@tonic-gate * Generate a list of the devices allocated on a specific key. 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (argcount == 1) { 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate /* Extract the key from the command */ 2677c478bd9Sstevel@tonic-gate lkey = strtol(*argp, &p, 10); 2687c478bd9Sstevel@tonic-gate if (*p || (lkey <= 0) || (lkey > MAXINT)) { 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* <key> argument invalid */ 2717c478bd9Sstevel@tonic-gate (void) snprintf(txt, sizeof(txt), M_INVKEY, *argp); 2727c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, txt); 2737c478bd9Sstevel@tonic-gate exitcode = EX_ERROR; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate } else { 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate key = (int) lkey; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* Get the list of reserved devices ... */ 2807c478bd9Sstevel@tonic-gate if (rsvd = reservdev()) { 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate /* For each reserved device, write the alias to stdout */ 2837c478bd9Sstevel@tonic-gate exitcode = EX_OK; 2847c478bd9Sstevel@tonic-gate for (plk = rsvd ; *plk ; plk++) { 2857c478bd9Sstevel@tonic-gate if ((*plk)->key == key) (void) puts((*plk)->devname); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate } else { 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate /* Problems getting the list of reserved devices */ 2917c478bd9Sstevel@tonic-gate if (((errno == EINVAL) || (errno == EACCES)) && (rsvtab = _rsvtabpath())) { 2927c478bd9Sstevel@tonic-gate (void) snprintf(txt, sizeof(txt), M_RSVTAB, rsvtab); 2937c478bd9Sstevel@tonic-gate exitcode = EX_TABLES; 2947c478bd9Sstevel@tonic-gate sev = MM_ERROR; 2957c478bd9Sstevel@tonic-gate } else { 2967c478bd9Sstevel@tonic-gate (void) sprintf(txt, M_ERROR, errno); 2977c478bd9Sstevel@tonic-gate exitcode = EX_ERROR; 2987c478bd9Sstevel@tonic-gate sev = MM_HALT; 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, sev, txt); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* Finished */ 3057c478bd9Sstevel@tonic-gate exit(exitcode); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * devreserv key devlist [...] 3117c478bd9Sstevel@tonic-gate * 3127c478bd9Sstevel@tonic-gate * Reserve specific devices 3137c478bd9Sstevel@tonic-gate */ 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* Open the device file (if there's one to be opened) */ 3167c478bd9Sstevel@tonic-gate if (!_opendevtab("r")) { 3177c478bd9Sstevel@tonic-gate if (devtab = _devtabpath()) { 3187c478bd9Sstevel@tonic-gate (void) snprintf(txt, sizeof(txt), M_DEVTAB, devtab); 3197c478bd9Sstevel@tonic-gate exitcode = EX_TABLES; 3207c478bd9Sstevel@tonic-gate sev = MM_ERROR; 3217c478bd9Sstevel@tonic-gate } else { 3227c478bd9Sstevel@tonic-gate (void) sprintf(txt, M_ERROR, errno); 3237c478bd9Sstevel@tonic-gate exitcode = EX_ERROR; 3247c478bd9Sstevel@tonic-gate sev = MM_HALT; 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, sev, txt); 3277c478bd9Sstevel@tonic-gate exit(exitcode); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* Extract the key from the command */ 3317c478bd9Sstevel@tonic-gate lkey = strtol(*argp, &p, 10); 3327c478bd9Sstevel@tonic-gate if (*p || (lkey <= 0) || (lkey > MAXINT)) { 3337c478bd9Sstevel@tonic-gate (void) snprintf(txt, sizeof(txt), M_INVKEY, *argp); 3347c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, txt); 3357c478bd9Sstevel@tonic-gate exit(EX_ERROR); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate key = (int) lkey; 3397c478bd9Sstevel@tonic-gate argp++; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate /* Build the device request list from the command arguments */ 3427c478bd9Sstevel@tonic-gate if (reqlist = buildreqlist(argp)) { 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* Attempt to allocate the devices */ 3457c478bd9Sstevel@tonic-gate if (alloclist = devreserv(key, reqlist)) { 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * For each allocated device, write the alias to stdout 3497c478bd9Sstevel@tonic-gate * and free the space allocated for the string. 3507c478bd9Sstevel@tonic-gate */ 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate for (pp = alloclist; *pp; pp++) { 3537c478bd9Sstevel@tonic-gate (void) puts(*pp); 3547c478bd9Sstevel@tonic-gate free(*pp); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate /* Free the list of allocated devices */ 3587c478bd9Sstevel@tonic-gate free((char *) alloclist); 3597c478bd9Sstevel@tonic-gate exitcode = EX_OK; 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate else { 3627c478bd9Sstevel@tonic-gate /* Device allocation failed */ 3637c478bd9Sstevel@tonic-gate if (errno == EAGAIN) { 3647c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, M_UNABLE); 3657c478bd9Sstevel@tonic-gate exitcode = EX_NOALLOC; 3667c478bd9Sstevel@tonic-gate } else if (errno == ENODEV) { 3677c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, M_NODEV); 3687c478bd9Sstevel@tonic-gate exitcode = EX_NOALLOC; 3697c478bd9Sstevel@tonic-gate } else { 3707c478bd9Sstevel@tonic-gate (void) sprintf(txt, M_ERROR, errno); 3717c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_HALT, txt); 3727c478bd9Sstevel@tonic-gate exitcode = EX_ERROR; 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate freereqlist(reqlist); 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* Exit with the appropriate code */ 3807c478bd9Sstevel@tonic-gate return(exitcode); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * char ***buildreqlist(args) 3857c478bd9Sstevel@tonic-gate * char **args 3867c478bd9Sstevel@tonic-gate * 3877c478bd9Sstevel@tonic-gate * Build the list of lists of devices to request, as described by the 3887c478bd9Sstevel@tonic-gate * arguments on the command line. 3897c478bd9Sstevel@tonic-gate * 3907c478bd9Sstevel@tonic-gate * Arguments: 3917c478bd9Sstevel@tonic-gate * char **args The address of the first argument of the list of 3927c478bd9Sstevel@tonic-gate * lists of devices to allocate. (This list is 3937c478bd9Sstevel@tonic-gate * terminated with a (char *) NULL.) 3947c478bd9Sstevel@tonic-gate * 3957c478bd9Sstevel@tonic-gate * Returns: char *** 3967c478bd9Sstevel@tonic-gate * A pointer to a list containing addresses of lists of pointers to 3977c478bd9Sstevel@tonic-gate * character-strings, as expected by "devreserv()" 3987c478bd9Sstevel@tonic-gate * 3997c478bd9Sstevel@tonic-gate * Notes: 4007c478bd9Sstevel@tonic-gate * - Assuming that strtok() won't return "". If it does, the 4017c478bd9Sstevel@tonic-gate * parsing algorithm needs to be enhanced a bit to eliminate 4027c478bd9Sstevel@tonic-gate * these cases. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate static char *** 4067c478bd9Sstevel@tonic-gate buildreqlist(args) 4077c478bd9Sstevel@tonic-gate char **args; 4087c478bd9Sstevel@tonic-gate { 4097c478bd9Sstevel@tonic-gate /* Local automatic data */ 4107c478bd9Sstevel@tonic-gate char ***addrlist; /* Addr of space for ptrs to lists */ 4117c478bd9Sstevel@tonic-gate char ***ppp; /* Pointer to pointers to pointers */ 4127c478bd9Sstevel@tonic-gate char **pp; /* Pointer to pointers */ 4137c478bd9Sstevel@tonic-gate char **qq; /* Pointer to pointers */ 4147c478bd9Sstevel@tonic-gate int noerror; /* FLAG, TRUE if all's well */ 4157c478bd9Sstevel@tonic-gate int i; /* Counter */ 4167c478bd9Sstevel@tonic-gate int n; /* Another counter */ 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* Count the number of lists we have to work with */ 4207c478bd9Sstevel@tonic-gate i = 1; 4217c478bd9Sstevel@tonic-gate for (pp = args ; *pp ; pp++) i++; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /* If we can allocate space for the list of lists ... */ 4257c478bd9Sstevel@tonic-gate if (addrlist = (char ***) malloc(i*sizeof(char **))) { 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate /* Parse each list, putting that list in the list of lists */ 4287c478bd9Sstevel@tonic-gate ppp = addrlist; 4297c478bd9Sstevel@tonic-gate noerror = TRUE; 4307c478bd9Sstevel@tonic-gate for (pp = args ; noerror && *pp ; pp++) { 4317c478bd9Sstevel@tonic-gate n = ndevsin(*pp, TOKDELIMS); 4327c478bd9Sstevel@tonic-gate if (*ppp = (char **) malloc((n+1)*sizeof(char *))) { 4337c478bd9Sstevel@tonic-gate qq = *ppp++; 4347c478bd9Sstevel@tonic-gate if (*qq++ = strtok(*pp, TOKDELIMS)) 4357c478bd9Sstevel@tonic-gate while (*qq++ = strtok((char *) NULL, TOKDELIMS)); 4367c478bd9Sstevel@tonic-gate } else noerror = FALSE; 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate /* If there was an error, clean up the malloc()s we've made */ 4407c478bd9Sstevel@tonic-gate if (!noerror) { 4417c478bd9Sstevel@tonic-gate freereqlist(addrlist); 4427c478bd9Sstevel@tonic-gate addrlist = (char ***) NULL; 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* Return ptr to the list of addresses of lists (or NULL if none) */ 4477c478bd9Sstevel@tonic-gate return(addrlist); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* 4517c478bd9Sstevel@tonic-gate * void freereqlist(list) 4527c478bd9Sstevel@tonic-gate * char ***list 4537c478bd9Sstevel@tonic-gate * 4547c478bd9Sstevel@tonic-gate * This function frees the space allocated to the list of lists 4557c478bd9Sstevel@tonic-gate * referenced by <list> 4567c478bd9Sstevel@tonic-gate * 4577c478bd9Sstevel@tonic-gate * Arguments: 4587c478bd9Sstevel@tonic-gate * char ***list Address of the list of lists 4597c478bd9Sstevel@tonic-gate * 4607c478bd9Sstevel@tonic-gate * Returns: void 4617c478bd9Sstevel@tonic-gate */ 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate static void 4647c478bd9Sstevel@tonic-gate freereqlist(list) 4657c478bd9Sstevel@tonic-gate char ***list; 4667c478bd9Sstevel@tonic-gate { 4677c478bd9Sstevel@tonic-gate char ***ppp; 4687c478bd9Sstevel@tonic-gate if (list) { 4697c478bd9Sstevel@tonic-gate for (ppp = list ; *ppp ; ppp++) free((char *) *ppp); 4707c478bd9Sstevel@tonic-gate free((char *) list); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * int ndevsin(list, delims) 4767c478bd9Sstevel@tonic-gate * char *list 4777c478bd9Sstevel@tonic-gate * char *delims 4787c478bd9Sstevel@tonic-gate * 4797c478bd9Sstevel@tonic-gate * This function determines how many tokens are in the list <list>. 4807c478bd9Sstevel@tonic-gate * The tokens are delimited by fields of characters in the string 4817c478bd9Sstevel@tonic-gate * <delims>. It returns the number of tokens in the list. 4827c478bd9Sstevel@tonic-gate * 4837c478bd9Sstevel@tonic-gate * Arguments: 4847c478bd9Sstevel@tonic-gate * char *list The <delims>list of tokens to scan 4857c478bd9Sstevel@tonic-gate * char *delims The list of delimiters that define the list 4867c478bd9Sstevel@tonic-gate * 4877c478bd9Sstevel@tonic-gate * Returns: int 4887c478bd9Sstevel@tonic-gate * The number of elements in the list. 4897c478bd9Sstevel@tonic-gate * 4907c478bd9Sstevel@tonic-gate * Notes: 4917c478bd9Sstevel@tonic-gate * - This function does not recognize "null" elements. For example, 4927c478bd9Sstevel@tonic-gate * a,b,,,,c,,d contains 4 elememts (if delims contains a ',') 4937c478bd9Sstevel@tonic-gate */ 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate static int 4967c478bd9Sstevel@tonic-gate ndevsin(list, delims) 4977c478bd9Sstevel@tonic-gate char *list; /* List to scan */ 4987c478bd9Sstevel@tonic-gate char *delims; /* Delimiters */ 4997c478bd9Sstevel@tonic-gate { 5007c478bd9Sstevel@tonic-gate char *p; /* Running character pointer */ 5017c478bd9Sstevel@tonic-gate int count; /* Number of tokens seen so far */ 5027c478bd9Sstevel@tonic-gate int tokflag; /* TRUE if we're parsing a token */ 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate count = 0; /* None seen yet */ 5057c478bd9Sstevel@tonic-gate tokflag = FALSE; /* Not in a token */ 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* Scan the character-string containing the list of tokens */ 5087c478bd9Sstevel@tonic-gate for (p = list ; *p ; p++) { 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate /* If a delimiter, we're not in a token */ 5117c478bd9Sstevel@tonic-gate if (strchr(delims, *p)) tokflag = FALSE; 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate /* Otherwise, if we weren't in a token, we've found one */ 5147c478bd9Sstevel@tonic-gate else if (!tokflag) { 5157c478bd9Sstevel@tonic-gate tokflag = TRUE; 5167c478bd9Sstevel@tonic-gate count++; 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate /* Return the number of elements in the list */ 5217c478bd9Sstevel@tonic-gate return(count); 5227c478bd9Sstevel@tonic-gate } 523