|
|
BSD 4.0
#
/*
* 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);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.