+#include <ctype.h>
#include <stdio.h>
#include <pwd.h>
#include <utmp.h>
#define LSIZE 256
#define MAXLET 300 /* maximum number of letters */
#define MAILMODE (~0644) /* mode of created mail */
+#define RMAIL "/usr/net/bin/sendberkmail"
+#define LOCNAM1 "csvax"
+#define LOCNAM2 "ucbvax"
+#define LOCNAM3 "vax"
+#define LOCNAM4 "v"
char line[LSIZE];
char resp[LSIZE];
int nlet = 0;
char lfil[50];
long iop, time();
+char *getenv();
+char *index();
char lettmp[] = "/tmp/maXXXXX";
char maildir[] = "/usr/spool/mail/";
char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxx";
char dead[] = "dead.letter";
char *thissys = sysname;
+char *netname = "vax";
char forwmsg[] = " forwarded\n";
-char *curlock;
-int lockerror;
FILE *tmpf;
FILE *malf;
char *my_name;
char *getlogin();
struct passwd *getpwuid();
int error;
-int locked;
int changed;
int forward;
char from[] = "From ";
int flgf;
int flgp;
int delflg = 1;
+int hseqno;
jmp_buf sjbuf;
main(argc, argv)
mktemp(lettmp);
unlink(lettmp);
my_name = getlogin();
- if (my_name == NULL) {
+ if (my_name == NULL || strlen(my_name) == 0) {
struct passwd *pwent;
pwent = getpwuid(getuid());
if (pwent==NULL)
done();
}
if (argv[0][0] != 'r' && /* no favors for rmail*/
- (argc == 1 || argv[1][0] == '-'))
+ (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rh")))
printmail(argc, argv);
else
sendmail(argc, argv);
signal(i, f);
}
+any(c, str)
+ register int c;
+ register char *str;
+{
+
+ while (*str)
+ if (c == *str++)
+ return(1);
+ return(0);
+}
+
printmail(argc, argv)
char **argv;
{
}
} else if (argv[1][1]=='r') {
forward = 1;
+ } else if (argv[1][1]=='h') {
+ forward = 1;
} else {
fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
done();
print = 0;
continue;
}
- if (resp[1] == '\n' || resp[1] == '\0')
- cat(resp+1, "mbox", "");
+ if (resp[1] == '\n' || resp[1] == '\0') {
+ p = getenv("HOME");
+ if(p != 0)
+ cat(resp+1, p, "/mbox");
+ else
+ cat(resp+1, "", "mbox");
+ }
for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
malf = fopen(lfil, "a");
if (malf == NULL) {
continue;
}
for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
- if (!sendrmt(j, lfil)) /* couldn't send it */
+ if (!sendrmt(j, lfil, "/bin/mail")) /* couldn't send it */
flg++;
if (flg)
print = 0;
sendmail(argc, argv)
char **argv;
{
+ char truename[100];
+ int first;
+ register char *cp;
+ int gaver = 0;
+
+ truename[0] = 0;
+ line[0] = '\0';
+ /*
+ * When we fall out of this, argv[1] should be first name,
+ * argc should be number of names + 1.
+ */
+
+ while (argc > 1 && *argv[1] == '-') {
+ cp = *++argv;
+ argc--;
+ switch (cp[1]) {
+ case 'r':
+ if (argc <= 0) {
+ usage();
+ done();
+ }
+ gaver++;
+ strcpy(truename, argv[1]);
+ fgets(line, LSIZE, stdin);
+ if (strcmpn("From", line, 4) == 0)
+ line[0] = '\0';
+ argv++;
+ argc--;
+ break;
+
+ case 'h':
+ if (argc <= 0) {
+ usage();
+ done();
+ }
+ hseqno = atoi(argv[1]);
+ argv++;
+ argc--;
+ break;
+
+ default:
+ usage();
+ done();
+ }
+ }
+ if (argc <= 1) {
+ usage();
+ done();
+ }
+ if (gaver == 0)
+ strcpy(truename, my_name);
+ /*
+ if (argc > 4 && strcmp(argv[1], "-r") == 0) {
+ strcpy(truename, argv[2]);
+ argc -= 2;
+ argv += 2;
+ fgets(line, LSIZE, stdin);
+ if (strcmpn("From", line, 4) == 0)
+ line[0] = '\0';
+ } else
+ strcpy(truename, my_name);
+ */
time(&iop);
- fprintf(tmpf, "%s%s %s", from, my_name, ctime(&iop));
+ fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
iop = ftell(tmpf);
flgf = 1;
- while (fgets(line, LSIZE, stdin) != NULL) {
- if (line[0] == '.' && line[1] == '\n')
+ for (first = 1;; first = 0) {
+ if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL)
+ break;
+ if (!first && fgets(line, LSIZE, stdin) == NULL)
+ break;
+ if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin)))
break;
if (isfrom(line))
fputs(">", tmpf);
return;
}
while (--argc > 0)
- if (!send(0, *++argv)) /* couldn't send to him */
+ if (!send(0, *++argv, truename))
error++;
if (error) {
setuid(getuid());
fclose(tmpf);
}
-sendrmt(n, name)
+sendrmt(n, name, rcmd)
char *name;
+char *rcmd;
{
FILE *rmf, *popen();
register char *p;
int sts;
local = 0;
+ if (index(name, '^')) {
+ while (p = index(name, '^'))
+ *p = '!';
+ if (strncmp(name, "researc", 7)) {
+ strcpy(rsys, "research");
+ if (*name != '!')
+ --name;
+ goto skip;
+ }
+ }
if (*name=='!')
name++;
for(p=rsys; *name!='!'; *p++ = *name++)
fprintf(stdout, "null name\n");
return(0);
}
+skip:
if ((pid = fork()) == -1) {
fprintf(stderr, "mail: can't create proc for remote\n");
return(0);
}
setuid(getuid());
if (local)
- sprintf(cmd, "mail %s", rsys);
+ sprintf(cmd, "%s %s", rcmd, rsys);
else {
if (index(name+1, '!'))
sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
}
if ((rmf=popen(cmd, "w")) == NULL)
exit(1);
- copylet(n, rmf, local? FORWARD: REMOTE);
+ copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
pclose(rmf);
exit(0);
}
-send(n, name) /* send letter n to name */
+/*
+ * Send mail on the Berkeley network.
+ * Sorry Bill, sendrmt() is so awful we just gave up.
+ */
+
+sendberkmail(n, name, fromaddr)
+ char name[];
+ char fromaddr[];
+{
+ char cmd[200];
+ register FILE *cmdf;
+
+ sprintf(cmd, "%s -h %d -f %s -t %s", RMAIL, hseqno, fromaddr, name);
+ if ((cmdf = popen(cmd, "w")) == NULL) {
+ perror(RMAIL);
+ return(0);
+ }
+ copylet(n, cmdf, ORDINARY);
+ pclose(cmdf);
+ return(9);
+}
+
+usage()
+{
+
+ fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
+}
+
+send(n, name, fromaddr)
int n;
char *name;
+char *fromaddr;
{
char file[50];
register char *p;
register mask;
struct passwd *pw, *getpwnam();
- for(p=name; *p!='!' &&*p!='\0'; p++)
+ stripfx(LOCNAM1, &name);
+ stripfx(LOCNAM2, &name);
+ stripfx(LOCNAM3, &name);
+ stripfx(LOCNAM4, &name);
+ if(*name == ':')name++; /* skip colon in to-name */
+ for(p=name; *p!=':' &&*p!='\0'; p++);
+ /* if(*p == ':') return(sendrmt(n, name, RMAIL)); */
+ if (*p == ':')
+ return(sendberkmail(n, name, fromaddr));
+ else if (strcmp(name, "msgs") == 0) return(sendrmt(n, "-s", "/usr/ucb/msgs"));
+ for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
;
- if (*p == '!')
- return(sendrmt(n, name));
+ if (*p == '!'|| *p=='^')
+ return(sendrmt(n, name, 0));
if ((pw = getpwnam(name)) == NULL) {
fprintf(stdout, "mail: can't send to %s\n", name);
return(0);
done();
}
-done()
-{
- if(!lockerror)
- unlock();
- unlink(lettmp);
- exit(error+lockerror);
-}
+/*
+ * 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.
+ */
+
+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(file)
char *file;
{
- struct stat stbuf;
+ register int f;
+ struct stat sbuf;
+ long curtime;
+ int statfailed;
if (locked || flgf)
- return;
- if (stat(file, &stbuf)<0)
- return;
- if (stbuf.st_mode&01) { /* user x bit is the lock */
- if (stbuf.st_ctime+60 >= time((long *)0)) {
- fprintf(stderr, "%s busy; try again in a minute\n", file);
- lockerror++;
- done();
+ return(0);
+ strcpy(curlock, file);
+ strcat(curlock, maillock);
+ strcpy(locktmp, lockname);
+ mktemp(locktmp);
+ unlink(locktmp);
+ statfailed = 0;
+ for (;;) {
+ f = lock1(locktmp, curlock);
+ if (f == 0) {
+ locked = 1;
+ return(0);
}
+ if (stat(curlock, &sbuf) < 0) {
+ if (statfailed++ > 5)
+ return(-1);
+ sleep(5);
+ continue;
+ }
+ statfailed = 0;
+ time(&curtime);
+ if (curtime < sbuf.st_ctime + 30) {
+ sleep(5);
+ continue;
+ }
+ unlink(curlock);
}
- locked = stbuf.st_mode & ~01;
- curlock = file;
- chmod(file, stbuf.st_mode|01);
}
+/*
+ * Remove the mail lock, and note that we no longer
+ * have it locked.
+ */
+
unlock()
{
- if (locked)
- chmod(curlock, 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);
+}
+
+done()
+{
+ if(locked)
+ unlock();
+ unlink(lettmp);
+ unlink(locktmp);
+ exit(error);
+}
+
cat(to, from1, from2)
char *to, *from1, *from2;
{
*s = '\0';
return(p);
}
+/*
+ stripfx(prefix string, pointer to string)
+
+ takes a ptr to string and compares it to prefix string.
+ may be called multiple times
+*/
+stripfx(pfx, name)
+ char *pfx;
+ char **name;
+{
+ register char *cp = *name;
+
+ while (*pfx && (*cp == *pfx || *cp == toupper(*pfx)))
+ cp++, pfx++;
+ if (*cp != ':' || *pfx != 0)
+ return;
+ *name = cp;
+}