⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mail.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  mail - send/receive mail 		 Author: Peter S. Housel *//* Version 0.2 of September 1990: added -e, -t, * options - cwr */#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#undef EOF			/* temporary hack */#include <signal.h>#include <pwd.h>#include <time.h>#include <setjmp.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <sys/wait.h>#include <stdio.h>#ifdef DEBUG#define D(Q) (Q)#else#define D(Q)#endif#define SHELL		"/bin/sh"#define DROPNAME 	"/usr/spool/mail/%s"#define LOCKNAME	"/usr/spool/mail/%s.lock"#define LOCKWAIT	5	/* seconds to wait after collision */#define LOCKTRIES	4	/* maximum number of collisions */#define MBOX		"mbox"#define HELPFILE	"/usr/lib/mail.help"#define PROMPT		"? "#define PATHLEN		80#define MAXRCPT		100	/* maximum number of recipients */#define LINELEN		512/* #define MAILER		"/usr/bin/smail"	*/ /* smart mailer */#define MAILERARGS		/* (unused) */#define UNREAD		1	/* 'not read yet' status */#define DELETED		2	/* 'deleted' status */#define READ		3	/* 'has been read' status */struct letter {  struct letter *prev, *next;	/* linked letter list */  int status;			/* letter status */  off_t location;		/* location within mailbox file */};struct letter *firstlet, *lastlet;int usemailer = 1;		/* use MAILER to deliver (if any) */int printmode = 0;		/* print-and-exit mode */int quitmode = 0;		/* take interrupts */int reversemode = 0;		/* print mailbox in reverse order */int usedrop = 1;		/* read the maildrop (no -f given) */int verbose = 0;		/* pass "-v" flag on to mailer */int needupdate = 0;		/* need to update mailbox */int msgstatus = 0;		/* return the mail status */int distlist = 0;		/* include distribution list */char mailbox[PATHLEN];		/* user's mailbox/maildrop */char tempname[PATHLEN] = "/tmp/mailXXXXXX";	/* temporary file */FILE *boxfp = NULL;		/* mailbox file */jmp_buf printjump;		/* for quitting out of letters */unsigned oldmask;		/* saved umask() */extern int optind;extern char *optarg;_PROTOTYPE(int main, (int argc, char **argv));_PROTOTYPE(int deliver, (int count, char *vec []));_PROTOTYPE(FILE *makerewindable, (void));_PROTOTYPE(int copy, (FILE *fromfp, FILE *tofp));_PROTOTYPE(void readbox, (void));_PROTOTYPE(void printall, (void));_PROTOTYPE(void interact, (void));_PROTOTYPE(void onint, (int dummy));_PROTOTYPE(void savelet, (struct letter *let, char *savefile));_PROTOTYPE(void updatebox, (void));_PROTOTYPE(void printlet, (struct letter *let, FILE *tofp));_PROTOTYPE(void doshell, (char *command));_PROTOTYPE(void usage, (void));_PROTOTYPE(char *basename, (char *name));_PROTOTYPE(char *whoami, (void));_PROTOTYPE(void dohelp, (void));_PROTOTYPE(int filesize, (char *name));int main(argc, argv)int argc;char *argv[];{  int c;  if ('l' == (basename(argv[0]))[0])	/* 'lmail' link? */	usemailer = 0;		/* yes, let's deliver it */  (void) mktemp(tempname);	/* name the temp file */  oldmask = umask(022);		/* change umask for security */  while (EOF != (c = getopt(argc, argv, "epqrf:tdv"))) switch (c) {	    case 'e':	++msgstatus;	break;		    case 't':	++distlist;	break;	    case 'p':	++printmode;	break;	    case 'q':	++quitmode;	break;	    case 'r':	++reversemode;	break;	    case 'f':		setuid(getuid());	/* won't need to lock */		usedrop = 0;		strncpy(mailbox, optarg, (size_t)(PATHLEN - 1));		break;	    case 'd':	usemailer = 0;	break;	    case 'v':	++verbose;	break;	    default:		usage();		exit(1);	}  if (optind < argc) {	if (deliver(argc - optind, argv + optind) < 0)		exit(1);	else		exit(0);  }  if (usedrop) sprintf(mailbox, DROPNAME, whoami());  D(printf("mailbox=%s\n", mailbox));  if (msgstatus) {	if (filesize(mailbox))		exit(0);	else		exit(1);  }  readbox();  if (printmode)	printall();  else	interact();  if (needupdate) updatebox();  return(0);}int deliver(count, vec)int count;char *vec[];{  int i, j;  int errs = 0;			/* count of errors */  int dropfd;			/* file descriptor for user's drop */  int created = 0;		/* true if we created the maildrop */  FILE *mailfp;			/* fp for mail */  struct stat stb;		/* for checking drop modes, owners */#ifdef __STDC__  void (*sigint)(int), (*sighup)(int), (*sigquit)(int);/* saving signal state */#else  void (*sigint) (), (*sighup) (), (*sigquit) ();      /* saving signal state */#endif  time_t now;			/* for datestamping the postmark */  char sender[32];		/* sender's login name */  char lockname[PATHLEN];	/* maildrop lock */  int locktries;		/* tries when box is locked */  struct passwd *pw;		/* sender and recipent */  int to_console;		/* deliver to console if everything fails */  if (count > MAXRCPT) {	fprintf(stderr, "mail: too many recipients\n");	return -1;  }#ifdef MAILER  if (usemailer) {	char *argvec[MAXRCPT + 3];	char **argp;	setuid(getuid());	argp = argvec;	*argp++ = "send-mail";	if (verbose) *argp++ = "-v";	for (i = 0; i < count; ++i) *argp++ = vec[i];	*argp = NULL;	execv(MAILER, argvec);	fprintf(stderr, "mail: couldn't exec %s\n", MAILER);	return -1;  }#endif /* MAILER */  if (NULL == (pw = getpwuid(getuid()))) {	fprintf(stderr, "mail: unknown sender\n");	return -1;  }  strcpy(sender, pw->pw_name);  /* If we need to rewind stdin and it isn't rewindable, make a copy */  if (isatty(0) || (count > 1 && lseek(0, 0L, 0) == (off_t) -1)) {	mailfp = makerewindable();  } else	mailfp = stdin;  /* Shut off signals during the delivery */  sigint = signal(SIGINT, SIG_IGN);  sighup = signal(SIGHUP, SIG_IGN);  sigquit = signal(SIGQUIT, SIG_IGN);  for (i = 0; i < count; ++i) {	if (count > 1) rewind(mailfp);	D(printf("deliver to %s\n", vec[i]));	if (NULL == (pw = getpwnam(vec[i]))) {		fprintf(stderr, "mail: user %s not known\n", vec[i]);		++errs;		continue;	}	sprintf(mailbox, DROPNAME, pw->pw_name);	sprintf(lockname, LOCKNAME, pw->pw_name);	D(printf("maildrop='%s', lock='%s'\n", mailbox, lockname));	/* Lock the maildrop while we're messing with it. Races are	 * possible (though not very likely) when we have to create	 * the maildrop, but not otherwise. If the box is already	 * locked, wait awhile and try again. */	locktries = created = to_console = 0;trylock:	if (link(mailbox, lockname) != 0) {		if (ENOENT == errno) {	/* user doesn't have a drop yet */			dropfd = creat(mailbox, 0600);			if (dropfd < 0 && errno == ENOENT) {				/* Probably missing spool dir; to console. */				boxfp = fopen("/dev/console", "w");				if (boxfp != NULL) {					to_console = 1;					goto nobox;				}			}			if (dropfd < 0) {				fprintf(stderr, "mail: couln't create a maildrop for user %s\n",					vec[i]);				++errs;				continue;			}			++created;			goto trylock;		} else {	/* somebody else has it locked, it seems -			 * wait */			if (++locktries >= LOCKTRIES) {				fprintf(stderr, "mail: couldn't lock maildrop for user %s\n",					vec[i]);				++errs;				continue;			}			sleep(LOCKWAIT);			goto trylock;		}	}	if (created) {		(void) chown(mailbox, pw->pw_uid, pw->pw_gid);		boxfp = fdopen(dropfd, "a");	} else		boxfp = fopen(mailbox, "a");	if (NULL == boxfp || stat(mailbox, &stb) < 0) {		fprintf(stderr, "mail: serious maildrop problems for %s\n", vec[i]);		unlink(lockname);		++errs;		continue;	}	if (stb.st_uid != pw->pw_uid || (stb.st_mode & S_IFMT) != S_IFREG) {		fprintf(stderr, "mail: mailbox for user %s is illegal\n", vec[i]);		unlink(lockname);		++errs;		continue;	}nobox:	if (to_console) {		fprintf(boxfp,			"-------------\n| Mail from %s to %s\n-------------\n",			sender, vec[i]);	} else {		(void) time(&now);		fprintf(boxfp, "From %s %24.24s\n", sender, ctime(&now));	}	if (distlist) {		fprintf(boxfp, "Dist: ");		for (j = 0; j < count; ++j)			if (getpwnam(vec[j]) != NULL && j != i)				fprintf(boxfp, "%s ", vec[j]) ;		fprintf(boxfp, "\n\n");	}	if ((copy(mailfp, boxfp) < 0) || (fclose(boxfp) != 0)) {		fprintf(stderr, "mail: error delivering to user %s", vec[i]);		perror(" ");		++errs;	}	unlink(lockname);  }  fclose(mailfp);  /* Put signals back the way they were */  signal(SIGINT, sigint);  signal(SIGHUP, sighup);  signal(SIGQUIT, sigquit);  return(0 == errs) ? 0 : -1;}/* 'stdin' isn't rewindable. Make a temp file that is. * Note that if one wanted to catch SIGINT and write a '~/dead.letter' * for interactive mails, this might be the place to do it (though the * case where a MAILER is being used would also need to be handled). */FILE *makerewindable(){  FILE *tempfp;			/* temp file used for copy */  int c;			/* character being copied */  int state;			/* ".\n" detection state */  if (NULL == (tempfp = fopen(tempname, "w"))) {	fprintf(stderr, "mail: can't create temporary file\n");	return NULL;  }  /* Here we copy until we reach the end of the letter (end of file or   * a line containing only a '.'), painstakingly avoiding setting a   * line length limit. */  state = '\n';  while (EOF != (c = getc(stdin))) switch (state) {	    case '\n':		if ('.' == c)			state = '.';		else {			if ('\n' != c) state = '\0';			putc(c, tempfp);		}		break;	    case '.':		if ('\n' == c) goto done;		state = '\0';		putc('.', tempfp);		putc(c, tempfp);		break;	    default:		state = ('\n' == c) ? '\n' : '\0';		putc(c, tempfp);	}done:  if (ferror(tempfp) || fclose(tempfp)) {	fprintf(stderr, "mail: couldn't copy letter to temporary file\n");	return NULL;  }  tempfp = freopen(tempname, "r", stdin);  unlink(tempname);		/* unlink name; file lingers on in limbo */  return tempfp;}int copy(fromfp, tofp)FILE *fromfp, *tofp;{  int c;			/* character being copied */  int state;			/* ".\n" and postmark detection state */  int blankline = 0;		/* was most recent line completely blank? */  static char postmark[] = "From ";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -