File: [local] / src / usr.bin / tip / Attic / value.c (download)
Revision 1.33, Mon Aug 23 19:05:08 2010 UTC (13 years, 9 months ago) by nicm
Branch: MAIN
CVS Tags: OPENBSD_5_7_BASE, OPENBSD_5_7, OPENBSD_5_6_BASE, OPENBSD_5_6, OPENBSD_5_5_BASE, OPENBSD_5_5, OPENBSD_5_4_BASE, OPENBSD_5_4, OPENBSD_5_3_BASE, OPENBSD_5_3, OPENBSD_5_2_BASE, OPENBSD_5_2, OPENBSD_5_1_BASE, OPENBSD_5_1, OPENBSD_5_0_BASE, OPENBSD_5_0, OPENBSD_4_9_BASE, OPENBSD_4_9 Changes since 1.32: +14 -14 lines
Clear options before setting up HOME and SHELL, not after. Fixes parsing
.tiprc reported by nick@.
|
/* $OpenBSD: value.c,v 1.33 2010/08/23 19:05:08 nicm Exp $ */
/* $NetBSD: value.c,v 1.6 1997/02/11 09:24:09 mrg Exp $ */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <paths.h>
#include "tip.h"
/*
* Variable manipulation.
*/
value_t vtable[] = {
{ "beautify", V_BOOL, "be", NULL, 0 },
{ "baudrate", V_NUMBER, "ba", NULL, 0 },
{ "connect", V_STRING|V_READONLY, "cm", NULL, 0 },
{ "device", V_STRING|V_READONLY, "dv", NULL, 0 },
{ "eofread", V_STRING, "eofr", NULL, 0 },
{ "eofwrite", V_STRING, "eofw", NULL, 0 },
{ "eol", V_STRING, NULL, NULL, 0 },
{ "escape", V_CHAR, "es", NULL, 0 },
{ "exceptions", V_STRING, "ex", NULL, 0 },
{ "force", V_CHAR, "fo", NULL, 0 },
{ "framesize", V_NUMBER, "fr", NULL, 0 },
{ "host", V_STRING|V_READONLY, "ho", NULL, 0 },
{ "log", V_STRING, NULL, NULL, 0 },
{ "prompt", V_CHAR, "pr", NULL, 0 },
{ "raise", V_BOOL, "ra", NULL, 0 },
{ "raisechar", V_CHAR, "rc", NULL, 0 },
{ "record", V_STRING, "rec", NULL, 0 },
{ "remote", V_STRING|V_READONLY, NULL, NULL, 0 },
{ "script", V_BOOL, "sc", NULL, 0 },
{ "tabexpand", V_BOOL, "tab", NULL, 0 },
{ "verbose", V_BOOL, "verb", NULL, 0 },
{ "SHELL", V_STRING, NULL, NULL, 0 },
{ "HOME", V_STRING, NULL, NULL, 0 },
{ "echocheck", V_BOOL, "ec", NULL, 0 },
{ "disconnect", V_STRING, "di", NULL, 0 },
{ "tandem", V_BOOL, "ta", NULL, 0 },
{ "linedelay", V_NUMBER, "ldelay", NULL, 0 },
{ "chardelay", V_NUMBER, "cdelay", NULL, 0 },
{ "etimeout", V_NUMBER, "et", NULL, 0 },
{ "rawftp", V_BOOL, "raw", NULL, 0 },
{ "halfduplex", V_BOOL, "hdx", NULL, 0 },
{ "localecho", V_BOOL, "le", NULL, 0 },
{ "parity", V_STRING, "par", NULL, 0 },
{ "hardwareflow", V_BOOL, "hf", NULL, 0 },
{ "linedisc", V_NUMBER, "ld", NULL, 0 },
{ "direct", V_BOOL, "dc", NULL, 0 },
{ NULL, 0, NULL, NULL, 0 },
};
static int vlookup(char *);
static void vtoken(char *);
static size_t vprint(value_t *);
static void vprintall(void);
static char *vinterp(char *, int);
/* Get a string value. */
char *
vgetstr(int value)
{
value_t *vp = &vtable[value];
int type;
type = vp->v_flags & V_TYPEMASK;
if (type != V_STRING)
errx(1, "variable %s not a string", vp->v_name);
return (vp->v_string);
}
/* Get a number value. */
int
vgetnum(int value)
{
value_t *vp = &vtable[value];
int type;
type = vp->v_flags & V_TYPEMASK;
if (type != V_NUMBER && type != V_BOOL && type != V_CHAR)
errx(1, "variable %s not a number", vp->v_name);
return (vp->v_number);
}
/* Set a string value. */
void
vsetstr(int value, char *string)
{
value_t *vp = &vtable[value];
int type;
type = vp->v_flags & V_TYPEMASK;
if (type != V_STRING)
errx(1, "variable %s not a string", vp->v_name);
if (value == RECORD && string != NULL)
string = expand(string);
free(vp->v_string);
if (string != NULL) {
vp->v_string = strdup(string);
if (vp->v_string == NULL)
err(1, "strdup");
} else
vp->v_string = NULL;
}
/* Set a number value. */
void
vsetnum(int value, int number)
{
value_t *vp = &vtable[value];
int type;
type = vp->v_flags & V_TYPEMASK;
if (type != V_NUMBER && type != V_BOOL && type != V_CHAR)
errx(1, "variable %s not a number", vp->v_name);
vp->v_number = number;
}
/* Print a single variable and its value. */
static size_t
vprint(value_t *p)
{
char *cp;
size_t width;
width = size(p->v_name);
switch (p->v_flags & V_TYPEMASK) {
case V_BOOL:
if (!p->v_number) {
width++;
putchar('!');
}
printf("%s", p->v_name);
break;
case V_STRING:
printf("%s=", p->v_name);
width++;
if (p->v_string) {
cp = interp(p->v_string);
width += size(cp);
printf("%s", cp);
}
break;
case V_NUMBER:
width += 6;
printf("%s=%-5d", p->v_name, p->v_number);
break;
case V_CHAR:
printf("%s=", p->v_name);
width++;
if (p->v_number) {
cp = ctrl(p->v_number);
width += size(cp);
printf("%s", cp);
}
break;
}
return (width);
}
/* Print all variables. */
static void
vprintall(void)
{
value_t *vp;
size_t width;
#define MIDDLE 35
width = 0;
for (vp = vtable; vp->v_name; vp++) {
if (vp->v_flags & V_READONLY)
continue;
if (width > 0 && width < MIDDLE) {
while (width++ < MIDDLE)
putchar(' ');
}
width += vprint(vp);
if (width > MIDDLE) {
printf("\r\n");
width = 0;
}
}
#undef MIDDLE
}
/* Find index of variable by name or abbreviation. */
static int
vlookup(char *s)
{
value_t *vp;
u_int i;
for (i = 0; vtable[i].v_name != NULL; i++) {
vp = &vtable[i];
if (strcmp(vp->v_name, s) == 0 ||
(vp->v_abbrev != NULL && strcmp(vp->v_abbrev, s) == 0))
return (i);
}
return (-1);
}
void
vinit(void)
{
struct passwd *pw;
value_t *vp;
char file[FILENAME_MAX], *cp;
int written;
FILE *fp;
/* Clear the table and set the defaults. */
for (vp = vtable; vp->v_name != NULL; vp++) {
vp->v_string = NULL;
vp->v_number = 0;
}
vsetnum(BEAUTIFY, 1);
vsetnum(ESCAPE, '~');
vsetnum(FORCE, CTRL('p'));
vsetnum(PROMPT, '\n');
vsetnum(TAND, 1);
vsetnum(VERBOSE, 1);
vsetstr(LOG, _PATH_ACULOG);
/* Read environment variables. */
if ((cp = getenv("HOME")) != NULL)
vsetstr(HOME, cp);
else {
pw = getpwuid(getuid());
if (pw != NULL && pw->pw_dir != NULL)
vsetstr(HOME, pw->pw_dir);
else
vsetstr(HOME, "/");
}
if ((cp = getenv("SHELL")) != NULL)
vsetstr(SHELL, cp);
else
vsetstr(SHELL, _PATH_BSHELL);
/* Read the .tiprc file in the HOME directory. */
written = snprintf(file, sizeof(file), "%s/.tiprc", vgetstr(HOME));
if (written < 0 || written >= sizeof(file)) {
(void)fprintf(stderr, "Home directory path too long: %s\n",
vgetstr(HOME));
} else {
if ((fp = fopen(file, "r")) != NULL) {
char *tp;
while (fgets(file, sizeof(file), fp) != NULL) {
if (vflag)
printf("set %s", file);
if ((tp = strrchr(file, '\n')))
*tp = '\0';
vlex(file);
}
fclose(fp);
}
}
}
void
vlex(char *s)
{
char *cp;
if (strcmp(s, "all") == 0)
vprintall();
else {
do {
if ((cp = vinterp(s, ' ')))
cp++;
vtoken(s);
s = cp;
} while (s);
}
}
/* Set a variable from a token. */
static void
vtoken(char *s)
{
value_t *vp;
int i, value;
char *cp;
const char *cause;
if ((cp = strchr(s, '='))) {
*cp = '\0';
if ((i = vlookup(s)) != -1) {
vp = &vtable[i];
if (vp->v_flags & V_READONLY) {
printf("access denied\r\n");
return;
}
cp++;
switch (vp->v_flags & V_TYPEMASK) {
case V_STRING:
vsetstr(i, cp);
break;
case V_BOOL:
vsetnum(i, 1);
break;
case V_NUMBER:
value = strtonum(cp, 0, INT_MAX, &cause);
if (cause != NULL) {
printf("%s: number %s\r\n", s, cause);
return;
}
vsetnum(i, value);
break;
case V_CHAR:
if (cp[0] != '\0' && cp[1] != '\0') {
printf("%s: character too big\r\n", s);
return;
}
vsetnum(i, *cp);
}
vp->v_flags |= V_CHANGED;
return;
}
} else if ((cp = strchr(s, '?'))) {
*cp = '\0';
if ((i = vlookup(s)) != -1) {
if (vprint(&vtable[i]) > 0)
printf("\r\n");
return;
}
} else {
if (*s != '!')
i = vlookup(s);
else
i = vlookup(s + 1);
if (i != -1) {
vp = &vtable[i];
if (vp->v_flags & V_READONLY) {
printf("%s: access denied\r\n", s);
return;
}
if ((vp->v_flags & V_TYPEMASK) != V_BOOL) {
printf("%s: not a boolean\r\n", s);
return;
}
vsetnum(i, *s != '!');
vp->v_flags |= V_CHANGED;
return;
}
}
printf("%s: unknown variable\r\n", s);
}
static char *
vinterp(char *s, int stop)
{
char *p = s, c;
int num;
while ((c = *s++) && c != stop) {
switch (c) {
case '^':
if (*s)
*p++ = *s++ - 0100;
else
*p++ = c;
break;
case '\\':
num = 0;
c = *s++;
if (c >= '0' && c <= '7')
num = (num<<3)+(c-'0');
else {
char *q = "n\nr\rt\tb\bf\f";
for (; *q; q++)
if (c == *q++) {
*p++ = *q;
goto cont;
}
*p++ = c;
cont:
break;
}
if ((c = *s++) >= '0' && c <= '7') {
num = (num<<3)+(c-'0');
if ((c = *s++) >= '0' && c <= '7')
num = (num<<3)+(c-'0');
else
s--;
} else
s--;
*p++ = num;
break;
default:
*p++ = c;
}
}
*p = '\0';
return (c == stop ? s-1 : NULL);
}