1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/mman.h> 28 #include <sys/stat.h> 29 #include <sys/wait.h> 30 #include <strings.h> 31 #include <unistd.h> 32 #include <errno.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <sys/modctl.h> 36 #include <zone.h> 37 38 void usage(); 39 void exec_userfile(char *execfile, int id, char **envp); 40 41 extern void fatal(char *fmt, ...); 42 extern void error(char *fmt, ...); 43 44 /* 45 * Unload a loaded module. 46 */ 47 int 48 main(int argc, char *argv[], char *envp[]) 49 { 50 int child; 51 int status; 52 int id; 53 char *execfile = NULL; 54 int opt; 55 extern char *optarg; 56 57 if (argc < 3) 58 usage(); 59 60 while ((opt = getopt(argc, argv, "i:e:")) != -1) { 61 switch (opt) { 62 case 'i': 63 if (sscanf(optarg, "%d", &id) != 1) 64 fatal("Invalid id %s\n", optarg); 65 break; 66 case 'e': 67 execfile = optarg; 68 } 69 } 70 71 if (getzoneid() != GLOBAL_ZONEID) { 72 fatal("modunload can only be run from the global zone\n"); 73 } 74 75 if (execfile) { 76 child = fork(); 77 if (child == -1) 78 error("can't fork %s", execfile); 79 else if (child == 0) 80 exec_userfile(execfile, id, envp); 81 else { 82 (void) wait(&status); 83 if (status != 0) { 84 (void) printf("%s returned error %d.\n", 85 execfile, status); 86 (void) exit(status >> 8); 87 } 88 } 89 } 90 91 /* 92 * Unload the module. 93 */ 94 if (modctl(MODUNLOAD, id) < 0) { 95 if (errno == EPERM) 96 fatal("Insufficient privileges to unload a module\n"); 97 else if (id != 0) 98 error("can't unload the module"); 99 } 100 101 return (0); /* success */ 102 } 103 104 /* 105 * exec the user file. 106 */ 107 void 108 exec_userfile(char *execfile, int id, char **envp) 109 { 110 struct modinfo modinfo; 111 112 char modid[8]; 113 char mod0[8]; 114 115 modinfo.mi_id = modinfo.mi_nextid = id; 116 modinfo.mi_info = MI_INFO_ONE; 117 if (modctl(MODINFO, id, &modinfo) < 0) 118 error("can't get module information"); 119 120 (void) sprintf(modid, "%d", id); 121 (void) sprintf(mod0, "%d", modinfo.mi_msinfo[0].msi_p0); 122 123 (void) execle(execfile, execfile, modid, mod0, NULL, envp); 124 125 error("couldn't exec %s\n", execfile); 126 } 127 128 129 void 130 usage() 131 { 132 fatal("usage: modunload -i <module_id> [-e <exec_file>]\n"); 133 } 134