+ fchmod(fileno(spoolfile), 0400);
+
+ /*
+ * The protection mechanism works like this:
+ * We are running ruid=user, euid=daemon. So far we have been
+ * messing around in the spool directory, so we needed the
+ * daemon stuff. Now, we want to read the users file,
+ * so we must give up the daemon protection, but we might
+ * need the daemon's protection if the user interrupts and
+ * we need to remove the spool files.
+ * So, we fork and let the kid set the real and effective
+ * user id's to the user, so he can read everything of his
+ * own, but not his professor's final exam and not stuff
+ * owned by daemon. If the kid exits with non-zero status,
+ * that means that the user typed interrupt, and the parent
+ * (still with daemon permissions) removes the spool file.
+ */
+ signal(SIGINT, SIG_IGN);
+ pid = fork();
+ if (pid == -1) {
+ perror("fork");
+ exit(1);
+ }
+ if (pid) {
+ int wpid, status;
+
+ /*
+ * We are the parent. If the kid has problems,
+ * cleanup the spool directory.
+ */
+ wpid = wait(&status);
+ if (wpid != pid || status) {
+ cleanup();
+ exit(1);
+ }
+ /*
+ * The kid should have alread flushed the buffers.
+ */
+ _exit(0);
+ }
+
+ /*
+ * Exit on interrupt.
+ */
+ signal(SIGINT, SIG_DFL);
+
+ /*
+ * We are the kid, give up daemon permissions.
+ */
+ setuid(getuid());
+
+ /*
+ * Open the input file with the user's permissions.
+ */
+ if (!standardin) {
+ jobfile = *argv;
+ if ((inputfile = fopen(jobfile, "r")) == NULL) {
+ perror(jobfile);
+ exit(1);
+ }
+ }
+