|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 14328 (0x37f8)
Types: TextFile
Names: »intrp.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Warp/intrp.c«
/* $Header: intrp.c,v 7.0.1.2 86/12/12 16:59:04 lwall Exp $
*
* $Log: intrp.c,v $
* Revision 7.0.1.2 86/12/12 16:59:04 lwall
* Baseline for net release.
*
* Revision 7.0.1.1 86/10/16 10:51:43 lwall
* Added Damage. Fixed random bugs.
*
* Revision 7.0 86/10/08 15:12:19 lwall
* Split into separate files. Added amoebas and pirates.
*
*/
#include "EXTERN.h"
#include "warp.h"
#include "sig.h"
#include "util.h"
#include "term.h"
#include "INTERN.h"
#include "intrp.h"
/* name of this host */
#ifdef GETHOSTNAME
char *ghostname;
# undef HOSTNAME
# define HOSTNAME ghostname
#else /* !GETHOSTNAME */
# ifdef DOUNAME
# include <sys/utsname.h>
struct utsname uts;
# undef HOSTNAME
# define HOSTNAME uts.nodename
# else /* !DOUNAME */
# ifdef PHOSTNAME
char *ghostname;
# undef HOSTNAME
# define HOSTNAME ghostname
# else /* !PHOSTNAME */
# ifdef WHOAMI
# undef HOSTNAME
# define HOSTNAME sysname
# endif /* WHOAMI */
# endif /* PHOSTNAME */
# endif /* DOUNAME */
#endif /* GETHOSTNAME */
#ifdef TILDENAME
static char *tildename = Nullch;
static char *tildedir = Nullch;
#endif
char *dointerp();
char *getrealname();
#ifdef CONDSUB
char *skipinterp();
#endif
static void abort_interp();
void
intrp_init(tcbuf)
char *tcbuf;
{
char *getlogin();
/* get environmental stuff */
/* 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
/* 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 this host (%H) */
#ifdef GETHOSTNAME
gethostname(buf,sizeof buf);
hostname = savestr(buf);
#else
#ifdef DOUNAME
/* get sysname */
uname(&uts);
#else
#ifdef PHOSTNAME
{
FILE *popen();
FILE *pipefp = popen(PHOSTNAME,"r");
if (pipefp == Nullfp) {
printf("Can't find hostname\r\n");
sig_catcher(0);
}
Fgets(buf,sizeof buf,pipefp);
buf[strlen(buf)-1] = '\0'; /* wipe out newline */
hostname = savestr(buf);
pclose(pipefp);
}
#endif
#endif
#endif
if (index(HOSTNAME,'.'))
hostname = savestr(HOSTNAME);
else {
char hname[128];
strcpy(hname,HOSTNAME);
strcat(hname,MYDOMAIN);
hostname=savestr(hname);
}
warplib = savestr(filexp(WARPLIB));
if (scorespec) /* that getwd below takes ~1/3 sec. */
return; /* and we do not need it for -s */
(void) getwd(tcbuf); /* find working directory name */
origdir = savestr(tcbuf); /* and remember it */
}
/* expand filename via %, ~, and $ interpretation */
/* returns pointer to static area */
/* Note that there is a 1-deep cache of ~name interpretation */
char *
filexp(s)
Reg1 char *s;
{
static char filename[CBUFLEN];
char scrbuf[CBUFLEN];
Reg2 char *d;
#ifdef DEBUGGING
if (debug & DEB_FILEXP)
printf("< %s\r\n",s);
#endif
interp(filename, (sizeof filename), s); /* interpret any % escapes */
#ifdef DEBUGGING
if (debug & DEB_FILEXP)
printf("%% %s\r\n",filename);
#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\r\n",scrbuf);
#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\r\n",tildename,tildedir);
#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");
sig_catcher(0);
}
while (fgets(tmpbuf,512,pfp) != Nullch) {
d = cpytill(scrbuf,tmpbuf,':');
#ifdef DEBUGGING
if (debug & DEB_FILEXP)
printf("p %s\r\n",tmpbuf);
#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.\r\n",stdout);
ELSE
#endif
#ifdef TERSE
fputs("~login not impl.\r\n",stdout);
#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\r\n",scrbuf);
#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\r\n",filename);
#endif
return filename;
}
#ifdef CONDSUB
/* skip interpolations */
char *
skipinterp(pattern,stoppers)
Reg1 char *pattern;
char *stoppers;
{
while (*pattern && (!stoppers || !index(stoppers,*pattern))) {
#ifdef DEBUGGING
if (debug & 8)
printf("skipinterp till %s at %s\r\n",stoppers?stoppers:"",pattern);
#endif
if (*pattern == '%' && pattern[1]) {
switch (*++pattern) {
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)
Reg1 char *dest;
Reg2 int destsize;
Reg3 char *pattern;
char *stoppers;
{
Reg4 char *s;
Reg5 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\r\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 '{':
pattern = cpytill(scrbuf,pattern+1,'}');
if (s = index(scrbuf,'-'))
*s++ = '\0';
else
s = nullstr;
s = getval(scrbuf,s);
break;
#ifdef CONDSUB
case '(': {
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 (*scrbuf == '^' && scrbuf[strlen(scrbuf)-1] == '$') {
scrbuf[strlen(scrbuf)-1] = '\0';
matched = strEQ(scrbuf+1,dest);
}
else
matched = instr(dest,scrbuf) != Nullch;
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;
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("\r\nCan't run %s\r\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);
resetty();
gets(scrbuf);
crmode();
raw();
noecho();
nonl();
s = scrbuf;
break;
#endif
case '~':
s = homedir;
break;
case '.':
s = dotdir;
break;
case '$':
s = scrbuf;
Sprintf(s,"%d",getpid());
break;
case 'H': /* host name */
s = hostname;
break;
case 'L': /* login id */
s = logname;
break;
case 'N': /* full name */
s = getval("NAME",realname);
break;
case 'O':
s = origdir;
break;
case 'p':
s = cwd;
break;
case 'X': /* warp library */
s = warplib;
break;
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:
return pattern; /* where we left off */
}
void
interp(dest,destsize,pattern)
char *dest;
int destsize;
char *pattern;
{
(void) dointerp(dest,destsize,pattern,Nullch);
#ifdef DEBUGGING
if (debug & DEB_FILEXP)
fputs(dest,stdout);
#endif
}
/* 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;
#ifdef PASSNAMES
#ifdef GETPWENT
struct passwd *pwd = getpwuid(uid);
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,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);
}
else {
resetty();
printf("What is your name? ");
Fgets(buf,(sizeof buf),stdin);
crmode();
raw();
noecho();
nonl();
if (fork())
wait(0);
else {
setuid(getuid());
if ((tmpfp = fopen(filexp(FULLNAMEFILE),"w")) == NULL)
exit(1);
fprintf(tmpfp, "%s\n", buf);
Fclose(tmpfp);
exit(0);
}
}
buf[strlen(buf)-1] = '\0';
return buf;
#endif
}
static void
abort_interp()
{
fputs("\r\n% interp buffer overflow!\r\n",stdout);
sig_catcher(0);
}