Date: Mon, 24 Apr 2006 22:50:18 GMT From: Alex Kozlov <spam@rm-rf.kiev.ua> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/96248: vipw fail on RO /etc Message-ID: <200604242250.k3OMoInb087183@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/96248; it has been noted by GNATS. From: Alex Kozlov <spam@rm-rf.kiev.ua> To: Maxim Konovalov <maxim@macomnet.ru> Cc: bug-followup@freebsd.org Subject: Re: bin/96248: vipw fail on RO /etc Date: Tue, 25 Apr 2006 01:44:02 +0300 On Mon, Apr 24, 2006 at 11:16:01PM +0400, Maxim Konovalov wrote: > On Mon, 24 Apr 2006, 21:46+0300, Alex Kozlov wrote: > > > Hi, Maxim > > > > No need to touch pw_util. > > > > Have pw_tmp in one certain place will be nice, but different fs problem... > > Hmm. > > > > Much easier to teach vipw call PAGER if pw_edit fall on RO fs. > > > > This patch can be accepted? If no, you may close PR. > > I haven't seen any patches yet but personally don't see much sense in > such subtle mechanism. It trivial. Something like this: --- vipw.c Tue Apr 19 19:18:07 2006 +++ vipw.c.new Tue Apr 25 00:16:16 2006 @@ -50,9 +50,13 @@ #include <sys/types.h> #include <sys/stat.h> +#include <sys/errno.h> +#include <sys/wait.h> #include <err.h> +#include <libgen.h> #include <pwd.h> +#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -66,9 +70,14 @@ main(int argc, char *argv[]) { const char *passwd_dir = NULL; + const char *pager; int ch, pfd, tfd; + int pstat; char *line; size_t len; + struct sigaction sa, sa_int, sa_quit; + sigset_t oldsigset, sigset; + static pid_t pagerpid = -1; while ((ch = getopt(argc, argv, "d:")) != -1) switch (ch) { @@ -93,8 +102,67 @@ err(1, "pw_lock()"); } if ((tfd = pw_tmp(pfd)) == -1) { - pw_fini(); - err(1, "pw_tmp()"); + if (errno == EROFS) { + /* pw_view */ + + (void)close(tfd); + + if ((pager = getenv("PAGER")) == NULL) + //pager = _PATH_MORE + pager = "/usr/bin/more"; + + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGINT, &sa, &sa_int); + sigaction(SIGQUIT, &sa, &sa_quit); + sigemptyset(&sigset); + sigaddset(&sigset, SIGCHLD); + sigprocmask(SIG_BLOCK, &sigset, &oldsigset); + switch ((pagerpid = fork())) { + case -1: + err(1, "pw_view()"); + case 0: + sigaction(SIGINT, &sa_int, NULL); + sigaction(SIGQUIT, &sa_quit, NULL); + sigprocmask(SIG_SETMASK, &oldsigset, NULL); + + errno = 0; + dup2(pfd, STDIN_FILENO); + execlp(pager, basename(pager), NULL, (char *)NULL); + _exit(errno); + default: + (void)close(pfd); + pw_fini(); + /* parent */ + break; + } + + for (;;) { + if (waitpid(pagerpid, &pstat, WUNTRACED) == -1) { + if (errno == EINTR) + continue; + pagerpid = -1; + break; + } else if (WIFSTOPPED(pstat)) { + raise(WSTOPSIG(pstat)); + } else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0) { + pagerpid = -1; + break; + } else { + pagerpid = -1; + break; + } + } + sigaction(SIGINT, &sa_int, NULL); + sigaction(SIGQUIT, &sa_quit, NULL); + sigprocmask(SIG_SETMASK, &oldsigset, NULL); + + exit(0); + } else { + pw_fini(); + err(1, "pw_tmp()"); + } } (void)close(tfd); /* Force umask for partial writes made in the edit phase */ > I believe a simple script could solve the problem in your environment. Almost any missing features can be done with wrapper script. But programs continue to improve. Also I don't want script in sudo case. P.S. Btw, lib/libutil don't respect NO_INET6 knob. Fix is simple. Shall I fill another PR? -- Adios
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200604242250.k3OMoInb087183>