/* $Header: intrp.c,v 4.3.1.5 85/05/23 17:21:24 lwall Exp $
* 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
* Revision 4.3.1.1 85/05/10 11:33:51 lwall
* Revision 4.3 85/05/01 11:40:54 lwall
* Baseline for release with 4.3bsd.
char orgname
[] = ORGNAME
;
# define SITENAME hostname
# include <sys/utsname.h>
# define SITENAME uts.nodename
# define SITENAME hostname
# define SITENAME sysname
static char *tildename
= Nullch
;
static char *tildedir
= Nullch
;
char *realname
INIT(Nullch
); /* real name of sender from /etc/passwd */
static void abort_interp();
spool
= savestr(filexp(SPOOL
)); /* usually /usr/spool/news */
/* get environmental stuff */
homedir
= getenv("HOME");
homedir
= getenv("LOGDIR");
dotdir
= getval("DOTDIR",homedir
);
logname
= getenv("USER");
logname
= getenv("LOGNAME");
logname
= savestr(getlogin());
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) */
gethostname(buf
,sizeof buf
);
FILE *pipefp
= popen(PHOSTNAME
,"r");
printf("Can't find hostname\n");
fgets(buf
,sizeof buf
,pipefp
);
buf
[strlen(buf
)-1] = '\0'; /* wipe out newline */
sitename
= savestr(SITENAME
);
/* expand filename via %, ~, and $ interpretation */
/* returns pointer to static area */
/* Note that there is a 1-deep cache of ~name interpretation */
static char filename
[CBUFLEN
];
printf("< %s\n",s
) FLUSH
;
interp(filename
, (sizeof filename
), s
); /* interpret any % escapes */
printf("%% %s\n",filename
) FLUSH
;
if (*s
== '~') { /* does destination start with ~? */
if (!*(++s
) || *s
== '/') {
sprintf(scrbuf
,"%s%s",homedir
,s
);
printf("~ %s\n",scrbuf
) FLUSH
;
for (d
=scrbuf
; isalnum(*s
); s
++,d
++)
if (tildedir
&& strEQ(tildename
,scrbuf
)) {
strcpy(filename
, scrbuf
);
printf("r %s %s\n",tildename
,tildedir
) FLUSH
;
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
);
if (strEQ(newsadmin
,tildename
))
newsuid
= atoi(pwd
->pw_uid
);
#else /* this will run faster, and is less D space */
{ /* just be sure LOGDIRFIELD is correct */
FILE *pfp
= fopen("/etc/passwd","r");
printf(cantopen
,"passwd") FLUSH
;
while (fgets(tmpbuf
,512,pfp
) != Nullch
) {
d
= cpytill(scrbuf
,tmpbuf
,':');
printf("p %s\n",tmpbuf
) FLUSH
;
if (strEQ(scrbuf
,tildename
)) {
if (strEQ(newsadmin
,tildename
))
newsuid
= atoi(index(d
,':')+1);
for (i
=LOGDIRFIELD
-2; i
; i
--) {
tildedir
= savestr(scrbuf
);
fputs("~loginname not implemented.\n",stdout
) FLUSH
;
fputs("~login not impl.\n",stdout
) FLUSH
;
else if (*s
== '$') { /* starts with some env variable? */
for (s
++; isalnum(*s
); s
++) *d
++ = *s
;
printf("$ %s\n",scrbuf
) FLUSH
;
interp(filename
, (sizeof filename
), scrbuf
);
/* this might do some extra '%'s but */
/* that is how the Mercedes Benz */
printf("> %s\n",filename
) FLUSH
;
/* skip interpolations */
skipinterp(pattern
,stoppers
)
while (*pattern
&& (!stoppers
|| !index(stoppers
,*pattern
))) {
printf("skipinterp till %s at %s\n",stoppers
?stoppers
:"",pattern
);
if (*pattern
== '%' && pattern
[1]) {
for (pattern
++; *pattern
&& *pattern
!= '}'; pattern
++)
for (pattern
++; *pattern
&& *pattern
!= ']'; pattern
++)
pattern
= skipinterp(pattern
+1,"!=");
for (pattern
++; *pattern
&& *pattern
!= '?'; pattern
++)
pattern
= skipinterp(pattern
+1,":)");
pattern
= skipinterp(pattern
+1,")");
pattern
= skipinterp(pattern
+1,"`");
pattern
= skipinterp(pattern
+1,"\"");
if (*pattern
== '^' && pattern
[1])
else if (*pattern
== '\\' && pattern
[1])
return pattern
; /* where we left off */
/* interpret interpolations */
dointerp(dest
,destsize
,pattern
,stoppers
)
char *artid_buf
= Nullch
;
char *reply_buf
= Nullch
;
char *follow_buf
= Nullch
;
while (*pattern
&& (!stoppers
|| !index(stoppers
,*pattern
))) {
printf("dointerp till %s at %s\n",stoppers
?stoppers
:"",pattern
);
if (*pattern
== '%' && pattern
[1]) {
if (!index("/?g",pattern
[-2]))
if (pattern
[-2] != 'g') {
if (index("/?",pattern
[-2]))
else if (art_howmuch
== 2)
pattern
= cpytill(scrbuf
,pattern
+1,'}');
if (s
= index(scrbuf
,'-'))
pattern
= cpytill(scrbuf
,pattern
+1,']');
i
= set_line_type(scrbuf
,scrbuf
+strlen(scrbuf
));
s
= line_buf
= fetchlines(art
,i
);
COMPEX
*oldbra_compex
= bra_compex
;
init_compex(&cond_compex
);
pattern
= dointerp(dest
,destsize
,pattern
+1,"!=");
pattern
= cpytill(scrbuf
,pattern
+1,'?');
if (s
= compile(&cond_compex
,scrbuf
,TRUE
,TRUE
)) {
printf("%s: %s\n",scrbuf
,s
) FLUSH
;
pattern
+= strlen(pattern
);
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,":)");
pattern
= skipinterp(pattern
+1,")");
pattern
= skipinterp(pattern
+1,":)");
pattern
= dointerp(dest
,destsize
,pattern
,")");
bra_compex
= oldbra_compex
;
free_compex(&cond_compex
);
pattern
= dointerp(scrbuf
,(sizeof scrbuf
),pattern
+1,"`");
pipefp
= popen(scrbuf
,"r");
len
= fread(scrbuf
,sizeof(char),(sizeof scrbuf
)-1,
printf("\nCan't run %s\n",scrbuf
);
for (s
=scrbuf
; *s
; s
++) {
pattern
= dointerp(scrbuf
,(sizeof scrbuf
),pattern
+1,"\"");
fputs(scrbuf
,stdout
) FLUSH
;
sprintf(s
,"%d",getpid());
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
s
= getbracket(bra_compex
,*pattern
- '0');
sprintf(s
,"%ld",(long)art
);
s
= linkartname
; /* so Eunice people get right file */
sprintf(s
,"%s/%s/%ld",spool
,ngdir
,(long)art
);
sprintf(s
,"%ld",(long)savefrom
);
sprintf(s
,"%s/%s",spool
,ngdir
);
s
= dist_buf
= fetchlines(art
,DIST_LINE
);
case 'f': /* from line */
if (htype
[REPLY_LINE
].ht_minpos
>= 0) {
/* was there a reply line? */
s
= reply_buf
= fetchlines(art
,REPLY_LINE
);
else if (!(s
= from_buf
))
s
= from_buf
= fetchlines(art
,FROM_LINE
);
if (htype
[FOLLOW_LINE
].ht_minpos
>= 0)
/* is there a Followup-To line? */
s
= follow_buf
= fetchlines(art
,FOLLOW_LINE
);
s
= ngs_buf
= fetchlines(art
,NGS_LINE
);
if (h
= instr(s
,"net.general")) {
strcpy(scrbuf
+off
+4,"followup");
safecpy(scrbuf
+off
+12,h
+11,sizeof(scrbuf
));
case 'h': /* header file name */
case 'H': /* host name */
s
= artid_buf
= fetchlines(art
,MESSID_LINE
);
sprintf(scrbuf
,"<%s>",artid_buf
);
case 'I': /* ref article indicator */
sprintf(scrbuf
,"'%s'",indstr
);
case 'l': /* rn library */
case 'm': /* current mode */
sprintf(scrbuf
,"%ld",(long)dmcount
);
case 'n': /* newsgroups */
s
= ngs_buf
= fetchlines(art
,NGS_LINE
);
case 'N': /* full name */
s
= getval("NAME",realname
);
case 'o': /* organization */
s
= getval("ORGANIZATION",orgname
);
FILE *ofp
= fopen(s
,"r");
fgets(scrbuf
,sizeof scrbuf
,ofp
);
if (htype
[REFS_LINE
].ht_minpos
>= 0) {
refs_buf
= fetchlines(art
,REFS_LINE
);
refscpy(scrbuf
,(sizeof scrbuf
),refs_buf
);
if (htype
[REFS_LINE
].ht_minpos
>= 0) {
refs_buf
= fetchlines(art
,REFS_LINE
);
refscpy(scrbuf
,(sizeof scrbuf
),refs_buf
);
artid_buf
= fetchlines(art
,MESSID_LINE
);
safecat(scrbuf
,artid_buf
,sizeof(scrbuf
));
sprintf(tmpbuf
,"<%s>",artid_buf
);
safecat(scrbuf
,tmpbuf
,sizeof(scrbuf
));
s
= subj_buf
= fetchsubj(art
,TRUE
,TRUE
);
while ((*s
=='R'||*s
=='r')&&(s
[1]=='E'||s
[1]=='e')&&s
[2]==':') {
if (h
= instr(s
,"- (nf"))
s
= subj_buf
= fetchsubj(art
,TRUE
,TRUE
);
if ((*s
=='R'||*s
=='r')&&(s
[1]=='E'||s
[1]=='e')&&s
[2]==':') {
if (htype
[REPLY_LINE
].ht_minpos
>= 0) {
/* was there a reply line? */
s
= reply_buf
= fetchlines(art
,REPLY_LINE
);
else if (!(s
= from_buf
))
s
= from_buf
= fetchlines(art
,FROM_LINE
);
if (htype
[PATH_LINE
].ht_minpos
>= 0) {
/* should we substitute path? */
s
= path_buf
= fetchlines(art
,PATH_LINE
);
if (strnEQ(sitename
,s
,i
) && s
[i
] == '!')
if ((h
=index(s
,'(')) != Nullch
)
/* strip garbage from end */
else if ((h
=index(s
,'<')) != Nullch
) {
/* or perhaps from beginning */
if ((h
=index(s
,'>')) != Nullch
)
sprintf(scrbuf
,"%ld",(long)toread
[ng
]);
(long)(((ART_NUM
)toread
[ng
]) - 1 + was_read(art
)));
case 'x': /* news library */
case 'X': /* rn library */
s
= linkartname
; /* so Eunice people get right file */
sprintf(s
,"%ld",(long)art
);
if (stat(s
,&filestat
) < 0)
sprintf(scrbuf
,"%5ld",(long)filestat
.st_size
);
*dest
++ = *pattern
| metabit
;
safecpy(scrbuf
,s
,(sizeof scrbuf
));
if (upper
|| !(t
=rindex(s
,'/')))
while (*t
&& !isalpha(*t
))
i
= metabit
; /* maybe get into register */
if (*pattern
== '^' && pattern
[1]) {
++pattern
; /* skip uparrow */
i
= *pattern
; /* get char into a register */
*dest
++ = '\177' | metabit
;
*dest
++ = i
& 037 | metabit
;
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') {
while (i
< 01000 && *pattern
>= '0' && *pattern
<= '7') {
*dest
++ = i
& 0377 | metabit
;
*dest
++ = '\b' | metabit
;
*dest
++ = '\f' | metabit
;
*dest
++ = '\n' | metabit
;
*dest
++ = '\r' | metabit
;
*dest
++ = '\t' | metabit
;
*dest
++ = *pattern
++ | metabit
;
if (subj_buf
!= Nullch
) /* return any checked out storage */
if (follow_buf
!= Nullch
)
return pattern
; /* where we left off */
interp(dest
,destsize
,pattern
)
dointerp(dest
,destsize
,pattern
,Nullch
);
/* copy a references line, normalizing as we go */
refscpy(dest
,destsize
,src
)
register char *dest
, *src
;
register char *dot
, *at
, *beg
;
while (*src
&& *src
!= ' ' && *src
!= ',') {
sprintf(tmpbuf
,"%s@%s.UUCP",dot
,beg
);
while (*src
&& --destsize
> 0 && (*dest
++ = *src
++) != '>') ;
while (*src
== ' ' || *src
== ',') src
++;
if (*src
&& --destsize
> 0)
/* get the person's real name from /etc/passwd */
/* (string is overwritten, so it must be copied) */
struct passwd
*pwd
= getpwuid(uid
);
for (s
=tmpbuf
, i
=GCOSFIELD
-1; i
; i
--) {
while (*s
&& !isalnum(*s
) && *s
!= '&') s
++;
if ((c
= index(s
, ',')) != Nullch
)
if ((c
= index(s
, ';')) != Nullch
)
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 */
*c
= toupper(*c
); /* gack and double gack */
if ((c
= index(s
, '(')) != Nullch
)
if ((c
= index(s
, '-')) != Nullch
)
return buf
; /* return something static */
if ((tmpfp
=fopen(filexp(FULLNAMEFILE
),"r")) != Nullfp
) {
fgets(buf
,sizeof buf
,tmpfp
);
buf
[strlen(buf
)-1] = '\0';
return "PUT YOUR NAME HERE";
fputs("\n% interp buffer overflow!\n",stdout
) FLUSH
;