home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
trn-3.3
/
part09
/
intrp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-27
|
28KB
|
1,259 lines
/* $Id: intrp.c,v 3.0 1992/02/01 03:09:32 davison Trn $
*/
/* This software is Copyright 1991 by Stan Barber.
*
* Permission is hereby granted to copy, reproduce, redistribute or otherwise
* use this software as long as: there is no monetary profit gained
* specifically from the use or reproduction of this software, it is not
* sold, rented, traded or otherwise marketed, and this copyright notice is
* included prominently in any copy made.
*
* The authors make no claims as to the fitness or correctness of this software
* for any use whatsoever, and it is provided as is. Any use of this software
* is at the user's own risk.
*/
#include "EXTERN.h"
#include "common.h"
#include "util.h"
#include "search.h"
#include "cache.h"
#include "bits.h"
#include "head.h"
#include "trn.h"
#include "artsrch.h"
#include "ng.h"
#include "ngdata.h"
#include "respond.h"
#include "rcstuff.h"
#include "artio.h"
#include "init.h"
#include "term.h"
#include "final.h"
#include "rthread.h"
#include "rt-select.h"
#include "rt-util.h"
#include "nntp.h"
#include "INTERN.h"
#include "intrp.h"
static char * regexp_specials = "^$.*[\\/?%";
char orgname[] = ORGNAME;
#ifdef HAS_UNAME
#include <sys/utsname.h>
struct utsname utsn;
#endif
#ifdef TILDENAME
static char *tildename = Nullch;
static char *tildedir = Nullch;
#endif
#ifdef CONDSUB
COMPEX cond_compex;
char *skipinterp _((char *,char *));
#endif
static void abort_interp _((void));
void
intrp_init(tcbuf)
char *tcbuf;
{
char *getlogin();
#ifdef CONDSUB
init_compex(&cond_compex);
#endif
/* get environmental stuff */
#ifdef NEWS_ADMIN
{
#ifdef HAS_GETPWENT
struct passwd *getpwnam();
struct passwd *pwd = getpwnam(NEWS_ADMIN);
if (pwd != NULL)
newsuid = pwd->pw_uid;
#else
#ifdef TILDENAME
char tildenews[2+sizeof NEWS_ADMIN];
strcpy(tildenews, "~");
strcat(tildenews, NEWS_ADMIN);
(void) filexp(tildenews);
#else
??? "Define either HAS_GETPWENT or TILDENAME to get NEWS_ADMIN"
#endif /* TILDENAME */
#endif /* HAS_GETPWENT */
}
#endif /* NEWS_ADMIN */
/* get home directory */
homedir = getenv("HOME");
if (homedir == Nullch)
homedir = getenv("LOGDIR");
dotdir = getval("DOTDIR",homedir);
/* get login name */
loginName = getenv("USER");
if (loginName == Nullch)
loginName = getenv("LOGNAME");
#ifdef GETLOGIN
if (loginName == Nullch)
loginName = savestr(getlogin());
#endif
spool = savestr(filexp(NEWSSPOOL)); /* usually /usr/spool/news */
threaddir = filexp(THREAD_DIR);
if (strEQ(threaddir,spool))
threaddir = spool;
else
threaddir = savestr(threaddir);
overviewdir = filexp(OVERVIEW_DIR);
if (strEQ(overviewdir,spool))
overviewdir = spool;
else
overviewdir = savestr(overviewdir);
#ifdef NEWS_ADMIN
/* if this is the news admin then load his UID into newsuid */
if (strEQ(loginName,NEWS_ADMIN))
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 loginName is read in because BERKNAMES uses that */
strcpy(tcbuf,getrealname((long)getuid()));
realname = savestr(tcbuf);
/* name of header file (%h) */
headname = savestr(filexp(HEADNAME));
/* host name that goes in postings (%H) */
phostname = PHOSTNAME;
if (*phostname == '/') {
if ((tmpfp = fopen(phostname,"r")) == NULL) {
printf("Warning: Couldn't open %s to determine hostname!\n",
phostname);
sig_catcher(0);
}
fgets(buf, sizeof(buf), tmpfp);
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = 0;
fclose(tmpfp);
phostname = savestr(buf);
}
else {
#ifdef HAS_GETHOSTNAME
gethostname(buf,sizeof buf);
#else
# ifdef HAS_UNAME
/* get sysname */
uname(&utsn);
strcpy(buf,utsn.nodename);
# else
# ifdef PHOSTCMD
{
FILE *popen();
FILE *pipefp = popen(PHOSTCMD,"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 */
pclose(pipefp);
}
# else
*buf = '\0';
# endif /* PHOSTCMD */
# endif /* HAS_UNAME */
#endif /* HAS_GETHOSTNAME */
if (*buf) {
char *cp = index(buf,'.');
if (cp)
*cp = '\0';
cp = index(phostname,'.');
if (cp)
strcat(buf,cp);
phostname = savestr(buf);
}
}
}
/* 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 DEBUG
if (debug & DEB_FILEXP)
printf("< %s\n",s) FLUSH;
#endif
interp(filename, (sizeof filename), s);
/* interpret any % escapes */
#ifdef DEBUG
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 DEBUG
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 DEBUG
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 HAS_GETPWENT /* getpwnam() is not the paragon of efficiency */
{
#ifdef notdef
struct passwd *getpwnam _((char*));
#endif
struct passwd *pwd = getpwnam(tildename);
if (pwd == NULL) {
printf("%s is an unknown user. Using default.\n",tildename) FLUSH;
return Nullch;
}
sprintf(scrbuf,"%s%s",pwd->pw_dir,s);
tildedir = savestr(pwd->pw_dir);
strcpy(filename,scrbuf);
endpwent();
}
#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 DEBUG
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 DEBUG
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 DEBUG
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 DEBUG
if (debug & DEB_INTRP)
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;
char *line_split = Nullch;
char *orig_dest = dest;
register char *s, *h;
register int i;
char scrbuf[512];
char spfbuf[512];
bool upper = FALSE;
bool lastcomp = FALSE;
bool re_quote = FALSE;
bool tick_quote = FALSE;
bool address_parse = FALSE;
bool comment_parse = FALSE;
bool proc_sprintf = FALSE;
int metabit = 0;
while (*pattern && (!stoppers || !index(stoppers,*pattern))) {
#ifdef DEBUG
if (debug & DEB_INTRP)
printf("dointerp till %s at %s\n",stoppers?stoppers:"",pattern);
#endif
if (*pattern == '%' && pattern[1]) {
upper = FALSE;
lastcomp = FALSE;
re_quote = FALSE;
tick_quote = FALSE;
address_parse = FALSE;
comment_parse = FALSE;
proc_sprintf = FALSE;
for (s=Nullch; !s; ) {
switch (*++pattern) {
case '^':
upper = TRUE;
break;
case '_':
lastcomp = TRUE;
break;
case '\\':
re_quote = TRUE;
break;
case '\'':
tick_quote = TRUE;
break;
case '>':
address_parse = TRUE;
break;
case ')':
comment_parse = TRUE;
break;
case ':':
proc_sprintf = TRUE;
h = spfbuf;
*h++ = '%';
pattern++; /* Skip over ':' */
while (*pattern
&& (*pattern=='.' || *pattern=='-' || isdigit(*pattern))) {
*h++ = *pattern++;
}
*h++ = 's';
*h++ = '\0';
pattern--;
break;
case '/':
#ifdef ARTSEARCH
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_doread)
*s++ = 'r';
if (art_howmuch != ARTSCOPE_SUBJECT) {
*s++ = scopestr[art_howmuch];
if (art_howmuch == ARTSCOPE_ONEHDR) {
safecpy(s,art_srchhdr,
(sizeof scrbuf) - (s-scrbuf));
s = index(s,':') + 1;
if (!s)
s = scrbuf+(sizeof scrbuf)-1;
}
}
}
*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;
char rch;
bool matched;
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);
free_compex(&cond_compex);
goto getout;
}
matched = (execute(&cond_compex,dest) != Nullch);
if (getbracket(&cond_compex, 0)) /* 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,"%ld",our_pid);
break;
case '#':
s = scrbuf;
sprintf(s,"%d",perform_cnt);
break;
case '?':
s = " ";
line_split = dest;
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;
#ifdef USE_NNTP
sprintf(s,"%s/%s",spool,nntp_artname());
#else
sprintf(s,"%s/%s/%ld",spool,ngdir,(long)art);
#endif
#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 ? extractprog : "-");
break;
case 'E':
s = extractdest;
break;
case 'f': /* from line */
parseheader(art);
if (htype[REPLY_LINE].ht_minpos >= 0 && !comment_parse) {
/* 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':
parseheader(art);
if (htype[FOLLOW_LINE].ht_minpos >= 0)
/* is there a Followup-To line? */
s = follow_buf = fetchlines(art,FOLLOW_LINE);
else
s = ngs_buf = fetchlines(art,NGS_LINE);
break;
case 'h': /* header file name */
s = headname;
break;
case 'H': /* host name in postings */
s = phostname;
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 NEWS_ADMIN
s = newsadmin;
#else
s = "???";
#endif
break;
case 'L': /* login id */
s = loginName;
break;
case 'm': /* current mode */
s = scrbuf;
*s = mode;
s[1] = '\0';
break;
case 'M':
sprintf(scrbuf,"%ld",(long)dmcount);
s = scrbuf;
break;
case 'n': /* newsgroups */
s = ngs_buf = fetchlines(art,NGS_LINE);
break;
case 'N': /* full name */
s = getval("NAME",realname);
break;
case 'o': /* organization */
#ifdef IGNOREORG
s = getval("NEWSORG",orgname);
#else
s = getenv("NEWSORG");
if (s == Nullch)
s = getval("ORGANIZATION",orgname);
#endif
#ifdef ORGFILE
if (*s == '/') {
FILE *ofp = fopen(s,"r");
if (ofp) {
fgets(scrbuf,sizeof scrbuf,ofp);
fclose(ofp);
s = scrbuf+strlen(scrbuf)-1;
if (*s == '\n')
*s = '\0';
s = scrbuf;
}
}
#endif
break;
case 'O':
s = origdir;
break;
case 'p':
s = cwd;
break;
case 'P':
s = spool;
break;
case 'r':
parseheader(art);
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':
parseheader(art);
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 PLUS the
** root article allowed, including the one
** concatenated below */
if ((s = rindex(scrbuf,'<')) > scrbuf) {
*s = '\0';
h = rindex(scrbuf,'<');
*s = '<';
if (h > scrbuf) {
s = index(scrbuf+1,'<');
if (s < h)
strcpy(s,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);
/* 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", TRUE))
*h = '\0';
break;
case 'S':
if (!(s=subj_buf))
s = subj_buf = fetchsubj(art,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':
parseheader(art);
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);
else
s = "noname";
if (*pattern == 'T') {
if (htype[PATH_LINE].ht_minpos >= 0) {
/* should we substitute path? */
s = path_buf = fetchlines(art,PATH_LINE);
}
i = strlen(phostname);
if (strnEQ(phostname,s,i) && s[i] == '!')
s += i + 1;
}
address_parse = TRUE; /* just the good part */
break;
case 'u':
sprintf(scrbuf,"%ld",(long)toread[ng]);
s = scrbuf;
break;
case 'U': {
int unseen;
unseen = (art <= lastart) && !was_read(art);
if (selected_only) {
int selected;
selected = (curr_artp->flags & AF_SEL);
sprintf(scrbuf,"%ld",
(long)selected_count - (selected && unseen));
}
else
sprintf(scrbuf,"%ld",(long)toread[ng] - unseen);
s = scrbuf;
break;
}
case 'v': {
int selected, unseen;
selected = (curr_artp->flags & AF_SEL);
unseen = (art <= lastart) && !was_read(art);
sprintf(scrbuf,"%ld",(long)toread[ng] - selected_count
- (!selected && unseen));
s = scrbuf;
break;
}
case 'W':
s = threaddir;
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;
case 'Z':
sprintf(scrbuf,"%ld",(long)selected_count);
s = scrbuf;
break;
default:
if (--destsize <= 0)
abort_interp();
*dest++ = *pattern | metabit;
s = nullstr;
break;
}
}
if (!s)
s = nullstr;
if (proc_sprintf) {
sprintf(scrbuf,spfbuf,s);
s = scrbuf;
}
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);
}
/* Do we have room left? */
i = strlen(s);
if (destsize <= i)
abort_interp();
destsize -= i; /* adjust the size now. */
/* A maze of twisty little conditions, all alike... */
if (address_parse || comment_parse) {
if (s != scrbuf) {
safecpy(scrbuf,s,(sizeof scrbuf));
s = scrbuf;
}
if (address_parse) {
if ((h=index(s,'<')) != Nullch) { /* grab the good part */
s = h+1;
if ((h=index(s,'>')) != Nullch)
*h = '\0';
} else if ((h=index(s,'(')) != Nullch) {
while (h-- != s && *h == ' ')
;
h[1] = '\0'; /* or strip the comment */
}
} else {
if (!(s = extract_name(s)))
s = nullstr;
}
}
if (metabit) {
/* set meta bit while copying. */
i = metabit; /* maybe get into register */
if (s == dest) {
while (*dest)
*dest++ |= i;
} else {
while (*s)
*dest++ = *s++ | i;
}
} else if (re_quote || tick_quote) {
/* put a backslash before regexp specials while copying. */
if (s == dest) {
/* copy out so we can copy in. */
safecpy(scrbuf, s, sizeof scrbuf);
s = scrbuf;
if (i > sizeof scrbuf) /* we truncated, ack! */
abort_interp();
}
if (tick_quote) {
*dest++ = '\'';
if ((destsize -= 2) <= 0)
abort_interp();
}
while (*s) {
if ((re_quote && index(regexp_specials, *s))
|| (tick_quote && *s == '\'')) {
if (--destsize <= 0)
abort_interp();
*dest++ = '\\';
}
*dest++ = *s++;
}
if (tick_quote)
*dest++ = '\'';
} else {
/* straight copy. */
if (s == dest) {
dest += i;
} else {
while (*s)
*dest++ = *s++;
}
}
}
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';
if (line_split != Nullch)
if (strlen(orig_dest) > 79)
*line_split = '\n';
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 DEBUG
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 == '\t' || *src == '\n' || *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)
long uid;
{
char *s, *c;
#ifdef PASSNAMES
#ifdef HAS_GETPWENT
#ifdef notdef
struct passwd *getpwuid _((uid_t));
#endif
struct passwd *pwd = getpwuid(uid);
if (!pwd)
return nullstr;
s = pwd->pw_gecos;
#else
char tmpbuf[512];
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,loginName); /* 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,s);
#endif
#ifdef HAS_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);
}