X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/blobdiff_plain/98b9b13628a7613868e0fda618e6303961932550..9d966eb7af70d029a9b4862efb67b0c90d32688e:/server/admin.c diff --git a/server/admin.c b/server/admin.c index 78188f54..ad44132f 100644 --- a/server/admin.c +++ b/server/admin.c @@ -2470,12 +2470,12 @@ void a_daemon(void) { flags |= F_DAEMON; } * @gid_t g@ = group to own the socket * @mode_t m@ = permissions to set on the socket * - * Returns: --- + * Returns: Zero on success, @-1@ on failure. * * Use: Creates the admin listening socket. */ -void a_listen(const char *name, uid_t u, gid_t g, mode_t m) +int a_listen(const char *name, uid_t u, gid_t g, mode_t m) { int fd; int n = 5; @@ -2488,7 +2488,7 @@ void a_listen(const char *name, uid_t u, gid_t g, mode_t m) sz = strlen(name) + 1; if (sz > sizeof(sun.sun_path)) { a_warn("ADMIN", "admin-socket", "%s", name, "name-too-long", A_END); - exit(EXIT_FAILURE); + goto fail_0; } BURN(sun); sun.sun_family = AF_UNIX; @@ -2502,7 +2502,7 @@ again: if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "create-failed", "?ERRNO", A_END); - exit(EXIT_FAILURE); + goto fail_1; } if (bind(fd, (struct sockaddr *)&sun, sz) < 0) { struct stat st; @@ -2510,34 +2510,34 @@ again: if (errno != EADDRINUSE) { a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "bind-failed", "?ERRNO", A_END); - exit(EXIT_FAILURE); + goto fail_2; } if (!n) { a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "too-many-retries", A_END); - exit(EXIT_FAILURE); + goto fail_2; } n--; if (!connect(fd, (struct sockaddr *)&sun, sz)) { a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "already-in-use", A_END); - exit(EXIT_FAILURE); + goto fail_2; } if (errno != ECONNREFUSED) { a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "bind-failed", "?ERR", e, A_END); - exit(EXIT_FAILURE); + goto fail_2; } if (stat(sun.sun_path, &st)) { if (errno == ENOENT) { close(fd); goto again; } a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "stat-failed", "?ERRNO", A_END); - exit(EXIT_FAILURE); + goto fail_2; } if (!S_ISSOCK(st.st_mode)) { a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "not-a-socket", A_END); - exit(EXIT_FAILURE); + goto fail_2; } T( trace(T_ADMIN, "admin: stale socket found; removing it"); ) unlink(sun.sun_path); @@ -2547,26 +2547,39 @@ again: if (chown(sun.sun_path, u, g)) { a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "chown-failed", "?ERRNO", A_END); - exit(EXIT_FAILURE); + goto fail_3; } if (chmod(sun.sun_path, m)) { a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "chmod-failed", "?ERRNO", A_END); - exit(EXIT_FAILURE); + goto fail_3; } - umask(omask); fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); if (listen(fd, 5)) { a_warn("ADMIN", "admin-socket", "%s", sun.sun_path, "listen-failed", "?ERRNO", A_END); - exit(EXIT_FAILURE); + goto fail_3; } + umask(omask); /* --- Listen to the socket --- */ sel_initfile(&sel, &sock, fd, SEL_READ, a_accept, 0); sel_addfile(&sock); sockname = name; + + return (0); + + /* --- Clean up if things go sideways --- */ + +fail_3: + unlink(sun.sun_path); +fail_2: + close(fd); +fail_1: + umask(omask); +fail_0: + return (-1); } /* --- @a_unlisten@ --- * @@ -2633,21 +2646,17 @@ void a_signals(void) * * Arguments: --- * - * Returns: --- + * Returns: Zero on success, @-1@ on failure. * * Use: Creates the admin listening socket. */ -void a_init(void) +int a_init(void) { #ifdef HAVE_LIBADNS int err; #endif - /* --- Create services table --- */ - - sym_create(&a_svcs); - /* --- Prepare the background name resolver --- */ #ifdef HAVE_LIBADNS @@ -2657,12 +2666,20 @@ void a_init(void) adns_if_noautosys), 0)) != 0) { a_warn("ADMIN", "adns-init-failed", "?ERRNO", A_END); - exit(EXIT_FAILURE); + return (-1); } sel_addhook(&sel, &hook, before_select, after_select, 0); #else bres_init(&sel); #endif + + /* --- Create services table --- */ + + sym_create(&a_svcs); + + /* --- All done --- */ + + return (0); } /*----- That's all, folks -------------------------------------------------*/