SRI-NOSC/ncpp/mail/sndmsg.c
#/*
Module Name:
sndmsg.c
Installation:
if $1e = finale goto finale
cc -c sndmsg.c
if ! -r sndmsg.c exit
cc sndmsg.o /usr/net/hnconv.c
rm -f sndmsg.o hnconv.o
exit
: finale
cc -O -c -s sndmsg.c
if ! -r sndmsg.o exit
cc -O -s sndmsg.o /usr/net/hnconv.c
rm -f sndmsg.o hnconv.o
if ! -r a.out exit
su cp a.out /bin/sndmsg
rm a.out
Module History:
(((Most recent changes first)))
change NOSC-SDL to be the HOSTNAME value in siteinfo.h; also to get the
local IMP number from NETNUMBER in siteinfo.h
changed Rand-Unix to be NOSC-SDL
change RAND-ISD to Rand-Unix in 'from'
only snoop if SNOOPFILE exists
restore @ as line-delete before asking for subject, not after
added 'copy of mail for xxx' to messages for snoop copy
restore @ as line-delete before exiting if no 'To' list given
changed SNOOP to MAILCOPY
added message separaters
added ability to be called by server FTP
added aliases
added mail snoop
change '@' to ' at ' in to list
*/
#include "/usr/sys/h/siteinfo.h"
#define MSGSEP "\001\001\001\001\n"
#define MSGSEPL 5
#define loop for(;;)
#define SNOOPFILE "/change/snoop.bak" /* if this file is there, then snoop */
#define SNOOP "Mailcopy@RCC\n" /* 0 or snoop mailbox name ended with \n */
#define LOCIMP (NETNUMBER&077) /* local imp number */
#define true 1
#define false 0
#define SMALLBUFLEN 256
#define controla 001
#define controlb 002
#define controlc 003
#define controld 004
#define controlf 006
#define controlh 010
#define controlq 021
#define controlr 022
#define controls 023
#define controlw 027
#define controlx 030
#define controlz 032
#define backspace 036
#define del 0177
#define abortchar 034
int goaway();
struct status
{
char s_minor;
char s_major;
int s_number;
int s_mode;
char s_nlinks;
char s_uid;
char s_gid;
char s_size0;
int s_size1;
int s_addr[8];
int s_actime[2];
int s_modtime[2];
} statb;
struct {
char ispeed;
char ospeed;
char erase;
char kill;
int mode;
} *sttyptr &ttys;
struct iobuf {
int fildes;
int nleft;
char *nextp;
char buff[512];
} afilebuf;
struct iobuf *afileptr &afilebuf;
int savekill;
int pwfd;
int afile;
int tmpfd;
int fd;
int namefd;
int mbfd;
char bigbuf[512];
char pwbuf[512];
char *pwptr;
int pwcount;
int filecnt;
int netmsgs;
char cc[SMALLBUFLEN],to[SMALLBUFLEN],subject[SMALLBUFLEN];
char answer[10];
char user[40];
char dbuf[32];
char tempfile[64],mailbox[64],netfile[64],from[64],returnto[64];
char hostname[64];
char realname[80];
char *letter,*date;
int ttys[3];
int oldmode,uid,gid,myuid;
int unsent false;
int snoopcopy false;
int snoop false; /* becomes true if any non-Rand recipients */
int file false;
int oldfile false;
int orighost;
char hex[] "0123456789ABCDEF";
/* name:
send
function:
A message sending program modeled after the tenex program
sndmsg.
parameters:
None have been defined as of yet.
returns:
It delivers local mail by appending it to a file called mailbox
in the user's root.
The delivery of network mail is not yet implemented, but will
probably by dropping the file into a daemons mailbox.
If mail is undeliverable, a copy of the letter is left in
a file called unsent.mail, in the senders current directory.
history:
Originally written by someone at Berkeley (Murray Bowles?)
Reorganized and augmented by Mark Kampe 10/75
*/
main(argc,argv)
char *argv[];
int argc;
{
char *lp;
register char *p1, *p2;
int register i;
int vector[2];
if ((pwfd = open("/etc/passwd",0)) < 0)
{
printf("Couldn't open password file!\n");
exit();
}
afile=fopen("/usr/net/aliases",afileptr);
if (argc==3 && *argv[0]=='\001') /* is being called by FTP */
{ if ((tmpfd=open(argv[1],0)) < 0) /* second argument is file name */
exit();
orighost=argv[0][1]; /* originating host */
returnto[0] = '\0';
p1 = "mailer";
p2 = from;
while(*p1++ = *p1++);
send(argv[2],0); /* third argument is user name */
if ((orighost&077) != LOCIMP)
snoop++;
snoopcopy = argv[2];
if (snoop && SNOOP && stat(SNOOPFILE,&statb) >= 0)
send(SNOOP,0);
close(tmpfd);
unlink(argv[1]);
exit();
}
getname(from);
findlocal(from);
p1 = mailbox;
p2 = returnto;
while(*p2++ = *p1++); /* save user's directory for returning undeliverable*/
time(vector); /* mail */
chkill(); /* remove @ as line delete character */
date = arpadate(vector);
printf("To: "); gather(to);
if (*to == '\000')
{ printf("Can't send mail to nobody!\n");
rstkill();
exit();
}
printf("cc: "); gather(cc);
rstkill(); /* restore line delete */
printf("Subject: "); gather(subject);
printf("Type letter:\n-----\n"); input();
send(to,1);
send(cc,1);
if (snoop && SNOOP && stat(SNOOPFILE,&statb) >= 0)
{returnto[0] = '\0'; /* don't want to return this copy */
send(SNOOP,0);
/* printf("A copy of this message is being sent to correspondence\n");*/
}
if (unsent)
{ fd = creat("unsent.mail",0644);
if (fd < 0)
{ printf("unable to create unsent .mail\n");
exit(1);
}
writef(fd,letter);
close(fd);
chown("unsent.mail",myuid);
printf("A copy of this letter has been left in 'unsent.mail'\n");
}
close(tmpfd);
unlink(tempfile);
exit(0); /* [I don't know about this part!]
if (netmsgs)
{ printf("Send network mail now? ");
gather(answer);
if (answer[0] != 'y') exit(0);
else execl("/usr/bin/maildaemon", "send netmail", 0);
} */
}
/* name:
gather
function:
read a single line of console input into the user specified
buffer. Currently standard unix editing is in effect, but
this will later be changed to use the same sexy editing as
does the message inputting routine.
algorithm:
Read a character:
If it is an unescaped new line, null terminate the buffer and return.
Otherwise, stash the character into the buffer.
If the length of the buffer has been reached, echo a new line and
return.
parameters:
*char pointer to user buffer of length SMALLBUFLEN
returns:
nothing
globals:
SMALLBUFLEN
calls:
getchar
slashc
called by:
main
send
history:
Recoded by Mark Kampe 11/22/75
*/
gather(sp)
char *sp;
{
register char c;
register char *p;
p = sp;
while( ((c = getchar(0)) != '\n') && (c>0) )
{ if (c == '\\') *p++ = slashc();
else *p++ = c;
if ((p - sp) >= SMALLBUFLEN) break;
}
*p = '\0';
}
/* name:
writef
function:
Write a null terminated string
algorithm:
Determine the length of the string.
Write it out.
CAVEAT This call is not buffered, so use it carefully or pay the cost
of high I/O expense. It was writted to decrease subroutine linkage
global variable referencing and module size. But those wins can
easily be lost if writef is consistantly called with small strings.
parameters:
int file descriptor of output file.
*char pointer to null terminated string.
returns:
int value returned by write.
globals:
calls:
write (system)
called by:
lotsa people
history:
Initially coded by Mark Kampe 11/22/75
*/
writef(afd,str)
int afd;
char *str;
{ register int count;
register char *s;
s = str;
for(count=0; *s++; count++);
return(write(afd,str,count));
}
writef1(afd,str) /* same as writef except convert '@' to ' at ' */
int afd;
char *str;
{ char c;
while (c = *str++)
{ if (c == '@') write(afd," at ",4);
else write(afd,&c,1);
}
}
/* name:
input
function:
To accept the text of the message while doing all of the sexy
sndmsg type editing.
algorithm:
Allocate a huge buffer.
Read characters (editing sexily as I go)
Return when I get a ctl-d or ctl-z
parameters:
none
returns:
With a null terminated letter in the string pointed to by
the global variable letter.
globals:
letter address of the buffer.
calls:
rawmode
normal
writef
write system
printf
getchar
sbreak system
gtty system
called by:
main
history:
Originally coded by someone at Berkeley
Fixed up and augmented by Mark Kampe.
*/
input()
{
char *tp;
register char *p,c;
register int i;
int eomem;
char filename[50];
p = letter = sbrk(1000); /* Tried to avoid this! */
eomem = letter+1000;
gtty(0,ttys);
rawmode();
loop {
c = getchar(0);
if (p >= eomem)
{ sbrk(1000);
eomem =+ 1000;
}
switch (c)
{
case controla: /* tty oriented character delete */
if (p > letter)
{ write(1,"\\",1);
write(1,--p,1);
}
continue;
case controlb: /* input a file at this point */
case controlf: printf("\nInput file: ");
normal();
gather(filename);
if ((fd = open(filename,0)) < 0)
printf("Couldn't open %s\n",filename);
else
{ sbrk(512);
eomem =+ 512;
for(i=read(fd,p,512); i>0; i=read(fd,p,512))
{ p =+ i;
sbrk(512);
eomem =+ 512;
}
close(fd);
printf("%s has been included\n", filename);
}
rawmode();
continue;
case controlc: /* breakout */
case del: normal();
exit();
case controld: /* normal end of message */
case controlz: if (*(p-1) != '\n')
{ *p++ = '\n';
printf("\n");
/* Guarentee msg ends with a new line */
}
*p = '\000';
printf("-----\n");
goto out;
case backspace:
case controlh: if (p > letter) write(1," \b",2);
case '#': if (p > letter) p--;
continue;
case controlr: /* retype current line */
tp = p;
while ((tp > letter) && (*tp != '\n')) tp--;
*p = '\0';
if (tp == letter) write(1,"\n",1);
writef(1,tp);
continue;
case controls: /* retype entire message */
*p = '\000';
write(1,"\n",1);
writef(1,letter);
continue;
case controlw: /* back up over the last word typed */
--p;
while((p > letter) &&
((*p != ' ') &&
(*p != ',') &&
(*p != '\n') &&
(*p != '\t') ) )
{ write(1,"\b \b",3);
p--;
};
while ((p>letter) &&
((*p == ' ') || (*p == '\t')) )
{ write(1,"\b \b",3);
p--;
};
*++p = '\0';
continue;
case controlx: /* line delete */
write(1,"XXX",3);
case '@': write(1,"\n",1);
p--;
while ((p >= letter) && (*p != '\n')) p--;
*++p = '\0';
continue;
case abortchar: /* sigh */
normal();
abort();
case '\\': c = slashc();
default: *p++ = c;
} /* end switch */
} /* end of while loop */
out: /* restore console modes and make the tempfile */
normal();
tmpfile(tempfile); /* get a filename */
if ((tmpfd = creat(tempfile,0644)) < 0)
{ printf("Unable to create temp file\n");
exit(1);
}
write(tmpfd,"Date: ",6);
writef(tmpfd,date);
write(tmpfd,"\nFrom: ",7);
writef(tmpfd,from);
writef(tmpfd," at ");
writef(tmpfd,HOSTNAME);
if (*subject)
{ write(tmpfd,"\nSubject: ",10);
writef(tmpfd,subject);
}
write(tmpfd,"\nTo: ",5);
writef1(tmpfd,to);
if (*cc)
{ write(tmpfd,"\ncc: ",5);
writef1(tmpfd,cc);
}
write(tmpfd,"\n\n",2);
writef(tmpfd,letter);
write(tmpfd,"-------\n",8);
/* whole message is now in temp file */
/* close it and reopen it for input */
close(tmpfd);
tmpfd = open(tempfile,0);
} /* end of input */
/* name:
rawmode, normal, chkill, and rstkill
function:
to put the console into raw mode and normal mode and to change
and restore the line delete character.
globals:
oldmode
calls:
stty
called by:
input
history:
written at berkeley
*/
normal()
{
ttys[2] = oldmode;
stty(0,ttys);
}
rawmode()
{
oldmode = ttys[2];
ttys[2] =| 040; /* raw mode */
stty(0,ttys);
}
chkill()
{ gtty(0,ttys);
savekill = ttys[1];
sttyptr->kill = '\177'; /* change line delete to nothing! */
signal(2,&goaway);
stty(0,ttys);
}
rstkill()
{ ttys[1] = savekill;
stty(0,ttys);
signal(2,1);
signal(3,1);
}
goaway()
{ ttys[1] = savekill;
stty(0,ttys);
exit();
}
/* name:
send
function:
To take a list of recipients and take steps to deliver the
message (now in the temp file) to all of them.
algorithm:
parse off a name.
If it is a name:, open that file and read from it for a while.
If it is a local user id, call post
If it is a network user id, call netpost
parameters:
Pointer to a null terminated characterstring which is a list
of recipients.
returns:
globals:
unsent
calls:
valid
open (system)
printf
network
findlocal
netpost
post
called by:
main
history:
Coded by someone at berkely.
Minor modifications by Mark Kampe.
*/
send(list,infoflg)
char *list;
int infoflg;
{
register char *name,*curp;
register char c;
int ret;
int alias;
char *ap;
alias = false;
curp = list;
while (alias || file || *curp)
{ name = user;
while (valid(c = file?getchar(namefd):(alias?*ap++:*curp++)))
*name++ = c;
*name = '\0';
switch (c)
{
case ':': if (file)
{if (infoflg)
printf("Nested name files not allowed.\n");
continue;
}
if ((namefd = open(user,0)) < 0)
{
if (infoflg) printf("Couldn't open %s\n",user);
unsent++;
continue;
}
file++;
continue;
case -1: close(namefd);
file = false;
continue;
case '\0': if (!(file|alias))
--curp;
case '\n': if (!file && alias)
alias = false;
case ',':
case ' ':
if (*user == '\000') continue;
if (infoflg) printf("%s -- ",user);
if (ret=network(user))
{ if (ret == -1)
{ if (infoflg) printf("host unknown\n");
unsent++;
continue;
}
netpost(user,hostname,infoflg);
continue;
}
if (!alias && findalias(user))
{ alias++;
ap = realname;
if (infoflg) printf("(alias for %s)\n",realname);
continue;
}
if (findlocal(user))
{ stcat("/.mail",mailbox);
post(infoflg);
continue;
}
{ if (infoflg) printf("not a local user\n");
unsent++;
continue;
}
default: if (infoflg)
{printf("Illegal terminator %c.\n",c);
printf("User name %s ignored.\n",user);
}
} /* end switch */
}
} /* end send */
/* name:
findlocal
function:
To ascertain whether or not someone is a local user, and
if he is, to find the name of his root directory.
algorithm:
Rewind the password file.
Search it for a line starting with the user name.
If found:
extract all the info about uid, gid mailbox, etc.
return.
Else, continue the search.
Announce that he isn't a known user.
parameters:
*char pointer to null terminated user name.
returns:
boolean whether or not he was found.
globals:
pwfd
uid
gid
mailbox
pwcount
calls:
getpwchar
seek (system)
called by:
send
history:
Written by Mark Kampe
*/
findlocal(name)
char *name;
{
register char *np;
register char pwc;
/* rewind the password file */
seek(pwfd,0,0);
pwcount = 0;
pwc = 1;
while(pwc > 0)
{ np = name; /* search for a line starting with name */
for(pwc = getpwchar(); pwc == *np++; pwc = getpwchar());
if ((pwc == ':') && (*--np == '\000')) goto gotuser;
while( (pwc != '\n') && (pwc > 0) ) pwc = getpwchar();
}
return(false);
gotuser: /* extract all neat info from pw entry */
for(pwc = getpwchar(); pwc != ':'; pwc = getpwchar());
/* we have skipped over the password */
for(uid = 0; (pwc = getpwchar()) != ':'; uid =+ (9*uid) + pwc - '0');
for(gid = 0; (pwc = getpwchar()) != ':'; gid =+ (9*gid) + pwc - '0');
for(pwc = getpwchar(); pwc != ':'; pwc = getpwchar());
/* we have skipped over the gecos bin */
np = mailbox;
for(pwc = getpwchar(); pwc != ':'; pwc = getpwchar()) *np++ = pwc;
*np = '\000';
return(true);
}
/*name:
findalias
function:
To determine whether a name is in the alias file, and
if so to replace it with the real name.
algorithm:
Search the file for a line beginning with the name.
If found, move the real name(s) to 'realname'.
globals:
afile
afileptr
realname
calls:
getc(III)
seek(II)
called by:
send
history:
greep
*/
findalias(name)
char *name;
{
register char c, *p;
if (afile<0) return(false); /* alias file could not be opened */
seek(afileptr->fildes,0,0);
loop
{ for (p=name; *p++ == (c=getc(afileptr));); /* check for same name */
if (c<0) return(false);
if ((*--p == '\0') && (c == ':')) break; /* got it */
while(getc(afileptr) != '\n'); /* get to end of this line */
}
p = realname; /* move stuff after : to realname */
while ((*p++ = getc(afileptr)) != '\n');
*--p = '\0';
*++p = '\n';
return(true);
}
/* name:
network
function:
To determine whether a user is a network user, and if he
is, to break the name up into a hostname and ultimately
a list of user names.
algorithm:
Look for an @ in the name, if not found, not net
Copy the hostname into a separate buffer and truncate
it off of the user name.
parameters:
*char pointer to null terminated user name.
returns:
boolean Whether or not guy was a network user.
(will be -1 if network site name unknown)
and if he was:
Hostname has been truncated off of user name and
put into the global buffer hostname.
globals:
hostname.
calls:
hnconf (not part of this source) to verify host name
called by:
send
history:
Written by Mark Kampe 11/27/75
*/
network(name)
char *name;
{ register char *c;
register char *d;
int hostnum;
for(c = name; *c; c++) if (*c == '@') goto netname;
return(false);
netname:
*c++ = '\000';
d = hostname;
while(*d++ = *c++);
if ((hostnum=atoi(hnconv(hostname))) <= 0)
return(-1);
if ((hostnum&077) != LOCIMP) snoop++; /* check for rand (any host) */
return(true);
}
/* name:
tempfile
function:
To select a unique name for and creat a temporary file.
algorithm:
Use send<processid> as the filename.
parameters:
*char pointer to user buffer of adequate length.
returns:
*char pointer to the chosen name
and tmpfd is the file descriptor for that file.
globals:
tmpfd
calls:
creat
getpid
called by:
input
history:
Coded by someone at Berkeley
*/
tmpfile(ubuf)
char *ubuf;
{
register int i;
register char *p1;
register char *p2;
p1 = ubuf;
for(p2 = "/tmp/send"; *p2 ; *p1++ = *p2++);
p2 = getpid();
for(i=0; i<5; i++)
{ *p1++ = (p2 & 07) + '0';
p2 =>> 3;
}
return(ubuf);
}
/* name:
post
function:
To mail a letter (in tempfile) to some individual unix user.
algorithm:
Create a mailbox if he doesn't have one.
If he had one make sure it is not in use.
Append the contents of the tempfile to it.
Make recipient the owner if he wasn't already.
parameters:
none
but.. null terminated name of recipients directory is in in mailbox.
returns:
boolean Whether or not it was successfully sent.
globals:
mailbox
mbfd
tmpfd
bigbuf
unsent
calls:
creat
seek
read
write
printf
stcat
called by:
send
history:
Rewritten by Mark Kampe 11/24/75
*/
post(infoflg)
int infoflg;
{
register int i;
if (stat(mailbox,&statb) < 0)
{ mbfd = creat(mailbox,0666);
if (mbfd < 0)
{ if (infoflg) printf("Unable to create mailbox\n");
unsent++;
return(false);
}
}
else
{ /*** if (statb.s_nlinks > 1)
{ if (infoflg) printf("Mailbox is busy\n");
unsent++;
return(false);
}
***/ mbfd = open(mailbox,1);
if (mbfd < 0)
{ if (infoflg) printf("Mailbox is busy\n");
unsent++;
return(false);
}
seek(mbfd,0,2); /* seek end of file */
}
seek(tmpfd,0,0); /* rewind the file containing the message */
write(mbfd,MSGSEP,MSGSEPL);
/* writef(mbfd,"Mail received for ");
writef(mbfd,user);
writef(mbfd,"\n");
*/ i = read(tmpfd,bigbuf,512);
while(i > 0)
{ write(mbfd,bigbuf,i);
i = read(tmpfd,bigbuf,512);
}
write(mbfd,MSGSEP,MSGSEPL);
close(mbfd);
chown(mailbox,uid);
if (infoflg) printf("ok\n");
return(true);
} /* end post */
/* name:
netpost
function:
to attempt to mail off a piece of network mail.
algorithm:
Contrive a unique name for a network mail file.
Create it in the netmail daemon's mailbox
put destination host, users and sender names into file.
copy message into the file.
parameters:
*char pointer to null terminated user name
*char pointer to null terminated host name
returns:
boolean whether or not it worked
globals:
unsent
netmsgs count of number of net msgs so far
tmpfd
bigbuf
calls:
read
write
printf
creat
close
stat
chown
called by:
send
history:
Initially coded by Mark Kampe
*/
netpost(uname,hname,infoflg)
char *uname;
char *hname;
int infoflg;
{
register char *p1;
register char *p2;
register int i;
p2 = netfile;
for(p1 = "/usr/netmail/"; *p1; *p2++ = *p1++);
crname(p2);
mbfd = creat(netfile, 0444);
if (mbfd < 0)
{ if (infoflg) printf("Unable to create mailfile for %s@%s\n",
uname,hname);
unsent++;
return(false);
}
writef(mbfd,hname);
write (mbfd,":",1);
writef(mbfd,uname);
write (mbfd,":",1);
writef(mbfd,returnto);
write (mbfd, ":\n",2);
seek(tmpfd, 0, 0);
if (snoopcopy)
{ writef(mbfd,"Copy of mail received for ");
writef(mbfd,snoopcopy);
writef(mbfd,"\n");
}
for(i = read(tmpfd,bigbuf,512); i; i = read(tmpfd,bigbuf,512))
write(mbfd,bigbuf,i);
close(mbfd);
chown(netfile,myuid);
if (infoflg) printf("queued\n");
netmsgs++;
return(true);
}
/* name:
getname
function:
To find out the name of the user who forked me.
algorithm:
Get my real user id and look it up in the password table
parameters:
*char pointer to buffer where name should be placed.
returns:
*char pointer to buffer wher callers's name was placed.
globals:
calls:
getuid
getpw
printf
called by:
main
history:
Rewritten by Mark Kampe
*/
getname(caller)
char *caller;
{
char linebuf[100];
char *cp,*lp;
myuid = getuid() & 0377;
if (getpw(myuid, linebuf))
{
printf("Your user id is not in the password file?!?\n");
exit();
}
cp = caller;
lp = linebuf;
while(*lp != ':') *cp++ = *lp++;
*cp = '\000';
return(caller);
}
/* name:
slashc
function:
Given that the last input character seen was a backslash, this
routine returns the character that is being escaped.
algorithm:
If terminal is half ascii
If next char is lower case, return its upper case counterpart.
If it is the preimage of a non-half ascii character, return
that character.
Else, return the next character.
parameters:
returns:
A character.
globals:
ttys to check out the console modes.
calls:
getchar
called by:
people who do rawmode input (namely input)
history:
Initial coding by someone at berkeley.
*/
slashc()
{
char c;
c = getchar(0);
if (ttys[2] & 04) /* Half-ASCII */
{
if (c >= 'a' && c <= 'z') return(c-'a'+'A');
switch (c)
{
case '!': return('|');
case '\'': return('`');
case '^': return('~');
case '(': return('{');
case ')': return('}');
default: return(c);
} /* end switch */
} /* end half-ASCII */
else return(c);
} /* end slashc */
/* name:
getchar
function:
To read a character from a specified file.
algorithm:
Do a read, and if we got an end of file, return a -1.
CAVEAT Input is unbuffered.
parameters:
int file descriptor of file to be read from.
returns:
char or -1;
globals:
calls:
read (system)
called by:
lots of people
history:
Someone at berkeley.
*/
char getchar(cfd)
{ char c;
register int i;
i = read(cfd,&c,1);
if (i <= 0) return(-1);
else return(c&0177);
}
char getpwchar()
{
tryagain:
if (pwcount > 0)
{ pwcount--;
return(*pwptr++);
}
else
{ pwcount = read(pwfd,pwbuf,512);
if (pwcount <= 0) return(-1);
pwptr = pwbuf;
goto tryagain;
}
}
valid(ch)
char ch;
{
return(((ch >= 'a') && (ch <= 'z')) | ((ch >= '0') && (ch <= '9')) |
(ch == '.') | (ch == '/') | (ch == '-') | (ch == ';') |
(ch == '@') | (ch == '(') | (ch == ')') |
((ch >= 'A') && (ch <= 'Z')) );
}
stcat(latter,former)
char *latter,*former;
{
register char *fp,*lp;
fp = former;
lp = latter;
while (*fp++);
fp--;
while (*fp++ = *lp++);
}
/* name:
arpadate
function:
to get an ARPA format date (format described in rfc 680)
algorithm:
Get the unix format date and jumble it around to be arpa format
Unix format is:
day mmm dd hh:mm:ss yyyy
Arpa format is:
dd mmm yyyy at hhmm-zzz
parameters:
pointer to the doubleword time
returns:
pointer to the arpa format date corresponding to that time
globals:
dbuf
calls:
ctime
localtime
called by:
main
history:
Designed and coded by mark Kampe 1/9/76
*/
char *arpadate(tvec)
int tvec[2];
{ register int *i;
register char *p;
register char *t;
t = ctime(tvec);
p = dbuf;
*p++ = t[8];
*p++ = t[9];
*p++ = ' ';
*p++ = t[4];
*p++ = t[5];
*p++ = t[6];
*p++ = ' ';
*p++ = t[20];
*p++ = t[21];
*p++ = t[22];
*p++ = t[23];
*p++ = ' ';
*p++ = 'a';
*p++ = 't';
*p++ = ' ';
*p++ = t[11];
*p++ = t[12];
*p++ = t[14];
*p++ = t[15];
*p++ = '-';
*p++ = 'P';
i = localtime(tvec);
if (i[8]) *p++ = 'D';
else *p++ = 'S';
*p++ = 'T';
*p++ = '\000';
return(dbuf);
}
/*name:
function:
to create a unique file name
algorithm:
use the process id number, the date and time, and a reference count
paramters:
pointer to where the name is to be stored
globals:
hex
calls:
getpid
time
called by:
netpost
history:
greep
*/
crname(q)
char *q;
{
int i;
int tvec[4];
char *p;
p = &tvec[0];
tvec[2] = getpid();
tvec[3] = filecnt++;
if (filecnt==256)
{filecnt = 0;
sleep(1);
}
time(tvec);
for (i=7; i; --i)
{ *q++ = hex[(*p>>4)&017];
*q++ = hex[ *p++ &017];
}
*q = '\0';
}