diff options
author | Francis Dupont <fdupont@isc.org> | 2016-10-01 01:35:37 +0200 |
---|---|---|
committer | Francis Dupont <fdupont@isc.org> | 2016-10-01 01:35:37 +0200 |
commit | 29b23207c05a7a0ec1a90d42dc4e49d47f9b1a7f (patch) | |
tree | 502b9cbff8cdce72054798e5a6699624640c499e /client/dhclient.c | |
parent | a1372bbec77052d550678db54ee2c10721480177 (diff) | |
download | isc-dhcp-29b23207c05a7a0ec1a90d42dc4e49d47f9b1a7f.tar.gz |
Daemonize sooner (code from bind9/named) (rebased)
Diffstat (limited to 'client/dhclient.c')
-rw-r--r-- | client/dhclient.c | 124 |
1 files changed, 86 insertions, 38 deletions
diff --git a/client/dhclient.c b/client/dhclient.c index f7486c6a..caf80aec 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -84,6 +84,7 @@ u_int16_t remote_port = 0; int dhcp4o6_state = -1; /* -1 = stopped, 0 = polling, 1 = started */ #endif int no_daemon = 0; +int dfd[2] = { -1, -1 }; struct string_list *client_env = NULL; int client_env_count = 0; int onetry = 0; @@ -236,6 +237,51 @@ main(int argc, char **argv) { setlogmask(LOG_UPTO(LOG_INFO)); #endif + /* Parse arguments changing no_daemon */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-r")) { + no_daemon = 1; + } else if (!strcmp(argv[i], "-x")) { + no_daemon = 0; + } else if (!strcmp(argv[i], "-d")) { + no_daemon = 1; + } else if (!strcmp(argv[i], "--version")) { + const char vstring[] = "isc-dhclient-"; + IGNORE_RET(write(STDERR_FILENO, vstring, + strlen(vstring))); + IGNORE_RET(write(STDERR_FILENO, + PACKAGE_VERSION, + strlen(PACKAGE_VERSION))); + IGNORE_RET(write(STDERR_FILENO, "\n", 1)); + exit(0); + } + } + /* When not forbidden prepare to become a daemon */ + if (!no_daemon) { + int pid; + + if (pipe(dfd) == -1) + log_fatal("Can't get pipe: %m"); + if ((pid = fork ()) < 0) + log_fatal("Can't fork daemon: %m"); + if (pid != 0) { + /* Parent: wait for the child to start */ + int n; + + (void) close(dfd[1]); + do { + char buf; + + n = read(dfd[0], &buf, 1); + if (n == 1) + _exit((int)buf); + } while (n == -1 && errno == EINTR); + _exit(1); + } + /* Child */ + (void) close(dfd[0]); + } + /* Set up the isc and dns library managers */ status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB, NULL, NULL); @@ -260,7 +306,7 @@ main(int argc, char **argv) { for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-r")) { release_mode = 1; - no_daemon = 1; + /* no_daemon = 1; */ #ifdef DHCPv6 } else if (!strcmp(argv[i], "-4")) { if (local_family_set && local_family != AF_INET) @@ -288,7 +334,7 @@ main(int argc, char **argv) { #endif /* DHCPv6 */ } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */ release_mode = 0; - no_daemon = 0; + /* no_daemon = 0; */ exit_mode = 1; } else if (!strcmp(argv[i], "-p")) { if (++i == argc) @@ -297,7 +343,7 @@ main(int argc, char **argv) { log_debug("binding to user-specified port %d", ntohs(local_port)); } else if (!strcmp(argv[i], "-d")) { - no_daemon = 1; + /* no_daemon = 1; */ quiet = 0; } else if (!strcmp(argv[i], "-pf")) { if (++i == argc) @@ -422,15 +468,6 @@ main(int argc, char **argv) { std_dhcid = 1; } else if (!strcmp(argv[i], "-v")) { quiet = 0; - } else if (!strcmp(argv[i], "--version")) { - const char vstring[] = "isc-dhclient-"; - IGNORE_RET(write(STDERR_FILENO, vstring, - strlen(vstring))); - IGNORE_RET(write(STDERR_FILENO, - PACKAGE_VERSION, - strlen(PACKAGE_VERSION))); - IGNORE_RET(write(STDERR_FILENO, "\n", 1)); - exit(0); } else if (argv[i][0] == '-') { usage("Unknown command: %s", argv[i]); } else if (interfaces_requested < 0) { @@ -613,7 +650,7 @@ main(int argc, char **argv) { if (release_mode || (wanted_ia_na > 0) || wanted_ia_ta || wanted_ia_pd || (interfaces_requested != 1)) { - usage("Stateless commnad: %s incompatibile with " + usage("Stateless command: %s incompatibile with " "other commands", "-S"); } #if defined(DHCPv6) && defined(DHCP4o6) @@ -621,7 +658,7 @@ main(int argc, char **argv) { #else run_stateless(exit_mode, 0); #endif - return 0; + finish(0); } /* Discover all the network interfaces. */ @@ -663,7 +700,7 @@ main(int argc, char **argv) { if (!persist) { /* Nothing more to do. */ log_info("No broadcast interfaces found - exiting."); - exit(0); + finish(0); } } else if (!release_mode && !exit_mode) { /* Call the script with the list of interfaces. */ @@ -800,16 +837,16 @@ main(int argc, char **argv) { } if (exit_mode) - return 0; + finish(0); if (release_mode) { #ifndef DHCPv6 - return 0; + finish(0); #else if ((local_family == AF_INET6) || dhcpv4_over_dhcpv6) { if (onetry) - return 0; + finish(0); } else - return 0; + finish(0); #endif /* DHCPv6 */ } @@ -852,7 +889,7 @@ main(int argc, char **argv) { /* If we're not supposed to wait before getting the address, don't. */ if (nowait) - go_daemon(); + detach(); /* If we're not going to daemonize, write the pid file now. */ @@ -963,7 +1000,7 @@ void run_stateless(int exit_mode, u_int16_t port) /* If we're not supposed to wait before getting the address, don't. */ if (nowait) - go_daemon(); + detach(); /* If we're not going to daemonize, write the pid file now. */ @@ -1404,7 +1441,7 @@ void bind_lease (client) if (!quiet) log_info("Unable to obtain a lease on first " "try (declined). Exiting."); - exit(2); + finish(2); } else { state_init(client); return; @@ -1433,7 +1470,7 @@ void bind_lease (client) (long)(client->active->renewal - cur_time)); client->state = S_BOUND; reinitialize_interfaces(); - go_daemon(); + detach(); #if defined (NSUPDATE) if (client->config->do_forward_update) dhclient_schedule_updates(client, &client->active->address, 1); @@ -2373,7 +2410,7 @@ void state_panic (cpp) state_bound (client); } reinitialize_interfaces (); - go_daemon (); + detach (); return; } } @@ -2413,7 +2450,7 @@ void state_panic (cpp) if (!quiet) log_info ("Unable to obtain a lease on first try.%s", " Exiting."); - exit (2); + finish(2); } log_info ("No working leases in persistent database - sleeping."); @@ -2427,7 +2464,7 @@ void state_panic (cpp) tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ? random() % 1000000 : cur_tv.tv_usec; add_timeout(&tv, state_init, client, 0, 0); - go_daemon (); + detach (); } void send_request (cpp) @@ -4200,10 +4237,20 @@ int dhcp_option_ev_name (buf, buflen, option) return 1; } -void go_daemon () +void finish (char ret) { - static int state = 0; - int pid; + if (no_daemon || dfd[0] == -1 || dfd[1] == -1) + exit((int)ret); + if (write(dfd[1], &ret, 1) != 1) + log_fatal("write to parent: %m"); + (void) close(dfd[1]); + dfd[0] = dfd[1] = -1; + exit((int)ret); +} + +void detach () +{ + char buf = 0; /* Don't become a daemon if the user requested otherwise. */ if (no_daemon) { @@ -4212,18 +4259,18 @@ void go_daemon () } /* Only do it once. */ - if (state) + if (dfd[0] == -1 || dfd[1] == -1) return; - state = 1; + + /* Signal parent we started successfully. */ + if (write(dfd[1], &buf, 1) != 1) + log_fatal("write to parent: %m"); + (void) close(dfd[1]); + dfd[0] = dfd[1] = -1; /* Stop logging to stderr... */ log_perror = 0; - /* Become a daemon... */ - if ((pid = fork ()) < 0) - log_fatal ("Can't fork daemon: %m"); - else if (pid) - exit (0); /* Become session leader and get pid... */ (void) setsid (); @@ -4240,6 +4287,7 @@ void go_daemon () write_client_pid_file (); IGNORE_RET (chdir("/")); + } void write_client_pid_file () @@ -4376,7 +4424,7 @@ void do_release(client) #if defined(DHCPv6) && defined(DHCP4o6) if (dhcpv4_over_dhcpv6) - exit(0); + finish(0); #endif } @@ -4507,7 +4555,7 @@ static void shutdown_exit (void *foo) /* get rid of the pid if we can */ if (no_pid_file == ISC_FALSE) (void) unlink(path_dhclient_pid); - exit (0); + finish(0); } #if defined (NSUPDATE) |