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/wait.h>
28 #include <sys/param.h>
29 #include <sys/stat.h>
30 #include <sys/modctl.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <zone.h>
38
39 void l_exec_userfile(char *execfile, int id, char **envp);
40 void l_usage();
41
42 extern void fatal(char *fmt, ...);
43 extern void error(char *fmt, ...);
44
45 /*
46 * Load a module.
47 */
48 int
main(int argc,char * argv[],char * envp[])49 main(int argc, char *argv[], char *envp[])
50 {
51 char *execfile = NULL; /* name of file to exec after loading */
52 char *modpath = NULL;
53 int id;
54 extern int optind;
55 extern char *optarg;
56 int opt;
57 int use_path = 0;
58 char path[1024];
59
60 if (argc < 2 || argc > 5) {
61 l_usage();
62 }
63
64 while ((opt = getopt(argc, argv, "e:p")) != -1) {
65 switch (opt) {
66 case 'e':
67 execfile = optarg;
68 break;
69 case 'p':
70 use_path++;
71 break;
72 case '?':
73 l_usage();
74 }
75 }
76
77 if (getzoneid() != GLOBAL_ZONEID) {
78 fatal("modload can only be run from the global zone\n");
79 }
80
81 modpath = argv[optind];
82
83 if (modpath == NULL) {
84 (void) printf("modpath is null\n");
85 l_usage();
86 }
87 if (!use_path && modpath[0] != '/') {
88 if (getcwd(path, 1023 - strlen(modpath)) == NULL)
89 fatal("Can't get current directory\n");
90 (void) strcat(path, "/");
91 (void) strcat(path, modpath);
92 } else
93 (void) strcpy(path, modpath);
94
95 /*
96 * Load the module.
97 */
98 if (modctl(MODLOAD, use_path, path, &id) != 0) {
99 if (errno == EPERM)
100 fatal("Insufficient privileges to load a module\n");
101 else
102 error("can't load module");
103 }
104
105 /*
106 * Exec the user's file (if any)
107 */
108 if (execfile)
109 l_exec_userfile(execfile, id, envp);
110
111 return (0); /* success */
112 }
113
114 /*
115 * Exec the user's file
116 */
117 void
l_exec_userfile(char * execfile,int id,char ** envp)118 l_exec_userfile(char *execfile, int id, char **envp)
119 {
120 struct modinfo modinfo;
121
122 int child;
123 int status;
124 int waitret;
125 char module_id[8];
126 char mod0[8];
127
128 if ((child = fork()) == -1)
129 error("can't fork %s", execfile);
130
131 /*
132 * exec the user program.
133 */
134 if (child == 0) {
135 modinfo.mi_id = id;
136 modinfo.mi_nextid = id;
137 modinfo.mi_info = MI_INFO_ONE;
138 if (modctl(MODINFO, id, &modinfo) < 0)
139 error("can't get module status");
140
141 (void) sprintf(module_id, "%d", modinfo.mi_id);
142 (void) sprintf(mod0, "%d", modinfo.mi_msinfo[0].msi_p0);
143 (void) execle(execfile, execfile, module_id, mod0, NULL, envp);
144
145 /* Shouldn't get here if execle was successful */
146
147 error("couldn't exec %s", execfile);
148 } else {
149 do {
150 /* wait for exec'd program to finish */
151 waitret = wait(&status);
152 } while ((waitret != child) && (waitret != -1));
153
154 waitret = (waitret == -1) ? waitret : status;
155
156 if ((waitret & 0377) != 0) {
157 /* exited because of a signal */
158 (void) printf("'%s' terminated because of signal %d",
159 execfile, (waitret & 0177));
160 if (waitret & 0200)
161 (void) printf(" and produced a core file\n");
162 (void) printf(".\n");
163 exit(waitret >> 8);
164 } else {
165 /* simple termination */
166 if (((waitret >> 8) & 0377) != 0) {
167 (void) printf("'%s' returned error %d.\n",
168 execfile, (waitret >> 8) & 0377);
169 exit(waitret >> 8);
170 }
171 }
172 }
173 }
174
175 void
l_usage()176 l_usage()
177 {
178 fatal("usage: modload [-p] [-e <exec_file>] <filename>\n");
179 }
180