* lib/Makefile.am: Added lib/spawn.c and lib/spawn.h.
* lib/nscd.c, lib/spawn.c, lib/spawn.h: It is not possible to
differentiate between an nscd failure, and a failure to execute
due to no nscd with posix_spawn. Use our own run_command routine.
* src/userdel.c: Use run_command()
+2011-08-20 Jonathan Nieder <jrnieder@gmail.com>
+
+ * lib/Makefile.am: Added lib/spawn.c and lib/spawn.h.
+ * lib/nscd.c, lib/spawn.c, lib/spawn.h: It is not possible to
+ differentiate between an nscd failure, and a failure to execute
+ due to no nscd with posix_spawn. Use our own run_command routine.
+ * src/userdel.c: Use run_command()
+
2011-08-15 Nicolas François <nicolas.francois@centraliens.net>
* src/groupmod.c: Ignore return value from snprintf.
shadowio.c \
shadowio.h \
shadowmem.c \
+ spawn.c \
+ spawn.h \
utent.c
if WITH_TCB
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
+#include "exitcodes.h"
#include "defines.h"
+#include "spawn.h"
#include "nscd.h"
#define MSG_NSCD_FLUSH_CACHE_FAILED "Failed to flush the nscd cache.\n"
*/
int nscd_flush_cache (const char *service)
{
- pid_t pid, termpid;
- int err, status;
- char *spawnedArgs[] = {"/usr/sbin/nscd", "nscd", "-i", service, NULL};
- char *spawnedEnv[] = {NULL};
+ pid_t pid;
+ int err, status, code;
+ const char *spawnedArgs[] = {"/usr/sbin/nscd", "nscd", "-i", service, NULL};
+ const char *spawnedEnv[] = {NULL};
- /* spawn process */
- err = posix_spawn (&pid, spawnedArgs[0], NULL, NULL,
- spawnedArgs, spawnedEnv);
- if(0 != err)
+ err = run_command (spawnedArgs[0], spawnedArgs, spawnedEnv, &status);
+ if (0 != err)
{
+ /* run_command writes its own more detailed message. */
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
- (void) fprintf (stderr, "posix_spawn() error=%d\n", err);
return -1;
}
-
- /* Wait for the spawned process to exit */
- termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
- if (-1 == termpid)
+ code = WIFEXITED (status) ? WEXITSTATUS (status)
+ : (WTERMSIG (status) + 128);
+ if (code == E_CMD_NOTFOUND)
{
- (void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
- perror("waitpid");
- return -1;
+ /* nscd is not installed, or it is installed but uses an
+ interpreter that is missing. Probably the former. */
+ return 0;
}
- else if (termpid != pid)
+ if (code != 0)
{
+ (void) fprintf (stderr, "nscd exited with status %d", code);
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
- (void) fprintf (stderr, "waitpid returned %ld != %ld\n",
- (long int) termpid, (long int) pid);
return -1;
}
-
return 0;
}
#else /* USE_NSCD */
--- /dev/null
+/*
+ * Copyright (c) 2011, Jonathan Nieder
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD
+ * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+#include "exitcodes.h"
+#include "spawn.h"
+
+extern char **environ;
+
+int run_command (const char *cmd, const char *argv[], const char *envp[],
+ int *status)
+{
+ pid_t pid, wpid;
+
+ if (!envp)
+ envp = (const char **)environ;
+ pid = fork ();
+ if (pid == 0) {
+ execve (cmd, (char * const *) argv, (char * const *) envp);
+ if (errno == ENOENT)
+ exit (E_CMD_NOTFOUND);
+ perror(cmd);
+ exit (E_CMD_NOEXEC);
+ } else if ((pid_t)-1 == pid) {
+ int saved_errno = errno;
+ perror ("fork");
+ errno = saved_errno;
+ return -1;
+ }
+
+ do {
+ wpid = waitpid (pid, status, 0);
+ } while ((pid_t)-1 == wpid && errno == EINTR);
+
+ if ((pid_t)-1 == wpid) {
+ int saved_errno = errno;
+ perror ("waitpid");
+ return -1;
+ } else if (wpid != pid) {
+ (void) fprintf (stderr, "waitpid returned %ld != %ld\n",
+ (long int) wpid, (long int) pid);
+ errno = ECHILD;
+ return -1;
+ }
+ return 0;
+}
--- /dev/null
+#ifndef _SPAWN_H
+#define _SPAWN_H
+
+extern int run_command (const char *cmd, const char *argv[],
+ const char *envp[], int *status);
+
+#endif
#ifdef SHADOWGRP
#include "sgroupio.h"
#endif /* SHADOWGRP */
+#include "spawn.h"
#ifdef WITH_TCB
#include <tcb.h>
#include "tcbfuncs.h"
static void user_cancel (const char *user)
{
const char *cmd;
+ const char *argv[3];
pid_t pid, wpid;
int status;
if (NULL == cmd) {
return;
}
- pid = fork ();
- if (pid == 0) {
- execl (cmd, cmd, user, (char *) 0);
- perror (cmd);
- exit (errno == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
- } else if ((pid_t)-1 == pid) {
- perror ("fork");
- return;
- }
- do {
- wpid = wait (&status);
- } while ((wpid != pid) && ((pid_t)-1 != wpid));
+ argv[0] = cmd;
+ argv[1] = user;
+ argv[2] = (char *)0;
+ (void) run_command (cmd, argv, NULL, &status);
}
#ifdef EXTRA_CHECK_HOME_DIR