static char sccsid
[] = "@(#)v6mail.c 4.4 (Berkeley) %G%";
* a clean and simple mail program
* machine and version independent
* must run as setuid root to chown the destination mailbox
* if NOTROOT defined, doesn't need to run as root
* bitch to "csvax:schmidt" instead
* sends standard input to people
* mail -r fromaddr people
* sends mail from the network
* don't call sendmail, send mail directly
* mail to filename instead of user (must be at least one /)
* delete the invokers mailbox (more efficient than
* Ingres 11/70 multiple names/uid?
* Save? type 'x' - doesn't unlink the mail file
* BIFF is an immediate notification flag using the IPC stuff
/* for all machines at RAND */
/* for all machines at NOSC */
/* lump the CC machines into one */
# define MSGSCMD "/usr/ucb/bin/msgs"
# define MSGSCMD "/usr/bin/eecs/msgs"
# define MSGSCMD "/usr/bin/msgs"
# define MSGSCMD "/usr/ucb/msgs"
# define MSGSCMD "/usr/bin/msgs"
# define MSGSCMD "/usr/ucb/msgs"
# define MSGSCMD "/usr/bin/msgs"
# define MSGSCMD "/usr/ucb/msgs"
# define MSGSCMD "/usr/ucb/msgs"
# define MSGSCMD "/usr/bin/eecs/msgs"
# define MSGSCMD "/usr/ucb/msgs"
# define MSGSCMD "/usr/bin/msgs"
# define MSGSCMD "/usr/bin/msgs"
# define MSGSCMD "/usr/ucb/msgs"
# define MSGSCMD "/usr/ucb/bin/msgs"
# define MSGSCMD "/usr/bin/eecs/msgs"
# define MSGSCMD "/usr/bin/msgs"
/* end of berkeley defsn */
/* end of per-machine ifdefs */
# define MAILDIR "/usr/mail"
# define MAILDIR "/usr/spool/mail"
char lettmp
[] = "/tmp/MaXXXXX"; /* keep letter before sending it */
char preptmp
[] = "/tmp/mbXXXXX"; /* if prepending msg, use this file */
int chew
; /* if true, strip extra from lines */
int dflag
; /* if true, don't call sendmail */
char shopcnt
[30] = "0"; /* hop count parameter for rmt mail */
int errs
; /* no of errs in sending */
char deleteonly
; /* if true, just delete mailbox */
char remname
[50]; /* if non-empty, from line extra */
char namebuf
[128], *sn
= NULL
, logindir
[60];
if(sn
== NULL
|| *sn
== 0 || *sn
== ' '){
pwd
= getpwuid(myuid
); /* will read passwd file */
strcpy(logindir
,pwd
->pw_dir
);
fprintf(stderr
,"Who are you?\n");
for (argc
--, argv
++; argc
> 0 && argv
[0][0] == '-'; argc
--, argv
++)
printmail(argc
, argv
, namebuf
,logindir
);
case 'r': /* one-arg -r-- -r addr */
/* ignore -r if not network or root */
if (strcmp("network", namebuf
) == 0 || myuid
== 0 ||
strcmp("uucp", namebuf
) == 0 || index(argv
[1], '!') != NULL
) {
chew
++; /* eat From lines */
else strcpy(remname
, argv
[1]);
case 'h': /* hop count - used by network */
case 'd': /* really deliver this message */
case 'D': /* only delete the invokers mailbox */
goto hitit
; /* delete mail box, thats all */
/* if we are already ignoring signals, catch sigint */
if(signal(SIGINT
,SIG_IGN
) != SIG_IGN
)
bulkmail(argc
, argv
, namebuf
);
printmail(argc
, argv
, name
, logindir
)
char sfnmail
[60], mbox
[120];
pwd
= getpwuid(getuid());
fprintf(stderr
,"Can't get directory\n");
strcpy(logindir
, pwd
->pw_dir
);
sprintf(sfnmail
,"%s/.mail",logindir
);
sprintf(sfnmail
,"%s/%s",MAILDIR
,name
);
if (stat(sfnmail
, &statbuf
)>=0 && statbuf
.st_nlink
==1 &&
getsize(&statbuf
) > 0L && (fdin
= fopen(sfnmail
, "r")) != NULL
){
sprintf(mbox
,"%s/mbox",logindir
);
printf("Saved mail in 'mbox'\n");
if(insert(sfnmail
, mbox
, getuid(),getgid()))
else printf("In wrong directory\n");
else if(c
!= 'x') remove(sfnmail
);
bulkmail(argc
, argv
, from
)
** Ship off to sendmail if appropriate (and possible)
execv("/usr/lib/sendmail", argv
);
/* oops... better just deliver it. */
fprintf(stderr
, "Not using sendmail\n");
fdout
= fopen(lettmp
, "w");
* If delivering mail from the network via mail -r,
* Strip the leading line and throw it away, as long
* as it begins with "From ..." (and preserve the date if poss.)
fgets(linebuf
,BUFSIZ
,stdin
);
if(strncmp(linebuf
,"From ",5) != 0){
fprintf(fdout
,"%s", linebuf
);
else fline(fdout
,getdate(linebuf
),from
);
else fline(fdout
,NULL
,from
);
if(remname
[0]) fprintf(fdout
,"(from %s)\n",remname
);
/* on the image machine, promt with subj */
if(getput(stdin
,fdout
) == 0)
/* print from line, with date date, if date = NULL, compute it */
fprintf(fdout
,"From %s %s", from
, date
);
/* look over linebuf and return ptr to date, NULL if error */
if(strncmp(s
," Sun ",5) == 0
|| strncmp(s
," Mon ",5) == 0
|| strncmp(s
," Tue ",5) == 0
|| strncmp(s
," Wed ",5) == 0
|| strncmp(s
," Thu ",5) == 0
|| strncmp(s
," Fri ",5) == 0
|| strncmp(s
," Sat ",5) == 0)
register int hisuid
, hisgid
;
char sfnmail
[60], logindir
[60];
if(person
[0] == ':')person
++;
/* sendmail provides these services */
|| strcmp(person
,"msgs") == 0
while((pid
= fork()) == -1)sleep(2);
freopen(lettmp
,"r",stdin
);
setuid(getuid()); /* insure no security hole*/
if (strcmp(person
,"msgs") != 0) {
sendberkmail will add the machine, e.g.
CSVAX:schmidt, if the -f flag is not set
execl("/usr/net/bin/sendberkmail",
"sendberkmail", "-t",person
,"-h",shopcnt
,
chew
? "-f" : 0,fromaddr
,0);
perror("/usr/net/bin/sendberkmail");
execl(MSGSCMD
, "msgs", "-s", 0);
register int rcode
= wait(&pidchild
);
if ((pidchild
& 0377) != 0 || (pidchild
>> 8) != 0)
/* if name has no / in it, we assume it is a user's name */
hisuid
= uidfromsn(person
);
hisuid
= guid(pwd
->pw_uid
,pwd
->pw_gid
);
strcpy(logindir
,pwd
->pw_dir
);
fprintf(stderr
,"Can't send to %s.\n", person
);
if (isatty(0) && saved
==0) {
if (accesss("dead.letter")) {
printf("Letter saved in 'dead.letter'\n");
insert(lettmp
, "dead.letter",
printf("In wrong directory\n");
sprintf(sfnmail
,"%s/.mail",logindir
);
sprintf(sfnmail
,"%s/%s",MAILDIR
,person
);
insert(lettmp
, sfnmail
, hisuid
, hisgid
);
else { /* it has / in it, "person" is a file */
insert(lettmp
, person
, -1, -1);
fprintf(stderr
,"Can't access %s\n",person
);
/* return 1 if success, 0 otherwise */
insert(from
, to
, uid
, gid
)
return(prepend(from
,to
,uid
, gid
));
return(append(from
,to
,uid
, gid
));
/* return 1 if success, 0 otherwise */
register FILE *fdin
, *fdout
;
char *cp
, buf
[100], *rindex();
if (stat(to
, &statbuf
) >= 0 && (statbuf
.st_mode
&S_IFDIR
) != 0) {
fprintf(stderr
, "Exotic destination %s\n", to
);
if ((fdout
= fopen(to
, "a")) == NULL
) {
if(uid
!= -1)mchown(to
, uid
, gid
);
if(uid
!= -1)chmod(to
, MAILMODE
);
if ((fdin
= fopen(from
, "r")) == NULL
) {
{ s
= socket(AF_INET
, SOCK_STREAM
, 0, 0);
sprintf(buf
, "%s@%d\n", cp
+1, ftell(fdout
));
ret
= getput(fdin
,fdout
);
hp
= gethostbyname("localhost");
sp
= getservent("biff", "udp");
bcopy(hp
->h_addr
, &sin
.sin_addr
, hp
->h_length
);
sin
.sin_family
= hp
->h_addrtype
;
sin
.sin_port
= sp
->s_port
;
(void) sendto(s
, buf
, strlen(buf
) + 1, 0,
/* return 1 if success, 0 otherwise */
prepend(from
, to
, uid
, gid
)
if (stat(to
, &statbuf
) >= 0 && (statbuf
.st_mode
&S_IFDIR
) != 0) {
fprintf(stderr
, "Exotic destination %s\n", to
);
if ((fdout
= fopen(preptmp
, "w")) == NULL
) {
chmod(preptmp
, MAILMODE
);
if ((fdin
= fopen(from
, "r")) == NULL
) {
if(getput(fdin
,fdout
) == 0){
/* ignore error since may not exist */
if(fdin
!= NULL
&& getput(fdin
,fdout
) == 0){
if(fdin
!= NULL
)fclose(fdin
);
sig
= signal(SIGINT
, SIG_IGN
);
if ((fdout
= fopen(to
, "w")) == NULL
) {
if(uid
!= -1)chmod(to
,0666);
if(uid
!= -1)mchown(to
, uid
, gid
);
if(stat(to
, &statbuf
) < 0 || statbuf
.st_nlink
!= 1) {
if ((fdin
= fopen(preptmp
, "r")) == NULL
) {
ret
= getput(fdin
,fdout
);
/* return 1 if ok, 0 otherwise */
register FILE *fdin
, *fdout
;
while((c
= getc(fdin
)) != EOF
) {
if(stat(s1
,&statbuf
)<0 || access(s1
,2) == 0)
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.
if using OLDMAIL, and NOTROOT, cann't lock since can't necessarily
write on user's login directory
printf("Locked = %d\n", locked
);
sprintf(curlock
,"%s%s",file
,".lock");
sprintf(locktmp
,"%s/tmXXXXXX",MAILDIR
);
f
= lock1(locktmp
, curlock
);
if (stat(curlock
, &statbuf
) < 0)
if (curtime
< statbuf
.st_mtime
+ 30) {
* Remove the mail lock, and note that we no longer
* Attempt to set the lock by creating the temporary file,
* then doing a link/unlink. If it fails, return -1 else 0
fno
= creat(tempfile
, 0400);
if (link(tempfile
, name
) < 0) {
stripfx(prefix string, pointer to string)
takes a ptr to string and compares it to prefix string.
may be called multiple times
register char *cp
= *name
;
while (*pfx
&& (*cp
== *pfx
|| *cp
== toupper(*pfx
)))
if (*cp
!= ':' || *pfx
!= 0)
/* for machines at RAND */
stripfx("graphics",pperson
);
/* end of defns for Rand */
/* for machines at NOSC */
/* end of defns for NOSC */
stripfx("ing70",pperson
);
stripfx("ingres",pperson
);
stripfx("ingvax",pperson
);
stripfx("virus",pperson
);
stripfx("image",pperson
);
stripfx("esvax",pperson
);
stripfx("arpavax",pperson
);
stripfx("mathstat",pperson
);
stripfx("csvax",pperson
);
stripfx("eecs40",pperson
);
/* end of berkeley defns */
this removes the mail file sfn by either truncating it, as required
on OLDMAIL systems, or unlinking it. If the unlink fails, we truncate it.