+#
+
+/*
+ * mail command usage
+ * mail [-yn]
+ * prints your mail
+ * mail people
+ * sends standard input to people
+ *
+ * mail -r machine user people
+ * sends mail from the network
+ *
+ * if NOTROOT is defined, don't run as root.
+ */
+
+#define SIGINT 2
+#define DIRECT 040000
+#define RMAILCMD "/usr/net/bin/sendmail"
+#define GETUID() (getuid() & 0377)
+#define SPOOLDIR "/usr/spool/mail/"
+#define NOTROOT $
+
+struct inode {
+ char minor;
+ char major;
+ int inumber;
+ int flags;
+ char nlinks;
+ char uid;
+ char gid;
+ char size0;
+ int size1;
+ int addr[8];
+ int actime[2];
+ int modtime[2];
+} inode;
+
+char lettmp[] "/tmp/maXXXXX";
+char preptmp[] "/tmp/mbXXXXX";
+int pwfil;
+int chew;
+int errs;
+char *strcat(), *strcpy();
+
+main(argc, argv)
+char **argv;
+{
+ register int me;
+ extern int fout;
+ int uf, delexit();
+ char namebuf[20];
+
+ mktemp(lettmp);
+ mktemp(preptmp);
+ unlink(lettmp);
+ unlink(preptmp);
+ me = GETUID();
+ if (getname(me, namebuf) < 0) {
+ printf("Who are you?\n");
+ delexit(1);
+ }
+ if (argc < 2)
+ goto hitit;
+ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++)
+ switch(argv[0][1]) {
+ register char *cp, *np;
+
+ case 'y':
+ case 'n':
+ argc++, argv--;
+hitit:
+ printmail(argc, argv, namebuf);
+ delexit(0);
+
+ case 'r':
+ if (argc < 2)
+ continue;
+ case 'f':
+ if (argc < 1)
+ continue;
+ if (!equal("network", namebuf) && me != 0) {
+ printf("Nice try!\n");
+ delexit(1);
+ }
+ chew++;
+ np = namebuf;
+ for (cp = argv[1]; *cp; cp++)
+ *np++ = *cp;
+ if (argv[0][1] == 'r')
+ {
+ argc--, argv++;
+ *np++ = ':';
+ for (cp = argv[1]; *cp; cp++)
+ *np++ = *cp;
+ }
+ *np++ = 0;
+ argc--, argv++;
+ continue;
+ }
+ if ((signal(SIGINT, 01) & 01) == 0)
+ signal(SIGINT, delexit);
+ unlink(lettmp);
+# ifdef NOTROOT
+ fout = creat(lettmp, 0666);
+# else
+ fout = creat(lettmp, 0600);
+# endif
+ if (fout < 0) {
+ fout = 1;
+ perror(lettmp);
+ delexit(1);
+ }
+ argc++, argv--;
+ bulkmail(argc, argv, namebuf);
+ delexit(0);
+}
+
+printmail(argc, argv, name)
+char **argv;
+char *name;
+{
+ extern int fin, fout;
+ register n, c, f;
+ char *mname;
+
+ mname = cat(SPOOLDIR, name);
+ if (stat(mname, &inode)>=0 && inode.nlinks==1 &&
+ fopen(mname, &fin)>=0 && (c = getchar())) {
+ putchar(c);
+ getput();
+ close(fin);
+ c = 'x';
+ if (argc<2) {
+ if (ttyn(0)!='x') {
+ printf("Save?");
+ fin = 0;
+ c = getchar();
+ }
+ } else
+ c = argv[1][1];
+ if (!any(c, "yn"))
+ delexit(0);
+ if (c == 'y') {
+ if (accesss("mbox")) {
+ printf("Saved mail in 'mbox'\n");
+ prepend(mname, "mbox", GETUID());
+ unlink(mname);
+ } else
+ printf("In wrong directory\n");
+ } else
+ unlink(mname);
+ } else
+ printf("No mail.\n");
+}
+
+bulkmail(argc, argv, from)
+char **argv, *from;
+{
+ extern int fin, fout;
+ register int c;
+ register char *cp;
+ char linebuf[128];
+ int tbuf[2], ttyn1;
+
+ fin = 0;
+ (&fin)[1] = 0;
+ time(tbuf);
+ ttyn1 = ttyn(1);
+ if (ttyn1 < 033) {
+ ttyn1 =+ 'a' - 1;
+ ttyn1 =<< 8;
+ ttyn1 =| '^';
+ }
+ printf("From %s tty%c %s", from, ttyn1, ctime(tbuf));
+
+ /*
+ * If delivering mail from the network via mail -r,
+ * Strip the leading line and throw it away, as long
+ * as it begins with "From ..."
+ */
+
+ if (chew) {
+ cp = linebuf;
+ do {
+ c = getchar();
+ if (cp - linebuf < 120)
+ *cp++ = c;
+ } while (c != '\n' && c != 0);
+ *cp = '\0';
+ if (linebuf[0] != 'F' || linebuf[1] != 'r' ||
+ linebuf[2] != 'o' || linebuf[3] != 'm')
+ printf("%s", linebuf);
+ }
+ getput();
+ putchar('\n');
+ flush();
+ close(fout);
+ while (--argc > 0)
+ sendto(*++argv);
+ delexit(errs);
+}
+
+sendto(person)
+char *person;
+{
+ static int saved;
+ extern int fout, fin;
+ register char *filep;
+ register int him;
+ int i;
+
+ if ((person[0] == 'i' || person[0] == 'I') && person[1] == ':')
+ person += 2;
+ for (i = 0; person[i] != '\0'; i++)
+ {
+ if (person[i] == ':')
+ {
+ person[i] = '\0';
+ if (equal(person, "ing70") || equal(person, "ingres"))
+ person += i + 1;
+ else
+ person[i] = ':';
+ break;
+ }
+ }
+ if (person[i] == ':' || equal(person, "msgs"))
+ {
+ int i = fork();
+ int s;
+
+ if (i < 0) {
+ perror("fork");
+ goto assback;
+ }
+ if (i == 0) {
+ close(0);
+ open(lettmp, 0);
+ if (any(':', person)) {
+ execl(RMAILCMD, "sendmail", person, 0);
+ execl("/usr/bin/sendmail", "sendmail", person, 0);
+ execl("/bin/sendmail", "sendmail", person, 0);
+ perror("sendmail");
+ } else {
+ execl("/usr/new/msgs", "msgs", "-s", 0);
+ execl("/usr/ucb/msgs", "msgs", "-s", 0);
+ execl("/usr/bin/msgs", "msgs", "-s", 0);
+ }
+ exit(12);
+ }
+ for (;;) {
+ register int j = wait(&s);
+ if (j == -1)
+ goto assback;
+ if (j == i)
+ break;
+ }
+ if ((s & 0377) != 0 || (s >> 8) == 12)
+ goto assback;
+ return;
+ }
+
+ if ((him = getuserid(person)) == -1) {
+assback:
+ fout = 1;
+ flush();
+ printf("Can't send to %s.\n", person);
+ errs++;
+ if (ttyn(0)!='x' && saved==0) {
+ saved++;
+ if (accesss("dead.letter")) {
+ printf("Letter saved in 'dead.letter'\n");
+ prepend(lettmp, "dead.letter", GETUID());
+ } else
+ printf("In wrong directory\n");
+ }
+ return;
+ }
+ filep = cat(SPOOLDIR, person);
+ lock(filep);
+ prepend(lettmp, filep, him);
+ unlock();
+}
+
+prepend(from, to, own)
+char *from, *to;
+{
+ extern int fin, fout;
+ register int sig;
+ int statb[18];
+
+ if (stat(to, statb) >= 0 && (statb[2] & 060000) != 0) {
+ write(2, "Exotic destination\n", 19);
+ delexit(1);
+ }
+ unlink(preptmp);
+ if (fcreat(preptmp, &fout) < 0) {
+ fout = 1;
+ perror("mail");
+ delexit(1);
+ }
+ chmod(preptmp, 0600);
+ if (fopen(from, &fin) < 0) {
+ close(fout);
+ fout = 1;
+ perror("mail");
+ unlink(preptmp);
+ return(0);
+ }
+ getput();
+ close(fin);
+ fopen(to, &fin);
+ getput();
+ close(fin);
+ flush();
+ close(fout);
+ sig = signal(SIGINT, 01);
+ unlink(to);
+ if (fcreat(to, &fout) < 0) {
+ unlink(preptmp);
+ fout = 1;
+ signal(SIGINT, sig);
+ return(0);
+ }
+# ifdef NOTROOT
+ chmod(to, 0666);
+# else
+ chmod(to, 0600);
+ chown(to, own);
+# endif
+ if(stat(to, &inode) < 0 || inode.nlinks != 1) {
+ close(fout);
+ fout = 1;
+ unlink(preptmp);
+ signal(SIGINT, sig);
+ return(0);
+ }
+ if (fopen(preptmp, &fin) < 0) {
+ fout = 1;
+ perror("mail");
+ signal(SIGINT, sig);
+ errs++;
+ return(0);
+ }
+ getput();
+ flush();
+ close(fout);
+ close(fin);
+ fout = 1;
+ signal(SIGINT, sig);
+ return(1);
+}
+
+delexit(ex)
+{
+ unlock();
+ unlink(lettmp);
+ unlink(preptmp);
+ exit(ex);
+}
+
+equal(as1, as2)
+{
+ register char *s1, *s2;
+
+ s1 = as1;
+ s2 = as2;
+ while (*s1++ == *s2)
+ if (*s2++ == 0)
+ return(1);
+ return(0);
+}
+
+cat(ap1, ap2)
+char *ap1, *ap2;
+{
+ register char *p1, *p2;
+ static char fn[32];
+
+ p1 = ap1;
+ p2 = fn;
+ while (*p2++ = *p1++);
+ p2--;
+ p1 = ap2;
+ while (*p2++ = *p1++);
+ return(fn);
+}
+
+getput()
+{
+ extern int errno;
+ register c;
+
+ while(c = getchar()) {
+ errno = 0;
+ putchar(c);
+ if(errno) {
+ perror("mail");
+ delexit(1);
+ }
+ }
+}
+
+accesss(s1)
+{
+ if (access(".", 2) != -1 && (stat(s1, &inode)<0 || access(s1, 2)==0))
+ return(1);
+ return(0);
+}
+
+any(c, str)
+ char *str;
+{
+ register char *f;
+
+ f = str;
+ while (*f)
+ if (c == *f++)
+ return(1);
+ return(0);
+}
+
+char *maillock = ".lock"; /* Lock suffix for mailname */
+char *lockname = "/usr/spool/mail/tmXXXXXX";
+char locktmp[30]; /* Usable lock temporary */
+char curlock[50]; /* Last used name of lock */
+int locked; /* To note that we locked it */
+
+/*
+ * Lock the specified mail file by setting the file mailfile.lock.
+ * We must, of course, be careful to unlink the lock file by a call
+ * to unlock before we stop. The algorithm used here is to see if
+ * the lock exists, and if it does, to check its modify time. If it
+ * is older than 30 seconds, we assume error and set our own file.
+ * Otherwise, we wait for 5 seconds and try again.
+ */
+
+lock(file)
+char *file;
+{
+ register int f;
+ long age;
+ struct inode sbuf;
+ long curtime;
+
+ if (file == (char *) 0) {
+ printf("Locked = %d\n", locked);
+ return(0);
+ }
+ if (locked)
+ return(0);
+ strcpy(curlock, file);
+ strcat(curlock, maillock);
+ strcpy(locktmp, lockname);
+ mktemp(locktmp);
+ unlink(locktmp);
+ for (;;) {
+ f = lock1(locktmp, curlock);
+ if (f == 0) {
+ locked = 1;
+ return(0);
+ }
+ if (stat(curlock, &sbuf) < 0)
+ return(0);
+ time(&curtime);
+ age = * ((long *) sbuf.modtime);
+ if (curtime < age + 30) {
+ sleep(5);
+ continue;
+ }
+ unlink(curlock);
+ }
+}
+
+/*
+ * Remove the mail lock, and note that we no longer
+ * have it locked.
+ */
+
+unlock()
+{
+
+ if (locked)
+ unlink(curlock);
+ locked = 0;
+}
+
+/*
+ * Attempt to set the lock by creating the temporary file,
+ * then doing a link/unlink. If it fails, return -1 else 0
+ */
+
+lock1(tempfile, name)
+ char tempfile[], name[];
+{
+ register int fd;
+
+ fd = creat(tempfile, 0);
+ if (fd < 0)
+ return(-1);
+ close(fd);
+ if (link(tempfile, name) < 0) {
+ unlink(tempfile);
+ return(-1);
+ }
+ unlink(tempfile);
+ return(0);
+}
+
+/*
+ * Concatenate s2 on the end of s1. S1's space must be large enough.
+ * Return s1.
+ */
+
+char *
+strcat(s1, s2)
+register char *s1, *s2;
+{
+ register os1;
+
+ os1 = s1;
+ while (*s1++)
+ ;
+ *--s1;
+ while (*s1++ = *s2++)
+ ;
+ return(os1);
+}
+
+/*
+ * Copy string s2 to s1. s1 must be large enough.
+ * return s1
+ */
+
+char *
+strcpy(s1, s2)
+register char *s1, *s2;
+{
+ register os1;
+
+ os1 = s1;
+ while (*s1++ = *s2++)
+ ;
+ return(os1);
+}