Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/kinit/kinit.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 6300 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 #include <sys/mount.h>
2 #include <sys/stat.h>
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <alloca.h>
9 #include <limits.h>
10 #include <ctype.h>
11 #include <termios.h>
12
13 #include "kinit.h"
14 #include "ipconfig.h"
15 #include "run-init.h"
16 #include "resume.h"
17
18 const char *progname = "kinit";
19 int mnt_procfs;
20 int mnt_sysfs;
21
22 #ifdef INI_DEBUG
23 void dump_args(int argc, char *argv[])
24 {
25 int i;
26
27 printf(" argc == %d\n", argc);
28
29 for (i = 0; i < argc; i++) {
30 printf(" argv[%d]: \"%s\"\n", i, argv[i]);
31 }
32
33 if (argv[argc] != NULL) {
34 printf(" argv[%d]: \"%s\" (SHOULD BE NULL)\n",
35 argc, argv[argc]);
36 }
37 }
38 #endif
39
40
41 static int do_ipconfig(int argc, char *argv[])
42 {
43 int i, a = 0;
44 char **args = alloca((argc + 3) * sizeof(char *));
45
46 if (!args)
47 return -1;
48
49 args[a++] = (char *)"IP-Config";
50 args[a++] = (char *)"-i";
51 args[a++] = (char *)"Linux kinit";
52
53 DEBUG(("Running ipconfig\n"));
54
55 for (i = 1; i < argc; i++) {
56 if (strncmp(argv[i], "ip=", 3) == 0 ||
57 strncmp(argv[i], "nfsaddrs=", 9) == 0) {
58 args[a++] = argv[i];
59 }
60 }
61
62 if (a > 1) {
63 args[a] = NULL;
64 dump_args(a, args);
65 return ipconfig_main(a, args);
66 }
67
68 return 0;
69 }
70
71 static int split_cmdline(int cmdcmax, char *cmdv[], char *argv0,
72 char *cmdlines[], char *args[])
73 {
74 int was_space;
75 char c, *p;
76 int vmax = cmdcmax;
77 int v = 1;
78 int space;
79
80 if (cmdv)
81 cmdv[0] = argv0;
82
83 /* First, add the parsable command lines */
84
85 while (*cmdlines) {
86 p = *cmdlines++;
87 was_space = 1;
88 while (v < vmax) {
89 c = *p;
90 space = isspace(c);
91 if ((space || !c) && !was_space) {
92 if (cmdv)
93 *p = '\0';
94 v++;
95 } else if (was_space) {
96 if (cmdv)
97 cmdv[v] = p;
98 }
99
100 if (!c)
101 break;
102
103 was_space = space;
104 p++;
105 }
106 }
107
108 /* Second, add the explicit command line arguments */
109
110 while (*args && v < vmax) {
111 if (cmdv)
112 cmdv[v] = *args;
113 v++;
114 args++;
115 }
116
117 if (cmdv)
118 cmdv[v] = NULL;
119
120 return v;
121 }
122
123 static int mount_sys_fs(const char *check, const char *fsname,
124 const char *fstype)
125 {
126 struct stat st;
127
128 if (stat(check, &st) == 0) {
129 return 0;
130 }
131
132 mkdir(fsname, 0555);
133
134 if (mount("none", fsname, fstype, 0, NULL) == -1) {
135 fprintf(stderr, "%s: could not mount %s as %s\n",
136 progname, fsname, fstype);
137 return -1;
138 }
139
140 return 1;
141 }
142
143 static void check_path(const char *path)
144 {
145 struct stat st;
146
147 if (stat(path, &st) == -1) {
148 if (errno != ENOENT) {
149 perror("stat");
150 exit(1);
151 }
152 if (mkdir(path, 0755) == -1) {
153 perror("mkdir");
154 exit(1);
155 }
156 } else if (!S_ISDIR(st.st_mode)) {
157 fprintf(stderr, "%s: '%s' not a directory\n", progname, path);
158 exit(1);
159 }
160 }
161
162 static const char *find_init(const char *root, const char *user)
163 {
164 const char *init_paths[] = {
165 "/sbin/init", "/bin/init", "/etc/init", "/bin/sh", NULL
166 };
167 const char **p;
168 const char *path;
169
170 if (chdir(root)) {
171 perror("chdir");
172 exit(1);
173 }
174
175 if (user)
176 DEBUG(("Checking for init: %s\n", user));
177
178 if (user && user[0] == '/' && !access(user+1, X_OK)) {
179 path = user;
180 } else {
181 for (p = init_paths; *p; p++) {
182 DEBUG(("Checking for init: %s\n", *p));
183 if (!access(*p+1, X_OK))
184 break;
185 }
186 path = *p;
187 }
188 chdir("/");
189 return path;
190 }
191
192 /* This is the argc and argv we pass to init */
193 const char *init_path;
194 int init_argc;
195 char **init_argv;
196
197 extern ssize_t readfile(const char *, char **);
198
199 int main(int argc, char *argv[])
200 {
201 char **cmdv, **args;
202 char *cmdlines[3];
203 int i;
204 const char *errmsg;
205 int ret = 0;
206 int cmdc;
207 int fd;
208 struct timeval now;
209
210 gettimeofday(&now, NULL);
211 srand48(now.tv_usec ^ (now.tv_sec << 24));
212
213 /* Default parameters for anything init-like we execute */
214 init_argc = argc;
215 init_argv = alloca((argc+1)*sizeof(char *));
216 memcpy(init_argv, argv, (argc+1)*sizeof(char *));
217
218 if ((fd = open("/dev/console", O_RDWR)) != -1) {
219 dup2(fd, STDIN_FILENO);
220 dup2(fd, STDOUT_FILENO);
221 dup2(fd, STDERR_FILENO);
222
223 if (fd > STDERR_FILENO) {
224 close(fd);
225 }
226 }
227
228 mnt_procfs = mount_sys_fs("/proc/cmdline", "/proc", "proc") >= 0;
229 if (!mnt_procfs) {
230 ret = 1;
231 goto bail;
232 }
233
234 mnt_sysfs = mount_sys_fs("/sys/bus", "/sys", "sysfs") >= 0;
235 if (!mnt_sysfs) {
236 ret = 1;
237 goto bail;
238 }
239
240 /* Construct the effective kernel command line. The
241 effective kernel command line consists of /arch.cmd, if
242 it exists, /proc/cmdline, plus any arguments after an --
243 argument on the proper command line, in that order. */
244
245 ret = readfile("/arch.cmd", &cmdlines[0]);
246 if (ret < 0)
247 cmdlines[0] = "";
248
249 ret = readfile("/proc/cmdline", &cmdlines[1]);
250 if (ret < 0) {
251 fprintf(stderr, "%s: cannot read /proc/cmdline\n", progname);
252 ret = 1;
253 goto bail;
254 }
255
256 cmdlines[2] = NULL;
257
258 /* Find an -- argument, and if so append to the command line */
259 for (i = 1; i < argc; i++) {
260 if (!strcmp(argv[i], "--")) {
261 i++;
262 break;
263 }
264 }
265 args = &argv[i]; /* Points either to first argument past -- or
266 to the final NULL */
267
268 /* Count the number of arguments */
269 cmdc = split_cmdline(INT_MAX, NULL, argv[0], cmdlines, args);
270
271 /* Actually generate the cmdline array */
272 cmdv = (char **)alloca((cmdc+1)*sizeof(char *));
273 if (split_cmdline(cmdc, cmdv, argv[0], cmdlines, args) != cmdc) {
274 ret = 1;
275 goto bail;
276 }
277
278 /* Debugging... */
279 dump_args(cmdc, cmdv);
280
281 /* Resume from suspend-to-disk, if appropriate */
282 /* If successful, does not return */
283 do_resume(cmdc, cmdv);
284
285 /* Initialize networking, if applicable */
286 do_ipconfig(cmdc, cmdv);
287
288 check_path("/root");
289 do_mounts(cmdc, cmdv);
290
291 if (mnt_procfs) {
292 umount2("/proc", 0);
293 mnt_procfs = 0;
294 }
295
296 if (mnt_sysfs) {
297 umount2("/sys", 0);
298 mnt_sysfs = 0;
299 }
300
301 init_path = find_init("/root", get_arg(cmdc, cmdv, "init="));
302 if (!init_path) {
303 fprintf(stderr, "%s: init not found!\n", progname);
304 ret = 2;
305 goto bail;
306 }
307
308 init_argv[0] = strrchr(init_path, '/') + 1;
309
310 errmsg = run_init("/root", "/dev/console", init_path, init_argv);
311
312 /* If run_init returned, something went bad */
313 fprintf(stderr, "%s: %s: %s\n", progname, errmsg, strerror(errno));
314 ret = 2;
315 goto bail;
316
317 bail:
318 if (mnt_procfs)
319 umount2("/proc", 0);
320
321 if (mnt_sysfs)
322 umount2("/sys", 0);
323
324 /*
325 * If we get here, something bad probably happened, and the kernel
326 * will most likely panic. Drain console output so the user can
327 * figure out what happened.
328 */
329 tcdrain(2);
330 tcdrain(1);
331
332 return ret;
333 }