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 /* Always deallocate the extra reference this message carries. */
1206 if (MACH_PORT_VALID (credential)(((credential) != ((mach_port_t) 0)) && ((credential)
!= ((mach_port_t) ~0)))
)
1207 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), credential);
1208
1209 if (credential != host_priv)
1210 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1211
1212 fail = record_essential_task (name, task);
1213 if (fail)
1214 return fail;
1215
1216 if (!booted)
1217 {
1218 if (!strcmp (name, "auth"))
1219 authinit = 1;
1220 else if (!strcmp (name, "exec"))
1221 {
1222 execinit = 1;
1223 mach_port_t execproc;
1224 proc_task2proc (procserver, task, &execproc);
1225 proc_mark_important (execproc);
1226 }
1227 else if (!strcmp (name, "proc"))
1228 procinit = 1;
1229
1230 if (authinit && execinit && procinit)
1231 {
1232 /* Reply to this RPC, after that everything
1233 is ready for real startup to begin. */
1234 startup_essential_task_reply (reply, replytype, 0);
1235
1236 init_stdarrays ();
1237 frob_kernel_process ();
1238
1239 launch_system ();
1240
1241 booted = 1;
1242
1243 return MIG_NO_REPLY-305;
1244 }
1245 }
1246
1247 return 0;
1248}
1249
1250kern_return_t
1251S_startup_request_notification (mach_port_t server,
1252 mach_port_t notify,
1253 char *name)
1254{
1255 struct ntfy_task *nt;
1256
1257 request_dead_name (notify);
1258
1259 /* Note that the ntfy_tasks list is kept in inverse order of the
1260 calls; this is important. We need later notification requests
1261 to get executed first. */
1262 nt = malloc (sizeof (struct ntfy_task));
1263 nt->notify_port = notify;
1264 nt->next = ntfy_tasks;
1265 ntfy_tasks = nt;
1266 nt->name = malloc (strlen (name) + 1);
1267 strcpy (nt->name, name);
1268 return 0;
1269}
1270
1271kern_return_t
1272do_mach_notify_dead_name (mach_port_t notify,
1273 mach_port_t name)
1274{
1275 struct ntfy_task *nt, *pnt;
1276 struct ess_task *et;
1277
1278 assert (notify == startup)((notify == startup) ? (void) (0) : __assert_fail ("notify == startup"
, "../../init/init.c", 1278, __PRETTY_FUNCTION__))
;
1279
1280 /* Deallocate the extra reference the notification carries. */
1281 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), name);
1282
1283 for (et = ess_tasks; et != NULL((void*)0); et = et->next)
1284 if (et->task_port == name)
1285 /* An essential task has died. */
1286 {
1287 error (0, 0, "Crashing system; essential task %s died", et->name);
1288 crash_system ();
1289 }
1290
1291 for (nt = ntfy_tasks, pnt = NULL((void*)0); nt != NULL((void*)0); pnt = nt, nt = nt->next)
1292 if (nt->notify_port == name)
1293 {
1294 /* Someone who wanted to be notified is gone. */
1295 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), name);
1296 if (pnt != NULL((void*)0))
1297 pnt->next = nt->next;
1298 else
1299 ntfy_tasks = nt->next;
1300 free (nt);
1301
1302 return 0;
1303 }
1304
1305 if (! booted)
1306 {
1307 /* The system has not come up yet, so essential tasks are not yet
1308 registered. But the essential servers involved in the bootstrap
1309 handshake might crash before completing it, so we have requested
1310 dead-name notification on those tasks. */
1311 static const struct { task_t *taskp; const char *name; } boots[] =
1312 {
1313 {&fstask, "bootstrap filesystem"},
1314 {&authtask, "auth"},
1315 {&proctask, "proc"},
1316 };
1317 size_t i;
1318 for (i = 0; i < sizeof boots / sizeof boots[0]; ++i)
1319 if (name == *boots[i].taskp)
1320 {
1321 error (0, 0, "Crashing system; %s server died during bootstrap",
1322 boots[i].name);
1323 crash_mach ();
1324 }
1325 error (0, 0, "BUG! Unexpected dead-name notification (name %#zx)",
1326 name);
1327 crash_mach ();
1328 }
1329
1330 return 0;
1331}
1332
1333kern_return_t
1334S_startup_reboot (mach_port_t server,
1335 mach_port_t refpt,
1336 int code)
1337{
1338 if (refpt != host_priv)
1339 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1340
1341 reboot_system (code);
1342 for (;;);
1343}
1344
1345/* Stubs for unused notification RPCs. */
1346
1347kern_return_t
1348do_mach_notify_port_destroyed (mach_port_t notify,
1349 mach_port_t rights)
1350{
1351 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1352}
1353
1354kern_return_t
1355do_mach_notify_send_once (mach_port_t notify)
1356{
1357 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1358}
1359
1360kern_return_t
1361do_mach_notify_no_senders (mach_port_t port, mach_port_mscount_t mscount)
1362{
1363 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1364}
1365
1366kern_return_t
1367do_mach_notify_port_deleted (mach_port_t notify,
1368 mach_port_t name)
1369{
1370 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1371}
1372
1373kern_return_t
1374do_mach_notify_msg_accepted (mach_port_t notify,
1375 mach_port_t name)
1376{
1377 return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
1378}
1379
1380/* msg server */
1381
1382kern_return_t
1383S_msg_sig_post_untraced (mach_port_t msgport,
1384 mach_port_t reply, mach_msg_type_name_t reply_type,
1385 int signo, natural_t sigcode, mach_port_t refport)
1386{
1387 if (refport != mach_task_self ()((__mach_task_self_ + 0)))
1388 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1389 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), refport);
1390
1391 /* Reply immediately */
1392 msg_sig_post_untraced_reply (reply, reply_type, 0);
1393
1394 process_signal (signo);
1395 return MIG_NO_REPLY-305;
1396}
1397
1398kern_return_t
1399S_msg_sig_post (mach_port_t msgport,
1400 mach_port_t reply, mach_msg_type_name_t reply_type,
1401 int signo, natural_t sigcode, mach_port_t refport)
1402{
1403 if (refport != mach_task_self ()((__mach_task_self_ + 0)))
1404 return EPERM((0x10 << 26) | ((1) & 0x3fff));
1405 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), refport);
1406
1407 /* Reply immediately */
1408 msg_sig_post_reply (reply, reply_type, 0);
1409
1410 process_signal (signo);
1411 return MIG_NO_REPLY-305;
1412}
1413
1414
1415/* For the rest of the msg functions, just call the C library's
1416 internal server stubs usually run in the signal thread. */
1417
1418kern_return_t
1419S_msg_proc_newids (mach_port_t process,
1420 mach_port_t task,
1421 pid_t ppid,
1422 pid_t pgrp,
1423 int orphaned)
1424{ return _S_msg_proc_newids (process, task, ppid, pgrp, orphaned); }
1425
1426
1427kern_return_t
1428S_msg_add_auth (mach_port_t process,
1429 auth_t auth)
1430{ return _S_msg_add_auth (process, auth); }
1431
1432
1433kern_return_t
1434S_msg_del_auth (mach_port_t process,
1435 mach_port_t task,
1436 intarray_t uids,
1437 mach_msg_type_number_t uidsCnt,
1438 intarray_t gids,
1439 mach_msg_type_number_t gidsCnt)
1440{ return _S_msg_del_auth (process, task, uids, uidsCnt, gids, gidsCnt); }
1441
1442
1443kern_return_t
1444S_msg_get_init_port (mach_port_t process,
1445 mach_port_t refport,
1446 int which,
1447 mach_port_t *port,
1448 mach_msg_type_name_t *portPoly)
1449{ return _S_msg_get_init_port (process, refport, which, port, portPoly); }
1450
1451
1452kern_return_t
1453S_msg_set_init_port (mach_port_t process,
1454 mach_port_t refport,
1455 int which,
1456 mach_port_t port)
1457{ return _S_msg_set_init_port (process, refport, which, port); }
1458
1459
1460kern_return_t
1461S_msg_get_init_ports (mach_port_t process,
1462 mach_port_t refport,
1463 portarray_t *ports,
1464 mach_msg_type_name_t *portsPoly,
1465 mach_msg_type_number_t *portsCnt)
1466{ return _S_msg_get_init_ports (process, refport, ports, portsPoly, portsCnt); }
1467
1468
1469kern_return_t
1470S_msg_set_init_ports (mach_port_t process,
1471 mach_port_t refport,
1472 portarray_t ports,
1473 mach_msg_type_number_t portsCnt)
1474{ return _S_msg_set_init_ports (process, refport, ports, portsCnt); }
1475
1476
1477kern_return_t
1478S_msg_get_init_int (mach_port_t process,
1479 mach_port_t refport,
1480 int which,
1481 int *value)
1482{ return _S_msg_get_init_int (process, refport, which, value); }
1483
1484
1485kern_return_t
1486S_msg_set_init_int (mach_port_t process,
1487 mach_port_t refport,
1488 int which,
1489 int value)
1490{ return _S_msg_set_init_int (process, refport, which, value); }
1491
1492
1493kern_return_t
1494S_msg_get_init_ints (mach_port_t process,
1495 mach_port_t refport,
1496 intarray_t *values,
1497 mach_msg_type_number_t *valuesCnt)
1498{ return _S_msg_get_init_ints (process, refport, values, valuesCnt); }
1499
1500
1501kern_return_t
1502S_msg_set_init_ints (mach_port_t process,
1503 mach_port_t refport,
1504 intarray_t values,
1505 mach_msg_type_number_t valuesCnt)
1506{ return _S_msg_set_init_ints (process, refport, values, valuesCnt); }
1507
1508
1509kern_return_t
1510S_msg_get_dtable (mach_port_t process,
1511 mach_port_t refport,
1512 portarray_t *dtable,
1513 mach_msg_type_name_t *dtablePoly,
1514 mach_msg_type_number_t *dtableCnt)
1515{ return _S_msg_get_dtable (process, refport, dtable, dtablePoly, dtableCnt); }
1516
1517
1518kern_return_t
1519S_msg_set_dtable (mach_port_t process,
1520 mach_port_t refport,
1521 portarray_t dtable,
1522 mach_msg_type_number_t dtableCnt)
1523{ return _S_msg_set_dtable (process, refport, dtable, dtableCnt); }
1524
1525
1526kern_return_t
1527S_msg_get_fd (mach_port_t process,
1528 mach_port_t refport,
1529 int fd,
1530 mach_port_t *port,
1531 mach_msg_type_name_t *portPoly)
1532{ return _S_msg_get_fd (process, refport, fd, port, portPoly); }
1533
1534
1535kern_return_t
1536S_msg_set_fd (mach_port_t process,
1537 mach_port_t refport,
1538 int fd,
1539 mach_port_t port)
1540{ return _S_msg_set_fd (process, refport, fd, port); }
1541
1542
1543kern_return_t
1544S_msg_get_environment (mach_port_t process,
1545 data_t *value,
1546 mach_msg_type_number_t *valueCnt)
1547{ return _S_msg_get_environment (process, value, valueCnt); }
1548
1549
1550kern_return_t
1551S_msg_set_environment (mach_port_t process,
1552 mach_port_t refport,
1553 data_t value,
1554 mach_msg_type_number_t valueCnt)
1555{ return _S_msg_set_environment (process, refport, value, valueCnt); }
1556
1557
1558kern_return_t
1559S_msg_get_env_variable (mach_port_t process,
1560 string_t variable,
1561 data_t *value,
1562 mach_msg_type_number_t *valueCnt)
1563{ return _S_msg_get_env_variable (process, variable, value, valueCnt); }
1564
1565
1566kern_return_t
1567S_msg_set_env_variable (mach_port_t process,
1568 mach_port_t refport,
1569 string_t variable,
1570 string_t value,
1571 boolean_t replace)
1572{ return _S_msg_set_env_variable (process, refport, variable, value, replace); }
1573
1574error_t
1575S_msg_describe_ports (mach_port_t process,
1576 mach_port_t refport,
1577 mach_port_array_t names,
1578 mach_msg_type_number_t namesCnt,
1579 data_t *descriptions,
1580 mach_msg_type_number_t *descriptionsCnt)
1581{
1582 return _S_msg_describe_ports (process, refport, names, namesCnt,
1583 descriptions, descriptionsCnt);
1584}
1585
1586error_t
1587S_msg_report_wait (mach_port_t process, thread_t thread,
1588 string_t desc, mach_msg_id_t *rpc)
1589{
1590 *desc = 0;
1591 *rpc = 0;
1592 return 0;
1593}