summaryrefslogtreecommitdiff
path: root/usr.bin/mail/edit.c
diff options
context:
space:
mode:
authorRay Lai <ray@cvs.openbsd.org>2007-08-31 23:14:22 +0000
committerRay Lai <ray@cvs.openbsd.org>2007-08-31 23:14:22 +0000
commita91c7b12049b201657e775fb23f4ba66389f8ab5 (patch)
tree99e550fba0d0733e4b4ceee53e4527715fbd1e9f /usr.bin/mail/edit.c
parentcfd7923e0f652a21ff0ba1d2b5452cbff45fc84d (diff)
Copy editit() from sendbug, synchronizing editor calling code.
OK otto, millert, beck, mbalmer, deraadt.
Diffstat (limited to 'usr.bin/mail/edit.c')
-rw-r--r--usr.bin/mail/edit.c79
1 files changed, 74 insertions, 5 deletions
diff --git a/usr.bin/mail/edit.c b/usr.bin/mail/edit.c
index a74e7be4d2c..9ac54cf0481 100644
--- a/usr.bin/mail/edit.c
+++ b/usr.bin/mail/edit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: edit.c,v 1.14 2006/10/10 21:38:16 cloder Exp $ */
+/* $OpenBSD: edit.c,v 1.15 2007/08/31 23:14:21 ray Exp $ */
/* $NetBSD: edit.c,v 1.5 1996/06/08 19:48:20 christos Exp $ */
/*
@@ -34,14 +34,20 @@
#if 0
static const char sccsid[] = "@(#)edit.c 8.1 (Berkeley) 6/6/93";
#else
-static const char rcsid[] = "$OpenBSD: edit.c,v 1.14 2006/10/10 21:38:16 cloder Exp $";
+static const char rcsid[] = "$OpenBSD: edit.c,v 1.15 2007/08/31 23:14:21 ray Exp $";
#endif
#endif /* not lint */
+#include <sys/types.h>
+#include <sys/wait.h>
+
#include "rcv.h"
+#include <errno.h>
#include <fcntl.h>
#include "extern.h"
+int editit(const char *, const char *);
+
/*
* Mail -- a mail program
*
@@ -184,9 +190,16 @@ run_editor(FILE *fp, off_t size, int type, int readonly)
goto out;
}
nf = NULL;
- if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NULL)
- edit = type == 'e' ? _PATH_EX : _PATH_VI;
- if (run_command(edit, 0, 0, -1, tempname, NULL, NULL) < 0) {
+ if (type == 'e') {
+ edit = value("EDITOR");
+ if (edit == NULL || edit[0] == '\0')
+ edit = _PATH_EX;
+ } else {
+ edit = value("VISUAL");
+ if (edit == NULL || edit[0] == '\0')
+ edit = _PATH_VI;
+ }
+ if (editit(edit, tempname) == -1) {
(void)rm(tempname);
goto out;
}
@@ -218,3 +231,59 @@ run_editor(FILE *fp, off_t size, int type, int readonly)
out:
return(nf);
}
+
+/*
+ * Execute an editor on the specified pathname, which is interpreted
+ * from the shell. This means flags may be included.
+ *
+ * Returns -1 on error, or the exit value on success.
+ */
+int
+editit(const char *ed, const char *pathname)
+{
+ char *argp[] = {"sh", "-c", NULL, NULL}, *p;
+ sig_t sighup, sigint, sigquit;
+ pid_t pid;
+ int saved_errno, st;
+
+ if (ed == NULL)
+ ed = getenv("VISUAL");
+ if (ed == NULL || ed[0] == '\0')
+ ed = getenv("EDITOR");
+ if (ed == NULL || ed[0] == '\0')
+ ed = _PATH_VI;
+ if (asprintf(&p, "%s %s", ed, pathname) == -1)
+ return (-1);
+ argp[2] = p;
+
+ sighup = signal(SIGHUP, SIG_IGN);
+ sigint = signal(SIGINT, SIG_IGN);
+ sigquit = signal(SIGQUIT, SIG_IGN);
+ if ((pid = fork()) == -1)
+ goto fail;
+ if (pid == 0) {
+ execv(_PATH_BSHELL, argp);
+ _exit(127);
+ }
+ while (waitpid(pid, &st, 0) == -1)
+ if (errno != EINTR)
+ goto fail;
+ free(p);
+ (void)signal(SIGHUP, sighup);
+ (void)signal(SIGINT, sigint);
+ (void)signal(SIGQUIT, sigquit);
+ if (!WIFEXITED(st)) {
+ errno = EINTR;
+ return (-1);
+ }
+ return (WEXITSTATUS(st));
+
+ fail:
+ saved_errno = errno;
+ (void)signal(SIGHUP, sighup);
+ (void)signal(SIGINT, sigint);
+ (void)signal(SIGQUIT, sigquit);
+ free(p);
+ errno = saved_errno;
+ return (-1);
+}