Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/lib/gen/getenv.c
There are 8 other files named getenv.c in the archive. Click here to see a list.
/* 
** GETENV, PUTENV - Get and put value for environment name
**
**	Copyright (c) 1987 by Ken Harrenstien, SRI International
**
** Original idea of using logical names from:
**	Bill Palmer / Stanford University / November 1984
*/

#include <c-env.h>
#if SYS_T20+SYS_10X+SYS_T10+SYS_CSI+SYS_WTS	/* Systems supported for */

#include <stddef.h>		/* For NULL */
#include <stdlib.h>
#include <string.h>

#if __STDC__
#define CONST const
#else
#define CONST
#endif

#ifndef _MAXENVNAME
#define _MAXENVNAME 40		/* Max size of environment name (less 1) */
#endif

struct evar {
	struct evar *enext;
	char *ename;
	char *evalue;
};

#if (SYS_T20+SYS_10X)
#include <jsys.h>
#include <monsym.h>		/* For term type defs */
#include <ctype.h>		/* For isupper/tolower */

#elif SYS_T10+SYS_CSI+SYS_WTS
#include <muuo.h>
#include <macsym.h>
#include <stdio.h>		/* For sprintf */
#endif

static struct evar *env_list = 0;

static struct evar *iputenv(), *sevterm(), *sevhome();

char *
getenv(name)
CONST char *name;
{
    register struct evar *ep;

    /* Search existing env vars for a match */
    for (ep = env_list; ep; ep = ep->enext) {
	if (strcmp(name, ep->ename)==0)		/* If matched exactly, */
	    return ep->evalue;			/* return value for name! */
    }

    /* No existing match, try to check other sources */
#if SYS_T20
	/* For TOPS-20, we use silly hack of having logical name defs
	** be environment vars.  To avoid conflicts with real device
	** names etc, all such vars have "CENV-" prefixed to the normal
	** variable name.  e.g. "TERM" is looked up as the logical name
	** "CENV-TERM:".
	*/
    {
	register char *cp;
	int acs[5];
	char lognam[5 + _MAXENVNAME];
	char logbuf[1000];		/* Lots of room */

	strncat(strcpy(lognam,"CENV-"), name, _MAXENVNAME-5-1);
	acs[1] = _LNSJB;		/* First try jobwide logical name */
	acs[2] = (int)(lognam-1);	/* Need backed-up BP for jsys */
	acs[3] = (int)(logbuf-1);	/* Store into here */
	logbuf[0] = 0;			/* Ensure buffer starts clear */
	if (jsys(LNMST, acs) == 0) {	/* If jobwide failed, */
	    acs[1] = _LNSSY;		/* then try systemwide */
	    jsys(LNMST, acs);
	}
	if (logbuf[0]) {			/* If we won... */
	    for (cp = logbuf; *cp; ++cp)	/* Convert to lowercase */
		if (isupper(*cp))
		    *cp = tolower(*cp);
	    ep = iputenv(name, logbuf);		/* Store it as env var! */
	    return (ep ? ep->evalue : NULL);	/* and return alloced value */
	}
    }

#elif SYS_CSI
	/* On CSI, try using "global command variables" in a similar fashion,
	** where the prefix is "C$" (short since name length is limited)
	** The string returned in the block will have this format:
	**	"C$VAR :=[=] text-of-variable"
	** The variable names are forced to uppercase, and there may be
	** either one or two equal signs (plus space) separating it from the
	** actual text of the variable.
	** Fortunately, variable text is stored exactly as-is, without case
	** smashing.
	*/
    {
#define NAMEWDS 500
	int i;
	char *cp;
	int bigblk[NAMEWDS];

	bigblk[0] = NAMEWDS-1;
	cp = (char *)(int)(_KCCtype_char7 *)&bigblk[1];	/* 7-bit pointer */
	i = strlen(name);
	if (i > (NAMEWDS-4)*sizeof(int))
	    return NULL;		/* Name too long */
	strcpy(cp, "C$");
	strncpy(cp+2, name, i+6);	/* Ensure last word cleared */
	if (CSIUUO_AC("REDUU$", XWD(-014,(int)bigblk))) {
	    /* Won!  Parse returned string to extract actual text */
	    if ((cp = strstr(cp, ":=")) && (cp = strchr(cp, ' '))) {
		ep = iputenv(name, ++cp);		/* Store as env var! */
		return (ep ? ep->evalue : NULL);	/* and return value */
	    }
	}
    }
#endif

    /* Try checking for specific names which have standard meanings */
    if (strcmp(name, "TERM")==0)	/* TERMCAP terminal type */
	return (ep = sevterm()) ? ep->evalue : 0;
    if (strcmp(name, "HOME")==0)	/* User's home directory */
	return (ep = sevhome()) ? ep->evalue : 0;

    return NULL;			/* Give up, failed */
}
/* PUTENV - based on SYSV description.
**	Argument is a string in "name=value" form.  Adds this to 
** the environment of current process.  Not clear if we want to
** emulate the (vague) SYSV description which indicates that putenv
** may only store a pointer, and the actual string buffer remains under
** user control.
*/
int
putenv(namval)
char *namval;
{
    register char *np, *cp;
    register int i;
    register struct evar *ep, *prep;
    char name[_MAXENVNAME];

    /* Get "name" part isolated in temp buffer (to avoid changing orig str) */
    for (i = _MAXENVNAME, cp = name, np = namval; *np != '=';) {
	if (*np == 0 || --i > 0)	/* If not in name=val format */
	    return -1;			/* then fail */
	*cp++ = *np++;
    }
    *cp = 0;			/* Tie off name string */
    ++np;			/* Point to value string */

    /* Search existing env vars for a match */
    for (ep = env_list, prep = NULL; ep; ep = ep->enext) {
	if (strcmp(name, ep->ename)==0)		/* If matched exactly, */
	    break;				/* stop loop */
	prep = ep;				/* Save previous ptr */
    }

    if (ep == NULL)				/* If didn't find, */
	return (iputenv(name, np) ? 0 : -1);	/* just add it */

    if (strlen(np) <= strlen(ep->evalue)) {	/* If new string small enuf */
	strcpy(ep->evalue, np);			/* just copy over old one */
	return 0;				/* and win! */
    }

    /* Must delete old entry, then add new one */
    if (prep) prep->enext = ep->enext;		/* Unlink from list */
    else env_list = ep->enext;
    free((char *)ep);				/* Free up old struct */
    return (iputenv(name, np) ? 0 : -1);	/* Then add new and return */
}
/* IPUTENV - auxiliary for getenv() and putenv().
**	Takes a name/value pair and strings it into the environment
** variable list.
*/
static struct evar *
iputenv(name, value)
char *name, *value;
{
    register struct evar *ep;
    register int nl, vl;

    nl = strlen(name);
    vl = strlen(value);
    ep = (struct evar *) malloc(sizeof(struct evar) + nl+1 + vl+1);
    if (ep != NULL) {
	ep->ename = (char *)(ep+1);	/* Name starts right after struct */
	ep->evalue = ep->ename + nl+1;	/* Value right after that */
	strcpy(ep->ename, name);	/* Copy the strings */
	strcpy(ep->evalue, value);
	ep->enext = env_list;		/* Link into head of list */
	env_list = ep;
    }
    return ep;		/* NULL or pointer to new linked-in var */
}
/* Auxiliary routines for specific environment names */

/* Find and set HOME variable */
static struct evar *
sevhome()
{
    char buf[500];

#if SYS_T20+SYS_10X
    int acs[5];
    jsys(GJINF, acs);		/* Get user # in AC 1 */
    acs[2] = acs[1];		/* Set up for DIRST% */
#if SYS_T20
    strcpy(buf, "PS:<");	/* on T20 must add punctuation */
    acs[1] = (int) (buf+3);
#else				/* on 10X system adds punct for us */
    acs[1] = (int) (buf-1);
#endif
    if (!jsys(DIRST, acs))
	return NULL;
#if SYS_T20
    strcat((char *)acs[1], ">");
#endif

#elif SYS_T10+SYS_CSI
    int ppn = 0;
    MUUO_ACVAL("GETPPN", 0, &ppn);
    sprintf(buf, "[%o,%o]", FLDGET(ppn, _LHALF), ppn&_RHALF);

#else

    strcpy(buf, "DSK:");	/* Cheat */
#endif

    return iputenv("HOME", buf);
}
/* Find and set TERM variable */

static struct evar *
sevterm()
{
#if SYS_T20+SYS_10X
    register char *str;
    int acs[5];

    acs[1] = _CTTRM;
    jsys(GTTYP, acs);		/* Get our terminal type */
    switch (acs[2]) {
	default:	str = NULL;	break;	/* If don't know type */

#if monsymdefined(".TT33")
	case monsym(".TT33"):	str = "tty33";	break;
#endif
#if monsymdefined(".TT35")
	case monsym(".TT35"):	str = "tty35";	break;
#endif
#if monsymdefined(".TT37")
	case monsym(".TT37"):	str = "tty37";	break;
#endif
#if monsymdefined(".TTEXE")
	case monsym(".TTEXE"):	str = "execuport"; break; /* Probably not in TERMCAP */
#endif
#if monsymdefined(".TTDEF")
	case monsym(".TTDEF"):	str = "DEFAULT";	break;	/* ???? */
#endif
#if monsymdefined(".TTIDL")
	case monsym(".TTIDL"):	str = "IDEAL";	break;		/* ???? */
#endif
#if monsymdefined(".TTV05")
	case monsym(".TTV05"):	str = "vt05";	break;		/* Not in TERMCAP */
#endif
#if monsymdefined(".TTV50")
	case monsym(".TTV50"):	str = "vt50";	break;
#endif
#if monsymdefined(".TTL30")
	case monsym(".TTL30"):	str = "la30";	break;		/* Not in TERMCAP? */
#endif
#if monsymdefined(".TTG40")
	case monsym(".TTG40"):	str = "gt40";	break;
#endif
#if monsymdefined(".TTL36")
	case monsym(".TTL36"):	str = "la36";	break;		/* Not in TERMCAP? */
#endif
#if monsymdefined(".TTV52")
	case monsym(".TTV52"):	str = "vt52";	break;
#endif
#if monsymdefined(".TT100")
	case monsym(".TT100"):	str = "vt100";	break;
#endif
#if monsymdefined(".TTL38")
	case monsym(".TTL38"):	str = "la38";	break;		/* Not in TERMCAP? */
#endif
#if monsymdefined(".TT120")
	case monsym(".TT120"):	str = "la120";	break;
#endif
#if monsymdefined(".TT125")
	case monsym(".TT125"):	str = "vt125";	break;
#endif
#if monsymdefined(".TTK10")
	case monsym(".TTK10"):	str = "gigi";	break;	/* DEC VK100 */
#endif
#if monsymdefined(".TT102")
	case monsym(".TT102"):	str = "vt102";	break;
#endif
#if monsymdefined(".TTH19")
	case monsym(".TTH19"):	str = "h19";	break;
#endif
#if monsymdefined(".TT131")
	case monsym(".TT131"):	str = "vt131";	break;		/* Not in TERMCAP? */
#endif
#if monsymdefined(".TT200")
	case monsym(".TT200"):	str = "vt200";	break;
#endif
#if monsymdefined(".TTADM")
	case monsym(".TTADM"):	str = "adm3a";	break;
#endif
#if monsymdefined(".TTDAM")
	case monsym(".TTDAM"):	str = "dm2500";	break;
#endif
#if monsymdefined(".TTHP")
	case monsym(".TTHP"):	str = "hp2645";	break;
#endif
#if monsymdefined(".TTHAZ")
	case monsym(".TTHAZ"):	str = "h1500";	break;
#endif
#if monsymdefined(".TT43")
	case monsym(".TT43"):	str = "tty43";	break;
#endif
#if monsymdefined(".TTSRC")
	case monsym(".TTSRC"):	str = "soroc";	break;	/* Soroc 120 */
#endif
#if monsymdefined(".TTGIL")
	case monsym(".TTGIL"):	str = "gillotine"; break;	/* Not in TERMCAP? */
#endif
#if monsymdefined(".TTTEL")
	case monsym(".TTTEL"):	str = "t1061";	break;	/* Teleray 1061 */
#endif
#if monsymdefined(".TTTEK")
	case monsym(".TTTEK"):	str = "tek4025";	break;
#endif
#if monsymdefined(".TTANN")
	case monsym(".TTANN"):	str = "aaa";	break;	/* Ann Arbor */
#endif
#if monsymdefined(".TTCPT")
	case monsym(".TTCPT"):	str = "concept100";	break;
#endif
#if monsymdefined(".TTIBM")
	case monsym(".TTIBM"):	str = "ibm3101";	break;	/* IBM 3101-20 */
#endif
#if monsymdefined(".TTTVI")
	case monsym(".TTTVI"):	str = "tvi912";	break;
#endif
#if monsymdefined(".TTTK3")
	case monsym(".TTTK3"):	str = "tek4023";	break;
#endif
#if monsymdefined(".TTDM2")
	case monsym(".TTDM2"):	str = "dm1520";	break;
#endif
#if monsymdefined(".TTAMB")
	case monsym(".TTAMB"):	str = "ambassador";	break;	/* Ann Arbor */
#endif
#if monsymdefined(".TTESP")
	case monsym(".TTESP"):	str = "esprit";	break;	/* Hazeltine */
#endif
#if monsymdefined(".TTFRD")
	case monsym(".TTFRD"):	str = "freedom100";	break;
#endif
#if monsymdefined(".TTFR2")
	case monsym(".TTFR2"):	str = "freedom200";	break;
#endif
#if monsymdefined(".TTANS")
	case monsym(".TTANS"):	str = "ansi";	break;
#endif
#if monsymdefined(".TTAVT")
	case monsym(".TTAVT"):	str = "avt";	break;	/* Concept AVT */
#endif
    }	/* end of switch on terminal type */

    if (str)				/* If found something */
	return iputenv("TERM", str);	/* return that! */
#endif	/* T20+10X */

    return NULL;			/* Fail */
}

#endif /* T20+10X+T10+CSI+WTS */