# /* EMACS_MODES: c !fill */ /* modified 1/27/78 by csk to use lseek instead of seek so that it can handle msg files bigger than 64k bytes */ /* modified 1/27/78 by csk to handle 256 msgs */ /* modified 1/27/78 by csk to use wait0 and wait1 so it can be compiled separated */ /* modified 3/12/79 by lauren to correct bug in "answer" code */ /* modified 4/16/79 by csk to allow bigger messages (change to long) */ /* modified 7/1/79 by Lauren Weinstein to implement replies to network mail. Considerable code additions and changes. */ /* modified 2/12/81 by Larry Allen to handle message files right; to wit: messages can be deleted from your mbox file, and messages are no longer automatically copied from other message files to your mbox file on exit */ /* modified 3/17/81 by Larry Allen to add handling of .mail.init files and to fix bug involving "exit " function */ /* modified 3/24/81 by Larry Allen to handle "reply-to" fields of messages right. */ /* modified 6/17/81 by Larry Allen to perform "MORE" processing */ /* modified 7/6/81 by Larry Allen to handle newly-received messages properly */ /* modified 7/7/81 by Larry Allen to perform message forwarding */ /* modified 10/15/81 by Larry Allen to fix header handling */ /* modified 10/9/83 by Larry Allen to eliminate reply to "Sender:" */ #include "rqfile.h" #include "init_rec.h" #include #define MSGSEP "\001\001" #define MSGSEPL 2 #define NMSGS 256 #define SIZEDATE 12 /* also have to change the printf */ #define SIZEFROM 21 #define SIZEREP 21 #define SIZESUBJ 41 #define DELETED 0000001 #define LINESIZE 100 #define VRBSEFLAG 1 #define DEL 0177 struct {long int start; long len; char flags; char date[SIZEDATE]; char from[SIZEFROM]; char repto[SIZEREP]; char subject[SIZESUBJ]; } msg[NMSGS], *p; struct status { char minor; char major; int inumber; int sflags; char nlinks; char uid; char gid; char size0; int size1; int addr[8]; long int actime; long int modtime; } statb1, statb2; /* used for comparing times */ int oldsig[4]; int pwr10[] {1,10,100,1000}; int ttyraw[3],ttynorm[3]; extern int errno; int nottty; long int curpos; int strtflag; long int newpos; long int filend; int nmsgs; int ndeleted; int msgno; int exitflag; /* make room for null */ char line[LINESIZE+1], templine[LINESIZE+1], *tlp; char filename[60], tempname[60], outfile[60], mbox[60]; char userid[20]; char flag1,flag2; int doflg; int msgbeg, msgend; char nxtchar; int needhead; int gotnl; int verbose; int orig; int curmsg; int inmsg; int wfile; int curline; int psize; int ttypos[] = { T_GET | T_PSIZ, -1 }; struct getcbuf {int fildes; int nleft; char *nextp; char buff[512]; } filebuf; char newmsgfn[] = ".mail"; char savmsgfn[] = "mbox"; struct init_rec inir; extern struct getcbuf fin; char clrscr[] = "\033H\033J"; onint() { signal(2, &onint); gotnl++; error("...interrupted\n"); } error(s) char *s; { if (wfile > 0) close(wfile); if (verbose) stty(0,ttyraw); printf("%s", s); if ((!(verbose || gotnl || nxtchar == '\n')) && (strtflag)) suckup(); stty(0,ttynorm); exitflag = 0; reset(); } gline(file) struct getcbuf *file; { register char *cp; char *linend; linend = line + LINESIZE; for(cp = line; cp < linend; cp++) { if((*cp = getc(file)) == -1) return(-1); if(*cp == '\n') break; } *cp = 0; /* don't count null if line didn't end in nl */ if (cp >= linend) cp--; return(cp-line+1); } prefix(s1, s2) char *s1, *s2; { while(*s2) if(*s1++ != *s2++) return(0); return(1); } copy(s1, s2) char *s1, *s2; { while(*s2++ = *s1++); } setup() { int count; nmsgs = curpos = newpos = ndeleted = needhead = curmsg = inmsg = 0; if (filebuf.fildes > 0) close(filebuf.fildes); if(fopen(filename, &filebuf) < 0) { if(mainbox()) { printf("\nNO NEW MAIL.\n\n"); error(""); } else { printf("cannot open %s\n", filename); error(""); } } fstat(filebuf.fildes,&statb1); if (statb1.size0 == 0 && statb1.size1 == 0) { printf ("\nNO NEW MAIL.\n\n"); error (""); } gfile(&filebuf); printf("\n%d message%c in %s\n\n",nmsgs, nmsgs == 1 ? '' : 's',filename); } gfile (pgcbuf) struct getcbuf *pgcbuf; { int count; while ((count=gline(pgcbuf)) != -1) { curpos = newpos; newpos =+ count; if((line[0] == MSGSEP[0]) && (line[1] == MSGSEP[1])) inmsg = 0; else {if (!inmsg) begmsg(); p->len =+ count; if (needhead) gethead(); } } filend = newpos; } nxtfld(s) char *s; { while (*s && (*s++ != ' ')); while(*s == ' ') s++; return(s); } nxtfld1() { char c; if (!verbose) while((c = getc(&fin)) != '\n' && c != ' '); else c=getc(&fin); if (c == ' ') while((c = getc(&fin)) == ' '); return(c); } prhdr() { char c; if (inir.in_blkscr && (curline >= psize)) { printf ("--MORE--"); if ((c = getraw()) == DEL) { printf ("\n"); reset(); } else blkscr(); } printf("%3d%c %-11s %-20s %-40s\n", msgno, p->flags&DELETED ? '*' : ' ', p-> date, p->from, p->subject); } main(argc, argv) int argc; char *argv[]; { int restrt; int nd; extern prmsg(), delmsg(), undelmsg(), prhdr(), movmsg(), putmsg(), lstmsg(), ansmsg(); orig = signal(2, &onint); if (gtty(0,ttynorm) < 0) nottty++; ttyraw[0] = ttynorm[0]; ttyraw[2] = ttynorm[2] | 040; getuser(); getinit(); restrt = 0; strtflag = 0; if (argc > 1) copy(argv[1],filename); setexit(); if (!(restrt++)) { if (inir.in_blkscr) { ttymod (1, ttypos); psize = ttypos[0] & 0377; blkscr (); } setup(); } if (VRBSEFLAG && !nottty) { verbose++; stty(0,ttyraw); } strtflag = 1; printf("For help type ?\n"); setexit(); for(;;) { if (verbose) stty(0,ttyraw); printf("<- "); curline = 1; flag1 = flag2 = gotnl = 0; nxtchar = getc(&fin); stty(0,ttynorm); if (nmsgs == 0 && !(nxtchar == '?' || nxtchar == 'q' || nxtchar == 'j' || nxtchar == 'v'|| nxtchar == 'g' || nxtchar == 'e')) error("\nNo file\n"); switch(nxtchar) { case '\n': break; case 'h': if (verbose) printf("eaders "); rditer(&prhdr); break; case 'j': if (verbose) printf("ump "); getfn("to program: ",templine); xeq(); break; case '?': if (verbose) printf("\n"); help(); break; case 'c': if (verbose) printf("urrent "); printf("message is %d of %d messages in file %s\n", curmsg,nmsgs,filename); break; case 'd': if (verbose) printf("elete "); rditer(&delmsg); break; case 'u': if (verbose) printf("ndelete "); rditer(&undelmsg); break; case 'r': if (verbose) printf("ead "); rditer(&prmsg); break; case 'n': if (verbose) printf("ext message is:\n"); if (curmsg == nmsgs) error("There is no next message\n"); p = &msg[curmsg]; msgno = ++curmsg; prmsg(); break; case 'b': if (verbose) printf("acking up to:\n"); if (curmsg <= 1) error("There is no previous message\n"); msgno = --curmsg; p = &msg[curmsg - 1]; prmsg(); break; case 'm': if (verbose) printf("ove "); rditer1(); getfn("to file: ",outfile); cpymsg(&movmsg); break; case 'p': if (verbose) printf("ut "); rditer1(); getfn("to file: ",outfile); cpymsg(&putmsg); break; case 'l': if (verbose) printf("ist "); rditer1(); getfn("to file: ",outfile); cpymsg(&lstmsg); break; case 'e': exitflag = 1; case 's': if (verbose && !exitflag) printf("ave "); else if (verbose) printf("xit and save " ); confirm(); nd = ndeleted; if (nmsgs == 0) if (exitflag) { stty (0, ttynorm); exit (0); } else error ("\nNo file\n"); if (mainbox ()) save(); else copy (filename, outfile); overwrit(); if (mainbox () && nd != nmsgs) { printf("\nUndeleted messages have been appended to %s\n\n", outfile); } if (exitflag) { stty(0,ttynorm); exit(); } if (ndeleted == nmsgs) { printf("\nDeleting %s\n\n", filename); nmsgs = ndeleted = 0; } else setup(); break; case 'g': if (verbose) printf("et "); getfn("from file: ",filename); setup(); break; case 'q': if (verbose) printf("uit "); confirm(); stty(0,ttynorm); exit(); case 'v': if (verbose) { printf("erbose off\n"); stty(0,ttynorm); verbose = 0; gotnl++; } else { suckup(); if (nottty) error("Input not tty\n"); printf("verbose on\n"); verbose++; stty(0,ttyraw); } break; case 'f': if (verbose) printf("orward "); get_temp(outfile); rditer1(); cpymsg(&lstmsg); forwmsg(outfile); unlink(outfile); break; case 'a': if (verbose) printf("nswer "); rditer( &ansmsg ); break; default: printf(" ? For help type ?\n"); } if (!(verbose || gotnl || nxtchar == '\n')) suckup(); } } delmsg() { if (!(p->flags & DELETED)) ndeleted++; p->flags =| DELETED ; return; } undelmsg() { if (p->flags & DELETED) ndeleted--; p->flags =& ~DELETED; return; } save() { extern movmsg(); flag1 = 'u'; copy(mbox,outfile); if ((wfile=open(outfile,1)) < 0) { if (errno != 2) { printf("Can't open %s",outfile); error("\n"); } if ((wfile=creat(outfile,0600)) < 0) { printf("Can't create %s",outfile); error("\n"); } } else (seek(wfile,0,2)); doiter(&movmsg,1,nmsgs); close(wfile); wfile = 0; } getfn(s,f) char *s,*f; { char tmpbuf[100]; char *cp; if (verbose) stty(0,ttynorm); printf("%s",s); read(0,tmpbuf,100); for (cp = tmpbuf; *cp != '\n'; cp++); *cp = 0; if (cp == tmpbuf) error("Invalid name\n"); copy(tmpbuf,f); if (verbose) stty(0,ttyraw); } cpymsg(fn) int (*fn)(); { if ((wfile=open(outfile,1)) < 0) { if (errno != 2) error("can't open file\n"); if ((wfile=creat(outfile,0600)) < 0) error("can't create file\n"); } else seek(wfile,0,2); rditer2(fn); close(wfile); wfile = 0; } movmsg() { putmsg(); delmsg(); } putmsg() { write(wfile,MSGSEP,MSGSEPL); write(wfile,"\n",1); lstmsg(); write(wfile,MSGSEP,MSGSEPL); write(wfile,"\n",1); } lstmsg() { long size; int count; char tmpbuf[512]; lseek(filebuf.fildes,p->start,0); for (size = p->len; size; size =- count) { count = size<512? size : 512; if (read(filebuf.fildes,tmpbuf,count) < 0) error("read error\n"); if (write(wfile,tmpbuf,count) < 0) error("write error\n"); } } prmsg() { long size; int count; char c; printf("\n(Message %d%s, %ld bytes)\n",msgno, p->flags&DELETED ? "*" : "",p->len); fseek(&filebuf,p->start,0); size = p->len; for (count = 0; count < size;) { if (inir.in_blkscr && (curline >= psize)) { printf ("--MORE--"); c = getraw(); blkscr(); if (c == DEL) break; } count =+ gline(&filebuf); printf("%s\n", line); } curmsg = msgno; } ansmsg() { register char c; register char *p1, *p2; int msgline, pid; char reply[100]; char subject[256]; char to[100]; char line1[LINESIZE+1]; int replyflag 0; int subflag 0; copy("-RYour message of (no date found)", reply); copy("-SMy response", subject); copy(p->from,line1); cnvlc(line1); fseek(&filebuf, p->start, 0); msgline = 0; while( gline(&filebuf) != -1) { msgline++; copy(line, line1); cnvlc(line1); if (prefix(line1,"date:")) { copy(line+6,reply+18); continue; } if (prefix(line1,"subject:")) { copy ("Re: ",subject+2); copy(line+9,subject+6); subflag++; continue; } if (!replyflag) /* reply address not parsed yet */ { if (prefix(line1,"from")) { replyflag++; /* so we don't try this again */ parsereply(line, to); continue; } } if (prefix(line1,"reply-to:")) { parsereply(line,to); continue; } if (prefix(line,MSGSEP) && (msgline > 1)) break; /* we've already seen the subject, so header is finished when we find the "to:" */ if (subflag && prefix(line1, "to:")) break; /* if we find the subject BEFORE the "to:", we'll consider the "In-reply-to" to be the end of the header (damn these random net headers!) */ if (!subflag && prefix(line1, "in")) break; } if (!replyflag) { printf("Sorry, can't parse an address to reply to!\n"); return; } if (inir.in_repme) { p1 = to; while (*p1) p1++; *p1++ = ','; p2 = userid; while (*p1++ = *p2++); } printf("To: %s\n", to); printf("In-reply-to: %s\n", reply+2); if (verbose) stty(0, ttynorm); save_sig(); if ( pid = fork() ) while( wait(0) != pid ); else { signal(1, 0); signal(2, 0); signal(3, 0); execl("/bin/send", "answer", to, reply, subject, 0); } restore_sig(); if (verbose) stty(0, ttyraw); } overwrit() { char tmpbuf[512]; int size; int count; int j; if (ndeleted == 0 && !str_cmp(filename,outfile)) { printf("File NOT changed, so NOT updated\n"); return; } if (stat(filename,&statb2) >= 0 && statb1.modtime != statb2.modtime) { count = nmsgs; fseek(&filebuf,filend,0); gfile(&filebuf); fstat(filebuf.fildes,&statb1); count = nmsgs - count; printf("\n%d new message%c in %s\n", count, count==1?'':'s', filename); error(""); } if (ndeleted == nmsgs) { if (!mainbox())unlink(filename); else close(creat(filename)); return; } if ((wfile=creat(tempname,0600)) < 0) error("can't create temporary file\n"); chmod (tempname, (statb2.sflags) & 07777); /* save protection bits */ flag1 = 'u'; doiter(&putmsg,1,nmsgs); close(wfile); if (unlink(filename) < 0) error("can't delete old file\n"); if (link(tempname,filename) < 0) error("can't rename temp file\n"); unlink(tempname); } xeq() { int process, status; if (verbose) stty(0,ttynorm); save_sig(); process = fork(); if(!process) { execl("/bin/sh", "-", "-c", templine, 0); printf("cannot execute %s\n", templine); exit(); } else wait(&status); if (verbose) stty(0,ttyraw); restore_sig(); } save_sig() { register int i; for(i = 1; i < 4; i++) oldsig[i] = signal(i,1); } restore_sig() { register int i; for(i = 1; i < 4; i++) signal(i, oldsig[i]); } help() { if (inir.in_blkscr) blkscr(); printf("Commands are:\n"); printf("h[eaders] list one-line header for each message\n"); printf("r[ead] list messages on terminal\n"); printf("n[ext message] list next message on terminal\n"); printf("b[ack up] list previous message on terminal\n"); printf("c[urrent message] list current message number and file name\n"); printf("d[elete] mark messages as being deleted\n"); printf("u[ndelete] remove deleted marking from messages\n"); printf("s[ave] update current file and reread\n"); printf("q[uit] exit without changing any files\n"); printf("e[xit and save] save then exit\n"); printf("l[ist] copy messages (without separators) to file\n"); printf("p[ut] copy messages (with separators) to file\n"); printf("m[ove] same as put + delete\n"); printf("a[nswer] reply to messages\n"); printf("f[orward] forward messages to another user\n"); printf("j[ump] jump to program - can be any shell command\n"); printf("g[et] get new message file\n"); printf("v[erbose] verbose/concise toggle\n"); } rditer(fn) int (*fn)(); { rditer1(); rditer2(fn); } rditer1() { int n1, n2; int begin, end; if (verbose) stty(0,ttyraw); switch (nxtchar = nxtfld1()) { case '\n': if (curmsg == 0 || curmsg > nmsgs) curmsg = 1; /* set current message to '1' */ msgbeg = msgend = curmsg; break; case 'a': if (verbose) printf("ll messages\n"); msgbeg = 1; msgend = nmsgs; break; case 'd': case 'u': flag1 = nxtchar; /* save 'u' or 'd' */ if (verbose) printf(nxtchar == 'd' ? "eleted%s" : "ndeleted%s"," messages\n"); msgbeg = 1; msgend = nmsgs; break; default: flag2++; rditer2(0); /* indicate only checking */ } stty(0,ttynorm); } rditer2(fn) int (*fn)(); { int n1, n2, t; int begin, end; doflg = fn; tlp = templine; if (doflg) nxtchar = *tlp++; else *tlp++ = nxtchar; if (flag2) /* only do this if a msg-sequence is present */ while (nxtchar != '\n') { while (nxtchar == ' ' || nxtchar == ',') if (doflg) nxtchar = *tlp++; else *tlp++ = nxtchar = getc(&fin); if (nxtchar == '\n') break; n1 = getnum(&begin); end = begin; switch(nxtchar) { case '-': if (n1 == 0) error("'-' must be preceeded by number\n"); if (begin == 0 || begin > nmsgs) error(" Invalid starting number\n"); if (doflg) nxtchar = *tlp++; else *tlp++ = nxtchar = getc(&fin); n2 = getnum(&end); if (n2 == 0) error("'-' must be followed by number\n"); if (end > nmsgs) error(" Invalid ending number\n"); if (n1 > n2) /* here comes the class! */ { t = pwr10[n2]; end =+ begin / t * t; } if (begin > end) error("Invalid order for '-'\n"); break; case '\n': case ' ': case ',': if (begin == 0 || begin > nmsgs) error("Invalid number\n"); break; case ':': case '>': if (n1 == 0) begin = 1; if (begin == 0 || begin > nmsgs) error(" Invalid starting number\n"); if (doflg) nxtchar = *tlp++; else *tlp++ = nxtchar = getc(&fin); n2 = getnum(&end); if (n2 == 0) end = nmsgs; if (end == 0 || end > nmsgs) error(" Invalid ending number\n"); break; default: error(" Invalid number\n"); } if (doflg) doiter(fn,begin,end); } else if (doflg) /* no msg-sequence */ doiter(fn,msgbeg,msgend); } getnum(result) int *result; { register int i; register int n; i = n = 0; while (nxtchar >= '0' && nxtchar <= '9') { n = n*10 + nxtchar - '0'; i++; if (doflg) nxtchar = *tlp++; else *tlp++ = nxtchar = getc(&fin); } *result = n; return(i); } doiter(fn,begin,end) int begin,end; int (*fn)(); { if (begin <= end) for(msgno = begin; msgno <= end; msgno++) { p = &msg[msgno-1]; if (flag1 == 0 || (flag1 == 'd' && (p->flags&DELETED)) || (flag1 == 'u' && !(p->flags&DELETED)) ) (*fn)(); } else for(msgno = begin; msgno >= end; --msgno) { p = &msg[msgno-1]; if (flag1 == 0 || (flag1 == 'd' && (p->flags&DELETED)) || (flag1 == 'u' && !(p->flags&DELETED)) ) (*fn)(); } } str_cpy(s1,s2) char *s1, *s2; { register char *p1, *p2; p1 = s1; p2 = s2; while(*p2++ = *p1++); return(p2-s2-1); } str_cmp(s1,s2) char *s1, *s2; { while (*s1++ == *s2++) if (!(*s1 | *s2)) return(1); return(0); } begmsg() { if (nmsgs == NMSGS) { printf("Too many messages!\n"); reset(); } p = &msg[nmsgs++]; p->from[0] = p->date[0] = p->subject[0] = p->repto[0] = p->flags = 0; p->start = curpos; p->len = 0; needhead = 1; inmsg++; } copy1(src,dst,maxlen) char *src, *dst; int maxlen; { register char *s, *d; register int count; s = src; d = dst; for (count = 0; count < maxlen; count++) if ( (*d++ = *s++) == 0) break; *--d = 0; } /* Return pointer to the first nonblank character in a header field */ char *findfld(str) register char *str; { while (*str != 0 && (*str == ' ' || *str == '\t')) str++; return (str); } gethead() /* make room for null */ { char line1[LINESIZE+1]; if (line[0] == 0 || line[0] == ' ') goto ret1; copy(line,line1); cnvlc(line1); if (prefix(line1,"date:")) { copy1(findfld(line+6),p->date,SIZEDATE); goto ret; } if (prefix(line1,"sender:")) { copy1(findfld(line+8),p->from,SIZEFROM); goto ret; } if (prefix(line1,"from:")) { copy1(findfld(line+6),p->from,SIZEFROM); goto ret; } if (prefix(line1,"subject:")) { copy1(findfld(line+9),p->subject,SIZESUBJ); goto ret; } if (prefix(line1,"reply-to:")) { copy1(findfld(line+10),p->repto,SIZEREP); goto ret; } if (prefix(line1,"to:")) if (prefix(p->from,userid)) copy1(line,p->from,SIZEFROM); goto ret; ret1: needhead = 0; ret: ; } cnvlc(linep) char *linep; { register char *s; for (s = linep; *s; s++) if (*s >= 'A' && *s <= 'Z') *s =| ' '; } fseek(bufptr,loc,type) struct getcbuf *bufptr; long int loc; int type; { lseek(bufptr->fildes,loc,type); bufptr->nleft = 0; bufptr->nextp = 0; } getuser() { register char *s, *d; int i; char pwbuf[120]; if (getpw(getuid(),pwbuf)) { printf("Can't locate user name\n"); exit(); } s = pwbuf; d = userid; while ((*d = *s++) != ':') d++; /* get user name */ *d = 0; for (i=4; i; --i) while(*s++ != ':'); d = filename; while((*d = *s++) != ':')d++; *d = 0; copy(filename,tempname); copy(filename,mbox); copy("/tmpmail",tempname+d-filename); } confirm() { char c; printf("[confirm] "); if (verbose) stty(0,ttyraw); if ((c = getc(&fin)) == 'y' && verbose) printf("es\n"); if (!verbose) suckup(); /* suck up rest of line */ if (c != 'y' && c != '\n') error("command ignored\n"); stty(0,ttynorm); } suckup() { while((nxtchar=getc(&fin)) != '\n'); } mainbox() /* return non-0 if last part of filename indicates */ { char *cp; /* it is the main mailbox */ cp = filename; while(*cp++); /* get to end of name */ while(--cp != filename && *cp != '/'); /* find last part */ if (*cp == '/') cp++; return (str_cmp(cp,inir.in_mail)); } /* parsereply -- parse off the address we need to reply to a message */ parsereply(line, to) char *line, *to; { register char *p, *q; char buf[100], buf1[100]; p = line; while (*p != ' ') p++; /* get past field heading */ while (*p == ' ') p++; /* get past leading spaces */ q = buf; while (*p) { /* convert " at " to "@" */ if (*p == ' ' && (*(p+1) == 'a' || *(p+1) == 'A') && (*(p+2) == 't' || *(p+2) == 'T') && *(p+3) == ' ') { *q++ = '@'; p =+ 4; } else *q++ = *p++; } *q = 0; /* null terminate */ p = buf; q = buf1; while (*p) { /* find name in "<>", if any */ if (*p++ == '<') { while (*p != '>') *q++ = *p++; *q = 0; /* null terminate */ copy(buf1, buf); break; } } q = p = buf; /* truncate address as necessary */ while (*p != '\0') if (*p++ != ' ') q = p; *q = '\0'; copy (buf, to); } getinit () { char initnam[60]; int infd; register char *p, *q; p = filename; q = initnam; while (*q = *p++) q++; *q++ = '/'; p = INITFILE; while (*q++ = *p++); if ((infd = open (initnam, 0)) < 0){ /* if you can't open it, tough */ str_cpy (newmsgfn, inir.in_mail); str_cat ("/", filename); str_cat (newmsgfn, filename); str_cat ("/", mbox); str_cat (savmsgfn, mbox); } else { read (infd, &inir, sizeof(inir)); close (infd); str_cat ("/", filename); str_cat (inir.in_mail, filename); str_cat ("/", mbox); str_cat (inir.in_mbox, mbox); } } blkscr () { printf ("%s", clrscr); /* yuck */ curline = 1; } str_cat (p1, p2) register char *p1, *p2; { while (*p2) p2++; while (*p2++ = *p1++); } getraw () { register char c; static int ttyraw[] = { T_SET | T_FLAG0 | T0_RAW, T_SET | T_FLAG2 | T2_EEI, -1 }; static int ttynorm[] = { T_CLEAR | T_FLAG0 | T0_RAW, T_CLEAR | T_FLAG2 | T2_EEI, -1 }; int traw[sizeof (ttyraw)]; int i; for (i = 0; i < sizeof (ttyraw); i++) traw[i] = ttyraw[i]; ttymod (0,traw); c = getc(&fin); for (i = 0; i < sizeof (ttyraw); i++) traw[i] = ttynorm[i]; ttymod (0, traw); return (c); } forwmsg(file) char *file; { char flags[60]; int pid, wpid; str_cpy("-f",flags); str_cat(file,flags); if (verbose) stty(0,ttynorm); save_sig(); if ((pid = fork()) == 0) execl("/bin/send","/bin/send",flags,0); else while ((wpid = wait(0)) != pid && wpid != -1); if (verbose) stty(0,ttyraw); restore_sig(); } /* itos (ps, n, b) * * Converts its integer numeric object n into an ASCII string * in the space pointed to by ps, according to the base b. */ char *itos (ps, n, b) register char *ps; int n, b; { register int a; if (a = n / b) ps = itos (ps, a, b); a = n % b; *ps++ = a + (a > 9 ? 'A' - 10 : '0'); *ps = 0; return (ps); } /* get_temp - get a unique temporary name. Uses pid converted to Ascii. */ get_temp (tempnam) char *tempnam; { struct status buf; int pid = getpid (); do { itos (tempnam, pid, 10); pid++; } while (stat (tempnam, &buf) >= 0); }