#-h- cpb 115 asc 29-apr-81 20:26:19 [002,100] common / cpb / bp, bf(MAXLINE) integer bp # put back pointer for gadtok character bf # buffer used by gadtok #-h- csndm 412 asc 29-apr-81 20:26:20 [002,100] common / csndm / tofile(FILENAMESIZE), ccfile(FILENAMESIZE), subjct(MAXLINE), msgfil(FILENAMESIZE), reply(MAXLINE) character tofile # file containing To addresses; init = EOS character ccfile # file containing Cc addresses; init = EOS character subjct # subject string for message; init = EOS character msgfil # file containing message; init = EOS character reply # in-reply-to string; init = EOS #-h- sndbuf 95 asc 29-apr-81 20:26:21 [002,100] common / scrbuf / buf(MAXLINE) character buf # scratch buffer used for getlin's throughout #-h- sndscr 407 asc 29-apr-81 20:26:22 [002,100] common / sndscr / nusers, temp0(FILENAMESIZE), temp1(FILENAMESIZE), temp2(FILENAMESIZE), temp3(FILENAMESIZE) integer nusers # running count of valid users character temp0 # temporary file for complete message character temp1 # temporary file to hold processed To addresses character temp2 # temporary file to hold processed Cc addresses character temp3 # temporary file to hold body of message #-h- sndmsg.r 13639 asc 29-apr-81 20:26:26 [002,100] #-h- defns 212 asc 27-apr-81 17:32:22 [002,100] define(USERSIZE,60) define(DO_ALL,1) define(DO_FIRST,2) define(TIMEZONE,"PST") define(RIGHTMARGIN,80) define(TERMEOF,"^Z") define(USERWIDTH,15) define(MEM_SIZE,2000) # size of dynamic storage in integers #-h- main 774 asc 27-apr-81 17:32:22 [002,100] DRIVER(sndmsg) include csndm include sndscr string tos "To: " string ccs "Cc: " string errmsg "No valid user names specified." call query("usage: sndmsg [-tfile] [-cfile] [-ssubject] [-rreply].") call sndcmd # process command arguments call sndint # initialize tblook table nusers = 0 # initialize number of users call sndadr(tofile, temp1, tos) # get To addresses call sndadr(ccfile, temp2, ccs) # get Cc addresses if (nusers == 0) call snderr(errmsg) # no valid users call getsbj(subjct) # get subject string call genmsg(msgfil, temp3) # get body of message call mmerge # merge pieces onto temp0 call sdmail(temp0, temp1) # send to To call sdmail(temp0, temp2) # send to Cc call cleanf # clean up temp files DRETURN end #-h- addusr 842 asc 27-apr-81 17:41:07 [002,100] subroutine addusr(user, unit) integer unit, n integer tblook, isatty, prompt character user(USERSIZE), temp(FILENAMESIZE), utemp(USERSIZE), c character clower include sndscr string errmsg "Invalid user name: " string qpstr "Do you wish to f[orget it], r[eplace it] or l[ist valid users]? " string rpstr "Replacement address: " call scopy(user, 1, utemp, 1) repeat { if (tblook(utemp, temp) == YES) { nusers = nusers + 1 call putlin(utemp, unit) call putch(NEWLINE, unit) break } else { call putlin(errmsg, ERROUT) call remark(utemp) if (isatty(STDIN) == YES) { n = prompt(qpstr, utemp, STDIN) c = clower(utemp(1)) if (c == LETR) { n=prompt(rpstr,utemp,STDIN); utemp(n)=EOS } else if (c == LETL) { call usrlst; utemp(1) = EOS } else return } } } return end #-h- adhelp 758 asc 27-apr-81 17:32:25 [002,100] subroutine adhelp call remark("Valid responses to the To and Cc prompts are sequences") call remark("of usernames separated by commas. If it is necessary") call remark("to continue the list of users on the next line, simply") call remark("type a comma before hitting the carriage return.") call putch(NEWLINE, ERROUT) call remark("If the username 'all' is specified, all known users on") call remark("the system will be included. A username preceded by a") call remark("less than symbol (<) is taken to be the name of a file") call remark("containing usernames separated by blanks and tabs (old") call remark("mail style mailing lists), and each user found therein") call remark("will be included.") call putch(NEWLINE, ERROUT) return end #-h- badarg 153 asc 27-apr-81 17:32:26 [002,100] subroutine badarg(arg) character arg(ARB) string errmsg "Ignoring invalid argument: " call putlin(errmsg, ERROUT) call remark(arg) return end #-h- cleanf 131 asc 27-apr-81 17:32:27 [002,100] subroutine cleanf include sndscr call remove(temp0) call remove(temp1) call remove(temp2) call remove(temp3) return end #-h- domlst 618 asc 27-apr-81 17:32:28 [002,100] subroutine domlst(file, key, unit) integer key, unit, int, i integer open, getlin, index, getwrd character file(ARB), token(USERSIZE) include sndbuf string errmsg "Error opening mailing list file: " int = open(file, READ) if (int != ERR) { while (getlin(buf, int) != EOF) { i = index(buf, SHARP) if (i > 0) buf(i) = EOS i = 1 if (getwrd(buf, i, token) > 0) call addusr(token, unit) if (key == DO_ALL) while (getwrd(buf, i, token) > 0) call addusr(token, unit) } call close(int) } else { call putlin(errmsg, ERROUT) call remark(file) } return end #-h- dotcst 654 asc 27-apr-81 17:32:29 [002,100] subroutine dotcst(file, pstr, out, user) integer out, in, i, j, n integer open, length, getlin character user(MAXLINE), file(ARB), pstr(ARB) string bls " " in = open(file, READ) if (in == ERR) return call putlin(pstr, out) j = 9 for (i=getlin(user,in); i != EOF; i=getlin(user,in)) { user(i) = EOS n = j + length(user) + 1 if (n > RIGHTMARGIN) { call putch(COMMA, out) call putch(NEWLINE, out) call putlin(bls, out) j = 9 } if (j > 9) call putch(COMMA, out) call putch(BLANK, out) call putlin(user, out) j = j + length(user) + 2 } call putch(NEWLINE, out) call close(in) return end #-h- editit 474 asc 29-apr-81 20:22:14 [002,100] subroutine editit(file, buf) character file(FILENAMESIZE), buf(ARB), proc(FILENAMESIZE), pid(PIDSIZE) integer i, spawn, loccom string suffix IMAGE_SUFFIX string ed "ed" call impath(buf) if (loccom(ed, buf, suffix, proc) != BINARY) call error("Cannot locate ed image file.") i = 1 call stcopy(ed, 1, buf, i) call chcopy(BLANK, buf, i) call scopy(file, 1, buf, i) if (spawn(proc, buf, pid, WAIT) != OK) call error("Error in spawning ed!") return end #-h- gadtok 706 asc 27-apr-81 17:32:31 [002,100] integer function gadtok(pstr, token, int) integer i, int integer prompt, length, equal character pstr(ARB), token(USERSIZE) include cpb string help "?@n" repeat { while (bp == 0) { if (prompt(pstr, bf, int) == EOF) return(EOF) if (equal(bf, help) == YES) { call adhelp bp = 0 } else bp = 1 } if (bf(bp) == NEWLINE) return(EOF) call skipbl(bf, bp) for (i=1; ; i=i+1) { if (bf(bp) == COMMA | bf(bp) == NEWLINE) break token(i) = bf(bp) bp = bp + 1 } token(i) = EOS if (bf(bp) == COMMA) { bp = bp + 1 if (bf(bp) == NEWLINE) bp = 0 } call sqzblk(token) i = length(token) if (i > 0) return(i) } end #-h- genmsg 1455 asc 27-apr-81 17:32:32 [002,100] subroutine genmsg(infile, outfil) character infile(ARB), outfil(ARB), file(FILENAMESIZE) character clower integer out, edit, int, junk integer create, open, isatty, prompt, getlin, fsize include sndbuf string errmsg "Error generating message to send." string pstr "Do you want to use ed to create your mail? [y/n] " string sde "sde" string inps "Input message: (type q to quit or " string eofs TERMEOF out = create(outfil, WRITE) if (out == ERR) call snderr(errmsg) edit = NO if (infile(1) != EOS) int = open(infile, READ) else int = STDIN if (int == STDIN & isatty(int) == YES) { junk = prompt(pstr, buf, STDIN) if (clower(buf(1)) == LETY) { edit = YES call scratf(sde, file) call remark("You are now entering ed to create your mail.") call remark("Please wait for ed to prompt for a command.") call editit(file, buf) int = open(file, READ) } else { call putlin(inps, ERROUT) call putlin(eofs, ERROUT) call remark(" to send).") } } if (int == ERR) { call close(out) call snderr(errmsg) } while (getlin(buf,int) != EOF) if (clower(buf(1)) == LETQ & buf(2) == NEWLINE & edit == NO & int == STDIN) { call close(out) call remove(outfil) out = create(outfil, WRITE) break } else call putlin(buf, out) call close(out) if (fsize(outfil) == 0) call snderr(errmsg) if (int != STDIN) call close(int) if (edit == YES) call remove(file) return end #-h- getsbj 283 asc 27-apr-81 17:32:34 [002,100] subroutine getsbj(subjct) character subjct(MAXLINE) integer n integer prompt, isatty string pstr "Subject: " if (subjct(1) == EOS & isatty(STDIN) == YES) { n = prompt(pstr, subjct, STDIN) if (n > 0) subjct(n) = EOS else subjct(1) = EOS } return end #-h- mmerge 334 asc 27-apr-81 17:32:35 [002,100] subroutine mmerge integer out, int integer create, open include sndscr string errmsg "Error opening temp0." out = create(temp0, WRITE) if (out == ERR) call snderr(errmsg) call pstmrk(out) int = open(temp3, READ) if (int != ERR) { call fcopy(int, out) call close(int) } call close(out) return end #-h- pbinit 56 asc 27-apr-81 17:32:35 [002,100] subroutine pbinit include cpb bp = 0 return end #-h- pstmrk 1053 asc 27-apr-81 17:32:36 [002,100] subroutine pstmrk(int) integer int, now(7) character idate(10), itime(10), user(USERSIZE), hdrpat(4) include csndm include sndscr include sndbuf string dates "Date: " string dashst " - " string timzon TIMEZONE string froms "From: " string subjs "Subject: " string repls "In-reply-to: " string tos "To: " string ccs "Cc: " data hdrpat/1, 1, NEWLINE, EOS/ call mailid(user) call getnow(now) call fmtdat(idate, itime, now, LETTER) call putlin(hdrpat, int) call putlin(dates, int) call putlin(idate, int) call putch(BLANK, int) call putlin(itime, int) call putlin(dashst, int) call putlin(timzon, int) call putch(NEWLINE, int) call putlin(froms, int) call putlin(user, int) call putch(NEWLINE, int) call putlin(subjs, int) call putlin(subjct, int) call putch(NEWLINE, int) if (reply(1) != EOS) { call putlin(repls, int) call putlin(reply, int) call putch(NEWLINE, int) } call dotcst(temp1, tos, int, buf) call dotcst(temp2, ccs, int, buf) call putch(NEWLINE, int) return end #-h- sdmail 863 asc 27-apr-81 17:32:38 [002,100] subroutine sdmail(msg, mlist) integer inp, int, n, junk, out, topfil(2) integer open, getlin, tblook, create character msg(ARB), mlist(ARB), file(FILENAMESIZE) include sndbuf string mymail "mymail" string posted "Mail posted to " string errmsg "Cannot send mail to " inp = open(msg, READ) if (inp != ERR) { call markl(inp, topfil) int = open(mlist, READ) if (int != ERR) { for (n=getlin(buf,int); n != EOF; n=getlin(buf,int)) { buf(n) = EOS junk = tblook(buf, file) call concat(file, mymail, file) call seek(topfil, inp) out = create(file, APPEND) if (out == ERR) { call putlin(errmsg, ERROUT) call remark(buf) } else { call fcopy(inp, out) call close(out) call putlin(posted, ERROUT) call remark(buf) } } call close(int) } call close(inp) } return end #-h- sndadr 811 asc 27-apr-81 17:32:39 [002,100] subroutine sndadr(infile, outfil, pstr) character infile(ARB), outfil(ARB), pstr(ARB), token(USERSIZE) integer int, out integer open, create, gadtok, equal, isatty string all "all" if (infile(1) == EOS) if (isatty(STDIN) == YES) int = STDIN else int = ERR else int = open(infile, READ) if (int == ERR) return out = create(outfil, WRITE) if (out != ERR) { call pbinit while (gadtok(pstr, token, int) != EOF) { call fold(token) if (token(1) == LESS) { call scopy(token, 2, token, 1) call domlst(token, DO_ALL, out) } else if (equal(token, all) == YES) { call adrfil(token) call domlst(token, DO_FIRST, out) } else call addusr(token, out) } call close(out) } if (int != STDIN) call close(int) return end #-h- sndcmd 633 asc 27-apr-81 17:32:40 [002,100] subroutine sndcmd integer i integer getarg, equal character clower include csndm include sndbuf tofile(1) = EOS ccfile(1) = EOS msgfil(1) = EOS reply(1) = EOS subjct(1) = EOS for (i=1; getarg(i, buf, MAXLINE) != EOF; i=i+1) if (buf(1) == MINUS) { c = clower(buf(2)) if (c == LETT) call scopy(buf, 3, tofile, 1) else if (c == LETC) call scopy(buf, 3, ccfile, 1) else if (c == LETS) call scopy(buf, 3, subjct, 1) else if (c == LETM) call scopy(buf, 3, msgfil, 1) else if (c == LETR) call scopy(buf, 3, reply, 1) else call badarg(buf) } else call badarg(buf) return end #-h- snderr 90 asc 27-apr-81 17:32:41 [002,100] subroutine snderr(buf) character buf(ARB) call cleanf call error(buf) return end #-h- sndint 707 asc 27-apr-81 17:32:42 [002,100] subroutine sndint character user(USERSIZE), file(FILENAMESIZE) integer int, i, junk integer open, getlin, getwrd include sndscr include sndbuf DS_DECL(Mem,MEM_SIZE) # declare dynamic storage for symbol table string sm0 "sm0" string sm1 "sm1" string sm2 "sm2" string sm3 "sm3" call tbinit(MEM_SIZE) call adrfil(file) int = open(file, READ) if (int != ERR) { while (getlin(buf, int) != EOF) { i = 1 junk = getwrd(buf, i, user) junk = getwrd(buf, i, file) call tbinst(user, file) } call close(int) } else call error("Cannot open local user file.") call scratf(sm0, temp0) call scratf(sm1, temp1) call scratf(sm2, temp2) call scratf(sm3, temp3) return end #-h- sqzblk 219 asc 27-apr-81 17:32:43 [002,100] subroutine sqzblk(token) character token(ARB) integer i, j j = 1 for (i=1; token(i) != EOS; i=i+1) if (token(i) != BLANK & token(i) != TAB) { token(j) = token(i) j = j + 1 } token(j) = EOS return end #-h- usrlst 449 asc 27-apr-81 17:32:44 [002,100] subroutine usrlst character buf(MAXLINE), obuf(MAXLINE) integer int, i, nxtcol integer getlin, open call adrfil(buf) int = open(buf, READ) call inpack(nxtcol, RIGHTMARGIN, obuf, ERROUT) while (getlin(buf, int) != EOF) { for (i=1; buf(i) != BLANK & buf(i) != TAB; i=i+1) ; buf(i) = EOS call dopack(buf, nxtcol, RIGHTMARGIN, obuf, ERROUT) } call flpack(nxtcol, RIGHTMARGIN, obuf, ERROUT) call close(int) return end #-h- sndmsg.rof 1885 asc 11-may-81 11:51:34 [002,100] .in 5 .rm 75 .pl 60 .he 'SNDMSG'10/28/80'SNDMSG' .fo //-#-/ .bp 1 NAME .in +3 sndmsg - utility for sending mail to other users .ti -3 SYNOPSIS sndmsg .ti -3 DESCRIPTION `sndmsg' is the utility used to send mail to other users of the mail system. The user is prompted for all of the necessary input in the following manner: .sp .in +5 .ti -3 1. The list of To addresses. .ti -3 2. The list of Cc (carbon copy) addresses .ti -3 3. The subject of the message .ti -3 4. The body of the message .sp .in -5 The responses to the To and Cc prompts consist of user-names separated by commas. If it is necessary to continue the list of addresses onto another line, a comma typed at the end of the line causes `sndmsg' to prompt for another line of addresses. If the string `all' is typed as an address, all users of the mail system will receive a copy of the message. If the address consists of `