📄 intrp.c
字号:
/* $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 author 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 "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 TILDENAMEstatic char *tildename = Nullch;static char *tildedir = Nullch;#endif#ifdef CONDSUBchar *skipinterp _((char *,char *));#endifstatic void abort_interp _((void));voidintrp_init(tcbuf)char *tcbuf;{ char *getlogin(); /* 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 */ logname = getenv("USER"); if (logname == Nullch) logname = getenv("LOGNAME");#ifdef GETLOGIN if (logname == Nullch) logname = 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 than load his UID into newsuid */ if ( strEQ(logname,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 logname 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); } 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; register char *s, *h; register int i; char scrbuf[512]; char spfbuf[512]; bool upper = FALSE; bool lastcomp = FALSE; bool re_quote = 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; proc_sprintf = FALSE; for (s=Nullch; !s; ) { switch (*++pattern) { case '^': upper = TRUE; break; case '_': lastcomp = TRUE; break; case '\\': re_quote = 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 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,"%ld",our_pid); break; case '#':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -