home *** CD-ROM | disk | FTP | other *** search
- /* $Header: intrp.c,v 4.3.3.3 91/01/16 02:43:42 davison Trn $
- *
- * $Log: intrp.c,v $
- * Revision 4.3.3.3 91/01/16 02:43:42 davison
- * Integrated rn patches 48-54.
- *
- * Revision 4.3.3.2 90/08/20 16:29:08 davison
- * Added HOSTFILE handling. Add OURDOMAIN if site has no '.'
- *
- * Revision 4.3.3.1 90/07/21 20:20:13 davison
- * Initial Trn Release
- *
- * Revision 4.3.2.11 90/12/31 11:47:44 sob
- * NEWSADMIN could not cancel articles because it was not getting set.
- *
- * Revision 4.3.2.10 90/12/31 00:02:55 sob
- * Moved HIDDENET to remove unneeded cruft.
- *
- * Revision 4.3.2.9 90/12/30 03:48:11 sob
- * Changed "hidden" to "hiddennet" to be like nntp and bnews.
- * Made it possible to cancel articles if hiddennet is defined.
- *
- * Revision 4.3.2.8 90/11/22 13:52:27 sob
- * Made changes to keep preprocessors from complaining.
- *
- * Revision 4.3.2.7 90/11/05 23:59:33 sob
- * moved the definition of tmpbuf such that it get defined before it is used.
- *
- * Revision 4.3.2.6 90/11/03 18:52:31 sob
- * Fixed bug in the definition of the nodename using the uname() system call.
- *
- * Revision 4.3.2.5 90/10/01 01:31:18 sob
- * Fixed problem with struct utsname reported by jrallen@devildog.att.com
- * when rn is compiled on the Amdahl 5890 UTS 2.0 system.
- *
- * Revision 4.3.2.4 90/04/23 00:31:20 sob
- * Removed unneeded atoi call.
- *
- * Revision 4.3.2.3 90/03/22 23:04:35 sob
- * Fixes provided by Wayne Davison <drivax!davison>
- *
- * Revision 4.3.2.2 90/03/17 17:03:12 sob
- * Fixed determination of the news superuser's id. Fix provided by Chip
- * Rosenthal <chip@chinacat.lonestar.org>.
- *
- * Revision 4.3.2.1 89/12/17 02:54:55 sob
- * Removed redundant include directive.
- *
- * Revision 4.3.1.5 85/05/23 17:21:24 lwall
- * Now allows 'r' and 'f' on null articles.
- *
- * Revision 4.3.1.4 85/05/21 13:35:21 lwall
- * Sped up "rn -c" by not doing unnecessary initialization.
- *
- * Revision 4.3.1.3 85/05/17 10:37:11 lwall
- * Fixed & substitution to capitalize last name too.
- *
- * Revision 4.3.1.2 85/05/15 14:39:45 lwall
- * Spelled gecos right.
- *
- * Revision 4.3.1.1 85/05/10 11:33:51 lwall
- * Branch for patches.
- *
- * Revision 4.3 85/05/01 11:40:54 lwall
- * Baseline for release with 4.3bsd.
- *
- */
-
- #include "EXTERN.h"
- #include "common.h"
- #include "util.h"
- #include "search.h"
- #include "head.h"
- #include "rn.h"
- #include "artsrch.h"
- #include "ng.h"
- #include "respond.h"
- #include "rcstuff.h"
- #include "bits.h"
- #include "artio.h"
- #include "term.h"
- #include "final.h"
- #ifdef USETHREADS
- #include "rthreads.h"
- #endif
- #include "INTERN.h"
- #include "intrp.h"
-
- char orgname[] = ORGNAME;
-
- /* name of this site */
- #ifndef HIDDENNET
- #ifdef GETHOSTNAME
- char *hostname;
- # undef SITENAME
- # define SITENAME hostname
- #else /* !GETHOSTNAME */
- # ifdef DOUNAME
- # include <sys/utsname.h>
- struct utsname utsn;
- # undef SITENAME
- # define SITENAME utsn.nodename
- # else /* !DOUNAME */
- # ifdef PHOSTNAME
- char *hostname;
- # undef SITENAME
- # define SITENAME hostname
- # else /* !PHOSTNAME */
- # ifdef WHOAMI
- # undef SITENAME
- # define SITENAME sysname
- # endif /* WHOAMI */
- # endif /* PHOSTNAME */
- # endif /* DOUNAME */
- #endif /* GETHOSTNAME */
- #endif /*HIDDENNET */
-
- #ifdef TILDENAME
- static char *tildename = Nullch;
- static char *tildedir = Nullch;
- #endif
-
- char *realname INIT(Nullch); /* real name of sender from /etc/passwd */
-
- #ifdef CONDSUB
- char *skipinterp ANSI((char *,char *));
- #endif
-
- static void abort_interp ANSI((void));
-
- void
- intrp_init(tcbuf)
- char *tcbuf;
- {
- char *getlogin();
-
- spool = savestr(filexp(SPOOL)); /* usually /usr/spool/news */
-
- /* get environmental stuff */
-
- #ifdef NEWSADMIN
- #ifdef GETPWENT
- {
- struct passwd *getpwnam();
- struct passwd *pwd = getpwnam(NEWSADMIN);
-
- if (pwd != NULL)
- newsuid = pwd->pw_uid;
- }
- #endif /* GETPWENT */
- #endif /* NEWSADMIN */
- /* get home directory */
-
- homedir = getenv("HOME");
- if (homedir == Nullch)
- homedir = getenv("LOGDIR");
-
- dotdir = getval("DOTDIR",homedir);
-
- /* get login name */
-
- logname = getenv("USER");
- if (logname == Nullch)
- logname = getenv("LOGNAME");
- #ifdef GETLOGIN
- if (logname == Nullch)
- logname = savestr(getlogin());
- #endif
-
- #ifdef NEWSADMIN
- /* if this is the news admin than load his UID into newsuid */
-
- if ( strEQ(logname,NEWSADMIN) )
- newsuid = getuid();
- #endif
-
- if (checkflag) /* that getwd below takes ~1/3 sec. */
- return; /* and we do not need it for -c */
- getwd(tcbuf); /* find working directory name */
- origdir = savestr(tcbuf); /* and remember it */
-
- /* get the real name of the person (%N) */
- /* Must be done after logname is read in because BERKNAMES uses that */
-
- strcpy(tcbuf,getrealname(getuid()));
- realname = savestr(tcbuf);
-
- /* name of header file (%h) */
-
- headname = savestr(filexp(HEADNAME));
-
- /* name of this site (%H) */
-
- #ifndef HIDDENNET
- #ifdef HOSTFILE
- if ((tmpfp = fopen(HOSTFILE,"r")) == NULL) {
- hostname = "unknown";
- printf("Warning: Couldn't open %s to determine hostname!\n", HOSTFILE);
- } else {
- fgets(buf, sizeof(buf), tmpfp);
- buf[strlen(buf)-1] = 0;
- hostname = savestr(buf);
- fclose(tmpfp);
- }
- #else
- #ifdef GETHOSTNAME
- gethostname(buf,sizeof buf);
- hostname = savestr(buf);
- #else
- #ifdef DOUNAME
- /* get sysname */
- uname(&utsn);
- #else
- #ifdef PHOSTNAME
- {
- FILE *popen();
- FILE *pipefp = popen(PHOSTNAME,"r");
-
- if (pipefp == Nullfp) {
- printf("Can't find hostname\n");
- sig_catcher(0);
- }
- fgets(buf,sizeof buf,pipefp);
- buf[strlen(buf)-1] = '\0'; /* wipe out newline */
- hostname = savestr(buf);
- pclose(pipefp);
- }
- #endif /* PHOSTNAME */
- #endif /* DOUNAME */
- #endif /* GETHOSTNAME */
- #endif /* HOSTFILE */
- if (index(SITENAME,'.') == NULL) {
- sprintf(buf, "%s.%s", SITENAME, OURDOMAIN);
- sitename = savestr(buf);
- } else
- sitename = savestr(SITENAME);
- #else
- sitename = savestr(OURDOMAIN);
- #endif
- }
-
- /* expand filename via %, ~, and $ interpretation */
- /* returns pointer to static area */
- /* Note that there is a 1-deep cache of ~name interpretation */
-
- char *
- filexp(s)
- register char *s;
- {
- static char filename[CBUFLEN];
- char scrbuf[CBUFLEN];
- register char *d;
-
- #ifdef DEBUGGING
- if (debug & DEB_FILEXP)
- printf("< %s\n",s) FLUSH;
- #endif
- interp(filename, (sizeof filename), s); /* interpret any % escapes */
- #ifdef DEBUGGING
- if (debug & DEB_FILEXP)
- printf("%% %s\n",filename) FLUSH;
- #endif
- s = filename;
- if (*s == '~') { /* does destination start with ~? */
- if (!*(++s) || *s == '/') {
- sprintf(scrbuf,"%s%s",homedir,s);
- /* swap $HOME for it */
- #ifdef DEBUGGING
- if (debug & DEB_FILEXP)
- printf("~ %s\n",scrbuf) FLUSH;
- #endif
- strcpy(filename,scrbuf);
- }
- else {
- #ifdef TILDENAME
- for (d=scrbuf; isalnum(*s); s++,d++)
- *d = *s;
- *d = '\0';
- if (tildedir && strEQ(tildename,scrbuf)) {
- strcpy(scrbuf,tildedir);
- strcat(scrbuf, s);
- strcpy(filename, scrbuf);
- #ifdef DEBUGGING
- if (debug & DEB_FILEXP)
- printf("r %s %s\n",tildename,tildedir) FLUSH;
- #endif
- }
- else {
- if (tildename) {
- free(tildename);
- free(tildedir);
- }
- tildedir = Nullch;
- tildename = savestr(scrbuf);
- #ifdef GETPWENT /* getpwnam() is not the paragon of efficiency */
- {
- struct passwd *getpwnam();
- struct passwd *pwd = getpwnam(tildename);
-
- sprintf(scrbuf,"%s%s",pwd->pw_dir,s);
- tildedir = savestr(pwd->pw_dir);
- strcpy(filename,scrbuf);
- #ifdef GETPWENT
- endpwent();
- #endif
- }
- #else /* this will run faster, and is less D space */
- { /* just be sure LOGDIRFIELD is correct */
- FILE *pfp = fopen("/etc/passwd","r");
- char tmpbuf[512];
- int i;
-
- if (pfp == Nullfp) {
- printf(cantopen,"passwd") FLUSH;
- sig_catcher(0);
- }
- while (fgets(tmpbuf,512,pfp) != Nullch) {
- d = cpytill(scrbuf,tmpbuf,':');
- #ifdef DEBUGGING
- if (debug & DEB_FILEXP)
- printf("p %s\n",tmpbuf) FLUSH;
- #endif
- if (strEQ(scrbuf,tildename)) {
- for (i=LOGDIRFIELD-2; i; i--) {
- if (d)
- d = index(d+1,':');
- }
- if (d) {
- cpytill(scrbuf,d+1,':');
- tildedir = savestr(scrbuf);
- strcat(scrbuf,s);
- strcpy(filename,scrbuf);
- }
- break;
- }
- }
- fclose(pfp);
- }
- #endif
- }
- #else /* !TILDENAME */
- #ifdef VERBOSE
- IF(verbose)
- fputs("~loginname not implemented.\n",stdout) FLUSH;
- ELSE
- #endif
- #ifdef TERSE
- fputs("~login not impl.\n",stdout) FLUSH;
- #endif
- #endif
- }
- }
- else if (*s == '$') { /* starts with some env variable? */
- d = scrbuf;
- *d++ = '%';
- if (s[1] == '{')
- strcpy(d,s+2);
- else {
- *d++ = '{';
- for (s++; isalnum(*s); s++) *d++ = *s;
- /* skip over token */
- *d++ = '}';
- strcpy(d,s);
- }
- #ifdef DEBUGGING
- if (debug & DEB_FILEXP)
- printf("$ %s\n",scrbuf) FLUSH;
- #endif
- interp(filename, (sizeof filename), scrbuf);
- /* this might do some extra '%'s but */
- /* that is how the Mercedes Benz */
- }
- #ifdef DEBUGGING
- if (debug & DEB_FILEXP)
- printf("> %s\n",filename) FLUSH;
- #endif
- return filename;
- }
-
- #ifdef CONDSUB
- /* skip interpolations */
-
- char *
- skipinterp(pattern,stoppers)
- register char *pattern;
- char *stoppers;
- {
-
- while (*pattern && (!stoppers || !index(stoppers,*pattern))) {
- #ifdef DEBUGGING
- if (debug & 8)
- printf("skipinterp till %s at %s\n",stoppers?stoppers:"",pattern);
- #endif
- if (*pattern == '%' && pattern[1]) {
- switch (*++pattern) {
- case '{':
- for (pattern++; *pattern && *pattern != '}'; pattern++)
- if (*pattern == '\\')
- pattern++;
- break;
- case '[':
- for (pattern++; *pattern && *pattern != ']'; pattern++)
- if (*pattern == '\\')
- pattern++;
- break;
- #ifdef CONDSUB
- case '(': {
- pattern = skipinterp(pattern+1,"!=");
- if (!*pattern)
- goto getout;
- for (pattern++; *pattern && *pattern != '?'; pattern++)
- if (*pattern == '\\')
- pattern++;
- if (!*pattern)
- goto getout;
- pattern = skipinterp(pattern+1,":)");
- if (*pattern == ':')
- pattern = skipinterp(pattern+1,")");
- break;
- }
- #endif
- #ifdef BACKTICK
- case '`': {
- pattern = skipinterp(pattern+1,"`");
- break;
- }
- #endif
- #ifdef PROMPTTTY
- case '"':
- pattern = skipinterp(pattern+1,"\"");
- break;
- #endif
- default:
- break;
- }
- pattern++;
- }
- else {
- if (*pattern == '^' && pattern[1])
- pattern += 2;
- else if (*pattern == '\\' && pattern[1])
- pattern += 2;
- else
- pattern++;
- }
- }
- getout:
- return pattern; /* where we left off */
- }
- #endif
-
- /* interpret interpolations */
-
- char *
- dointerp(dest,destsize,pattern,stoppers)
- register char *dest;
- register int destsize;
- register char *pattern;
- char *stoppers;
- {
- char *subj_buf = Nullch;
- char *ngs_buf = Nullch;
- char *refs_buf = Nullch;
- char *artid_buf = Nullch;
- char *reply_buf = Nullch;
- char *from_buf = Nullch;
- char *path_buf = Nullch;
- char *follow_buf = Nullch;
- char *dist_buf = Nullch;
- char *line_buf = Nullch;
- register char *s, *h;
- register int i;
- char scrbuf[512];
- bool upper = FALSE;
- bool lastcomp = FALSE;
- int metabit = 0;
-
- while (*pattern && (!stoppers || !index(stoppers,*pattern))) {
- #ifdef DEBUGGING
- if (debug & 8)
- printf("dointerp till %s at %s\n",stoppers?stoppers:"",pattern);
- #endif
- if (*pattern == '%' && pattern[1]) {
- upper = FALSE;
- lastcomp = FALSE;
- for (s=Nullch; !s; ) {
- switch (*++pattern) {
- case '^':
- upper = TRUE;
- break;
- case '_':
- lastcomp = TRUE;
- break;
- case '/':
- #ifdef ARTSRCH
- s = scrbuf;
- if (!index("/?g",pattern[-2]))
- *s++ = '/';
- strcpy(s,lastpat);
- s += strlen(s);
- if (pattern[-2] != 'g') {
- if (index("/?",pattern[-2]))
- *s++ = pattern[-2];
- else
- *s++ = '/';
- if (art_howmuch == 1)
- *s++ = 'h';
- else if (art_howmuch == 2)
- *s++ = 'a';
- if (art_doread)
- *s++ = 'r';
- }
- *s = '\0';
- s = scrbuf;
- #else
- s = nullstr;
- #endif
- break;
- case '{':
- pattern = cpytill(scrbuf,pattern+1,'}');
- if (s = index(scrbuf,'-'))
- *s++ = '\0';
- else
- s = nullstr;
- s = getval(scrbuf,s);
- break;
- case '[':
- pattern = cpytill(scrbuf,pattern+1,']');
- i = set_line_type(scrbuf,scrbuf+strlen(scrbuf));
- if (line_buf)
- free(line_buf);
- s = line_buf = fetchlines(art,i);
- break;
- #ifdef CONDSUB
- case '(': {
- COMPEX *oldbra_compex = bra_compex;
- COMPEX cond_compex;
- char rch;
- bool matched;
-
- init_compex(&cond_compex);
- pattern = dointerp(dest,destsize,pattern+1,"!=");
- rch = *pattern;
- if (rch == '!')
- pattern++;
- if (*pattern != '=')
- goto getout;
- pattern = cpytill(scrbuf,pattern+1,'?');
- if (!*pattern)
- goto getout;
- if (s = compile(&cond_compex,scrbuf,TRUE,TRUE)) {
- printf("%s: %s\n",scrbuf,s) FLUSH;
- pattern += strlen(pattern);
- goto getout;
- }
- matched = (execute(&cond_compex,dest) != Nullch);
- if (cond_compex.nbra) /* were there brackets? */
- bra_compex = &cond_compex;
- if (matched==(rch == '=')) {
- pattern = dointerp(dest,destsize,pattern+1,":)");
- if (*pattern == ':')
- pattern = skipinterp(pattern+1,")");
- }
- else {
- pattern = skipinterp(pattern+1,":)");
- if (*pattern == ':')
- pattern++;
- pattern = dointerp(dest,destsize,pattern,")");
- }
- s = dest;
- bra_compex = oldbra_compex;
- free_compex(&cond_compex);
- break;
- }
- #endif
- #ifdef BACKTICK
- case '`': {
- FILE *pipefp, *popen();
-
- pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"`");
- pipefp = popen(scrbuf,"r");
- if (pipefp != Nullfp) {
- int len;
-
- len = fread(scrbuf,sizeof(char),(sizeof scrbuf)-1,
- pipefp);
- scrbuf[len] = '\0';
- pclose(pipefp);
- }
- else {
- printf("\nCan't run %s\n",scrbuf);
- *scrbuf = '\0';
- }
- for (s=scrbuf; *s; s++) {
- if (*s == '\n') {
- if (s[1])
- *s = ' ';
- else
- *s = '\0';
- }
- }
- s = scrbuf;
- break;
- }
- #endif
- #ifdef PROMPTTTY
- case '"':
- pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"\"");
- fputs(scrbuf,stdout) FLUSH;
- resetty();
- gets(scrbuf);
- noecho();
- crmode();
- s = scrbuf;
- break;
- #endif
- case '~':
- s = homedir;
- break;
- case '.':
- s = dotdir;
- break;
- case '$':
- s = scrbuf;
- sprintf(s,"%d",getpid());
- break;
- case '#':
- s = scrbuf;
- sprintf(s,"%d",perform_cnt);
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- #ifdef CONDSUB
- s = getbracket(bra_compex,*pattern - '0');
- #else
- s = nullstr;
- #endif
- break;
- case 'a':
- s = scrbuf;
- sprintf(s,"%ld",(long)art);
- break;
- case 'A':
- #ifdef LINKART
- s = linkartname; /* so Eunice people get right file */
- #else
- s = scrbuf;
- sprintf(s,"%s/%s/%ld",spool,ngdir,(long)art);
- #endif
- break;
- case 'b':
- s = savedest;
- break;
- case 'B':
- s = scrbuf;
- sprintf(s,"%ld",(long)savefrom);
- break;
- case 'c':
- s = ngdir;
- break;
- case 'C':
- s = ngname;
- break;
- case 'd':
- s = scrbuf;
- sprintf(s,"%s/%s",spool,ngdir);
- break;
- case 'D':
- s = dist_buf = fetchlines(art,DIST_LINE);
- break;
- case 'e':
- s = extractprog;
- break;
- #ifdef USETHREADS
- case 'E': {
- int sel, unseen;
-
- sel = curr_p_art && (selected_roots[curr_p_art->root] & 1);
- unseen = (art <= lastart) && !was_read(art);
- sprintf(scrbuf,"%ld",(long)toread[ng]-selected_count
- -unthreaded-(!sel && unseen));
- s = scrbuf;
- break;
- }
- #endif
- case 'f': /* from line */
- #ifdef ASYNC_PARSE
- parse_maybe(art);
- #endif
- if (htype[REPLY_LINE].ht_minpos >= 0) {
- /* was there a reply line? */
- if (!(s=reply_buf))
- s = reply_buf = fetchlines(art,REPLY_LINE);
- }
- else if (!(s = from_buf))
- s = from_buf = fetchlines(art,FROM_LINE);
- break;
- case 'F':
- #ifdef ASYNC_PARSE
- parse_maybe(art);
- #endif
- if (htype[FOLLOW_LINE].ht_minpos >= 0)
- /* is there a Followup-To line? */
- s = follow_buf = fetchlines(art,FOLLOW_LINE);
- else {
- int off;
-
- s = ngs_buf = fetchlines(art,NGS_LINE);
- if (h = instr(s,"net.general")) {
- off = h-s;
- strncpy(scrbuf,s,off+4);
- strcpy(scrbuf+off+4,"followup");
- safecpy(scrbuf+off+12,h+11,sizeof(scrbuf));
- s = scrbuf;
- }
- }
- break;
- case 'h': /* header file name */
- s = headname;
- break;
- case 'H': /* host name */
- s = sitename;
- break;
- case 'i':
- if (!(s=artid_buf))
- s = artid_buf = fetchlines(art,MESSID_LINE);
- if (*s && *s != '<') {
- sprintf(scrbuf,"<%s>",artid_buf);
- s = scrbuf;
- }
- break;
- case 'I': /* ref article indicator */
- s = scrbuf;
- sprintf(scrbuf,"'%s'",indstr);
- break;
- case 'l': /* rn library */
- #ifdef NEWSADMIN
- s = newsadmin;
- #else
- s = "???";
- #endif
- break;
- case 'L': /* login id */
- s = logname;
- break;
- case 'm': /* current mode */
- s = scrbuf;
- *s = mode;
- s[1] = '\0';
- break;
- case 'M':
- #ifdef DELAYMARK
- sprintf(scrbuf,"%ld",(long)dmcount);
- s = scrbuf;
- #else
- s = nullstr;
- #endif
- break;
- case 'n': /* newsgroups */
- s = ngs_buf = fetchlines(art,NGS_LINE);
- break;
- case 'N': /* full name */
- s = getval("NAME",realname);
- break;
- case 'o': /* organization */
- s = getval("ORGANIZATION",orgname);
- #ifdef ORGFILE
- if (*s == '/') {
- FILE *ofp = fopen(s,"r");
-
- if (ofp) {
- fgets(scrbuf,sizeof scrbuf,ofp);
- fclose(ofp);
- s = scrbuf;
- s[strlen(s)-1] = '\0';
- }
- }
- #endif
- break;
- case 'O':
- s = origdir;
- break;
- case 'p':
- s = cwd;
- break;
- case 'P':
- s = spool;
- break;
- case 'r':
- #ifdef ASYNC_PARSE
- parse_maybe(art);
- #endif
- if (htype[REFS_LINE].ht_minpos >= 0) {
- refs_buf = fetchlines(art,REFS_LINE);
- refscpy(scrbuf,(sizeof scrbuf),refs_buf);
- }
- else
- *scrbuf = '\0';
- s = rindex(scrbuf,'<');
- break;
- case 'R':
- #ifdef ASYNC_PARSE
- parse_maybe(art);
- #endif
- if (htype[REFS_LINE].ht_minpos >= 0) {
- refs_buf = fetchlines(art,REFS_LINE);
- refscpy(scrbuf,(sizeof scrbuf),refs_buf);
- /* no more than 3 prior references allowed,
- ** including the one concatenated below */
- if ((s = rindex(scrbuf,'<')) > scrbuf) {
- *s = '\0';
- h = rindex(scrbuf,'<');
- *s = '<';
- if (h > scrbuf)
- strcpy(scrbuf,h);
- }
- }
- else
- *scrbuf = '\0';
- if (!artid_buf)
- artid_buf = fetchlines(art,MESSID_LINE);
- if (artid_buf[0] == '<')
- safecat(scrbuf,artid_buf,sizeof(scrbuf));
- else if (artid_buf[0]) {
- char tmpbuf[64];
-
- sprintf(tmpbuf,"<%s>",artid_buf);
- safecat(scrbuf,tmpbuf,sizeof(scrbuf));
- }
- s = scrbuf;
- break;
- case 's':
- if (!(s=subj_buf))
- s = subj_buf = fetchsubj(art,TRUE,TRUE);
- /* get subject handy */
- while ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')&&s[2]==':') {
- /* skip extra Re: */
- s += 3;
- if (*s == ' ')
- s++;
- }
- if (h = instr(s,"- (nf"))
- *h = '\0';
- break;
- case 'S':
- if (!(s=subj_buf))
- s = subj_buf = fetchsubj(art,TRUE,TRUE);
- /* get subject handy */
- if ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')&&s[2]==':') {
- /* skip extra Re: */
- s += 3;
- if (*s == ' ')
- s++;
- }
- break;
- case 't':
- case 'T':
- #ifdef ASYNC_PARSE
- parse_maybe(art);
- #endif
- if (htype[REPLY_LINE].ht_minpos >= 0) {
- /* was there a reply line? */
- if (!(s=reply_buf))
- s = reply_buf = fetchlines(art,REPLY_LINE);
- }
- else if (!(s = from_buf))
- s = from_buf = fetchlines(art,FROM_LINE);
- if (*pattern == 'T') {
- if (htype[PATH_LINE].ht_minpos >= 0) {
- /* should we substitute path? */
- s = path_buf = fetchlines(art,PATH_LINE);
- }
- i = strlen(sitename);
- if (strnEQ(sitename,s,i) && s[i] == '!')
- s += i + 1;
- }
- if ((h=index(s,'(')) != Nullch)
- /* strip garbage from end */
- *(h-1) = '\0';
- else if ((h=index(s,'<')) != Nullch) {
- /* or perhaps from beginning */
- s = h+1;
- if ((h=index(s,'>')) != Nullch)
- *h = '\0';
- }
- break;
- case 'u':
- sprintf(scrbuf,"%ld",(long)toread[ng]);
- s = scrbuf;
- break;
- case 'U': {
- int unseen;
-
- unseen = (art <= lastart) && !was_read(art);
- #ifdef USETHREADS
- if (selected_root_cnt) {
- int sel;
-
- sel = curr_p_art
- && (selected_roots[curr_p_art->root] & 1);
- sprintf(scrbuf,"%ld",
- (long)selected_count-(sel && unseen));
- }
- else
- sprintf(scrbuf,"%ld",(long)toread[ng]-unthreaded
- -unseen);
- #else
- sprintf(scrbuf,"%ld",(long)toread[ng]-unseen);
- #endif
- s = scrbuf;
- break;
- }
- case 'x': /* news library */
- s = lib;
- break;
- case 'X': /* rn library */
- s = rnlib;
- break;
- case 'z':
- #ifdef LINKART
- s = linkartname; /* so Eunice people get right file */
- #else
- s = scrbuf;
- sprintf(s,"%ld",(long)art);
- #endif
- if (stat(s,&filestat) < 0)
- filestat.st_size = 0L;
- sprintf(scrbuf,"%5ld",(long)filestat.st_size);
- s = scrbuf;
- break;
- #ifdef USETHREADS
- case 'Z':
- sprintf(scrbuf,"%ld",(long)selected_count);
- s = scrbuf;
- break;
- #endif
- default:
- if (--destsize <= 0)
- abort_interp();
- *dest++ = *pattern | metabit;
- s = nullstr;
- break;
- }
- }
- if (!s)
- s = nullstr;
- pattern++;
- if (upper || lastcomp) {
- char *t;
-
- if (s != scrbuf) {
- safecpy(scrbuf,s,(sizeof scrbuf));
- s = scrbuf;
- }
- if (upper || !(t=rindex(s,'/')))
- t = s;
- while (*t && !isalpha(*t))
- t++;
- if (islower(*t))
- *t = toupper(*t);
- }
- i = metabit; /* maybe get into register */
- if (s == dest) {
- while (*dest) {
- if (--destsize <= 0)
- abort_interp();
- *dest++ |= i;
- }
- }
- else {
- while (*s) {
- if (--destsize <= 0)
- abort_interp();
- *dest++ = *s++ | i;
- }
- }
- }
- else {
- if (--destsize <= 0)
- abort_interp();
- if (*pattern == '^' && pattern[1]) {
- ++pattern; /* skip uparrow */
- i = *pattern; /* get char into a register */
- if (i == '?')
- *dest++ = '\177' | metabit;
- else if (i == '(') {
- metabit = 0200;
- destsize++;
- }
- else if (i == ')') {
- metabit = 0;
- destsize++;
- }
- else
- *dest++ = i & 037 | metabit;
- pattern++;
- }
- else if (*pattern == '\\' && pattern[1]) {
- ++pattern; /* skip backslash */
- i = *pattern; /* get char into a register */
-
- /* this used to be a switch but the if may save space */
-
- if (i >= '0' && i <= '7') {
- i = 1;
- while (i < 01000 && *pattern >= '0' && *pattern <= '7') {
- i <<= 3;
- i += *pattern++ - '0';
- }
- *dest++ = i & 0377 | metabit;
- --pattern;
- }
- else if (i == 'b')
- *dest++ = '\b' | metabit;
- else if (i == 'f')
- *dest++ = '\f' | metabit;
- else if (i == 'n')
- *dest++ = '\n' | metabit;
- else if (i == 'r')
- *dest++ = '\r' | metabit;
- else if (i == 't')
- *dest++ = '\t' | metabit;
- else
- *dest++ = i | metabit;
- pattern++;
- }
- else
- *dest++ = *pattern++ | metabit;
- }
- }
- *dest = '\0';
- getout:
- if (subj_buf != Nullch) /* return any checked out storage */
- free(subj_buf);
- if (ngs_buf != Nullch)
- free(ngs_buf);
- if (refs_buf != Nullch)
- free(refs_buf);
- if (artid_buf != Nullch)
- free(artid_buf);
- if (reply_buf != Nullch)
- free(reply_buf);
- if (from_buf != Nullch)
- free(from_buf);
- if (path_buf != Nullch)
- free(path_buf);
- if (follow_buf != Nullch)
- free(follow_buf);
- if (dist_buf != Nullch)
- free(dist_buf);
- if (line_buf != Nullch)
- free(line_buf);
- return pattern; /* where we left off */
- }
-
- void
- interp(dest,destsize,pattern)
- char *dest;
- int destsize;
- char *pattern;
- {
- dointerp(dest,destsize,pattern,Nullch);
- #ifdef DEBUGGING
- if (debug & DEB_FILEXP)
- fputs(dest,stdout);
- #endif
- }
-
- /* copy a references line, normalizing as we go */
-
- void
- refscpy(dest,destsize,src)
- register char *dest, *src;
- register int destsize;
- {
- register char *dot, *at, *beg;
- char tmpbuf[64];
-
- while (*src) {
- if (*src != '<') {
- if (--destsize <= 0)
- break;
- *dest++ = '<';
- at = dot = Nullch;
- beg = src;
- while (*src && *src != ' ' && *src != ',') {
- if (*src == '.')
- dot = src;
- else if (*src == '@')
- at = src;
- if (--destsize <= 0)
- break;
- *dest++ = *src++;
- }
- if (destsize <= 0)
- break;
- if (dot && !at) {
- int len;
-
- *dest = *dot++ = '\0';
- sprintf(tmpbuf,"%s@%s.UUCP",dot,beg);
- len = strlen(tmpbuf);
- if (destsize > len) {
- strcpy(dest,tmpbuf);
- dest = dest + len;
- destsize -= len;
- }
- }
- if (--destsize <= 0)
- break;
- *dest++ = '>';
- }
- else {
- while (*src && --destsize > 0 && (*dest++ = *src++) != '>') ;
- if (destsize <= 0)
- break;
- }
- while (*src == ' ' || *src == ',') src++;
- if (*src && --destsize > 0)
- *dest++ = ' ';
- }
- *dest = '\0';
- }
-
- /* get the person's real name from /etc/passwd */
- /* (string is overwritten, so it must be copied) */
-
- char *
- getrealname(uid)
- int uid;
- {
- char *s, *c;
- char tmpbuf[512];
-
- #ifdef PASSNAMES
- #ifdef GETPWENT
- struct passwd *pwd = getpwuid(uid);
-
- s = pwd->pw_gecos;
- #else
- int i;
-
- getpw(uid, tmpbuf);
- for (s=tmpbuf, i=GCOSFIELD-1; i; i--) {
- if (s)
- s = index(s,':')+1;
- }
- if (!s)
- return nullstr;
- cpytill(tmpbuf,s,':');
- s = tmpbuf;
- #endif
- #ifdef BERKNAMES
- #ifdef BERKJUNK
- while (*s && !isalnum(*s) && *s != '&') s++;
- #endif
- if ((c = index(s, ',')) != Nullch)
- *c = '\0';
- if ((c = index(s, ';')) != Nullch)
- *c = '\0';
- s = cpytill(buf,s,'&');
- if (*s == '&') { /* whoever thought this one up was */
- c = buf + strlen(buf); /* in the middle of the night */
- strcat(c,logname); /* before the morning after */
- strcat(c,s+1);
- if (islower(*c))
- *c = toupper(*c); /* gack and double gack */
- }
- #else
- if ((c = index(s, '(')) != Nullch)
- *c = '\0';
- if ((c = index(s, '-')) != Nullch)
- s = c;
- strcpy(buf,tmpbuf);
- #endif
- #ifdef GETPWENT
- endpwent();
- #endif
- return buf; /* return something static */
- #else
- if ((tmpfp=fopen(filexp(FULLNAMEFILE),"r")) != Nullfp) {
- fgets(buf,sizeof buf,tmpfp);
- fclose(tmpfp);
- buf[strlen(buf)-1] = '\0';
- return buf;
- }
- return "PUT YOUR NAME HERE";
- #endif
- }
-
- static void
- abort_interp()
- {
- fputs("\n% interp buffer overflow!\n",stdout) FLUSH;
- sig_catcher(0);
- }
-
-
-