version 1.15, 2007/02/26 08:32:00 |
version 1.16, 2007/04/25 05:02:17 |
|
|
|
|
#include <ctype.h> |
#include <ctype.h> |
#include <err.h> |
#include <err.h> |
|
#include <errno.h> |
|
#include <paths.h> |
|
#include <signal.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
#include "common.h" |
#include "common.h" |
#include "extern.h" |
#include "extern.h" |
|
|
static void edit(const char *); |
int editit(const char *); |
|
|
/* |
/* |
* Takes the name of a file and opens it with an editor. |
* Takes the name of a file and opens it with an editor. |
*/ |
*/ |
static void |
int |
edit(const char *filename) |
editit(const char *pathname) |
{ |
{ |
int status; |
char *argp[] = {"sh", "-c", NULL, NULL}, *ed, *p; |
|
sig_t sighup, sigint, sigquit; |
pid_t pid; |
pid_t pid; |
const char *editor; |
int st; |
|
|
editor = getenv("VISUAL"); |
ed = getenv("VISUAL"); |
if (editor == NULL) |
if (ed == NULL || ed[0] == '\0') |
editor = getenv("EDITOR"); |
ed = getenv("EDITOR"); |
if (editor == NULL) |
if (ed == NULL || ed[0] == '\0') |
editor = "vi"; |
ed = _PATH_VI; |
|
if (asprintf(&p, "%s %s", ed, pathname) == -1) |
|
return (-1); |
|
argp[2] = p; |
|
|
/* Start editor on temporary file. */ |
top: |
switch (pid = fork()) { |
sighup = signal(SIGHUP, SIG_IGN); |
case 0: |
sigint = signal(SIGINT, SIG_IGN); |
/* child */ |
sigquit = signal(SIGQUIT, SIG_IGN); |
execlp(editor, editor, filename, (void *)NULL); |
if ((pid = fork()) == -1) { |
warn("could not execute editor: %s", editor); |
int saved_errno = errno; |
cleanup(filename); |
|
case -1: |
|
warn("could not fork"); |
|
cleanup(filename); |
|
} |
|
|
|
/* parent */ |
(void)signal(SIGHUP, sighup); |
/* Wait for editor to exit. */ |
(void)signal(SIGINT, sigint); |
if (waitpid(pid, &status, 0) == -1) { |
(void)signal(SIGQUIT, sigquit); |
warn("waitpid"); |
if (saved_errno == EAGAIN) { |
cleanup(filename); |
sleep(1); |
|
goto top; |
|
} |
|
free(p); |
|
errno = saved_errno; |
|
return (-1); |
} |
} |
|
if (pid == 0) { |
/* Check that editor terminated normally. */ |
execv(_PATH_BSHELL, argp); |
if (!WIFEXITED(status)) { |
_exit(127); |
warn("%s terminated abnormally", editor); |
|
cleanup(filename); |
|
} |
} |
|
free(p); |
|
for (;;) { |
|
if (waitpid(pid, &st, 0) == -1) { |
|
if (errno != EINTR) |
|
return (-1); |
|
} else |
|
break; |
|
} |
|
(void)signal(SIGHUP, sighup); |
|
(void)signal(SIGINT, sigint); |
|
(void)signal(SIGQUIT, sigquit); |
|
if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) { |
|
errno = ECHILD; |
|
return (-1); |
|
} |
|
return (0); |
} |
} |
|
|
/* |
/* |
|
|
free(text); |
free(text); |
|
|
/* Edit temp file. */ |
/* Edit temp file. */ |
edit(filename); |
if (editit(filename) == -1) { |
|
if (errno == ECHILD) |
|
warnx("editor terminated abnormally"); |
|
else |
|
warn("error editing %s", filename); |
|
cleanup(filename); |
|
} |
|
|
/* Open temporary file. */ |
/* Open temporary file. */ |
if (!(file = fopen(filename, "r"))) { |
if (!(file = fopen(filename, "r"))) { |