Bug Summary

File:obj-scan-build/startup/../../startup/startup.c
Location:line 473, column 5
Description:Value stored to 'progname' is never read

Annotated Source Code

1/* Start and maintain hurd core servers and system run state
2
3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
4 2005, 2008, 2013 Free Software Foundation, Inc.
5 This file is part of the GNU Hurd.
6
7 The GNU Hurd is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 The GNU Hurd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with the GNU Hurd; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21/* Written by Michael I. Bushnell and Roland McGrath. */
22
23/* This is probably more include files than I've ever seen before for
24 one file. */
25#include <hurd.h>
26#include <hurd/fs.h>
27#include <hurd/fsys.h>
28#include <device/device.h>
29#include <stdio.h>
30#include <assert.h>
31#include <hurd/paths.h>
32#include <sys/reboot.h>
33#include <sys/file.h>
34#include <unistd.h>
35#include <string.h>
36#include <mach/gnumach.h>
37#include <mach/notify.h>
38#include <stdlib.h>
39#include <hurd/msg.h>
40#include <hurd/term.h>
41#include <hurd/fshelp.h>
42#include <paths.h>
43#include <sys/mman.h>
44#include <hurd/msg_server.h>
45#include <wire.h>
46#include <sys/wait.h>
47#include <error.h>
48#include <hurd/msg_reply.h>
49#include <argz.h>
50#include <maptime.h>
51#include <version.h>
52#include <argp.h>
53#include <pids.h>
54
55#include "startup_notify_U.h"
56#include "startup_reply_U.h"
57#include "startup_S.h"
58#include "notify_S.h"
59#include "mung_msg_S.h"
60
61/* host_reboot flags for when we crash. */
62static int crash_flags = RB_AUTOBOOT0;
63
64#define BOOT(flags)((flags & 0x08) ? "halt" : "reboot") ((flags & RB_HALT0x08) ? "halt" : "reboot")
65
66
67const char *argp_program_version = STANDARD_HURD_VERSION (startup)"startup" " (GNU Hurd) " "0.5";
68
69static struct argp_option
70options[] =
71{
72 {"single-user", 's', 0, 0, "Startup system in single-user mode"},
73 {"query", 'q', 0, 0, "Ask for the names of servers to start"},
74 {"init-name", 'n', 0, 0 },
75 {"crash-debug", 'H', 0, 0, "On system crash, go to kernel debugger"},
76 {"debug", 'd', 0, 0 },
77 {"fake-boot", 'f', 0, 0, "This hurd hasn't been booted on the raw machine"},
78 {0, 'x', 0, OPTION_HIDDEN0x2},
79 {0}
80};
81
82static char doc[] = "Start and maintain hurd core servers and system run state";
83
84static int booted; /* Set when the core servers are up. */
85
86/* This structure keeps track of each notified task. */
87struct ntfy_task
88 {
89 mach_port_t notify_port;
90 struct ntfy_task *next;
91 char *name;
92 };
93
94/* This structure keeps track of each registered essential task. */
95struct ess_task
96 {
97 struct ess_task *next;
98 task_t task_port;
99 char *name;
100 };
101
102/* These are linked lists of all of the registered items. */
103static struct ess_task *ess_tasks;
104static struct ntfy_task *ntfy_tasks;
105
106
107/* Our receive right */
108static mach_port_t startup;
109
110/* Ports to the kernel */
111static mach_port_t host_priv, device_master;
112
113/* Args to bootstrap, expressed as flags */
114static int bootstrap_args = 0;
115
116/* Stored information for returning proc and auth startup messages. */
117static mach_port_t procreply, authreply;
118static mach_msg_type_name_t procreplytype, authreplytype;
119
120/* Our ports to auth and proc. */
121static mach_port_t authserver;
122static mach_port_t procserver;
123
124/* Our bootstrap port, on which we call fsys_getpriv and fsys_init. */
125static mach_port_t bootport;
126
127/* Set iff we are a `fake' bootstrap. */
128static int fakeboot;
129
130/* The tasks of auth and proc and the bootstrap filesystem. */
131static task_t authtask, proctask, fstask;
132
133static mach_port_t default_ports[INIT_PORT_MAX];
134static mach_port_t default_dtable[3];
135static int default_ints[INIT_INT_MAX];
136
137static char **global_argv;
138static char *startup_envz;
139static size_t startup_envz_len;
140
141void launch_system (void);
142void process_signal (int signo);
143
144/** Utility functions **/
145
146/* Read a string from stdin into BUF. */
147static int
148getstring (char *buf, size_t bufsize)
149{
150 if (fgets (buf, bufsize, stdinstdin) != NULL((void*)0) && buf[0] != '\0')
151 {
152 size_t len = strlen (buf);
153 if (buf[len - 1] == '\n' || buf[len - 1] == '\r')
154 buf[len - 1] = '\0';
155 return 1;
156 }
157 return 0;
158}
159
160
161/** System shutdown **/
162
163/* Reboot the microkernel. */
164void
165reboot_mach (int flags)
166{
167 if (fakeboot)
168 {
169 printf ("%s: Would %s Mach with flags %#x\n",
170 program_invocation_short_name, BOOT (flags)((flags & 0x08) ? "halt" : "reboot"), flags);
171 fflush (stdoutstdout);
172 exit (1);
173 }
174 else
175 {
176 error_t err;
177 printf ("%s: %sing Mach (flags %#x)...\n",
178 program_invocation_short_name, BOOT (flags)((flags & 0x08) ? "halt" : "reboot"), flags);
179 fflush (stdoutstdout);
180 sleep (5);
181 while ((err = host_reboot (host_priv, flags)))
182 error (0, err, "reboot");
183 for (;;);
184 }
185}
186
187/* Reboot the microkernel, specifying that this is a crash. */
188void
189crash_mach (void)
190{
191 reboot_mach (crash_flags);
192}
193
194/* Notify all tasks that have requested shutdown notifications */
195void
196notify_shutdown (const char *msg)
197{
198 struct ntfy_task *n;
199
200 for (n = ntfy_tasks; n != NULL((void*)0); n = n->next)
201 {
202 error_t err;
203 printf ("%s: notifying %s of %s...",
204 program_invocation_short_name, n->name, msg);
205 fflush (stdoutstdout);
206 err = startup_dosync (n->notify_port, 60000); /* 1 minute to reply */
207 if (err == MACH_SEND_INVALID_DEST0x10000003)
208 puts ("(no longer present)");
209 else if (err)
210 puts (strerror (err));
211 else
212 puts ("done");
213 fflush (stdoutstdout);
214 }
215}
216
217/* Reboot the Hurd. */
218void
219reboot_system (int flags)
220{
221 notify_shutdown (BOOT (flags)((flags & 0x08) ? "halt" : "reboot"));
222
223 if (fakeboot)
224 {
225 pid_t *pp;
226 size_t npids = 0;
227 error_t err;
228 int ind;
229
230 err = proc_getallpids (procserver, &pp, &npids);
231 if (err == MACH_SEND_INVALID_DEST0x10000003)
232 {
233 procbad:
234 /* The procserver must have died. Give up. */
235 error (0, 0, "Can't simulate crash; proc has died");
236 reboot_mach (flags);
237 }
238 for (ind = 0; ind < npids; ind++)
239 {
240 task_t task;
241
242 err = proc_pid2task (procserver, pp[ind], &task);
243 if (err == MACH_SEND_INVALID_DEST0x10000003)
244 goto procbad;
245 else if (err)
246 {
247 error (0, err, "Getting task for pid %d", pp[ind]);
248 continue;
249 }
250
251 /* Postpone self so we can finish; postpone proc
252 so that we can finish. */
253 if (task != mach_task_self ()((__mach_task_self_ + 0)) && task != proctask)
254 {
255 struct procinfo *pi = 0;
256 size_t pisize = 0;
257 char *noise;
258 size_t noise_len = 0;
259 int flags;
260 err = proc_getprocinfo (procserver, pp[ind], &flags,
261 (int **)&pi, &pisize,
262 &noise, &noise_len);
263 if (err == MACH_SEND_INVALID_DEST0x10000003)
264 goto procbad;
265 if (err)
266 {
267 error (0, err, "Getting procinfo for pid %d", pp[ind]);
268 continue;
269 }
270 if (!(pi->state & PI_NOPARENT0x0000080))
271 {
272 printf ("%s: Killing pid %d\n",
273 program_invocation_short_name, pp[ind]);
274 fflush (stdoutstdout);
275 task_terminate (task);
276 }
277 if (noise_len > 0)
278 munmap (noise, noise_len);
279 }
280 }
281 printf ("%s: Killing proc server\n", program_invocation_short_name);
282 fflush (stdoutstdout);
283 task_terminate (proctask);
284 printf ("%s: Exiting", program_invocation_short_name);
285 fflush (stdoutstdout);
286 }
287 reboot_mach (flags);
288}
289
290/* Reboot the Hurd, specifying that this is a crash. */
291void
292crash_system (void)
293{
294 reboot_system (crash_flags);
295}
296
297
298
299/* Request a dead-name notification sent to our port. */
300static void
301request_dead_name (mach_port_t name)
302{
303 mach_port_t prev;
304 mach_port_request_notification (mach_task_self ()((__mach_task_self_ + 0)), name,
305 MACH_NOTIFY_DEAD_NAME(0100 + 010), 1, startup,
306 MACH_MSG_TYPE_MAKE_SEND_ONCE21, &prev);
307 if (prev != MACH_PORT_NULL((mach_port_t) 0))
308 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), prev);
309}
310
311/* Record an essential task in the list. */
312static error_t
313record_essential_task (const char *name, task_t task)
314{
315 struct ess_task *et;
316 /* Record this task as essential. */
317 et = malloc (sizeof (struct ess_task));
318 if (et == NULL((void*)0))
319 return ENOMEM((0x10 << 26) | ((12) & 0x3fff));
320 et->task_port = task;
321 et->name = strdup (name);
322 if (et->name == NULL((void*)0))
323 {
324 free (et);
325 return ENOMEM((0x10 << 26) | ((12) & 0x3fff));
326 }
327 et->next = ess_tasks;
328 ess_tasks = et;
329
330 /* Dead-name notification on the task port will tell us when it dies. */
331 request_dead_name (task);
332
333#if 0
334 /* Taking over the exception port will give us a better chance
335 if the task tries to get wedged on a fault. */
336 task_set_special_port (task, TASK_EXCEPTION_PORT3, startup);
337#endif
338
339 return 0;
340}
341
342
343/** Starting programs **/
344
345/* Run SERVER, giving it INIT_PORT_MAX initial ports from PORTS.
346 Set TASK to be the task port of the new image. */
347void
348run (const char *server, mach_port_t *ports, task_t *task)
349{
350 char buf[BUFSIZ8192];
351 const char *prog = server;
352
353 if (bootstrap_args & RB_INITNAME0x10)
354 {
355 printf ("Server file name (default %s): ", server);
356 if (getstring (buf, sizeof (buf)))
357 prog = buf;
358 }
359
360 while (1)
361 {
362 file_t file;
363 error_t err;
364
365 file = file_name_lookup (prog, O_EXEC0x0004, 0);
366 if (file == MACH_PORT_NULL((mach_port_t) 0))
367 error (0, errno(*__errno_location ()), "%s", prog);
368 else
369 {
370 task_create (mach_task_self ()((__mach_task_self_ + 0)),
371#ifdef KERN_INVALID_LEDGER
372 NULL((void*)0), 0, /* OSF Mach */
373#endif
374 0, task);
375 if (bootstrap_args & RB_KDB0x04)
376 {
377 printf ("Pausing for %s\n", prog);
378 getchar ();
379 }
380 task_set_name (*task, (char *) prog);
381 err = file_exec (file, *task, 0,
382 (char *)prog, strlen (prog) + 1, /* Args. */
383 startup_envz, startup_envz_len,
384 default_dtable, MACH_MSG_TYPE_COPY_SEND19, 3,
385 ports, MACH_MSG_TYPE_COPY_SEND19, INIT_PORT_MAX,
386 default_ints, INIT_INT_MAX,
387 NULL((void*)0), 0, NULL((void*)0), 0);
388 if (!err)
389 break;
390
391 error (0, err, "%s", prog);
392 }
393
394 printf ("File name for server %s (or nothing to reboot): ", server);
395 if (getstring (buf, sizeof (buf)))
396 prog = buf;
397 else
398 crash_system ();
399 }
400
401#if 0
402 printf ("started %s\n", prog);
403 fflush (stdoutstdout);
404#endif
405
406 /* Dead-name notification on the task port will tell us when it dies,
407 so we can crash if we don't make it to a fully bootstrapped Hurd. */
408 request_dead_name (*task);
409}
410
411/* Run FILENAME as root with ARGS as its argv (length ARGLEN). Return
412 the task that we started. If CTTY is set, then make that the
413 controlling terminal of the new process and put it in its own login
414 collection. If SETSID is set, put it in a new session. Return
415 0 if the task was not created successfully. */
416pid_t
417run_for_real (char *filename, char *args, int arglen, mach_port_t ctty,
418 int setsid)
419{
420 file_t file;
421 error_t err;
422 task_t task;
423 char *progname;
424 int pid;
425
426#if 0
427 char buf[512];
428 do
429 {
430 printf ("File name [%s]: ", filename);
431 if (getstring (buf, sizeof (buf)) && *buf)
432 filename = buf;
433 file = file_name_lookup (filename, O_EXEC0x0004, 0);
434 if (file == MACH_PORT_NULL((mach_port_t) 0))
435 error (0, errno(*__errno_location ()), "%s", filename);
436 }
437 while (file == MACH_PORT_NULL((mach_port_t) 0));
438#else
439 file = file_name_lookup (filename, O_EXEC0x0004, 0);
440 if (file == MACH_PORT_NULL((mach_port_t) 0))
441 {
442 error (0, errno(*__errno_location ()), "%s", filename);
443 return 0;
444 }
445#endif
446
447 task_create (mach_task_self ()((__mach_task_self_ + 0)),
448#ifdef KERN_INVALID_LEDGER
449 NULL((void*)0), 0, /* OSF Mach */
450#endif
451 0, &task);
452 proc_child (procserver, task);
453 proc_task2pid (procserver, task, &pid);
454 proc_task2proc (procserver, task, &default_ports[INIT_PORT_PROC]);
455 proc_mark_exec (default_ports[INIT_PORT_PROC]);
456 if (setsid)
457 proc_setsid (default_ports[INIT_PORT_PROC]);
458 if (ctty != MACH_PORT_NULL((mach_port_t) 0))
459 {
460 term_getctty (ctty, &default_ports[INIT_PORT_CTTYID]);
461 io_mod_owner (ctty, -pid);
462 proc_make_login_coll (default_ports[INIT_PORT_PROC]);
463 }
464 if (bootstrap_args & RB_KDB0x04)
465 {
466 printf ("Pausing for %s\n", filename);
467 getchar ();
468 }
469 progname = strrchr (filename, '/');
470 if (progname)
471 ++progname;
472 else
473 progname = filename;
Value stored to 'progname' is never read
474 err = file_exec (file, task, 0,
475 args, arglen,
476 startup_envz, startup_envz_len,
477 default_dtable, MACH_MSG_TYPE_COPY_SEND19, 3,
478 default_ports, MACH_MSG_TYPE_COPY_SEND19,
479 INIT_PORT_MAX,
480 default_ints, INIT_INT_MAX,
481 NULL((void*)0), 0, NULL((void*)0), 0);
482 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), default_ports[INIT_PORT_PROC]);
483 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), task);
484 if (ctty != MACH_PORT_NULL((mach_port_t) 0))
485 {
486 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)),
487 default_ports[INIT_PORT_CTTYID]);
488 default_ports[INIT_PORT_CTTYID] = MACH_PORT_NULL((mach_port_t) 0);
489 }
490 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), file);
491 if (err)
492 {
493 error (0, err, "Cannot execute %s", filename);
494 return 0;
495 }
496 return pid;
497}
498
499
500/** Main program and setup **/
501
502static int
503demuxer (mach_msg_header_t *inp,
504 mach_msg_header_t *outp)
505{
506 extern int notify_server (mach_msg_header_t *, mach_msg_header_t *);
507 extern int startup_server (mach_msg_header_t *, mach_msg_header_t *);
508 extern int msg_server (mach_msg_header_t *, mach_msg_header_t *);
509 extern int fsys_server (mach_msg_header_t *, mach_msg_header_t *);
510
511 return (notify_server (inp, outp) ||
512 msg_server (inp, outp) ||
513 fsys_server (inp, outp) ||
514 startup_server (inp, outp));
515}
516
517error_t
518install_as_translator (void)
519{
520 error_t err;
521 file_t node;
522
523 node = file_name_lookup (_SERVERS_STARTUP"/servers/" "startup", O_NOTRANS0x0080, 0);
524 if (! MACH_PORT_VALID (node)(((node) != ((mach_port_t) 0)) && ((node) != ((mach_port_t
) ~0)))
)
525 {
526 if (errno(*__errno_location ()) == ENOENT((0x10 << 26) | ((2) & 0x3fff)))
527 {
528 /* Degrade gracefully if the node does not exist. */
529 error (0, errno(*__errno_location ()), "%s", _SERVERS_STARTUP"/servers/" "startup");
530 return 0;
531 }
532 return errno(*__errno_location ());
533 }
534
535 err = file_set_translator (node,
536 0, FS_TRANS_SET0x00000004, 0,
537 NULL((void*)0), 0,
538 startup, MACH_MSG_TYPE_COPY_SEND19);
539 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), node);
540 return err;
541}
542
543static int
544parse_opt (int key, char *arg, struct argp_state *state)
545{
546 switch (key)
547 {
548 case 'q': bootstrap_args |= RB_ASKNAME0x01; break;
549 case 's': bootstrap_args |= RB_SINGLE0x02; break;
550 case 'd': bootstrap_args |= RB_KDB0x04; break;
551 case 'n': bootstrap_args |= RB_INITNAME0x10; break;
552 case 'f': fakeboot = 1; break;
553 case 'H': crash_flags = RB_DEBUGGER0x1000; break;
554 case 'x': /* NOP */ break;
555 default: return ARGP_ERR_UNKNOWN((0x10 << 26) | ((7) & 0x3fff));
556 }
557 return 0;
558}
559
560int
561main (int argc, char **argv, char **envp)
562{
563 volatile int err;
564 int i;
565 int flags;
566 mach_port_t consdev;
567 struct argp argp = { options, parse_opt, 0, doc };
568
569 /* Parse the arguments. We don't want the vector reordered, we
570 should pass on to our child the exact arguments we got and just
571 ignore any arguments that aren't flags for us. ARGP_NO_ERRS
572 suppresses --help and --version, so we only use that option if we
573 are booting. */
574 flags = ARGP_IN_ORDER0x08;
575 if (getpid () == 0)
576 flags |= ARGP_NO_ERRS0x02;
577 argp_parse (&argp, argc, argv, flags, 0, 0);
578
579 if (getpid () > 0)
580 error (2, 0, "can only be run by bootstrap filesystem");
581
582 global_argv = argv;
583
584 /* Fetch a port to the bootstrap filesystem, the host priv and
585 master device ports, and the console. */
586 if (task_get_bootstrap_port (mach_task_self (), &bootport)(task_get_special_port((((__mach_task_self_ + 0))), 4, (&
bootport)))
587 || fsys_getpriv (bootport, &host_priv, &device_master, &fstask)
588 || device_open (device_master, D_READ0x1|D_WRITE0x2, "console", &consdev))
589 crash_mach ();
590
591 wire_task_self ();
592
593 /* Clear our bootstrap port so our children don't inherit it. */
594 task_set_bootstrap_port (mach_task_self (), MACH_PORT_NULL)(task_set_special_port((((__mach_task_self_ + 0))), 4, (((mach_port_t
) 0))))
;
595
596 stderrstderr = stdoutstdout = mach_open_devstream (consdev, "w");
597 stdinstdin = mach_open_devstream (consdev, "r");
598 if (stdoutstdout == NULL((void*)0) || stdinstdin == NULL((void*)0))
599 crash_mach ();
600 setbuf (stdoutstdout, NULL((void*)0));
601
602 err = argz_create (envp, &startup_envz, &startup_envz_len);
603 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 603, __PRETTY_FUNCTION__))
;
604
605 /* At this point we can use assert to check for errors. */
606 err = mach_port_allocate (mach_task_self ()((__mach_task_self_ + 0)),
607 MACH_PORT_RIGHT_RECEIVE((mach_port_right_t) 1), &startup);
608 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 608, __PRETTY_FUNCTION__))
;
609 err = mach_port_insert_right (mach_task_self ()((__mach_task_self_ + 0)), startup, startup,
610 MACH_MSG_TYPE_MAKE_SEND20);
611 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 611, __PRETTY_FUNCTION__))
;
612
613 /* Crash if the boot filesystem task dies. */
614 request_dead_name (fstask);
615
616 /* Set up the set of ports we will pass to the programs we exec. */
617 for (i = 0; i < INIT_PORT_MAX; i++)
618 switch (i)
619 {
620 case INIT_PORT_CRDIR:
621 default_ports[i] = getcrdir ();
622 break;
623 case INIT_PORT_CWDIR:
624 default_ports[i] = getcwdir ();
625 break;
626 default:
627 default_ports[i] = MACH_PORT_NULL((mach_port_t) 0);
628 break;
629 }
630
631 default_dtable[0] = getdport (0);
632 default_dtable[1] = getdport (1);
633 default_dtable[2] = getdport (2);
634
635 /* All programs we start should ignore job control stop signals.
636 That way Posix.1 B.2.2.2 is satisfied where it says that programs
637 not run under job control shells are protected. */
638 default_ints[INIT_SIGIGN] = (sigmask (SIGTSTP)(((__sigset_t) 1) << ((18) - 1))
639 | sigmask (SIGTTIN)(((__sigset_t) 1) << ((21) - 1))
640 | sigmask (SIGTTOU)(((__sigset_t) 1) << ((22) - 1)));
641
642 default_ports[INIT_PORT_BOOTSTRAP] = startup;
643 run ("/hurd/proc", default_ports, &proctask);
644 printf (" proc");
645 fflush (stdoutstdout);
646 run ("/hurd/auth", default_ports, &authtask);
647 printf (" auth");
648 fflush (stdoutstdout);
649 default_ports[INIT_PORT_BOOTSTRAP] = MACH_PORT_NULL((mach_port_t) 0);
650
651 /* Wait for messages. When both auth and proc have started, we
652 run launch_system which does the rest of the boot. */
653 while (1)
654 {
655 err = mach_msg_server (demuxer, 0, startup);
656 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 656, __PRETTY_FUNCTION__))
;
657 }
658}
659
660void
661launch_core_servers (void)
662{
663 mach_port_t old;
664 mach_port_t authproc, fsproc, procproc;
665 error_t err;
666
667 /* Reply to the proc and auth servers. */
668 err = startup_procinit_reply (procreply, procreplytype, 0,
669 mach_task_self ()((__mach_task_self_ + 0)), authserver,
670 host_priv, MACH_MSG_TYPE_COPY_SEND19,
671 device_master, MACH_MSG_TYPE_COPY_SEND19);
672 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 672, __PRETTY_FUNCTION__))
;
673 if (!fakeboot)
674 {
675 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), device_master);
676 device_master = 0;
677 }
678
679 /* Mark us as important. */
680 err = proc_mark_important (procserver);
681 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 681, __PRETTY_FUNCTION__))
;
682 err = proc_mark_exec (procserver);
683 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 683, __PRETTY_FUNCTION__))
;
684
685 /* Declare that the filesystem and auth are our children. */
686 err = proc_child (procserver, fstask);
687 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 687, __PRETTY_FUNCTION__))
;
688 err = proc_child (procserver, authtask);
689 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 689, __PRETTY_FUNCTION__))
;
690
691 err = proc_task2proc (procserver, authtask, &authproc);
692 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 692, __PRETTY_FUNCTION__))
;
693 err = proc_mark_important (authproc);
694 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 694, __PRETTY_FUNCTION__))
;
695 err = proc_mark_exec (authproc);
696 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 696, __PRETTY_FUNCTION__))
;
697
698 err = install_as_translator ();
699 if (err)
700 /* Good luck. Who knows, maybe it's an old installation. */
701 error (0, err, "Failed to bind to " _SERVERS_STARTUP"/servers/" "startup");
702
703 err = startup_authinit_reply (authreply, authreplytype, 0, authproc,
704 MACH_MSG_TYPE_COPY_SEND19);
705 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 705, __PRETTY_FUNCTION__))
;
706 err = mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), authproc);
707 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 707, __PRETTY_FUNCTION__))
;
708
709 /* Give the library our auth and proc server ports. */
710 _hurd_port_set (&_hurd_ports[INIT_PORT_AUTH], authserver);
711 _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], procserver);
712
713 /* Do NOT run _hurd_proc_init! That will start signals, which we do not
714 want. We listen to our own message port. Tell the proc server where
715 our args and environment are. */
716 err = proc_set_arg_locations (procserver,
717 (vm_address_t) global_argv,
718 (vm_address_t) environ);
719 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 719, __PRETTY_FUNCTION__))
;
720
721 default_ports[INIT_PORT_AUTH] = authserver;
722
723 /* Declare that the proc server is our child. */
724 err = proc_child (procserver, proctask);
725 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 725, __PRETTY_FUNCTION__))
;
726 err = proc_task2proc (procserver, proctask, &procproc);
727 if (!err)
728 {
729 proc_mark_important (procproc);
730 proc_mark_exec (procproc);
731 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), procproc);
732 }
733
734 err = proc_register_version (procserver, host_priv,
735 "init", "", HURD_VERSION"0.5");
736 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 736, __PRETTY_FUNCTION__))
;
737
738 /* Get the bootstrap filesystem's proc server port.
739 We must do this before calling proc_setmsgport below. */
740 err = proc_task2proc (procserver, fstask, &fsproc);
741 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 741, __PRETTY_FUNCTION__))
;
742 err = proc_mark_important (fsproc);
743 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 743, __PRETTY_FUNCTION__))
;
744 err = proc_mark_exec (fsproc);
745 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 745, __PRETTY_FUNCTION__))
;
746
747#if 0
748 printf ("Init has completed.\n");
749 fflush (stdoutstdout);
750#endif
751 printf (".\n");
752 fflush (stdoutstdout);
753
754 /* Tell the proc server our msgport. Be sure to do this after we are all
755 done making requests of proc. Once we have done this RPC, proc
756 assumes it can send us requests, so we cannot block on proc again
757 before accepting more RPC requests! However, we must do this before
758 calling fsys_init, because fsys_init blocks on exec_init, and
759 exec_init will block waiting on our message port. */
760 err = proc_setmsgport (procserver, startup, &old);
761 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 761, __PRETTY_FUNCTION__))
;
762 if (old != MACH_PORT_NULL((mach_port_t) 0))
763 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), old);
764
765 /* Give the bootstrap FS its proc and auth ports. */
766 err = fsys_init (bootport, fsproc, MACH_MSG_TYPE_COPY_SEND19, authserver);
767 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), fsproc);
768 if (err)
769 error (0, err, "fsys_init"); /* Not necessarily fatal. */
770}
771
772/* Set up the initial value of the standard exec data. */
773void
774init_stdarrays ()
775{
776 auth_t nullauth;
777 mach_port_t pt;
778 mach_port_t ref;
779 mach_port_t *std_port_array;
780 int *std_int_array;
781 int i;
782
783 std_port_array = alloca (sizeof (mach_port_t) * INIT_PORT_MAX)__builtin_alloca (sizeof (mach_port_t) * INIT_PORT_MAX);
784 std_int_array = alloca (sizeof (int) * INIT_INT_MAX)__builtin_alloca (sizeof (int) * INIT_INT_MAX);
785
786 memset (std_port_array, 0, sizeof(mach_port_t) * INIT_PORT_MAX);
787 memset (std_int_array, 0, sizeof(int) * INIT_INT_MAX);
788
789 __USEPORT (AUTH, auth_makeauth (port, 0, MACH_MSG_TYPE_COPY_SEND, 0,({ struct hurd_port *const __p = (&_hurd_ports[INIT_PORT_AUTH
]); struct hurd_userlink __link; const mach_port_t port = _hurd_port_get
(__p, &__link); __typeof((auth_makeauth (port, 0, 19, 0,
0, 0, 0, 0, 0, 0, 0, 0, &nullauth))) __result = ((auth_makeauth
(port, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, &nullauth))); _hurd_port_free
(__p, &__link, port); __result; })
790 0, 0, 0, 0, 0, 0, 0, 0, &nullauth))({ struct hurd_port *const __p = (&_hurd_ports[INIT_PORT_AUTH
]); struct hurd_userlink __link; const mach_port_t port = _hurd_port_get
(__p, &__link); __typeof((auth_makeauth (port, 0, 19, 0,
0, 0, 0, 0, 0, 0, 0, 0, &nullauth))) __result = ((auth_makeauth
(port, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, &nullauth))); _hurd_port_free
(__p, &__link, port); __result; })
;
791
792 /* MAKE_SEND is safe in these transactions because we destroy REF
793 ourselves each time. */
794 pt = getcwdir ();
795 ref = mach_reply_port ();
796 io_reauthenticate (pt, ref, MACH_MSG_TYPE_MAKE_SEND20);
797 auth_user_authenticate (nullauth, ref, MACH_MSG_TYPE_MAKE_SEND20,
798 &std_port_array[INIT_PORT_CWDIR]);
799 mach_port_destroy (mach_task_self ()((__mach_task_self_ + 0)), ref);
800 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), pt);
801
802 pt = getcrdir ();
803 ref = mach_reply_port ();
804 io_reauthenticate (pt, ref, MACH_MSG_TYPE_MAKE_SEND20);
805 auth_user_authenticate (nullauth, ref, MACH_MSG_TYPE_MAKE_SEND20,
806 &std_port_array[INIT_PORT_CRDIR]);
807 mach_port_destroy (mach_task_self ()((__mach_task_self_ + 0)), ref);
808 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), pt);
809
810 std_port_array[INIT_PORT_AUTH] = nullauth;
811
812 std_int_array[INIT_UMASK] = CMASK0022;
813
814 __USEPORT (PROC, proc_setexecdata (port, std_port_array,({ struct hurd_port *const __p = (&_hurd_ports[INIT_PORT_PROC
]); struct hurd_userlink __link; const mach_port_t port = _hurd_port_get
(__p, &__link); __typeof((proc_setexecdata (port, std_port_array
, 19, INIT_PORT_MAX, std_int_array, INIT_INT_MAX))) __result =
((proc_setexecdata (port, std_port_array, 19, INIT_PORT_MAX,
std_int_array, INIT_INT_MAX))); _hurd_port_free (__p, &__link
, port); __result; })
815 MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,({ struct hurd_port *const __p = (&_hurd_ports[INIT_PORT_PROC
]); struct hurd_userlink __link; const mach_port_t port = _hurd_port_get
(__p, &__link); __typeof((proc_setexecdata (port, std_port_array
, 19, INIT_PORT_MAX, std_int_array, INIT_INT_MAX))) __result =
((proc_setexecdata (port, std_port_array, 19, INIT_PORT_MAX,
std_int_array, INIT_INT_MAX))); _hurd_port_free (__p, &__link
, port); __result; })
816 std_int_array, INIT_INT_MAX))({ struct hurd_port *const __p = (&_hurd_ports[INIT_PORT_PROC
]); struct hurd_userlink __link; const mach_port_t port = _hurd_port_get
(__p, &__link); __typeof((proc_setexecdata (port, std_port_array
, 19, INIT_PORT_MAX, std_int_array, INIT_INT_MAX))) __result =
((proc_setexecdata (port, std_port_array, 19, INIT_PORT_MAX,
std_int_array, INIT_INT_MAX))); _hurd_port_free (__p, &__link
, port); __result; })
;
817 for (i = 0; i < INIT_PORT_MAX; i++)
818 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), std_port_array[i]);
819}
820
821/* Frobnicate the kernel task and the proc server's idea of it (PID 2),
822 so the kernel command line can be read as for a normal Hurd process. */
823
824void
825frob_kernel_process (void)
826{
827 error_t err;
828 int argc, i;
829 char *argz, *entry;
830 size_t argzlen;
831 size_t windowsz;
832 vm_address_t mine, his;
833 task_t task;
834 process_t proc, kbs;
835
836 err = proc_pid2task (procserver, HURD_PID_KERNEL3, &task);
837 if (err)
838 {
839 error (0, err, "cannot get kernel task port");
840 return;
841 }
842 err = proc_task2proc (procserver, task, &proc);
843 if (err)
844 {
845 error (0, err, "cannot get kernel task's proc server port");
846 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), task);
847 return;
848 }
849
850 /* Mark the kernel task as an essential task so that we or the proc server
851 never want to task_terminate it. */
852 proc_mark_important (proc);
853
854 err = record_essential_task ("kernel", task);
855 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 855, __PRETTY_FUNCTION__))
;
856
857 err = task_get_bootstrap_port (task, &kbs)(task_get_special_port((task), 4, (&kbs)));
858 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 858, __PRETTY_FUNCTION__))
;
859 if (kbs == MACH_PORT_NULL((mach_port_t) 0))
860 {
861 /* The kernel task has no bootstrap port set, so we are presumably
862 the first Hurd to boot. Install the kernel task's proc port from
863 this Hurd's proc server as the task bootstrap port. Additional
864 Hurds will see this. */
865
866 err = task_set_bootstrap_port (task, proc)(task_set_special_port((task), 4, (proc)));
867 if (err)
868 error (0, err, "cannot set kernel task's bootstrap port");
869
870 if (fakeboot)
871 error (0, 0, "warning: --fake-boot specified but I see no other Hurd");
872 }
873 else
874 {
875 /* The kernel task has a bootstrap port set. Perhaps it is its proc
876 server port from another Hurd. If so, propagate the kernel
877 argument locations from that Hurd rather than diddling with the
878 kernel task ourselves. */
879
880 vm_address_t kargv, kenvp;
881 err = proc_get_arg_locations (kbs, &kargv, &kenvp);
882 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), kbs);
883 if (err)
884 error (0, err, "kernel task bootstrap port (ignoring)");
885 else
886 {
887 err = proc_set_arg_locations (proc, kargv, kenvp);
888 if (err)
889 error (0, err, "cannot propagate original kernel command line");
890 else
891 {
892 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), proc);
893 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), task);
894 if (! fakeboot)
895 error (0, 0, "warning: "
896 "I see another Hurd, but --fake-boot was not given");
897 return;
898 }
899 }
900 }
901
902 /* Our arguments make up the multiboot command line used to boot the
903 kernel. We'll write into the kernel task a page containing a
904 canonical argv array and argz of those words. */
905
906 err = argz_create (&global_argv[1], &argz, &argzlen);
907 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 907, __PRETTY_FUNCTION__))
;
908 argc = argz_count (argz, argzlen);
909
910 windowsz = round_page (((argc + 1) * sizeof (char *)) + argzlen)((((vm_offset_t) (((argc + 1) * sizeof (char *)) + argzlen) +
__vm_page_size - 1) / __vm_page_size) * __vm_page_size)
;
911
912 mine = (vm_address_t) mmap (0, windowsz, PROT_READ0x04|PROT_WRITE0x02,
913 MAP_ANON0x0002, 0, 0);
914 assert (mine != -1)((mine != -1) ? (void) (0) : __assert_fail ("mine != -1", "../../startup/startup.c"
, 914, __PRETTY_FUNCTION__))
;
915 err = vm_allocate (task, &his, windowsz, 1);
916 if (err)
917 {
918 error (0, err, "cannot allocate %Zu bytes in kernel task", windowsz);
919 free (argz);
920 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), proc);
921 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), task);
922 munmap ((caddr_t) mine, windowsz);
923 return;
924 }
925
926 for (i = 0, entry = argz; entry != NULL((void*)0);
927 ++i, entry = argz_next (argz, argzlen, entry))
928 ((char **) mine)[i] = ((char *) &((char **) his)[argc + 1]
929 + (entry - argz));
930 ((char **) mine)[argc] = NULL((void*)0);
931 memcpy (&((char **) mine)[argc + 1], argz, argzlen);
932
933 free (argz);
934
935 /* We have the data all set up in our copy, now just write it over. */
936 err = vm_write (task, his, mine, windowsz);
937 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), task);
938 munmap ((caddr_t) mine, windowsz);
939 if (err)
940 {
941 error (0, err, "cannot write command line into kernel task");
942 return;
943 }
944
945 /* The argument vector is set up in the kernel task at address HIS.
946 Finally, we can inform the proc server where to find it. */
947 err = proc_set_arg_locations (proc, his, his + (argc * sizeof (char *)));
948 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), proc);
949 if (err)
950 error (0, err, "proc_set_arg_locations for kernel task");
951}
952
953/** Running userland. **/
954
955/* In the "split-init" setup, we just run a single program (usually
956 /libexec/runsystem) that is not expected to ever exit (or stop).
957 If it does exit (or can't be started), we go to an emergency single-user
958 shell as a fallback. */
959
960
961static pid_t child_pid; /* PID of the child we run */
962static task_t child_task; /* and its (original) task port */
963
964static void launch_something (const char *why);
965
966
967/* SIGNO has arrived and has been validated. Do whatever work it
968 implies. */
969void
970process_signal (int signo)
971{
972 if (signo == SIGCHLD20)
973 {
974 /* A child died. Find its status. */
975 int status;
976 pid_t pid;
977
978 while (1)
979 {
980 pid = waitpid (WAIT_ANY(-1), &status, WNOHANG1 | WUNTRACED2);
981 if (pid <= 0)
982 break; /* No more children. */
983
984 /* Since we are init, orphaned processes get reparented to us and
985 alas, all our adopted children eventually die. Woe is us. We
986 just need to reap the zombies to relieve the proc server of
987 its burden, and then we can forget about the little varmints. */
988
989 if (pid == child_pid)
990 {
991 /* The big magilla bit the dust. */
992
993 char *desc = 0;
994
995 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), child_task);
996 child_task = MACH_PORT_NULL((mach_port_t) 0);
997 child_pid = -1;
998
999 if (WIFSIGNALED (status)(((signed char) ((((__extension__ (((union { __typeof(status)
__in; int __i; }) { .__in = (status) }).__i))) & 0x7f) +
1) >> 1) > 0)
)
1000 asprintf (&desc, "terminated abnormally (%s)",
1001 strsignal (WTERMSIG (status)(((__extension__ (((union { __typeof(status) __in; int __i; }
) { .__in = (status) }).__i))) & 0x7f)
));
1002 else if (WIFSTOPPED (status)((((__extension__ (((union { __typeof(status) __in; int __i; }
) { .__in = (status) }).__i))) & 0xff) == 0x7f)
)
1003 asprintf (&desc, "stopped abnormally (%s)",
1004 strsignal (WTERMSIG (status)(((__extension__ (((union { __typeof(status) __in; int __i; }
) { .__in = (status) }).__i))) & 0x7f)
));
1005 else if (WEXITSTATUS (status)((((__extension__ (((union { __typeof(status) __in; int __i; }
) { .__in = (status) }).__i))) & 0xff00) >> 8)
== 0)
1006 desc = strdup ("finished");
1007 else
1008 asprintf (&desc, "exited with status %d",
1009 WEXITSTATUS (status)((((__extension__ (((union { __typeof(status) __in; int __i; }
) { .__in = (status) }).__i))) & 0xff00) >> 8)
);
1010
1011 {
1012 char buf[40];
1013 snprintf (buf, sizeof buf, "%d", status);
1014 setenv ("STATUS", buf, 1);
1015 }
1016
1017 launch_something (desc);
1018 free (desc);
1019 }
1020 }
1021 }
1022}
1023
1024/* Start the child program PROG. It is run via /libexec/console-run
1025 with the given additional arguments. */
1026static int
1027start_child (const char *prog, char **progargs)
1028{
1029 file_t file;
1030 error_t err;
1031 char *args;
1032 size_t arglen;
1033
1034 if (progargs == 0)
1035 {
1036 const char *argv[] = { "/libexec/console-run", prog, 0 };
1037 err = argz_create ((char **) argv, &args, &arglen);
1038 }
1039 else
1040 {
1041 int argc = 0;
1042 while (progargs[argc] != 0)
1043 ++argc;
1044 {
1045 const char *argv[2 + argc + 1];
1046 argv[0] = "/libexec/console-run";
1047 argv[1] = prog;
1048 argv[2 + argc] = 0;
1049 while (argc-- > 0)
1050 argv[2 + argc] = progargs[argc];
1051 err = argz_create ((char **) argv, &args, &arglen);
1052 }
1053 }
1054 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "../../startup/startup.c"
, 1054, __PRETTY_FUNCTION__))
;
1055
1056 file = file_name_lookup (args, O_EXEC0x0004, 0);
1057 if (file == MACH_PORT_NULL((mach_port_t) 0))
1058 {
1059 error (0, errno(*__errno_location ()), "%s", args);
1060 free (args);
1061 return -1;
1062 }
1063
1064 task_create (mach_task_self ()((__mach_task_self_ + 0)),
1065#ifdef KERN_INVALID_LEDGER
1066 NULL((void*)0), 0, /* OSF Mach */
1067#endif
1068 0, &child_task);
1069 proc_set_init_task (procserver, child_task);
1070 proc_task2pid (procserver, child_task, &child_pid);
1071 proc_task2proc (procserver, child_task, &default_ports[INIT_PORT_PROC]);
1072
1073 if (bootstrap_args & RB_KDB0x04)
1074 {
1075 printf ("Pausing for %s\n", args);
1076 getchar ();
1077 }
1078
1079 err = file_exec (file, child_task, 0,
1080 args, arglen,
1081 startup_envz, startup_envz_len,
1082 NULL((void*)0), MACH_MSG_TYPE_COPY_SEND19, 0, /* No fds. */
1083 default_ports, MACH_MSG_TYPE_COPY_SEND19, INIT_PORT_MAX,
1084 default_ints, INIT_INT_MAX,
1085 NULL((void*)0), 0, NULL((void*)0), 0);
1086 proc_mark_important (default_ports[INIT_PORT_PROC]);
1087 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), default_ports[INIT_PORT_PROC]);
1088 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), file);
1089 if (err)
1090 {
1091 error (0, err, "Cannot execute %s", args);
1092 free (args);
1093 return -1;
1094 }
1095 free (args);
1096 return 0;
1097}
1098
1099static void
1100launch_something (const char *why)
1101{
1102 file_t something;
1103 static unsigned int try;
1104 static const char *const tries[] =
1105 {
1106 "/libexec/runsystem",
1107 _PATH_BSHELL"/bin/sh",
1108 "/bin/shd", /* XXX */
1109 };
1110
1111 if (why)
1112 error (0, 0, "%s %s", tries[try - 1], why);
1113
1114 something = file_name_lookup (tries[try], O_EXEC0x0004, 0);
1115 if (something != MACH_PORT_NULL((mach_port_t) 0))
1116 {
1117 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), something);
1118 if (try == 0 && start_child (tries[try++], &global_argv[1]) == 0)
1119 return;
1120 }
1121 else
1122 try++;
1123
1124 while (try < sizeof tries / sizeof tries[0])
1125 {
1126 something = file_name_lookup (tries[try], O_EXEC0x0004, 0);
1127 if (something != MACH_PORT_NULL((mach_port_t) 0))
1128 {
1129 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), something);
1130 if (start_child (tries[try++], NULL((void*)0)) == 0)
1131 return;
1132 }
1133 }
1134
1135 crash_system ();
1136}
1137
1138void
1139launch_system (void)
1140{
1141 launch_something (0);
1142}
1143
1144/** RPC servers **/
1145
1146kern_return_t
1147S_startup_procinit (startup_t server,
1148 mach_port_t reply,
1149 mach_msg_type_name_t reply_porttype,
1150 process_t proc,
1151 mach_port_t *startuptask,
1152 auth_t *auth,
1153 mach_port_t *priv,
1154 mach_msg_type_name_t *hostprivtype,
1155 mach_port_t *dev,
1156 mach_msg_type_name_t *devtype)
1157{
1158 if (procserver)
1159 /* Only one proc server. */
1160 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1161
1162 procserver = proc;
1163
1164 procreply = reply;
1165 procreplytype = reply_porttype;
1166
1167 /* Save the reply port until we get startup_authinit. */
1168 if (authserver)
1169 launch_core_servers ();
1170
1171 return MIG_NO_REPLY-305;
1172}
1173
1174/* Called by the auth server when it starts up. */
1175
1176kern_return_t
1177S_startup_authinit (startup_t server,
1178 mach_port_t reply,
1179 mach_msg_type_name_t reply_porttype,
1180 mach_port_t auth,
1181 mach_port_t *proc,
1182 mach_msg_type_name_t *proctype)
1183{
1184 if (authserver)
1185 /* Only one auth server. */
1186 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1187
1188 authserver = auth;
1189
1190 /* Save the reply port until we get startup_procinit. */
1191 authreply = reply;
1192 authreplytype = reply_porttype;
1193
1194 if (procserver)
1195 launch_core_servers ();
1196
1197 return MIG_NO_REPLY-305;
1198}
1199
1200
1201kern_return_t
1202S_startup_essential_task (mach_port_t server,
1203 mach_port_t reply,
1204 mach_msg_type_name_t replytype,
1205 task_t task,
1206 mach_port_t excpt,
1207 char *name,
1208 mach_port_t credential)
1209{
1210 static int authinit, procinit, execinit;
1211 int fail;
1212
1213 /* Always deallocate the extra reference this message carries. */
1214 if (MACH_PORT_VALID (credential)(((credential) != ((mach_port_t) 0)) && ((credential)
!= ((mach_port_t) ~0)))
)
1215 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), credential);
1216
1217 if (credential != host_priv)
1218 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1219
1220 fail = record_essential_task (name, task);
1221 if (fail)
1222 return fail;
1223
1224 if (!booted)
1225 {
1226 if (!strcmp (name, "auth"))
1227 authinit = 1;
1228 else if (!strcmp (name, "exec"))
1229 {
1230 execinit = 1;
1231 mach_port_t execproc;
1232 proc_task2proc (procserver, task, &execproc);
1233 proc_mark_important (execproc);
1234 }
1235 else if (!strcmp (name, "proc"))
1236 procinit = 1;
1237
1238 if (authinit && execinit && procinit)
1239 {
1240 /* Reply to this RPC, after that everything
1241 is ready for real startup to begin. */
1242 startup_essential_task_reply (reply, replytype, 0);
1243
1244 init_stdarrays ();
1245 frob_kernel_process ();
1246
1247 launch_system ();
1248
1249 booted = 1;
1250
1251 return MIG_NO_REPLY-305;
1252 }
1253 }
1254
1255 return 0;
1256}
1257
1258kern_return_t
1259S_startup_request_notification (mach_port_t server,
1260 mach_port_t notify,
1261 char *name)
1262{
1263 struct ntfy_task *nt;
1264
1265 request_dead_name (notify);
1266
1267 /* Note that the ntfy_tasks list is kept in inverse order of the
1268 calls; this is important. We need later notification requests
1269 to get executed first. */
1270 nt = malloc (sizeof (struct ntfy_task));
1271 nt->notify_port = notify;
1272 nt->next = ntfy_tasks;
1273 ntfy_tasks = nt;
1274 nt->name = malloc (strlen (name) + 1);
1275 strcpy (nt->name, name);
1276 return 0;
1277}
1278
1279kern_return_t
1280do_mach_notify_dead_name (mach_port_t notify,
1281 mach_port_t name)
1282{
1283 struct ntfy_task *nt, *pnt;
1284 struct ess_task *et;
1285
1286 assert (notify == startup)((notify == startup) ? (void) (0) : __assert_fail ("notify == startup"
, "../../startup/startup.c", 1286, __PRETTY_FUNCTION__))
;
1287
1288 /* Deallocate the extra reference the notification carries. */
1289 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), name);
1290
1291 for (et = ess_tasks; et != NULL((void*)0); et = et->next)
1292 if (et->task_port == name)
1293 /* An essential task has died. */
1294 {
1295 error (0, 0, "Crashing system; essential task %s died", et->name);
1296 crash_system ();
1297 }
1298
1299 for (nt = ntfy_tasks, pnt = NULL((void*)0); nt != NULL((void*)0); pnt = nt, nt = nt->next)
1300 if (nt->notify_port == name)
1301 {
1302 /* Someone who wanted to be notified is gone. */
1303 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), name);
1304 if (pnt != NULL((void*)0))
1305 pnt->next = nt->next;
1306 else
1307 ntfy_tasks = nt->next;
1308 free (nt);
1309
1310 return 0;
1311 }
1312
1313 if (! booted)
1314 {
1315 /* The system has not come up yet, so essential tasks are not yet
1316 registered. But the essential servers involved in the bootstrap
1317 handshake might crash before completing it, so we have requested
1318 dead-name notification on those tasks. */
1319 static const struct { task_t *taskp; const char *name; } boots[] =
1320 {
1321 {&fstask, "bootstrap filesystem"},
1322 {&authtask, "auth"},
1323 {&proctask, "proc"},
1324 };
1325 size_t i;
1326 for (i = 0; i < sizeof boots / sizeof boots[0]; ++i)
1327 if (name == *boots[i].taskp)
1328 {
1329 error (0, 0, "Crashing system; %s server died during bootstrap",
1330 boots[i].name);
1331 crash_mach ();
1332 }
1333 error (0, 0, "BUG! Unexpected dead-name notification (name %#zx)",
1334 name);
1335 crash_mach ();
1336 }
1337
1338 return 0;
1339}
1340
1341kern_return_t
1342S_startup_reboot (mach_port_t server,
1343 mach_port_t refpt,
1344 int code)
1345{
1346 if (refpt != host_priv)
1347 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1348
1349 reboot_system (code);
1350 for (;;);
1351}
1352
1353/* Stubs for unused notification RPCs. */
1354
1355kern_return_t
1356do_mach_notify_port_destroyed (mach_port_t notify,
1357 mach_port_t rights)
1358{
1359 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1360}
1361
1362kern_return_t
1363do_mach_notify_send_once (mach_port_t notify)
1364{
1365 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1366}
1367
1368kern_return_t
1369do_mach_notify_no_senders (mach_port_t port, mach_port_mscount_t mscount)
1370{
1371 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1372}
1373
1374kern_return_t
1375do_mach_notify_port_deleted (mach_port_t notify,
1376 mach_port_t name)
1377{
1378 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1379}
1380
1381kern_return_t
1382do_mach_notify_msg_accepted (mach_port_t notify,
1383 mach_port_t name)
1384{
1385 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1386}
1387
1388/* msg server */
1389
1390kern_return_t
1391S_msg_sig_post_untraced (mach_port_t msgport,
1392 mach_port_t reply, mach_msg_type_name_t reply_type,
1393 int signo, natural_t sigcode, mach_port_t refport)
1394{
1395 if (refport != mach_task_self ()((__mach_task_self_ + 0)))
1396 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1397 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), refport);
1398
1399 /* Reply immediately */
1400 msg_sig_post_untraced_reply (reply, reply_type, 0);
1401
1402 process_signal (signo);
1403 return MIG_NO_REPLY-305;
1404}
1405
1406kern_return_t
1407S_msg_sig_post (mach_port_t msgport,
1408 mach_port_t reply, mach_msg_type_name_t reply_type,
1409 int signo, natural_t sigcode, mach_port_t refport)
1410{
1411 if (refport != mach_task_self ()((__mach_task_self_ + 0)))
1412 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1413 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), refport);
1414
1415 /* Reply immediately */
1416 msg_sig_post_reply (reply, reply_type, 0);
1417
1418 process_signal (signo);
1419 return MIG_NO_REPLY-305;
1420}
1421
1422
1423/* For the rest of the msg functions, just call the C library's
1424 internal server stubs usually run in the signal thread. */
1425
1426kern_return_t
1427S_msg_proc_newids (mach_port_t process,
1428 mach_port_t task,
1429 pid_t ppid,
1430 pid_t pgrp,
1431 int orphaned)
1432{ return _S_msg_proc_newids (process, task, ppid, pgrp, orphaned); }
1433
1434
1435kern_return_t
1436S_msg_add_auth (mach_port_t process,
1437 auth_t auth)
1438{ return _S_msg_add_auth (process, auth); }
1439
1440
1441kern_return_t
1442S_msg_del_auth (mach_port_t process,
1443 mach_port_t task,
1444 intarray_t uids,
1445 mach_msg_type_number_t uidsCnt,
1446 intarray_t gids,
1447 mach_msg_type_number_t gidsCnt)
1448{ return _S_msg_del_auth (process, task, uids, uidsCnt, gids, gidsCnt); }
1449
1450
1451kern_return_t
1452S_msg_get_init_port (mach_port_t process,
1453 mach_port_t refport,
1454 int which,
1455 mach_port_t *port,
1456 mach_msg_type_name_t *portPoly)
1457{ return _S_msg_get_init_port (process, refport, which, port, portPoly); }
1458
1459
1460kern_return_t
1461S_msg_set_init_port (mach_port_t process,
1462 mach_port_t refport,
1463 int which,
1464 mach_port_t port)
1465{ return _S_msg_set_init_port (process, refport, which, port); }
1466
1467
1468kern_return_t
1469S_msg_get_init_ports (mach_port_t process,
1470 mach_port_t refport,
1471 portarray_t *ports,
1472 mach_msg_type_name_t *portsPoly,
1473 mach_msg_type_number_t *portsCnt)
1474{ return _S_msg_get_init_ports (process, refport, ports, portsPoly, portsCnt); }
1475
1476
1477kern_return_t
1478S_msg_set_init_ports (mach_port_t process,
1479 mach_port_t refport,
1480 portarray_t ports,
1481 mach_msg_type_number_t portsCnt)
1482{ return _S_msg_set_init_ports (process, refport, ports, portsCnt); }
1483
1484
1485kern_return_t
1486S_msg_get_init_int (mach_port_t process,
1487 mach_port_t refport,
1488 int which,
1489 int *value)
1490{ return _S_msg_get_init_int (process, refport, which, value); }
1491
1492
1493kern_return_t
1494S_msg_set_init_int (mach_port_t process,
1495 mach_port_t refport,
1496 int which,
1497 int value)
1498{ return _S_msg_set_init_int (process, refport, which, value); }
1499
1500
1501kern_return_t
1502S_msg_get_init_ints (mach_port_t process,
1503 mach_port_t refport,
1504 intarray_t *values,
1505 mach_msg_type_number_t *valuesCnt)
1506{ return _S_msg_get_init_ints (process, refport, values, valuesCnt); }
1507
1508
1509kern_return_t
1510S_msg_set_init_ints (mach_port_t process,
1511 mach_port_t refport,
1512 intarray_t values,
1513 mach_msg_type_number_t valuesCnt)
1514{ return _S_msg_set_init_ints (process, refport, values, valuesCnt); }
1515
1516
1517kern_return_t
1518S_msg_get_dtable (mach_port_t process,
1519 mach_port_t refport,
1520 portarray_t *dtable,
1521 mach_msg_type_name_t *dtablePoly,
1522 mach_msg_type_number_t *dtableCnt)
1523{ return _S_msg_get_dtable (process, refport, dtable, dtablePoly, dtableCnt); }
1524
1525
1526kern_return_t
1527S_msg_set_dtable (mach_port_t process,
1528 mach_port_t refport,
1529 portarray_t dtable,
1530 mach_msg_type_number_t dtableCnt)
1531{ return _S_msg_set_dtable (process, refport, dtable, dtableCnt); }
1532
1533
1534kern_return_t
1535S_msg_get_fd (mach_port_t process,
1536 mach_port_t refport,
1537 int fd,
1538 mach_port_t *port,
1539 mach_msg_type_name_t *portPoly)
1540{ return _S_msg_get_fd (process, refport, fd, port, portPoly); }
1541
1542
1543kern_return_t
1544S_msg_set_fd (mach_port_t process,
1545 mach_port_t refport,
1546 int fd,
1547 mach_port_t port)
1548{ return _S_msg_set_fd (process, refport, fd, port); }
1549
1550
1551kern_return_t
1552S_msg_get_environment (mach_port_t process,
1553 data_t *value,
1554 mach_msg_type_number_t *valueCnt)
1555{ return _S_msg_get_environment (process, value, valueCnt); }
1556
1557
1558kern_return_t
1559S_msg_set_environment (mach_port_t process,
1560 mach_port_t refport,
1561 data_t value,
1562 mach_msg_type_number_t valueCnt)
1563{ return _S_msg_set_environment (process, refport, value, valueCnt); }
1564
1565
1566kern_return_t
1567S_msg_get_env_variable (mach_port_t process,
1568 string_t variable,
1569 data_t *value,
1570 mach_msg_type_number_t *valueCnt)
1571{ return _S_msg_get_env_variable (process, variable, value, valueCnt); }
1572
1573
1574kern_return_t
1575S_msg_set_env_variable (mach_port_t process,
1576 mach_port_t refport,
1577 string_t variable,
1578 string_t value,
1579 boolean_t replace)
1580{ return _S_msg_set_env_variable (process, refport, variable, value, replace); }
1581
1582error_t
1583S_msg_describe_ports (mach_port_t process,
1584 mach_port_t refport,
1585 mach_port_array_t names,
1586 mach_msg_type_number_t namesCnt,
1587 data_t *descriptions,
1588 mach_msg_type_number_t *descriptionsCnt)
1589{
1590 return _S_msg_describe_ports (process, refport, names, namesCnt,
1591 descriptions, descriptionsCnt);
1592}
1593
1594error_t
1595S_msg_report_wait (mach_port_t process, thread_t thread,
1596 string_t desc, mach_msg_id_t *rpc)
1597{
1598 *desc = 0;
1599 *rpc = 0;
1600 return 0;
1601}
1602
1603/* fsys */
1604error_t
1605S_fsys_getroot (mach_port_t fsys_t,
1606 mach_port_t dotdotnode,
1607 uid_t *uids, size_t nuids,
1608 uid_t *gids, size_t ngids,
1609 int flags,
1610 retry_type *do_retry,
1611 char *retry_name,
1612 mach_port_t *ret,
1613 mach_msg_type_name_t *rettype)
1614{
1615 int is_root = 0;
1616 size_t i;
1617
1618 for (i = 0; i < nuids; i++)
1619 if (uids[i] == 0)
1620 {
1621 is_root = 1;
1622 break;
1623 }
1624
1625 if (! is_root)
1626 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1627
1628 *do_retry = FS_RETRY_NORMAL;
1629 *retry_name = '\0';
1630 *ret = startup;
1631 *rettype = MACH_MSG_TYPE_COPY_SEND19;
1632 return 0;
1633}
1634
1635error_t
1636S_fsys_goaway (mach_port_t control, int flags)
1637{
1638 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1639}
1640
1641error_t
1642S_fsys_startup (mach_port_t bootstrap, int flags, mach_port_t control,
1643 mach_port_t *real, mach_msg_type_name_t *realtype)
1644{
1645 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1646}
1647
1648error_t
1649S_fsys_syncfs (mach_port_t control,
1650 int wait,
1651 int recurse)
1652{
1653 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1654}
1655
1656error_t
1657S_fsys_set_options (mach_port_t control,
1658 char *data, mach_msg_type_number_t len,
1659 int do_children)
1660{
1661 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1662}
1663
1664error_t
1665S_fsys_get_options (mach_port_t control,
1666 char **data, mach_msg_type_number_t *len)
1667{
1668 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1669}
1670
1671error_t
1672S_fsys_getfile (mach_port_t control,
1673 uid_t *uids, size_t nuids,
1674 uid_t *gids, size_t ngids,
1675 char *handle, size_t handllen,
1676 mach_port_t *pt,
1677 mach_msg_type_name_t *pttype)
1678{
1679 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1680}
1681
1682error_t
1683S_fsys_getpriv (mach_port_t control,
1684 mach_port_t *host_priv, mach_msg_type_name_t *host_priv_type,
1685 mach_port_t *dev_master, mach_msg_type_name_t *dev_master_type,
1686 task_t *fs_task, mach_msg_type_name_t *fs_task_type)
1687{
1688 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1689}
1690
1691error_t
1692S_fsys_init (mach_port_t control,
1693 mach_port_t reply,
1694 mach_msg_type_name_t replytype,
1695 mach_port_t proc,
1696 auth_t auth)
1697{
1698 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1699}
1700
1701error_t
1702S_fsys_forward (mach_port_t server, mach_port_t requestor,
1703 char *argz, size_t argz_len)
1704{
1705 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1706}