mirror of
https://github.com/sudo-project/sudo.git
synced 2025-08-30 13:58:05 +00:00
Keep the temp file open instead of re-opening after the editor has exited.
This commit is contained in:
33
sudo_edit.c
33
sudo_edit.c
@@ -70,12 +70,13 @@ int sudo_edit(argc, argv)
|
|||||||
const char *tmpdir;
|
const char *tmpdir;
|
||||||
char **nargv, **ap, *editor, *cp;
|
char **nargv, **ap, *editor, *cp;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
int i, ac, ofd, tfd, nargc, rval;
|
int i, ac, ofd, nargc, rval;
|
||||||
sigaction_t sa;
|
sigaction_t sa;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
struct tempfile {
|
struct tempfile {
|
||||||
char *tfile;
|
char *tfile;
|
||||||
char *ofile;
|
char *ofile;
|
||||||
|
int tfd;
|
||||||
time_t omtime; /* XXX - use st_mtimespec / st_mtim? */
|
time_t omtime; /* XXX - use st_mtimespec / st_mtim? */
|
||||||
off_t osize;
|
off_t osize;
|
||||||
} *tf;
|
} *tf;
|
||||||
@@ -93,13 +94,13 @@ int sudo_edit(argc, argv)
|
|||||||
tmpdir = _PATH_TMP;
|
tmpdir = _PATH_TMP;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For each file specified, by the user, make a tempoary version
|
* For each file specified by the user, make a temporary version
|
||||||
* and copy the contents of the original to it. We make these files
|
* and copy the contents of the original to it. We make these files
|
||||||
* as root so the user can't steal them out from under us until we are
|
* as root so the user can't steal them out from under us until we are
|
||||||
* done writing (and at that point the user will be able to edit the
|
* done writing (and at that point the user will be able to edit the
|
||||||
* file anyway).
|
* file anyway).
|
||||||
* XXX - It would be nice to lock the original files but that means
|
* XXX - It would be nice to lock the original files but that means
|
||||||
* keeping an fd open for each file.
|
* keeping an extra fd open for each file.
|
||||||
*/
|
*/
|
||||||
tf = emalloc2(argc - 1, sizeof(*tf));
|
tf = emalloc2(argc - 1, sizeof(*tf));
|
||||||
memset(tf, 0, (argc - 1) * sizeof(*tf));
|
memset(tf, 0, (argc - 1) * sizeof(*tf));
|
||||||
@@ -135,13 +136,13 @@ int sudo_edit(argc, argv)
|
|||||||
else
|
else
|
||||||
cp = tf[i].ofile;
|
cp = tf[i].ofile;
|
||||||
easprintf(&tf[i].tfile, "%s%s.XXXXXXXX", tmpdir, cp);
|
easprintf(&tf[i].tfile, "%s%s.XXXXXXXX", tmpdir, cp);
|
||||||
if ((tfd = mkstemp(tf[i].tfile)) == -1) {
|
if ((tf[i].tfd = mkstemp(tf[i].tfile)) == -1) {
|
||||||
warn("mkstemp");
|
warn("mkstemp");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (ofd != -1) {
|
if (ofd != -1) {
|
||||||
while ((nread = read(ofd, buf, sizeof(buf))) != 0) {
|
while ((nread = read(ofd, buf, sizeof(buf))) != 0) {
|
||||||
if ((nwritten = write(tfd, buf, nread)) != nread) {
|
if ((nwritten = write(tf[i].tfd, buf, nread)) != nread) {
|
||||||
if (nwritten == -1)
|
if (nwritten == -1)
|
||||||
warn("%s", tf[i].tfile);
|
warn("%s", tf[i].tfile);
|
||||||
else
|
else
|
||||||
@@ -149,15 +150,13 @@ int sudo_edit(argc, argv)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(ofd);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_FCHOWN
|
#ifdef HAVE_FCHOWN
|
||||||
fchown(tfd, user_uid, user_gid);
|
fchown(tf[i].tfd, user_uid, user_gid);
|
||||||
#else
|
#else
|
||||||
chown(tf[i].tfile, user_uid, user_gid);
|
chown(tf[i].tfile, user_uid, user_gid);
|
||||||
#endif
|
#endif
|
||||||
if (ofd != -1)
|
|
||||||
close(ofd);
|
|
||||||
close(tfd);
|
|
||||||
touch(tf[i].tfile, tf[i].omtime);
|
touch(tf[i].tfile, tf[i].omtime);
|
||||||
}
|
}
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
@@ -214,6 +213,7 @@ int sudo_edit(argc, argv)
|
|||||||
(void) sigaction(SIGINT, &saved_sa_int, NULL);
|
(void) sigaction(SIGINT, &saved_sa_int, NULL);
|
||||||
(void) sigaction(SIGQUIT, &saved_sa_quit, NULL);
|
(void) sigaction(SIGQUIT, &saved_sa_quit, NULL);
|
||||||
(void) sigaction(SIGCHLD, &saved_sa_chld, NULL);
|
(void) sigaction(SIGCHLD, &saved_sa_chld, NULL);
|
||||||
|
closefrom(STDERR_FILENO + 1);
|
||||||
set_perms(PERM_FULL_USER);
|
set_perms(PERM_FULL_USER);
|
||||||
execvp(nargv[0], nargv);
|
execvp(nargv[0], nargv);
|
||||||
warn("unable to execute %s", nargv[0]);
|
warn("unable to execute %s", nargv[0]);
|
||||||
@@ -247,21 +247,21 @@ int sudo_edit(argc, argv)
|
|||||||
|
|
||||||
/* Copy contents of temp files to real ones */
|
/* Copy contents of temp files to real ones */
|
||||||
for (i = 0; i < argc - 1; i++) {
|
for (i = 0; i < argc - 1; i++) {
|
||||||
/* XXX - open file with PERM_USER for nfs? */
|
if (lseek(tf[i].tfd, (off_t)0, SEEK_SET) != 0) {
|
||||||
if ((tfd = open(tf[i].tfile, O_RDONLY, 0644)) == -1) {
|
warn("unable to rewind edited file %s, cannot update %s",
|
||||||
warn("unable to read edited file %s, cannot update %s",
|
|
||||||
tf[i].tfile, tf[i].ofile);
|
tf[i].tfile, tf[i].ofile);
|
||||||
|
close(tf[i].tfd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_FSTAT
|
#ifdef HAVE_FSTAT
|
||||||
if (fstat(tfd, &sb) == 0) {
|
if (fstat(tf[i].tfd, &sb) == 0) {
|
||||||
#else
|
#else
|
||||||
if (stat(tf[i].tfile, &sb) == 0) {
|
if (stat(tf[i].tfile, &sb) == 0) {
|
||||||
#endif
|
#endif
|
||||||
if (tf[i].osize == sb.st_size && tf[i].omtime == sb.st_mtime) {
|
if (tf[i].osize == sb.st_size && tf[i].omtime == sb.st_mtime) {
|
||||||
warnx("%s unchanged", tf[i].ofile);
|
warnx("%s unchanged", tf[i].ofile);
|
||||||
unlink(tf[i].tfile);
|
unlink(tf[i].tfile);
|
||||||
close(tfd);
|
close(tf[i].tfd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,10 +271,10 @@ int sudo_edit(argc, argv)
|
|||||||
if (ofd == -1) {
|
if (ofd == -1) {
|
||||||
warn("unable to write to %s", tf[i].ofile);
|
warn("unable to write to %s", tf[i].ofile);
|
||||||
warnx("contents of edit session left in %s", tf[i].tfile);
|
warnx("contents of edit session left in %s", tf[i].tfile);
|
||||||
close(tfd);
|
close(tf[i].tfd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
while ((nread = read(tfd, buf, sizeof(buf))) != 0) {
|
while ((nread = read(tf[i].tfd, buf, sizeof(buf))) != 0) {
|
||||||
if ((nwritten = write(ofd, buf, nread)) != nread) {
|
if ((nwritten = write(ofd, buf, nread)) != nread) {
|
||||||
if (nwritten == -1)
|
if (nwritten == -1)
|
||||||
warn("%s", tf[i].ofile);
|
warn("%s", tf[i].ofile);
|
||||||
@@ -290,7 +290,6 @@ int sudo_edit(argc, argv)
|
|||||||
warnx("contents of edit session left in %s", tf[i].tfile);
|
warnx("contents of edit session left in %s", tf[i].tfile);
|
||||||
}
|
}
|
||||||
close(ofd);
|
close(ofd);
|
||||||
close(tfd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return(rval);
|
return(rval);
|
||||||
|
Reference in New Issue
Block a user