Use the *at system calls instead of changing directories. - todd
Index: usr.bin/at/at.c =================================================================== RCS file: /cvs/src/usr.bin/at/at.c,v retrieving revision 1.70 diff -u -p -u -r1.70 at.c --- usr.bin/at/at.c 9 Nov 2015 15:57:39 -0000 1.70 +++ usr.bin/at/at.c 9 Nov 2015 21:48:05 -0000 @@ -214,8 +214,8 @@ writefile(const char *cwd, time_t runtim act.sa_flags = 0; sigaction(SIGINT, &act, NULL); - if ((lockdes = open(AT_SPOOL, O_RDONLY, 0)) < 0) - perr("Cannot open jobs dir"); + if ((lockdes = open(AT_SPOOL, O_RDONLY|O_DIRECTORY, 0)) < 0) + perr2("Cannot open ", AT_SPOOL); /* * Lock the jobs dir so we don't have to worry about someone @@ -479,7 +479,7 @@ list_jobs(int argc, char **argv, int cou uid_t *uids; char queue, *ep; DIR *spool; - int i, shortformat; + int dfd, i, shortformat; size_t numjobs, maxjobs; if (argc) { @@ -498,13 +498,11 @@ list_jobs(int argc, char **argv, int cou shortformat = strcmp(__progname, "at") == 0; - if (chdir(AT_SPOOL) != 0) - perr2("Cannot change to ", AT_SPOOL); - - if ((spool = opendir(".")) == NULL) + if ((dfd = open(AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 || + (spool = fdopendir(dfd)) == NULL) perr2("Cannot open ", AT_SPOOL); - if (fstat(dirfd(spool), &stbuf) != 0) + if (fstat(dfd, &stbuf) != 0) perr2("Cannot stat ", AT_SPOOL); /* @@ -520,8 +518,8 @@ list_jobs(int argc, char **argv, int cou /* Loop over every file in the directory. */ while ((dirent = readdir(spool)) != NULL) { - if (stat(dirent->d_name, &stbuf) != 0) - perr2("Cannot stat in ", AT_SPOOL); + if (fstatat(dfd, dirent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) != 0) + perr2("Cannot stat ", dirent->d_name); /* * See it's a regular file and has its x bit turned on and @@ -632,12 +630,10 @@ process_jobs(int argc, char **argv, int FILE *fp; DIR *spool; int job_matches, jobs_len, uids_len; - int error, i, ch, changed; - - if (chdir(AT_SPOOL) != 0) - perr2("Cannot change to ", AT_SPOOL); + int error, i, ch, changed, dfd; - if ((spool = opendir(".")) == NULL) + if ((dfd = open(AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 || + (spool = fdopendir(dfd)) == NULL) perr2("Cannot open ", AT_SPOOL); /* Convert argv into a list of jobs and uids. */ @@ -671,8 +667,8 @@ process_jobs(int argc, char **argv, int /* Loop over every file in the directory */ changed = 0; while ((dirent = readdir(spool)) != NULL) { - if (stat(dirent->d_name, &stbuf) != 0) - perr2("Cannot stat in ", AT_SPOOL); + if (fstatat(dfd, dirent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) != 0) + perr2("Cannot stat ", dirent->d_name); if (stbuf.st_uid != user_uid && user_uid != 0) continue; @@ -709,7 +705,7 @@ process_jobs(int argc, char **argv, int case ATRM: if (!interactive || (interactive && rmok(runtimer))) { - if (unlink(dirent->d_name) == 0) + if (unlinkat(dfd, dirent->d_name, 0) == 0) changed = 1; else perr(dirent->d_name); @@ -721,9 +717,10 @@ process_jobs(int argc, char **argv, int break; case CAT: - fp = fopen(dirent->d_name, "r"); - if (!fp) - perr("Cannot open file"); + i = openat(dfd, dirent->d_name, + O_RDONLY|O_NOFOLLOW); + if (i == -1 || (fp = fdopen(i, "r")) == NULL) + perr2("Cannot open ", dirent->d_name); while ((ch = getc(fp)) != EOF) putchar(ch); @@ -751,12 +748,8 @@ process_jobs(int argc, char **argv, int free(uids); /* If we modied the spool, poke cron so it knows to reload. */ - if (changed) { - if (chdir(CRONDIR) != 0) - perror(CRONDIR); - else - poke_daemon(AT_SPOOL, RELOAD_AT); - } + if (changed) + poke_daemon(AT_SPOOL, RELOAD_AT); return (error); }