2024年1月15日发(作者:)

#endif if (!(NewCrontab = fdopen(t, "r+"))) { perror("fdopen"); goto fatal; } Set_LineNum(1) /* ignore the top few comments since we probably put them there. */ x = 0; while (EOF != (ch = get_char(f))) { if ('#' != ch) { putc(ch, NewCrontab); break; } while (EOF != (ch = get_char(f))) if (ch == 'n') break; if (++x >= NHEADER_LINES) break; } /* copy the rest of the crontab (if any) to the temp file. */ if (EOF != ch) while (EOF != (ch = get_char(f))) putc(ch, NewCrontab); fclose(f); if (fflush(NewCrontab) < OK) { perror(Filename); exit(ERROR_EXIT); } utime(Filename, &utimebuf); again: rewind(NewCrontab); if (ferror(NewCrontab)) { fprintf(stderr, "%s: error while writing new crontab to %sn", ProgramName, Filename); fatal: unlink(Filename); exit(ERROR_EXIT); } if (((editor = getenv("VISUAL")) == NULL || *editor == '0') && ((editor = getenv("EDITOR")) == NULL || *editor == '0')) { editor = EDITOR; } /* we still have the file open. editors will generally rewrite the * original file rather than renaming/unlinking it and starting a * new one; even backup files are supposed to be made by copying * rather than by renaming. if some editor does not support this, * then don't use it. the security problems are more severe if we * close and reopen the file around the edit. */ switch (pid = fork()) { case -1: perror("fork"); goto fatal; case 0: /* child */ if (setgid(MY_GID(pw)) < 0) { perror("setgid(getgid())"); exit(ERROR_EXIT);

exit(ERROR_EXIT); } if (setuid(MY_UID(pw)) < 0) { perror("setuid(getuid())"); exit(ERROR_EXIT); } if (chdir(_PATH_TMP) < 0) { perror(_PATH_TMP); exit(ERROR_EXIT); } if (!glue_strings(q, sizeof q, editor, Filename, ' ')) { fprintf(stderr, "%s: editor command line too longn", ProgramName); exit(ERROR_EXIT); } execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", q, (char *)0); perror(editor); exit(ERROR_EXIT); /*NOTREACHED*/ default: /* parent */ break; } /* parent */ for (;;) { xpid = waitpid(pid, &waiter, WUNTRACED); if (xpid == -1) { if (errno != EINTR) fprintf(stderr, "%s: waitpid() failed waiting for PID %ld from "%s": %sn", ProgramName, (long)pid, editor, strerror(errno)); } else if (xpid != pid) { fprintf(stderr, "%s: wrong PID (%ld != %ld) from "%s"n", ProgramName, (long)xpid, (long)pid, editor); goto fatal; } else if (WIFSTOPPED(waiter)) { kill(getpid(), WSTOPSIG(waiter)); } else if (WIFEXITED(waiter) && WEXITSTATUS(waiter)) { fprintf(stderr, "%s: "%s" exited with status %dn", ProgramName, editor, WEXITSTATUS(waiter)); goto fatal; } else if (WIFSIGNALED(waiter)) { fprintf(stderr, "%s: "%s" killed; signal %d (%score dumped)n", ProgramName, editor, WTERMSIG(waiter), WCOREDUMP(waiter) ?"" :"no "); goto fatal; } else break; } (void)signal(SIGHUP, SIG_DFL); (void)signal(SIGINT, SIG_DFL); (void)signal(SIGQUIT, SIG_DFL); if (fstat(t, &statbuf) < 0) { perror("fstat"); goto fatal; } if (e == _mtime) { fprintf(stderr, "%s: no changes made to crontabn", ProgramName); goto remove; } fprintf(stderr, "%s: installing new crontabn", ProgramName); switch (replace_cmd()) { case 0: break;

break; case -1: for (;;) { printf("Do you want to retry the same edit? "); fflush(stdout); q[0] = '0'; (void) fgets(q, sizeof q, stdin); switch (q[0]) { case 'y': case 'Y': goto again; case 'n': case 'N': goto abandon; default: fprintf(stderr, "Enter Y or Nn"); } } /*NOTREACHED*/ case -2: abandon: fprintf(stderr, "%s: edits left in %sn", ProgramName, Filename); goto done; default: fprintf(stderr, "%s: panic: bad switch() in replace_cmd()n", ProgramName); goto fatal; } remove: unlink(Filename); done: log_it(RealUser, Pid, "END EDIT", User);}