📄 queue.c
字号:
return FALSE; } /* good file -- save this lock */ e->e_lockfp = qfp; /* do basic system initialization */ initsys(e); define('i', e->e_id, e); LineNumber = 0; e->e_flags |= EF_GLOBALERRS; OpMode = MD_DELIVER; if (Verbose) printf("\nRunning %s\n", e->e_id); ctladdr = NULL; while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) { register char *p; struct stat st; if (tTd(40, 4)) printf("+++++ %s\n", bp); switch (bp[0]) { case 'C': /* specify controlling user */ ctladdr = setctluser(&bp[1]); break; case 'R': /* specify recipient */ (void) sendtolist(&bp[1], ctladdr, &e->e_sendqueue, e); break; case 'E': /* specify error recipient */ (void) sendtolist(&bp[1], ctladdr, &e->e_errorqueue, e); break; case 'H': /* header */ (void) chompheader(&bp[1], FALSE, e); break; case 'M': /* message */ /* ignore this; we want a new message next time */ break; case 'S': /* sender */ setsender(newstr(&bp[1]), e, NULL, TRUE); break; case 'B': /* body type */ e->e_bodytype = newstr(&bp[1]); break; case 'D': /* data file name */ e->e_df = newstr(&bp[1]); e->e_dfp = fopen(e->e_df, "r"); if (e->e_dfp == NULL) { syserr("readqf: cannot open %s", e->e_df); e->e_msgsize = -1; } else if (fstat(fileno(e->e_dfp), &st) >= 0) e->e_msgsize = st.st_size; break; case 'T': /* init time */ e->e_ctime = atol(&bp[1]); break; case 'P': /* message priority */ e->e_msgpriority = atol(&bp[1]) + WkTimeFact; break; case 'F': /* flag bits */ for (p = &bp[1]; *p != '\0'; p++) { switch (*p) { case 'w': /* warning sent */ e->e_flags |= EF_WARNING; break; case 'r': /* response */ e->e_flags |= EF_RESPONSE; break; } } break; case '$': /* define macro */ define(bp[1], newstr(&bp[2]), e); break; case '\0': /* blank line; ignore */ break; default: syserr("readqf: %s: line %d: bad line \"%s\"", qf, LineNumber, bp); fclose(qfp); rename(qf, queuename(e, 'Q')); return FALSE; } if (bp != buf) free(bp); } /* ** If we haven't read any lines, this queue file is empty. ** Arrange to remove it without referencing any null pointers. */ if (LineNumber == 0) { errno = 0; e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE; } return TRUE;}/*** PRINTQUEUE -- print out a representation of the mail queue**** Parameters:** none.**** Returns:** none.**** Side Effects:** Prints a listing of the mail queue on the standard output.*/printqueue(){ register WORK *w; FILE *f; int nrequests; char buf[MAXLINE]; /* ** Check for permission to print the queue */ if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) { struct stat st;# ifdef NGROUPS int n; GIDSET_T gidset[NGROUPS];# endif if (stat(QueueDir, &st) < 0) { syserr("Cannot stat %s", QueueDir); return; }# ifdef NGROUPS n = getgroups(NGROUPS, gidset); while (--n >= 0) { if (gidset[n] == st.st_gid) break; } if (n < 0)# else if (RealGid != st.st_gid)# endif { usrerr("510 You are not permitted to see the queue"); setstat(EX_NOPERM); return; } } /* ** Read and order the queue. */ nrequests = orderq(TRUE); /* ** Print the work list that we have read. */ /* first see if there is anything */ if (nrequests <= 0) { printf("Mail queue is empty\n"); return; } CurrentLA = getla(); /* get load average */ printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s"); if (nrequests > QUEUESIZE) printf(", only %d printed", QUEUESIZE); if (Verbose) printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n"); else printf(")\n--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n"); for (w = WorkQ; w != NULL; w = w->w_next) { struct stat st; auto time_t submittime = 0; long dfsize = -1; int flags = 0; char message[MAXLINE]; char bodytype[MAXNAME]; printf("%8s", w->w_name + 2); f = fopen(w->w_name, "r"); if (f == NULL) { printf(" (job completed)\n"); errno = 0; continue; } if (!lockfile(fileno(f), w->w_name, NULL, LOCK_SH|LOCK_NB)) printf("*"); else if (shouldqueue(w->w_pri, w->w_ctime)) printf("X"); else printf(" "); errno = 0; message[0] = bodytype[0] = '\0'; while (fgets(buf, sizeof buf, f) != NULL) { register int i; register char *p; fixcrlf(buf, TRUE); switch (buf[0]) { case 'M': /* error message */ if ((i = strlen(&buf[1])) >= sizeof message) i = sizeof message - 1; bcopy(&buf[1], message, i); message[i] = '\0'; break; case 'B': /* body type */ if ((i = strlen(&buf[1])) >= sizeof bodytype) i = sizeof bodytype - 1; bcopy(&buf[1], bodytype, i); bodytype[i] = '\0'; break; case 'S': /* sender name */ if (Verbose) printf("%8ld %10ld%c%.12s %.38s", dfsize, w->w_pri, bitset(EF_WARNING, flags) ? '+' : ' ', ctime(&submittime) + 4, &buf[1]); else printf("%8ld %.16s %.45s", dfsize, ctime(&submittime), &buf[1]); if (message[0] != '\0' || bodytype[0] != '\0') { printf("\n %10.10s", bodytype); if (message[0] != '\0') printf(" (%.60s)", message); } break; case 'C': /* controlling user */ if (Verbose) printf("\n\t\t\t\t (---%.34s---)", &buf[1]); break; case 'R': /* recipient name */ if (Verbose) printf("\n\t\t\t\t\t %.38s", &buf[1]); else printf("\n\t\t\t\t %.45s", &buf[1]); break; case 'T': /* creation time */ submittime = atol(&buf[1]); break; case 'D': /* data file name */ if (stat(&buf[1], &st) >= 0) dfsize = st.st_size; break; case 'F': /* flag bits */ for (p = &buf[1]; *p != '\0'; p++) { switch (*p) { case 'w': flags |= EF_WARNING; break; } } } } if (submittime == (time_t) 0) printf(" (no control file)"); printf("\n"); (void) fclose(f); }}# endif /* QUEUE *//*** QUEUENAME -- build a file name in the queue directory for this envelope.**** Assigns an id code if one does not already exist.** This code is very careful to avoid trashing existing files** under any circumstances.**** Parameters:** e -- envelope to build it in/from.** type -- the file type, used as the first character** of the file name.**** Returns:** a pointer to the new file name (in a static buffer).**** Side Effects:** If no id code is already assigned, queuename will** assign an id code, create a qf file, and leave a** locked, open-for-write file pointer in the envelope.*/char *queuename(e, type) register ENVELOPE *e; int type;{ static int pid = -1; static char c0; static char c1; static char c2; time_t now; struct tm *tm; static char buf[MAXNAME]; if (e->e_id == NULL) { char qf[20]; /* find a unique id */ if (pid != getpid()) { /* new process -- start back at "AA" */ pid = getpid(); now = curtime(); tm = localtime(&now); c0 = 'A' + tm->tm_hour; c1 = 'A'; c2 = 'A' - 1; } (void) sprintf(qf, "qf%cAA%05d", c0, pid); while (c1 < '~' || c2 < 'Z') { int i; if (c2 >= 'Z') { c1++; c2 = 'A' - 1; } qf[3] = c1; qf[4] = ++c2; if (tTd(7, 20)) printf("queuename: trying \"%s\"\n", qf); i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode); if (i < 0) { if (errno == EEXIST) continue; syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", qf, QueueDir, geteuid()); exit(EX_UNAVAILABLE); } if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB)) { e->e_lockfp = fdopen(i, "w"); break; } /* a reader got the file; abandon it and try again */ (void) close(i); } if (c1 >= '~' && c2 >= 'Z') { syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", qf, QueueDir, geteuid()); exit(EX_OSERR); } e->e_id = newstr(&qf[2]); define('i', e->e_id, e); if (tTd(7, 1)) printf("queuename: assigned id %s, env=%x\n", e->e_id, e); if (tTd(7, 9)) { printf(" lockfd="); dumpfd(fileno(e->e_lockfp), TRUE, FALSE); }# ifdef LOG if (LogLevel > 93) syslog(LOG_DEBUG, "%s: assigned id", e->e_id);# endif /* LOG */ } if (type == '\0') return (NULL); (void) sprintf(buf, "%cf%s", type, e->e_id); if (tTd(7, 2)) printf("queuename: %s\n", buf); return (buf);}/*** UNLOCKQUEUE -- unlock the queue entry for a specified envelope**** Parameters:** e -- the envelope to unlock.**** Returns:** none**** Side Effects:** unlocks the queue for `e'.*/unlockqueue(e) ENVELOPE *e;{ if (tTd(51, 4)) printf("unlockqueue(%s)\n", e->e_id); /* if there is a lock file in the envelope, close it */ if (e->e_lockfp != NULL) xfclose(e->e_lockfp, "unlockqueue", e->e_id); e->e_lockfp = NULL; /* don't create a queue id if we don't already have one */ if (e->e_id == NULL) return; /* remove the transcript */# ifdef LOG if (LogLevel > 87) syslog(LOG_DEBUG, "%s: unlock", e->e_id);# endif /* LOG */ if (!tTd(51, 104)) xunlink(queuename(e, 'x'));}/*** SETCTLUSER -- create a controlling address**** Create a fake "address" given only a local login name; this is** used as a "controlling user" for future recipient addresses.**** Parameters:** user -- the user name of the controlling user.**** Returns:** An address descriptor for the controlling user.**** Side Effects:** none.*/ADDRESS *setctluser(user) char *user;{ register ADDRESS *a; struct passwd *pw; char *p; /* ** See if this clears our concept of controlling user. */ if (user == NULL || *user == '\0') return NULL; /* ** Set up addr fields for controlling user. */ a = (ADDRESS *) xalloc(sizeof *a); bzero((char *) a, sizeof *a); p = strchr(user, ':'); if (p != NULL) *p++ = '\0'; if (*user != '\0' && (pw = getpwnam(user)) != NULL) { if (strcmp(pw->pw_dir, "/") == 0) a->q_home = ""; else a->q_home = newstr(pw->pw_dir); a->q_uid = pw->pw_uid; a->q_gid = pw->pw_gid; a->q_user = newstr(user); a->q_flags |= QGOODUID; } else { a->q_user = newstr(DefUser); } a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ a->q_mailer = LocalMailer; if (p == NULL) a->q_paddr = a->q_user; else a->q_paddr = newstr(p); return a;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -