📄 mail.c
字号:
char *p, *q; /* Here we copy until we reach the end of the letter (end of file or * a line containing only a '.'). Postmarks (lines beginning with * "From ") are copied with a ">" prepended. Here we also complicate * things by not setting a line limit. */ state = '\n'; p = postmark; while (EOF != (c = getc(fromfp))) { switch (state) { case '\n': if ('.' == c) /* '.' at BOL */ state = '.'; else if (*p == c) { /* start of postmark */ ++p; state = 'P'; } else { /* anything else */ if ('\n' == c) blankline = 1; else { state = '\0'; blankline = 0; } putc(c, tofp); } break; case '.': if ('\n' == c) goto done; state = '\0'; putc('.', tofp); putc(c, tofp); break; case 'P': if (*p == c) { if (*++p == '\0') { /* successfully reached end */ p = postmark; putc('>', tofp); fputs(postmark, tofp); state = '\0'; break; } break; /* not there yet */ } state = ('\n' == c) ? '\n' : '\0'; for (q = postmark; q < p; ++q) putc(*q, tofp); putc(c, tofp); blankline = 0; p = postmark; break; default: state = ('\n' == c) ? '\n' : '\0'; putc(c, tofp); } } if ('\n' != state) putc('\n', tofp);done: if (!blankline) putc('\n', tofp); if (ferror(tofp)) return -1; return 0;}void readbox(){ char linebuf[512]; struct letter *let; off_t current; firstlet = lastlet = NULL; if (access(mailbox, 4) < 0 || NULL == (boxfp = fopen(mailbox, "r"))) { if (usedrop && ENOENT == errno) return; fprintf(stderr, "can't access mailbox "); perror(mailbox); exit(1); } current = 0L; while (1) { if (NULL == fgets(linebuf, sizeof linebuf, boxfp)) break; if (!strncmp(linebuf, "From ", (size_t)5)) { if (NULL == (let = (struct letter *) malloc(sizeof(struct letter)))) { fprintf(stderr, "Out of memory.\n"); exit(1); } if (NULL == lastlet) { firstlet = let; let->prev = NULL; } else { let->prev = lastlet; lastlet->next = let; } lastlet = let; let->next = NULL; let->status = UNREAD; let->location = current; D(printf("letter at %ld\n", current)); } current += strlen(linebuf); }}void printall(){ struct letter *let; let = reversemode ? firstlet : lastlet; if (NULL == let) { printf("No mail.\n"); return; } while (NULL != let) { printlet(let, stdout); let = reversemode ? let->next : let->prev; }}void interact(){ char linebuf[512]; /* user input line */ struct letter *let, *next; /* current and next letter */ int interrupted = 0; /* SIGINT hit during letter print */ int needprint = 1; /* need to print this letter */ char *savefile; /* filename to save into */ if (NULL == firstlet) { printf("No mail.\n"); return; } let = reversemode ? firstlet : lastlet; while (1) { next = reversemode ? let->next : let->prev; if (NULL == next) next = let; if (!quitmode) { interrupted = setjmp(printjump); signal(SIGINT, onint); } if (!interrupted && needprint) { if (DELETED != let->status) let->status = READ; printlet(let, stdout); } if (interrupted) putchar('\n'); needprint = 0; fputs(PROMPT, stdout); fflush(stdout); if (fgets(linebuf, sizeof linebuf, stdin) == NULL) break; if (!quitmode) signal(SIGINT, SIG_IGN); switch (linebuf[0]) { case '\n': let = next; needprint = 1; continue; case 'd': let->status = DELETED; if (next != let)/* look into this */ needprint = 1; needupdate = 1; let = next; continue; case 'p': needprint = 1; continue; case '-': next = reversemode ? let->prev : let->next; if (NULL == next) next = let; let = next; needprint = 1; continue; case 's': for (savefile = strtok(linebuf + 1, " \t\n"); savefile != NULL; savefile = strtok((char *) NULL, " \t\n")) { savelet(let, savefile); } continue; case '!': doshell(linebuf + 1); continue; case '*': dohelp(); continue; case 'q': return; case 'x': exit(0); default: fprintf(stderr, "Illegal command\n"); continue; } }}void onint(dummy)int dummy; /* to satisfy ANSI compilers */{ longjmp(printjump, 1);}void savelet(let, savefile)struct letter *let;char *savefile;{ int waitstat, pid; FILE *savefp; if ((pid = fork()) < 0) { perror("mail: couldn't fork"); return; } else if (pid != 0) { /* parent */ wait(&waitstat); return; } /* Child */ setgid(getgid()); setuid(getuid()); if ((savefp = fopen(savefile, "a")) == NULL) { perror(savefile); exit(0); } printlet(let, savefp); if ((ferror(savefp) != 0) | (fclose(savefp) != 0)) { fprintf(stderr, "savefile write error:"); perror(savefile); } exit(0);}void updatebox(){ FILE *tempfp; /* fp for tempfile */ char lockname[PATHLEN]; /* maildrop lock */ int locktries = 0; /* tries when box is locked */ struct letter *let; /* current letter */ int c; sprintf(lockname, LOCKNAME, whoami()); if (NULL == (tempfp = fopen(tempname, "w"))) { perror("mail: can't create temporary file"); return; } for (let = firstlet; let != NULL; let = let->next) { if (let->status != DELETED) { printlet(let, tempfp); D(printf("printed letter at %ld\n", let->location)); } } if (ferror(tempfp) || NULL == (tempfp = freopen(tempname, "r", tempfp))) { perror("mail: temporary file write error"); unlink(tempname); return; } /* Shut off signals during the update */ signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGQUIT, SIG_IGN); if (usedrop) while (link(mailbox, lockname) != 0) { if (++locktries >= LOCKTRIES) { fprintf(stderr, "mail: couldn't lock maildrop for update\n"); return; } sleep(LOCKWAIT); } if (NULL == (boxfp = freopen(mailbox, "w", boxfp))) { perror("mail: couldn't reopen maildrop"); fprintf(stderr, "mail may have been lost; look in %s\n", tempname); if (usedrop) unlink(lockname); return; } unlink(tempname); while ((c = getc(tempfp)) != EOF) putc(c, boxfp); fclose(boxfp); if (usedrop) unlink(lockname);}void printlet(let, tofp)struct letter *let;FILE *tofp;{ off_t current, limit; int c; fseek(boxfp, (current = let->location), 0); limit = (NULL != let->next) ? let->next->location : -1; while (current != limit && (c = getc(boxfp)) != EOF) { putc(c, tofp); ++current; }}void doshell(command)char *command;{ int waitstat, pid; char *shell; if (NULL == (shell = getenv("SHELL"))) shell = SHELL; if ((pid = fork()) < 0) { perror("mail: couldn't fork"); return; } else if (pid != 0) { /* parent */ wait(&waitstat); return; } /* Child */ setgid(getgid()); setuid(getuid()); umask(oldmask); execl(shell, shell, "-c", command, (char *) NULL); fprintf(stderr, "can't exec shell\n"); exit(127);}void usage(){ fprintf(stderr, "usage: mail [-v] user [...]\n"); fprintf(stderr, " mail [-epqr] [-f file] [-t arg]\n");}char *basename(name)char *name;{ char *p; if (NULL == (p = rindex(name, '/'))) return name; else return p + 1;}char *whoami(){ struct passwd *pw; if (NULL != (pw = getpwuid(getuid()))) return pw->pw_name; else return "nobody";}void dohelp(){ FILE *fp; char buffer[80]; if ( (fp = fopen(HELPFILE, "r")) == NULL) fprintf(stdout, "can't open helpfile %s\n", HELPFILE); else while (fgets(buffer, 80, fp)) fputs(buffer, stdout);}int filesize(name)char *name ;{ struct stat buf; if (stat(name, &buf) == -1) buf.st_size = 0L; return (buf.st_size ? 1 : 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -