Bug Summary

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