Bug Summary

File: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.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.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.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.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.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.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.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.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 }
965 }
966 }
967 else
968 {
969 /* Pass the signal on to the child. */
970 task_t task;
971 error_t err;
972
973 err = proc_pid2task (procserver, child_pid, &task);
974 if (err)
975 {
976 error (0, err, "proc_pid2task on %d", child_pid);
977 task = child_task;
978 }
979 else
980 {
981 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), child_task);
982 child_task = task;
983 }
984
985 if (signo == SIGKILL9)
986 {
987 err = task_terminate (task);
988 if (err != MACH_SEND_INVALID_DEST0x10000003)
989 error (0, err, "task_terminate");
990 }
991 else
992 {
993 mach_port_t msgport;
994 err = proc_getmsgport (procserver, child_pid, &msgport);
995 if (err)
996 error (0, err, "proc_getmsgport");
997 else
998 {
999 err = send_signal (msgport, signo, task,
1000 500); /* Block only half a second. */
1001 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), msgport);
1002 if (err)
1003 {
1004 error (0, err, "cannot send %s to child %d",
1005 strsignal (signo), child_pid);
1006 err = task_terminate (task);
1007 if (err != MACH_SEND_INVALID_DEST0x10000003)
1008 error (0, err, "task_terminate");
1009 }
1010 }
1011 }
1012 }
1013}
1014
1015/* Start the child program PROG. It is run via /libexec/console-run
1016 with the given additional arguments. */
1017static int
1018start_child (const char *prog, char **progargs)
1019{
1020 file_t file;
1021 error_t err;
1022 char *args;
1023 size_t arglen;
1024
1025 if (progargs == 0)
1026 {
1027 const char *argv[] = { "/libexec/console-run", prog, 0 };
1028 err = argz_create ((char **) argv, &args, &arglen);
1029 }
1030 else
1031 {
1032 int argc = 0;
1033 while (progargs[argc] != 0)
1034 ++argc;
1035 {
1036 const char *argv[2 + argc + 1];
1037 argv[0] = "/libexec/console-run";
1038 argv[1] = prog;
1039 argv[2 + argc] = 0;
1040 while (argc-- > 0)
1041 argv[2 + argc] = progargs[argc];
1042 err = argz_create ((char **) argv, &args, &arglen);
1043 }
1044 }
1045 assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "init.c",
1045, __PRETTY_FUNCTION__))
;
1046
1047 file = file_name_lookup (args, O_EXEC0x0004, 0);
1048 if (file == MACH_PORT_NULL((mach_port_t) 0))
1049 {
1050 error (0, errno(*__errno_location ()), "%s", args);
1051 free (args);
1052 return -1;
1053 }
1054
1055 task_create (mach_task_self ()((__mach_task_self_ + 0)),
1056#ifdef KERN_INVALID_LEDGER
1057 NULL((void*)0), 0, /* OSF Mach */
1058#endif
1059 0, &child_task);
1060 proc_child (procserver, child_task);
1061 proc_task2pid (procserver, child_task, &child_pid);
1062 proc_task2proc (procserver, child_task, &default_ports[INIT_PORT_PROC]);
1063
1064 if (bootstrap_args & RB_KDB0x04)
1065 {
1066 printf ("Pausing for %s\n", args);
1067 getchar ();
1068 }
1069
1070 err = file_exec (file, child_task, 0,
1071 args, arglen,
1072 startup_envz, startup_envz_len,
1073 NULL((void*)0), MACH_MSG_TYPE_COPY_SEND19, 0, /* No fds. */
1074 default_ports, MACH_MSG_TYPE_COPY_SEND19, INIT_PORT_MAX,
1075 default_ints, INIT_INT_MAX,
1076 NULL((void*)0), 0, NULL((void*)0), 0);
1077 proc_mark_important (default_ports[INIT_PORT_PROC]);
1078 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), default_ports[INIT_PORT_PROC]);
1079 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), file);
1080 if (err)
1081 {
1082 error (0, err, "Cannot execute %s", args);
1083 free (args);
1084 return -1;
1085 }
1086 free (args);
1087 return 0;
1088}
1089
1090static void
1091launch_something (const char *why)
1092{
1093 file_t something;
1094 static unsigned int try;
1095 static const char *const tries[] =
1096 {
1097 "/libexec/runsystem",
1098 _PATH_BSHELL"/bin/sh",
1099 "/bin/shd", /* XXX */
1100 };
1101
1102 if (why)
1103 error (0, 0, "%s %s", tries[try - 1], why);
1104
1105 something = file_name_lookup (tries[try], O_EXEC0x0004, 0);
1106 if (something != MACH_PORT_NULL((mach_port_t) 0))
1107 {
1108 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), something);
1109 if (try == 0 && start_child (tries[try++], &global_argv[1]) == 0)
1110 return;
1111 }
1112 else
1113 try++;
1114
1115 while (try < sizeof tries / sizeof tries[0])
1116 {
1117 something = file_name_lookup (tries[try], O_EXEC0x0004, 0);
1118 if (something != MACH_PORT_NULL((mach_port_t) 0))
1119 {
1120 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), something);
1121 if (start_child (tries[try++], NULL((void*)0)) == 0)
1122 return;
1123 }
1124 }
1125
1126 crash_system ();
1127}
1128
1129void
1130launch_system (void)
1131{
1132 launch_something (0);
1133}
1134
1135/** RPC servers **/
1136
1137kern_return_t
1138S_startup_procinit (startup_t server,
1139 mach_port_t reply,
1140 mach_msg_type_name_t reply_porttype,
1141 process_t proc,
1142 mach_port_t *startuptask,
1143 auth_t *auth,
1144 mach_port_t *priv,
1145 mach_msg_type_name_t *hostprivtype,
1146 mach_port_t *dev,
1147 mach_msg_type_name_t *devtype)
1148{
1149 if (procserver)
1150 /* Only one proc server. */
1151 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1152
1153 procserver = proc;
1154
1155 procreply = reply;
1156 procreplytype = reply_porttype;
1157
1158 /* Save the reply port until we get startup_authinit. */
1159 if (authserver)
1160 launch_core_servers ();
1161
1162 return MIG_NO_REPLY-305;
1163}
1164
1165/* Called by the auth server when it starts up. */
1166
1167kern_return_t
1168S_startup_authinit (startup_t server,
1169 mach_port_t reply,
1170 mach_msg_type_name_t reply_porttype,
1171 mach_port_t auth,
1172 mach_port_t *proc,
1173 mach_msg_type_name_t *proctype)
1174{
1175 if (authserver)
1176 /* Only one auth server. */
1177 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1178
1179 authserver = auth;
1180
1181 /* Save the reply port until we get startup_procinit. */
1182 authreply = reply;
1183 authreplytype = reply_porttype;
1184
1185 if (procserver)
1186 launch_core_servers ();
1187
1188 return MIG_NO_REPLY-305;
1189}
1190
1191
1192kern_return_t
1193S_startup_essential_task (mach_port_t server,
1194 mach_port_t reply,
1195 mach_msg_type_name_t replytype,
1196 task_t task,
1197 mach_port_t excpt,
1198 char *name,
1199 mach_port_t credential)
1200{
1201 static int authinit, procinit, execinit;
1202 int fail;
1203
1204 if (credential != host_priv)
1205 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1206
1207 fail = record_essential_task (name, task);
1208 if (fail)
1209 return fail;
1210
1211 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), credential);
1212
1213 if (!booted)
1214 {
1215 if (!strcmp (name, "auth"))
1216 authinit = 1;
1217 else if (!strcmp (name, "exec"))
1218 {
1219 execinit = 1;
1220 mach_port_t execproc;
1221 proc_task2proc (procserver, task, &execproc);
1222 proc_mark_important (execproc);
1223 }
1224 else if (!strcmp (name, "proc"))
1225 procinit = 1;
1226
1227 if (authinit && execinit && procinit)
1228 {
1229 /* Reply to this RPC, after that everything
1230 is ready for real startup to begin. */
1231 startup_essential_task_reply (reply, replytype, 0);
1232
1233 init_stdarrays ();
1234 frob_kernel_process ();
1235
1236 launch_system ();
1237
1238 booted = 1;
1239
1240 return MIG_NO_REPLY-305;
1241 }
1242 }
1243
1244 return 0;
1245}
1246
1247kern_return_t
1248S_startup_request_notification (mach_port_t server,
1249 mach_port_t notify,
1250 char *name)
1251{
1252 struct ntfy_task *nt;
1253
1254 request_dead_name (notify);
1255
1256 /* Note that the ntfy_tasks list is kept in inverse order of the
1257 calls; this is important. We need later notification requests
1258 to get executed first. */
1259 nt = malloc (sizeof (struct ntfy_task));
1260 nt->notify_port = notify;
1261 nt->next = ntfy_tasks;
1262 ntfy_tasks = nt;
1263 nt->name = malloc (strlen (name) + 1);
1264 strcpy (nt->name, name);
1265 return 0;
1266}
1267
1268kern_return_t
1269do_mach_notify_dead_name (mach_port_t notify,
1270 mach_port_t name)
1271{
1272 struct ntfy_task *nt, *pnt;
1273 struct ess_task *et;
1274
1275 assert (notify == startup)((notify == startup) ? (void) (0) : __assert_fail ("notify == startup"
, "init.c", 1275, __PRETTY_FUNCTION__))
;
1276
1277 /* Deallocate the extra reference the notification carries. */
1278 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), name);
1279
1280 for (et = ess_tasks; et != NULL((void*)0); et = et->next)
1281 if (et->task_port == name)
1282 /* An essential task has died. */
1283 {
1284 error (0, 0, "Crashing system; essential task %s died", et->name);
1285 crash_system ();
1286 }
1287
1288 for (nt = ntfy_tasks, pnt = NULL((void*)0); nt != NULL((void*)0); pnt = nt, nt = nt->next)
1289 if (nt->notify_port == name)
1290 {
1291 /* Someone who wanted to be notified is gone. */
1292 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), name);
1293 if (pnt != NULL((void*)0))
1294 pnt->next = nt->next;
1295 else
1296 ntfy_tasks = nt->next;
1297 free (nt);
1298
1299 return 0;
1300 }
1301
1302 if (! booted)
1303 {
1304 /* The system has not come up yet, so essential tasks are not yet
1305 registered. But the essential servers involved in the bootstrap
1306 handshake might crash before completing it, so we have requested
1307 dead-name notification on those tasks. */
1308 static const struct { task_t *taskp; const char *name; } boots[] =
1309 {
1310 {&fstask, "bootstrap filesystem"},
1311 {&authtask, "auth"},
1312 {&proctask, "proc"},
1313 };
1314 size_t i;
1315 for (i = 0; i < sizeof boots / sizeof boots[0]; ++i)
1316 if (name == *boots[i].taskp)
1317 {
1318 error (0, 0, "Crashing system; %s server died during bootstrap",
1319 boots[i].name);
1320 crash_mach ();
1321 }
1322 error (0, 0, "BUG! Unexpected dead-name notification (name %#zx)",
1323 name);
1324 crash_mach ();
1325 }
1326
1327 return 0;
1328}
1329
1330kern_return_t
1331S_startup_reboot (mach_port_t server,
1332 mach_port_t refpt,
1333 int code)
1334{
1335 if (refpt != host_priv)
1336 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1337
1338 reboot_system (code);
1339 for (;;);
1340}
1341
1342/* Stubs for unused notification RPCs. */
1343
1344kern_return_t
1345do_mach_notify_port_destroyed (mach_port_t notify,
1346 mach_port_t rights)
1347{
1348 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1349}
1350
1351kern_return_t
1352do_mach_notify_send_once (mach_port_t notify)
1353{
1354 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1355}
1356
1357kern_return_t
1358do_mach_notify_no_senders (mach_port_t port, mach_port_mscount_t mscount)
1359{
1360 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1361}
1362
1363kern_return_t
1364do_mach_notify_port_deleted (mach_port_t notify,
1365 mach_port_t name)
1366{
1367 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1368}
1369
1370kern_return_t
1371do_mach_notify_msg_accepted (mach_port_t notify,
1372 mach_port_t name)
1373{
1374 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1375}
1376
1377/* msg server */
1378
1379kern_return_t
1380S_msg_sig_post_untraced (mach_port_t msgport,
1381 mach_port_t reply, mach_msg_type_name_t reply_type,
1382 int signo, natural_t sigcode, mach_port_t refport)
1383{
1384 if (refport != mach_task_self ()((__mach_task_self_ + 0)))
1385 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1386 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), refport);
1387
1388 /* Reply immediately */
1389 msg_sig_post_untraced_reply (reply, reply_type, 0);
1390
1391 process_signal (signo);
1392 return MIG_NO_REPLY-305;
1393}
1394
1395kern_return_t
1396S_msg_sig_post (mach_port_t msgport,
1397 mach_port_t reply, mach_msg_type_name_t reply_type,
1398 int signo, natural_t sigcode, mach_port_t refport)
1399{
1400 if (refport != mach_task_self ()((__mach_task_self_ + 0)))
1401 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1402 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), refport);
1403
1404 /* Reply immediately */
1405 msg_sig_post_reply (reply, reply_type, 0);
1406
1407 process_signal (signo);
1408 return MIG_NO_REPLY-305;
1409}
1410
1411
1412/* For the rest of the msg functions, just call the C library's
1413 internal server stubs usually run in the signal thread. */
1414
1415kern_return_t
1416S_msg_proc_newids (mach_port_t process,
1417 mach_port_t task,
1418 pid_t ppid,
1419 pid_t pgrp,
1420 int orphaned)
1421{ return _S_msg_proc_newids (process, task, ppid, pgrp, orphaned); }
1422
1423
1424kern_return_t
1425S_msg_add_auth (mach_port_t process,
1426 auth_t auth)
1427{ return _S_msg_add_auth (process, auth); }
1428
1429
1430kern_return_t
1431S_msg_del_auth (mach_port_t process,
1432 mach_port_t task,
1433 intarray_t uids,
1434 mach_msg_type_number_t uidsCnt,
1435 intarray_t gids,
1436 mach_msg_type_number_t gidsCnt)
1437{ return _S_msg_del_auth (process, task, uids, uidsCnt, gids, gidsCnt); }
1438
1439
1440kern_return_t
1441S_msg_get_init_port (mach_port_t process,
1442 mach_port_t refport,
1443 int which,
1444 mach_port_t *port,
1445 mach_msg_type_name_t *portPoly)
1446{ return _S_msg_get_init_port (process, refport, which, port, portPoly); }
1447
1448
1449kern_return_t
1450S_msg_set_init_port (mach_port_t process,
1451 mach_port_t refport,
1452 int which,
1453 mach_port_t port)
1454{ return _S_msg_set_init_port (process, refport, which, port); }
1455
1456
1457kern_return_t
1458S_msg_get_init_ports (mach_port_t process,
1459 mach_port_t refport,
1460 portarray_t *ports,
1461 mach_msg_type_name_t *portsPoly,
1462 mach_msg_type_number_t *portsCnt)
1463{ return _S_msg_get_init_ports (process, refport, ports, portsPoly, portsCnt); }
1464
1465
1466kern_return_t
1467S_msg_set_init_ports (mach_port_t process,
1468 mach_port_t refport,
1469 portarray_t ports,
1470 mach_msg_type_number_t portsCnt)
1471{ return _S_msg_set_init_ports (process, refport, ports, portsCnt); }
1472
1473
1474kern_return_t
1475S_msg_get_init_int (mach_port_t process,
1476 mach_port_t refport,
1477 int which,
1478 int *value)
1479{ return _S_msg_get_init_int (process, refport, which, value); }
1480
1481
1482kern_return_t
1483S_msg_set_init_int (mach_port_t process,
1484 mach_port_t refport,
1485 int which,
1486 int value)
1487{ return _S_msg_set_init_int (process, refport, which, value); }
1488
1489
1490kern_return_t
1491S_msg_get_init_ints (mach_port_t process,
1492 mach_port_t refport,
1493 intarray_t *values,
1494 mach_msg_type_number_t *valuesCnt)
1495{ return _S_msg_get_init_ints (process, refport, values, valuesCnt); }
1496
1497
1498kern_return_t
1499S_msg_set_init_ints (mach_port_t process,
1500 mach_port_t refport,
1501 intarray_t values,
1502 mach_msg_type_number_t valuesCnt)
1503{ return _S_msg_set_init_ints (process, refport, values, valuesCnt); }
1504
1505
1506kern_return_t
1507S_msg_get_dtable (mach_port_t process,
1508 mach_port_t refport,
1509 portarray_t *dtable,
1510 mach_msg_type_name_t *dtablePoly,
1511 mach_msg_type_number_t *dtableCnt)
1512{ return _S_msg_get_dtable (process, refport, dtable, dtablePoly, dtableCnt); }
1513
1514
1515kern_return_t
1516S_msg_set_dtable (mach_port_t process,
1517 mach_port_t refport,
1518 portarray_t dtable,
1519 mach_msg_type_number_t dtableCnt)
1520{ return _S_msg_set_dtable (process, refport, dtable, dtableCnt); }
1521
1522
1523kern_return_t
1524S_msg_get_fd (mach_port_t process,
1525 mach_port_t refport,
1526 int fd,
1527 mach_port_t *port,
1528 mach_msg_type_name_t *portPoly)
1529{ return _S_msg_get_fd (process, refport, fd, port, portPoly); }
1530
1531
1532kern_return_t
1533S_msg_set_fd (mach_port_t process,
1534 mach_port_t refport,
1535 int fd,
1536 mach_port_t port)
1537{ return _S_msg_set_fd (process, refport, fd, port); }
1538
1539
1540kern_return_t
1541S_msg_get_environment (mach_port_t process,
1542 data_t *value,
1543 mach_msg_type_number_t *valueCnt)
1544{ return _S_msg_get_environment (process, value, valueCnt); }
1545
1546
1547kern_return_t
1548S_msg_set_environment (mach_port_t process,
1549 mach_port_t refport,
1550 data_t value,
1551 mach_msg_type_number_t valueCnt)
1552{ return _S_msg_set_environment (process, refport, value, valueCnt); }
1553
1554
1555kern_return_t
1556S_msg_get_env_variable (mach_port_t process,
1557 string_t variable,
1558 data_t *value,
1559 mach_msg_type_number_t *valueCnt)
1560{ return _S_msg_get_env_variable (process, variable, value, valueCnt); }
1561
1562
1563kern_return_t
1564S_msg_set_env_variable (mach_port_t process,
1565 mach_port_t refport,
1566 string_t variable,
1567 string_t value,
1568 boolean_t replace)
1569{ return _S_msg_set_env_variable (process, refport, variable, value, replace); }
1570
1571error_t
1572S_msg_describe_ports (mach_port_t process,
1573 mach_port_t refport,
1574 mach_port_array_t names,
1575 mach_msg_type_number_t namesCnt,
1576 data_t *descriptions,
1577 mach_msg_type_number_t *descriptionsCnt)
1578{
1579 return _S_msg_describe_ports (process, refport, names, namesCnt,
1580 descriptions, descriptionsCnt);
1581}
1582
1583error_t
1584S_msg_report_wait (mach_port_t process, thread_t thread,
1585 string_t desc, mach_msg_id_t *rpc)
1586{
1587 *desc = 0;
1588 *rpc = 0;
1589 return 0;
1590}