Home | History | Annotate | Line # | Download | only in kern
subr_userconf.c revision 1.23
      1  1.23  uebayasi /*	$NetBSD: subr_userconf.c,v 1.23 2011/05/26 04:25:27 uebayasi Exp $	*/
      2   1.1  gmcgarry 
      3   1.1  gmcgarry /*
      4   1.1  gmcgarry  * Copyright (c) 1996 Mats O Jansson <moj (at) stacken.kth.se>
      5   1.1  gmcgarry  * All rights reserved.
      6   1.1  gmcgarry  *
      7   1.1  gmcgarry  * Redistribution and use in source and binary forms, with or without
      8   1.1  gmcgarry  * modification, are permitted provided that the following conditions
      9   1.1  gmcgarry  * are met:
     10   1.1  gmcgarry  * 1. Redistributions of source code must retain the above copyright
     11   1.1  gmcgarry  *    notice, this list of conditions and the following disclaimer.
     12   1.1  gmcgarry  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1  gmcgarry  *    notice, this list of conditions and the following disclaimer in the
     14   1.1  gmcgarry  *    documentation and/or other materials provided with the distribution.
     15   1.1  gmcgarry  *
     16   1.1  gmcgarry  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     17   1.1  gmcgarry  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18   1.1  gmcgarry  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19   1.1  gmcgarry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     20   1.1  gmcgarry  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21   1.1  gmcgarry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22   1.1  gmcgarry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23   1.1  gmcgarry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24   1.1  gmcgarry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25   1.1  gmcgarry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26   1.1  gmcgarry  * SUCH DAMAGE.
     27   1.1  gmcgarry  *
     28   1.1  gmcgarry  *	OpenBSD: subr_userconf.c,v 1.19 2000/01/08 23:23:37 d Exp
     29   1.1  gmcgarry  */
     30   1.5     lukem 
     31   1.5     lukem #include <sys/cdefs.h>
     32  1.23  uebayasi __KERNEL_RCSID(0, "$NetBSD: subr_userconf.c,v 1.23 2011/05/26 04:25:27 uebayasi Exp $");
     33   1.1  gmcgarry 
     34   1.1  gmcgarry #include "opt_userconf.h"
     35   1.1  gmcgarry 
     36   1.1  gmcgarry #include <sys/param.h>
     37   1.1  gmcgarry #include <sys/systm.h>
     38   1.1  gmcgarry #include <sys/device.h>
     39   1.1  gmcgarry #include <sys/time.h>
     40  1.23  uebayasi #include <sys/userconf.h>
     41   1.1  gmcgarry 
     42   1.1  gmcgarry #include <dev/cons.h>
     43   1.1  gmcgarry 
     44   1.1  gmcgarry extern struct cfdata cfdata[];
     45   1.1  gmcgarry 
     46  1.15   thorpej static int userconf_base = 16;			/* Base for "large" numbers */
     47  1.15   thorpej static int userconf_maxdev = -1;		/* # of used device slots   */
     48  1.15   thorpej static int userconf_totdev = -1;		/* # of device slots        */
     49  1.15   thorpej #if 0
     50  1.15   thorpej static int userconf_maxlocnames = -1;		/* # of locnames            */
     51  1.15   thorpej #endif
     52  1.15   thorpej static int userconf_cnt = -1;			/* Line counter for ...     */
     53  1.15   thorpej static int userconf_lines = 12;			/* ... # of lines per page  */
     54  1.15   thorpej static int userconf_histlen = 0;
     55  1.15   thorpej static int userconf_histcur = 0;
     56  1.15   thorpej static char userconf_history[1024];
     57  1.15   thorpej static int userconf_histsz = sizeof(userconf_history);
     58  1.15   thorpej static char userconf_argbuf[40];		/* Additional input         */
     59  1.15   thorpej static char userconf_cmdbuf[40];		/* Command line             */
     60  1.15   thorpej static char userconf_histbuf[40];
     61   1.1  gmcgarry 
     62  1.11  junyoung static int getsn(char *, int);
     63   1.1  gmcgarry 
     64   1.1  gmcgarry #define UC_CHANGE 'c'
     65   1.1  gmcgarry #define UC_DISABLE 'd'
     66   1.1  gmcgarry #define UC_ENABLE 'e'
     67   1.1  gmcgarry #define UC_FIND 'f'
     68   1.1  gmcgarry #define UC_SHOW 's'
     69   1.1  gmcgarry 
     70  1.15   thorpej static const char *userconf_cmds[] = {
     71   1.1  gmcgarry 	"base",		"b",
     72   1.1  gmcgarry 	"change",	"c",
     73   1.1  gmcgarry 	"disable",	"d",
     74   1.1  gmcgarry 	"enable",	"e",
     75   1.1  gmcgarry 	"exit",		"q",
     76   1.1  gmcgarry 	"find",		"f",
     77   1.1  gmcgarry 	"help",		"h",
     78   1.1  gmcgarry 	"list",		"l",
     79   1.1  gmcgarry 	"lines",	"L",
     80   1.1  gmcgarry 	"quit",		"q",
     81   1.1  gmcgarry 	"?",		"h",
     82   1.1  gmcgarry 	"",		 "",
     83   1.1  gmcgarry };
     84   1.1  gmcgarry 
     85  1.23  uebayasi void
     86  1.15   thorpej userconf_init(void)
     87   1.1  gmcgarry {
     88   1.1  gmcgarry 	int i;
     89   1.1  gmcgarry 	struct cfdata *cf;
     90   1.1  gmcgarry 
     91   1.1  gmcgarry 	i = 0;
     92   1.8   thorpej 	for (cf = cfdata; cf->cf_name; cf++)
     93   1.1  gmcgarry 		i++;
     94   1.1  gmcgarry 
     95   1.1  gmcgarry 	userconf_maxdev = i - 1;
     96   1.1  gmcgarry 	userconf_totdev = i - 1;
     97  1.23  uebayasi 
     98  1.23  uebayasi #ifdef __HAVE_USERCONF_BOOTINFO
     99  1.23  uebayasi 	userconf_bootinfo();
    100  1.23  uebayasi #endif
    101   1.1  gmcgarry }
    102   1.1  gmcgarry 
    103  1.15   thorpej static int
    104  1.15   thorpej userconf_more(void)
    105   1.1  gmcgarry {
    106   1.1  gmcgarry 	int quit = 0;
    107   1.1  gmcgarry 	char c = '\0';
    108   1.1  gmcgarry 
    109   1.1  gmcgarry 	if (userconf_cnt != -1) {
    110   1.1  gmcgarry 		if (userconf_cnt == userconf_lines) {
    111   1.1  gmcgarry 			printf("-- more --");
    112   1.1  gmcgarry 			c = cngetc();
    113   1.1  gmcgarry 			userconf_cnt = 0;
    114   1.1  gmcgarry 			printf("\r            \r");
    115   1.1  gmcgarry 		}
    116   1.1  gmcgarry 		userconf_cnt++;
    117   1.1  gmcgarry 		if (c == 'q' || c == 'Q')
    118   1.1  gmcgarry 			quit = 1;
    119   1.1  gmcgarry 	}
    120   1.1  gmcgarry 	return (quit);
    121   1.1  gmcgarry }
    122   1.1  gmcgarry 
    123  1.15   thorpej static void
    124  1.15   thorpej userconf_hist_cmd(char cmd)
    125   1.1  gmcgarry {
    126   1.1  gmcgarry 	userconf_histcur = userconf_histlen;
    127   1.1  gmcgarry 	if (userconf_histcur < userconf_histsz) {
    128   1.1  gmcgarry 		userconf_history[userconf_histcur] = cmd;
    129   1.1  gmcgarry 		userconf_histcur++;
    130   1.1  gmcgarry 	}
    131   1.1  gmcgarry }
    132   1.1  gmcgarry 
    133  1.15   thorpej static void
    134  1.15   thorpej userconf_hist_int(int val)
    135   1.1  gmcgarry {
    136  1.12    itojun 	snprintf(userconf_histbuf, sizeof(userconf_histbuf), " %d", val);
    137   1.1  gmcgarry 	if ((userconf_histcur + strlen(userconf_histbuf)) < userconf_histsz) {
    138   1.4   thorpej 		memcpy(&userconf_history[userconf_histcur],
    139   1.4   thorpej 		      userconf_histbuf,
    140   1.1  gmcgarry 		      strlen(userconf_histbuf));
    141   1.1  gmcgarry 		userconf_histcur = userconf_histcur + strlen(userconf_histbuf);
    142   1.1  gmcgarry 	}
    143   1.1  gmcgarry }
    144   1.1  gmcgarry 
    145  1.15   thorpej static void
    146  1.15   thorpej userconf_hist_eoc(void)
    147   1.1  gmcgarry {
    148   1.1  gmcgarry 	if (userconf_histcur < userconf_histsz) {
    149   1.1  gmcgarry 		userconf_history[userconf_histcur] = '\n';
    150   1.1  gmcgarry 		userconf_histcur++;
    151   1.1  gmcgarry 		userconf_histlen = userconf_histcur;
    152   1.1  gmcgarry 	}
    153   1.1  gmcgarry }
    154   1.1  gmcgarry 
    155  1.15   thorpej static void
    156  1.15   thorpej userconf_pnum(int val)
    157   1.1  gmcgarry {
    158   1.1  gmcgarry 	if (val > -2 && val < 16) {
    159   1.1  gmcgarry 		printf("%d",val);
    160   1.1  gmcgarry 	} else {
    161   1.1  gmcgarry 		switch (userconf_base) {
    162   1.1  gmcgarry 		case 8:
    163   1.1  gmcgarry 			printf("0%o",val);
    164   1.1  gmcgarry 			break;
    165   1.1  gmcgarry 		case 10:
    166   1.1  gmcgarry 			printf("%d",val);
    167   1.1  gmcgarry 			break;
    168   1.1  gmcgarry 		case 16:
    169   1.1  gmcgarry 		default:
    170   1.1  gmcgarry 			printf("0x%x",val);
    171   1.1  gmcgarry 			break;
    172   1.1  gmcgarry 		}
    173   1.1  gmcgarry 	}
    174   1.1  gmcgarry }
    175   1.1  gmcgarry 
    176  1.15   thorpej static void
    177  1.15   thorpej userconf_pdevnam(short dev)
    178   1.1  gmcgarry {
    179   1.1  gmcgarry 	struct cfdata *cd;
    180   1.1  gmcgarry 
    181   1.1  gmcgarry 	cd = &cfdata[dev];
    182   1.8   thorpej 	printf("%s", cd->cf_name);
    183   1.1  gmcgarry 	switch (cd->cf_fstate) {
    184   1.1  gmcgarry 	case FSTATE_NOTFOUND:
    185   1.1  gmcgarry 	case FSTATE_DNOTFOUND:
    186   1.1  gmcgarry 		printf("%d", cd->cf_unit);
    187   1.1  gmcgarry 		break;
    188   1.1  gmcgarry 	case FSTATE_FOUND:
    189   1.1  gmcgarry 		printf("*FOUND*");
    190   1.1  gmcgarry 		break;
    191   1.1  gmcgarry 	case FSTATE_STAR:
    192   1.1  gmcgarry 	case FSTATE_DSTAR:
    193   1.1  gmcgarry 		printf("*");
    194   1.1  gmcgarry 		break;
    195   1.1  gmcgarry 	default:
    196   1.1  gmcgarry 		printf("*UNKNOWN*");
    197   1.1  gmcgarry 		break;
    198   1.1  gmcgarry 	}
    199   1.1  gmcgarry }
    200   1.1  gmcgarry 
    201  1.15   thorpej static void
    202  1.15   thorpej userconf_pdev(short devno)
    203   1.1  gmcgarry {
    204   1.1  gmcgarry 	struct cfdata *cd;
    205   1.7   thorpej 	const struct cfparent *cfp;
    206   1.1  gmcgarry 	int   *l;
    207  1.16  drochner 	const struct cfiattrdata *ia;
    208  1.16  drochner 	const struct cflocdesc *ld;
    209  1.16  drochner 	int nld, i;
    210   1.1  gmcgarry 
    211   1.1  gmcgarry 	if (devno > userconf_maxdev) {
    212   1.1  gmcgarry 		printf("Unknown devno (max is %d)\n", userconf_maxdev);
    213   1.1  gmcgarry 		return;
    214   1.1  gmcgarry 	}
    215   1.1  gmcgarry 
    216   1.1  gmcgarry 	cd = &cfdata[devno];
    217   1.1  gmcgarry 
    218   1.1  gmcgarry 	printf("[%3d] ", devno);
    219   1.1  gmcgarry 	userconf_pdevnam(devno);
    220   1.1  gmcgarry 	printf(" at");
    221   1.7   thorpej 	cfp = cd->cf_pspec;
    222   1.7   thorpej 	if (cfp == NULL)
    223   1.1  gmcgarry 		printf(" root");
    224   1.7   thorpej 	else if (cfp->cfp_parent != NULL && cfp->cfp_unit != -1)
    225   1.7   thorpej 		printf(" %s%d", cfp->cfp_parent, cfp->cfp_unit);
    226   1.7   thorpej 	else
    227   1.7   thorpej 		printf(" %s?", cfp->cfp_parent != NULL ? cfp->cfp_parent
    228   1.7   thorpej 						       : cfp->cfp_iattr);
    229   1.1  gmcgarry 	switch (cd->cf_fstate) {
    230   1.1  gmcgarry 	case FSTATE_NOTFOUND:
    231   1.1  gmcgarry 	case FSTATE_FOUND:
    232   1.1  gmcgarry 	case FSTATE_STAR:
    233   1.1  gmcgarry 		break;
    234   1.1  gmcgarry 	case FSTATE_DNOTFOUND:
    235   1.1  gmcgarry 	case FSTATE_DSTAR:
    236   1.1  gmcgarry 		printf(" disable");
    237   1.1  gmcgarry 		break;
    238   1.1  gmcgarry 	default:
    239   1.1  gmcgarry 		printf(" ???");
    240   1.1  gmcgarry 		break;
    241   1.1  gmcgarry 	}
    242  1.16  drochner 	if (cfp) {
    243  1.16  drochner 		l = cd->cf_loc;
    244  1.16  drochner 		ia = cfiattr_lookup(cfp->cfp_iattr, 0);
    245  1.16  drochner 		KASSERT(ia);
    246  1.16  drochner 		ld = ia->ci_locdesc;
    247  1.16  drochner 		nld = ia->ci_loclen;
    248  1.16  drochner 		for (i = 0; i < nld; i++) {
    249  1.16  drochner 			printf(" %s ", ld[i].cld_name);
    250  1.17  drochner 			if (!ld[i].cld_defaultstr
    251  1.17  drochner 			    || (l[i] != ld[i].cld_default))
    252  1.17  drochner 				userconf_pnum(l[i]);
    253  1.17  drochner 			else
    254  1.17  drochner 				printf("?");
    255  1.16  drochner 		}
    256   1.1  gmcgarry 	}
    257   1.1  gmcgarry 	printf("\n");
    258   1.1  gmcgarry }
    259   1.1  gmcgarry 
    260  1.15   thorpej static int
    261  1.15   thorpej userconf_number(char *c, int *val)
    262   1.1  gmcgarry {
    263   1.1  gmcgarry 	u_int num = 0;
    264   1.1  gmcgarry 	int neg = 0;
    265   1.1  gmcgarry 	int base = 10;
    266   1.1  gmcgarry 
    267   1.1  gmcgarry 	if (*c == '-') {
    268   1.1  gmcgarry 		neg = 1;
    269   1.1  gmcgarry 		c++;
    270   1.1  gmcgarry 	}
    271   1.1  gmcgarry 	if (*c == '0') {
    272   1.1  gmcgarry 		base = 8;
    273   1.1  gmcgarry 		c++;
    274   1.1  gmcgarry 		if (*c == 'x' || *c == 'X') {
    275   1.1  gmcgarry 			base = 16;
    276   1.1  gmcgarry 			c++;
    277   1.1  gmcgarry 		}
    278   1.1  gmcgarry 	}
    279   1.1  gmcgarry 	while (*c != '\n' && *c != '\t' && *c != ' ' && *c != '\0') {
    280   1.1  gmcgarry 		u_char cc = *c;
    281   1.1  gmcgarry 
    282   1.1  gmcgarry 		if (cc >= '0' && cc <= '9')
    283   1.1  gmcgarry 			cc = cc - '0';
    284   1.1  gmcgarry 		else if (cc >= 'a' && cc <= 'f')
    285   1.1  gmcgarry 			cc = cc - 'a' + 10;
    286   1.1  gmcgarry 		else if (cc >= 'A' && cc <= 'F')
    287   1.1  gmcgarry 			cc = cc - 'A' + 10;
    288   1.1  gmcgarry 		else
    289   1.1  gmcgarry 			return (-1);
    290   1.1  gmcgarry 
    291   1.1  gmcgarry 		if (cc > base)
    292   1.1  gmcgarry 			return (-1);
    293   1.1  gmcgarry 		num = num * base + cc;
    294   1.1  gmcgarry 		c++;
    295   1.1  gmcgarry 	}
    296   1.1  gmcgarry 
    297   1.1  gmcgarry 	if (neg && num > INT_MAX)	/* overflow */
    298   1.1  gmcgarry 		return (1);
    299   1.1  gmcgarry 	*val = neg ? - num : num;
    300   1.1  gmcgarry 	return (0);
    301   1.1  gmcgarry }
    302   1.1  gmcgarry 
    303  1.15   thorpej static int
    304  1.15   thorpej userconf_device(char *cmd, int *len, short *unit, short *state)
    305   1.1  gmcgarry {
    306   1.1  gmcgarry 	short u = 0, s = FSTATE_FOUND;
    307   1.1  gmcgarry 	int l = 0;
    308   1.1  gmcgarry 	char *c;
    309   1.1  gmcgarry 
    310   1.1  gmcgarry 	c = cmd;
    311   1.1  gmcgarry 	while (*c >= 'a' && *c <= 'z') {
    312   1.1  gmcgarry 		l++;
    313   1.1  gmcgarry 		c++;
    314   1.1  gmcgarry 	}
    315   1.1  gmcgarry 	if (*c == '*') {
    316   1.1  gmcgarry 		s = FSTATE_STAR;
    317   1.1  gmcgarry 		c++;
    318   1.1  gmcgarry 	} else {
    319   1.1  gmcgarry 		while (*c >= '0' && *c <= '9') {
    320   1.1  gmcgarry 			s = FSTATE_NOTFOUND;
    321   1.1  gmcgarry 			u = u*10 + *c - '0';
    322   1.1  gmcgarry 			c++;
    323   1.1  gmcgarry 		}
    324   1.1  gmcgarry 	}
    325   1.1  gmcgarry 	while (*c == ' ' || *c == '\t' || *c == '\n')
    326   1.1  gmcgarry 		c++;
    327   1.1  gmcgarry 
    328   1.1  gmcgarry 	if (*c == '\0') {
    329   1.1  gmcgarry 		*len = l;
    330   1.1  gmcgarry 		*unit = u;
    331   1.1  gmcgarry 		*state = s;
    332   1.1  gmcgarry 		return(0);
    333   1.1  gmcgarry 	}
    334   1.1  gmcgarry 
    335   1.1  gmcgarry 	return(-1);
    336   1.1  gmcgarry }
    337   1.1  gmcgarry 
    338  1.15   thorpej static void
    339  1.17  drochner userconf_modify(const struct cflocdesc *item, int *val)
    340   1.1  gmcgarry {
    341   1.1  gmcgarry 	int ok = 0;
    342   1.1  gmcgarry 	int a;
    343   1.1  gmcgarry 	char *c;
    344   1.1  gmcgarry 
    345   1.1  gmcgarry 	while (!ok) {
    346  1.17  drochner 		printf("%s [", item->cld_name);
    347  1.17  drochner 		if (item->cld_defaultstr && (*val == item->cld_default))
    348  1.17  drochner 			printf("?");
    349  1.17  drochner 		else
    350  1.17  drochner 			userconf_pnum(*val);
    351   1.1  gmcgarry 		printf("] ? ");
    352   1.1  gmcgarry 
    353  1.10    simonb 		getsn(userconf_argbuf, sizeof(userconf_argbuf));
    354   1.1  gmcgarry 
    355   1.1  gmcgarry 		c = userconf_argbuf;
    356   1.1  gmcgarry 		while (*c == ' ' || *c == '\t' || *c == '\n') c++;
    357   1.1  gmcgarry 
    358   1.1  gmcgarry 		if (*c != '\0') {
    359  1.17  drochner 			if (*c == '?') {
    360  1.17  drochner 				if (item->cld_defaultstr) {
    361  1.17  drochner 					*val = item->cld_default;
    362  1.17  drochner 					ok = 1;
    363  1.17  drochner 				} else
    364  1.17  drochner 					printf("No default\n");
    365  1.17  drochner 			} else if (userconf_number(c, &a) == 0) {
    366   1.1  gmcgarry 				*val = a;
    367   1.1  gmcgarry 				ok = 1;
    368   1.1  gmcgarry 			} else {
    369   1.1  gmcgarry 				printf("Unknown argument\n");
    370   1.1  gmcgarry 			}
    371   1.1  gmcgarry 		} else {
    372   1.1  gmcgarry 			ok = 1;
    373   1.1  gmcgarry 		}
    374   1.1  gmcgarry 	}
    375   1.1  gmcgarry }
    376   1.1  gmcgarry 
    377  1.15   thorpej static void
    378  1.15   thorpej userconf_change(int devno)
    379   1.1  gmcgarry {
    380   1.1  gmcgarry 	struct cfdata *cd;
    381   1.1  gmcgarry 	char c = '\0';
    382   1.1  gmcgarry 	int   *l;
    383   1.1  gmcgarry 	int   ln;
    384  1.16  drochner 	const struct cfiattrdata *ia;
    385  1.16  drochner 	const struct cflocdesc *ld;
    386  1.16  drochner 	int nld;
    387   1.1  gmcgarry 
    388   1.1  gmcgarry 	if (devno <=  userconf_maxdev) {
    389   1.1  gmcgarry 
    390   1.1  gmcgarry 		userconf_pdev(devno);
    391   1.1  gmcgarry 
    392   1.1  gmcgarry 		while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
    393   1.1  gmcgarry 			printf("change (y/n) ?");
    394   1.1  gmcgarry 			c = cngetc();
    395   1.1  gmcgarry 			printf("\n");
    396   1.1  gmcgarry 		}
    397   1.1  gmcgarry 
    398   1.1  gmcgarry 		if (c == 'y' || c == 'Y') {
    399  1.13     perry 
    400   1.1  gmcgarry 			/* XXX add cmd 'c' <devno> */
    401   1.1  gmcgarry 			userconf_hist_cmd('c');
    402   1.1  gmcgarry 			userconf_hist_int(devno);
    403  1.13     perry 
    404   1.1  gmcgarry 			cd = &cfdata[devno];
    405   1.1  gmcgarry 			l = cd->cf_loc;
    406  1.16  drochner 			ia = cfiattr_lookup(cd->cf_pspec->cfp_iattr, 0);
    407  1.16  drochner 			KASSERT(ia);
    408  1.16  drochner 			ld = ia->ci_locdesc;
    409  1.16  drochner 			nld = ia->ci_loclen;
    410   1.1  gmcgarry 
    411  1.16  drochner 			for (ln = 0; ln < nld; ln++)
    412   1.1  gmcgarry 			{
    413  1.17  drochner 				userconf_modify(&ld[ln], l);
    414  1.13     perry 
    415   1.1  gmcgarry 				/* XXX add *l */
    416   1.1  gmcgarry 				userconf_hist_int(*l);
    417  1.13     perry 
    418   1.1  gmcgarry 				l++;
    419   1.1  gmcgarry 			}
    420   1.1  gmcgarry 
    421   1.1  gmcgarry 			printf("[%3d] ", devno);
    422   1.1  gmcgarry 			userconf_pdevnam(devno);
    423   1.1  gmcgarry 			printf(" changed\n");
    424   1.1  gmcgarry 			userconf_pdev(devno);
    425   1.1  gmcgarry 
    426   1.1  gmcgarry 			/* XXX add eoc */
    427   1.1  gmcgarry 			userconf_hist_eoc();
    428  1.13     perry 
    429   1.1  gmcgarry 		}
    430   1.1  gmcgarry 	} else {
    431   1.1  gmcgarry 		printf("Unknown devno (max is %d)\n", userconf_maxdev);
    432   1.1  gmcgarry 	}
    433   1.1  gmcgarry }
    434   1.1  gmcgarry 
    435  1.15   thorpej static void
    436  1.15   thorpej userconf_disable(int devno)
    437   1.1  gmcgarry {
    438   1.1  gmcgarry 	int done = 0;
    439   1.1  gmcgarry 
    440   1.1  gmcgarry 	if (devno <= userconf_maxdev) {
    441   1.1  gmcgarry 		switch (cfdata[devno].cf_fstate) {
    442   1.1  gmcgarry 		case FSTATE_NOTFOUND:
    443   1.1  gmcgarry 			cfdata[devno].cf_fstate = FSTATE_DNOTFOUND;
    444   1.1  gmcgarry 			break;
    445   1.1  gmcgarry 		case FSTATE_STAR:
    446   1.1  gmcgarry 			cfdata[devno].cf_fstate = FSTATE_DSTAR;
    447   1.1  gmcgarry 			break;
    448   1.1  gmcgarry 		case FSTATE_DNOTFOUND:
    449   1.1  gmcgarry 		case FSTATE_DSTAR:
    450   1.1  gmcgarry 			done = 1;
    451   1.1  gmcgarry 			break;
    452   1.1  gmcgarry 		default:
    453   1.1  gmcgarry 			printf("Error unknown state\n");
    454   1.1  gmcgarry 			break;
    455   1.1  gmcgarry 		}
    456   1.1  gmcgarry 
    457   1.1  gmcgarry 		printf("[%3d] ", devno);
    458   1.1  gmcgarry 		userconf_pdevnam(devno);
    459   1.1  gmcgarry 		if (done) {
    460   1.1  gmcgarry 			printf(" already");
    461   1.1  gmcgarry 		} else {
    462   1.1  gmcgarry 			/* XXX add cmd 'd' <devno> eoc */
    463   1.1  gmcgarry 			userconf_hist_cmd('d');
    464   1.1  gmcgarry 			userconf_hist_int(devno);
    465   1.1  gmcgarry 			userconf_hist_eoc();
    466   1.1  gmcgarry 		}
    467   1.1  gmcgarry 		printf(" disabled\n");
    468   1.1  gmcgarry 	} else {
    469   1.1  gmcgarry 		printf("Unknown devno (max is %d)\n", userconf_maxdev);
    470   1.1  gmcgarry 	}
    471   1.1  gmcgarry }
    472   1.1  gmcgarry 
    473  1.15   thorpej static void
    474  1.15   thorpej userconf_enable(int devno)
    475   1.1  gmcgarry {
    476   1.1  gmcgarry 	int done = 0;
    477  1.13     perry 
    478   1.1  gmcgarry 	if (devno <= userconf_maxdev) {
    479   1.1  gmcgarry 		switch (cfdata[devno].cf_fstate) {
    480   1.1  gmcgarry 		case FSTATE_DNOTFOUND:
    481   1.1  gmcgarry 			cfdata[devno].cf_fstate = FSTATE_NOTFOUND;
    482   1.1  gmcgarry 			break;
    483   1.1  gmcgarry 		case FSTATE_DSTAR:
    484   1.1  gmcgarry 			cfdata[devno].cf_fstate = FSTATE_STAR;
    485   1.1  gmcgarry 			break;
    486   1.1  gmcgarry 		case FSTATE_NOTFOUND:
    487   1.1  gmcgarry 		case FSTATE_STAR:
    488   1.1  gmcgarry 			done = 1;
    489   1.1  gmcgarry 			break;
    490   1.1  gmcgarry 		default:
    491   1.1  gmcgarry 			printf("Error unknown state\n");
    492   1.1  gmcgarry 			break;
    493   1.1  gmcgarry 		}
    494   1.1  gmcgarry 
    495   1.1  gmcgarry 		printf("[%3d] ", devno);
    496   1.1  gmcgarry 		userconf_pdevnam(devno);
    497   1.1  gmcgarry 		if (done) {
    498   1.1  gmcgarry 			printf(" already");
    499   1.1  gmcgarry 		} else {
    500   1.1  gmcgarry 			/* XXX add cmd 'e' <devno> eoc */
    501   1.1  gmcgarry 			userconf_hist_cmd('d');
    502   1.1  gmcgarry 			userconf_hist_int(devno);
    503   1.1  gmcgarry 			userconf_hist_eoc();
    504   1.1  gmcgarry 		}
    505   1.1  gmcgarry 		printf(" enabled\n");
    506   1.1  gmcgarry 	} else {
    507   1.1  gmcgarry 		printf("Unknown devno (max is %d)\n", userconf_maxdev);
    508   1.1  gmcgarry 	}
    509   1.1  gmcgarry }
    510   1.1  gmcgarry 
    511  1.15   thorpej static void
    512  1.15   thorpej userconf_help(void)
    513   1.1  gmcgarry {
    514   1.1  gmcgarry 	int j = 0, k;
    515   1.1  gmcgarry 
    516   1.1  gmcgarry 	printf("command   args                description\n");
    517   1.1  gmcgarry 	while (*userconf_cmds[j] != '\0') {
    518  1.22     joerg 		printf("%s", userconf_cmds[j]);
    519   1.1  gmcgarry 		k = strlen(userconf_cmds[j]);
    520   1.1  gmcgarry 		while (k < 10) {
    521   1.1  gmcgarry 			printf(" ");
    522   1.1  gmcgarry 			k++;
    523   1.1  gmcgarry 		}
    524   1.1  gmcgarry 		switch (*userconf_cmds[j+1]) {
    525   1.1  gmcgarry 		case 'L':
    526   1.1  gmcgarry 			printf("[count]             number of lines before more");
    527   1.1  gmcgarry 			break;
    528   1.1  gmcgarry 		case 'b':
    529   1.1  gmcgarry 			printf("8|10|16             base on large numbers");
    530   1.1  gmcgarry 			break;
    531   1.1  gmcgarry 		case 'c':
    532   1.1  gmcgarry 			printf("devno|dev           change devices");
    533   1.1  gmcgarry 			break;
    534   1.1  gmcgarry 		case 'd':
    535   1.1  gmcgarry 			printf("devno|dev           disable devices");
    536   1.1  gmcgarry 			break;
    537   1.1  gmcgarry 		case 'e':
    538   1.1  gmcgarry 			printf("devno|dev           enable devices");
    539   1.1  gmcgarry 			break;
    540   1.1  gmcgarry 		case 'f':
    541   1.1  gmcgarry 			printf("devno|dev           find devices");
    542   1.1  gmcgarry 			break;
    543   1.1  gmcgarry 		case 'h':
    544   1.1  gmcgarry 			printf("                    this message");
    545   1.1  gmcgarry 			break;
    546   1.1  gmcgarry 		case 'l':
    547   1.1  gmcgarry 			printf("                    list configuration");
    548   1.1  gmcgarry 			break;
    549   1.1  gmcgarry 		case 'q':
    550   1.1  gmcgarry 			printf("                    leave userconf");
    551   1.1  gmcgarry 			break;
    552   1.1  gmcgarry 		default:
    553   1.1  gmcgarry 			printf("                    don't know");
    554   1.1  gmcgarry 			break;
    555   1.1  gmcgarry 		}
    556   1.1  gmcgarry 		printf("\n");
    557   1.1  gmcgarry 		j += 2;
    558   1.1  gmcgarry 	}
    559   1.1  gmcgarry }
    560   1.1  gmcgarry 
    561  1.15   thorpej static void
    562  1.15   thorpej userconf_list(void)
    563   1.1  gmcgarry {
    564   1.1  gmcgarry 	int i = 0;
    565   1.1  gmcgarry 
    566   1.1  gmcgarry 	userconf_cnt = 0;
    567   1.1  gmcgarry 
    568   1.9   thorpej 	while (cfdata[i].cf_name != NULL) {
    569   1.1  gmcgarry 		if (userconf_more())
    570   1.1  gmcgarry 			break;
    571   1.1  gmcgarry 		userconf_pdev(i++);
    572   1.1  gmcgarry 	}
    573   1.1  gmcgarry 
    574   1.1  gmcgarry 	userconf_cnt = -1;
    575   1.1  gmcgarry }
    576   1.1  gmcgarry 
    577  1.15   thorpej static void
    578  1.15   thorpej userconf_common_dev(char *dev, int len, short unit, short state, char routine)
    579   1.1  gmcgarry {
    580   1.1  gmcgarry 	int i = 0;
    581   1.1  gmcgarry 
    582   1.1  gmcgarry 	switch (routine) {
    583   1.1  gmcgarry 	case UC_CHANGE:
    584   1.1  gmcgarry 		break;
    585   1.1  gmcgarry 	default:
    586   1.1  gmcgarry 		userconf_cnt = 0;
    587   1.1  gmcgarry 		break;
    588   1.1  gmcgarry 	}
    589   1.1  gmcgarry 
    590   1.9   thorpej 	while (cfdata[i].cf_name != NULL) {
    591   1.8   thorpej 		if (strlen(cfdata[i].cf_name) == len) {
    592   1.1  gmcgarry 
    593   1.1  gmcgarry 			/*
    594   1.1  gmcgarry 			 * Ok, if device name is correct
    595   1.1  gmcgarry 			 *  If state == FSTATE_FOUND, look for "dev"
    596   1.1  gmcgarry 			 *  If state == FSTATE_STAR, look for "dev*"
    597   1.1  gmcgarry 			 *  If state == FSTATE_NOTFOUND, look for "dev0"
    598   1.1  gmcgarry 			 */
    599   1.8   thorpej 			if (strncasecmp(dev, cfdata[i].cf_name,
    600   1.1  gmcgarry 					len) == 0 &&
    601   1.1  gmcgarry 			    (state == FSTATE_FOUND ||
    602   1.1  gmcgarry 			     (state == FSTATE_STAR &&
    603   1.1  gmcgarry 			      (cfdata[i].cf_fstate == FSTATE_STAR ||
    604   1.1  gmcgarry 			       cfdata[i].cf_fstate == FSTATE_DSTAR)) ||
    605   1.1  gmcgarry 			     (state == FSTATE_NOTFOUND &&
    606   1.1  gmcgarry 			      cfdata[i].cf_unit == unit &&
    607   1.1  gmcgarry 			      (cfdata[i].cf_fstate == FSTATE_NOTFOUND ||
    608   1.1  gmcgarry 			       cfdata[i].cf_fstate == FSTATE_DNOTFOUND)))) {
    609   1.1  gmcgarry 				if (userconf_more())
    610   1.1  gmcgarry 					break;
    611   1.1  gmcgarry 				switch (routine) {
    612   1.1  gmcgarry 				case UC_CHANGE:
    613   1.1  gmcgarry 					userconf_change(i);
    614   1.1  gmcgarry 					break;
    615   1.1  gmcgarry 				case UC_ENABLE:
    616   1.1  gmcgarry 					userconf_enable(i);
    617   1.1  gmcgarry 					break;
    618   1.1  gmcgarry 				case UC_DISABLE:
    619   1.1  gmcgarry 					userconf_disable(i);
    620   1.1  gmcgarry 					break;
    621   1.1  gmcgarry 				case UC_FIND:
    622   1.1  gmcgarry 					userconf_pdev(i);
    623   1.1  gmcgarry 					break;
    624   1.1  gmcgarry 				default:
    625   1.1  gmcgarry 					printf("Unknown routine /%c/\n",
    626   1.1  gmcgarry 					    routine);
    627   1.1  gmcgarry 					break;
    628   1.1  gmcgarry 				}
    629   1.1  gmcgarry 			}
    630   1.1  gmcgarry 		}
    631   1.1  gmcgarry 		i++;
    632   1.1  gmcgarry 	}
    633   1.1  gmcgarry 
    634   1.1  gmcgarry 	switch (routine) {
    635   1.1  gmcgarry 	case UC_CHANGE:
    636   1.1  gmcgarry 		break;
    637   1.1  gmcgarry 	default:
    638   1.1  gmcgarry 		userconf_cnt = -1;
    639   1.1  gmcgarry 		break;
    640   1.1  gmcgarry 	}
    641   1.1  gmcgarry }
    642   1.1  gmcgarry 
    643  1.15   thorpej #if 0
    644  1.15   thorpej static void
    645  1.15   thorpej userconf_add_read(char *prompt, char field, char *dev, int len, int *val)
    646   1.1  gmcgarry {
    647   1.1  gmcgarry 	int ok = 0;
    648   1.1  gmcgarry 	int a;
    649   1.1  gmcgarry 	char *c;
    650   1.1  gmcgarry 
    651   1.1  gmcgarry 	*val = -1;
    652   1.1  gmcgarry 
    653   1.1  gmcgarry 	while (!ok) {
    654   1.1  gmcgarry 		printf("%s ? ", prompt);
    655   1.1  gmcgarry 
    656  1.10    simonb 		getsn(userconf_argbuf, sizeof(userconf_argbuf));
    657   1.1  gmcgarry 
    658   1.1  gmcgarry 		c = userconf_argbuf;
    659   1.1  gmcgarry 		while (*c == ' ' || *c == '\t' || *c == '\n') c++;
    660   1.1  gmcgarry 
    661   1.1  gmcgarry 		if (*c != '\0') {
    662   1.1  gmcgarry 			if (userconf_number(c, &a) == 0) {
    663   1.1  gmcgarry 				if (a > userconf_maxdev) {
    664   1.1  gmcgarry 					printf("Unknown devno (max is %d)\n",
    665   1.1  gmcgarry 					    userconf_maxdev);
    666   1.1  gmcgarry 				} else if (strncasecmp(dev,
    667   1.8   thorpej 				    cfdata[a].cf_name, len) != 0 &&
    668   1.1  gmcgarry 					field == 'a') {
    669   1.1  gmcgarry 					printf("Not same device type\n");
    670   1.1  gmcgarry 				} else {
    671   1.1  gmcgarry 					*val = a;
    672   1.1  gmcgarry 					ok = 1;
    673   1.1  gmcgarry 				}
    674   1.1  gmcgarry 			} else if (*c == '?') {
    675   1.1  gmcgarry 				userconf_common_dev(dev, len, 0,
    676   1.1  gmcgarry 				    FSTATE_FOUND, UC_FIND);
    677   1.1  gmcgarry 			} else if (*c == 'q' || *c == 'Q') {
    678   1.1  gmcgarry 				ok = 1;
    679   1.1  gmcgarry 			} else {
    680   1.1  gmcgarry 				printf("Unknown argument\n");
    681   1.1  gmcgarry 			}
    682   1.1  gmcgarry 		} else {
    683   1.1  gmcgarry 			ok = 1;
    684   1.1  gmcgarry 		}
    685   1.1  gmcgarry 	}
    686   1.1  gmcgarry }
    687  1.15   thorpej #endif /* 0 */
    688   1.1  gmcgarry 
    689  1.23  uebayasi int
    690  1.15   thorpej userconf_parse(char *cmd)
    691   1.1  gmcgarry {
    692   1.1  gmcgarry 	char *c, *v;
    693   1.1  gmcgarry 	int i = 0, j = 0, k, a;
    694   1.1  gmcgarry 	short unit, state;
    695   1.1  gmcgarry 
    696   1.1  gmcgarry 	c = cmd;
    697   1.1  gmcgarry 	while (*c == ' ' || *c == '\t')
    698   1.1  gmcgarry 		c++;
    699   1.1  gmcgarry 	v = c;
    700   1.1  gmcgarry 	while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
    701   1.1  gmcgarry 		c++;
    702   1.1  gmcgarry 		i++;
    703   1.1  gmcgarry 	}
    704   1.1  gmcgarry 
    705   1.1  gmcgarry 	k = -1;
    706   1.1  gmcgarry 	while (*userconf_cmds[j] != '\0') {
    707   1.1  gmcgarry 		if (strlen(userconf_cmds[j]) == i) {
    708   1.1  gmcgarry 			if (strncasecmp(v, userconf_cmds[j], i) == 0)
    709   1.1  gmcgarry 				k = j;
    710   1.1  gmcgarry 		}
    711   1.1  gmcgarry 		j += 2;
    712   1.1  gmcgarry 	}
    713   1.1  gmcgarry 
    714   1.1  gmcgarry 	while (*c == ' ' || *c == '\t' || *c == '\n')
    715   1.1  gmcgarry 		c++;
    716   1.1  gmcgarry 
    717   1.1  gmcgarry 	if (k == -1) {
    718   1.1  gmcgarry 		if (*v != '\n')
    719   1.1  gmcgarry 			printf("Unknown command, try help\n");
    720   1.1  gmcgarry 	} else {
    721   1.1  gmcgarry 		switch (*userconf_cmds[k+1]) {
    722   1.1  gmcgarry 		case 'L':
    723   1.1  gmcgarry 			if (*c == '\0')
    724   1.1  gmcgarry 				printf("Argument expected\n");
    725   1.1  gmcgarry 			else if (userconf_number(c, &a) == 0)
    726   1.1  gmcgarry 				userconf_lines = a;
    727   1.1  gmcgarry 			else
    728   1.1  gmcgarry 				printf("Unknown argument\n");
    729   1.1  gmcgarry 			break;
    730   1.1  gmcgarry 		case 'b':
    731   1.1  gmcgarry 			if (*c == '\0')
    732   1.1  gmcgarry 				printf("8|10|16 expected\n");
    733   1.1  gmcgarry 			else if (userconf_number(c, &a) == 0) {
    734   1.1  gmcgarry 				if (a == 8 || a == 10 || a == 16) {
    735   1.1  gmcgarry 					userconf_base = a;
    736   1.1  gmcgarry 				} else {
    737   1.1  gmcgarry 					printf("8|10|16 expected\n");
    738   1.1  gmcgarry 				}
    739   1.1  gmcgarry 			} else
    740   1.1  gmcgarry 				printf("Unknown argument\n");
    741   1.1  gmcgarry 			break;
    742   1.1  gmcgarry 		case 'c':
    743   1.1  gmcgarry 			if (*c == '\0')
    744   1.1  gmcgarry 				printf("DevNo or Dev expected\n");
    745   1.1  gmcgarry 			else if (userconf_number(c, &a) == 0)
    746   1.1  gmcgarry 				userconf_change(a);
    747   1.1  gmcgarry 			else if (userconf_device(c, &a, &unit, &state) == 0)
    748   1.1  gmcgarry 				userconf_common_dev(c, a, unit, state, UC_CHANGE);
    749   1.1  gmcgarry 			else
    750   1.1  gmcgarry 				printf("Unknown argument\n");
    751   1.1  gmcgarry 			break;
    752   1.1  gmcgarry 		case 'd':
    753   1.1  gmcgarry 			if (*c == '\0')
    754   1.1  gmcgarry 				printf("Attr, DevNo or Dev expected\n");
    755   1.1  gmcgarry 			else if (userconf_number(c, &a) == 0)
    756   1.1  gmcgarry 				userconf_disable(a);
    757   1.1  gmcgarry 			else if (userconf_device(c, &a, &unit, &state) == 0)
    758   1.1  gmcgarry 				userconf_common_dev(c, a, unit, state, UC_DISABLE);
    759   1.1  gmcgarry 			else
    760   1.1  gmcgarry 				printf("Unknown argument\n");
    761   1.1  gmcgarry 			break;
    762   1.1  gmcgarry 		case 'e':
    763   1.1  gmcgarry 			if (*c == '\0')
    764   1.1  gmcgarry 				printf("Attr, DevNo or Dev expected\n");
    765   1.1  gmcgarry 			else if (userconf_number(c, &a) == 0)
    766   1.1  gmcgarry 				userconf_enable(a);
    767   1.1  gmcgarry 			else if (userconf_device(c, &a, &unit, &state) == 0)
    768   1.1  gmcgarry 				userconf_common_dev(c, a, unit, state, UC_ENABLE);
    769   1.1  gmcgarry 			else
    770   1.1  gmcgarry 				printf("Unknown argument\n");
    771   1.1  gmcgarry 			break;
    772   1.1  gmcgarry 		case 'f':
    773   1.1  gmcgarry 			if (*c == '\0')
    774   1.1  gmcgarry 				printf("DevNo or Dev expected\n");
    775   1.1  gmcgarry 			else if (userconf_number(c, &a) == 0)
    776   1.1  gmcgarry 				userconf_pdev(a);
    777   1.1  gmcgarry 			else if (userconf_device(c, &a, &unit, &state) == 0)
    778   1.1  gmcgarry 				userconf_common_dev(c, a, unit, state, UC_FIND);
    779   1.1  gmcgarry 			else
    780   1.1  gmcgarry 				printf("Unknown argument\n");
    781   1.1  gmcgarry 			break;
    782   1.1  gmcgarry 		case 'h':
    783   1.1  gmcgarry 			userconf_help();
    784   1.1  gmcgarry 			break;
    785   1.1  gmcgarry 		case 'l':
    786   1.1  gmcgarry 			if (*c == '\0')
    787   1.1  gmcgarry 				userconf_list();
    788   1.1  gmcgarry 			else
    789   1.1  gmcgarry 				printf("Unknown argument\n");
    790   1.1  gmcgarry 			break;
    791   1.1  gmcgarry 		case 'q':
    792   1.1  gmcgarry 			/* XXX add cmd 'q' eoc */
    793   1.1  gmcgarry 			userconf_hist_cmd('q');
    794   1.1  gmcgarry 			userconf_hist_eoc();
    795   1.1  gmcgarry 			return(-1);
    796   1.1  gmcgarry 		case 's':
    797   1.1  gmcgarry 		default:
    798   1.1  gmcgarry 			printf("Unknown command\n");
    799   1.1  gmcgarry 			break;
    800   1.1  gmcgarry 		}
    801   1.1  gmcgarry 	}
    802   1.1  gmcgarry 	return(0);
    803   1.1  gmcgarry }
    804   1.1  gmcgarry 
    805   1.1  gmcgarry void
    806  1.23  uebayasi userconf_prompt(void)
    807   1.1  gmcgarry {
    808  1.20  drochner 	const char prompt[] = "uc> ";
    809   1.1  gmcgarry 
    810   1.1  gmcgarry 	printf("userconf: configure system autoconfiguration:\n");
    811   1.1  gmcgarry 
    812   1.1  gmcgarry 	while (1) {
    813   1.1  gmcgarry 		printf(prompt);
    814   1.1  gmcgarry 		if (getsn(userconf_cmdbuf, sizeof(userconf_cmdbuf)) > 0 &&
    815   1.1  gmcgarry 		    userconf_parse(userconf_cmdbuf))
    816   1.1  gmcgarry 			break;
    817   1.1  gmcgarry 	}
    818   1.1  gmcgarry 	printf("Continuing...\n");
    819   1.1  gmcgarry }
    820   1.1  gmcgarry 
    821   1.1  gmcgarry /*
    822   1.1  gmcgarry  * XXX shouldn't this be a common function?
    823   1.1  gmcgarry  */
    824   1.1  gmcgarry static int
    825  1.15   thorpej getsn(char *cp, int size)
    826   1.1  gmcgarry {
    827   1.1  gmcgarry 	char *lp;
    828   1.1  gmcgarry 	int c, len;
    829   1.1  gmcgarry 
    830   1.1  gmcgarry 	cnpollc(1);
    831   1.1  gmcgarry 
    832   1.1  gmcgarry 	lp = cp;
    833   1.1  gmcgarry 	len = 0;
    834   1.1  gmcgarry 	for (;;) {
    835   1.1  gmcgarry 		c = cngetc();
    836   1.1  gmcgarry 		switch (c) {
    837   1.1  gmcgarry 		case '\n':
    838   1.1  gmcgarry 		case '\r':
    839   1.1  gmcgarry 			printf("\n");
    840   1.1  gmcgarry 			*lp++ = '\0';
    841   1.1  gmcgarry 			cnpollc(0);
    842   1.1  gmcgarry 			return (len);
    843   1.1  gmcgarry 		case '\b':
    844   1.1  gmcgarry 		case '\177':
    845   1.1  gmcgarry 		case '#':
    846   1.1  gmcgarry 			if (len) {
    847   1.1  gmcgarry 				--len;
    848   1.1  gmcgarry 				--lp;
    849   1.1  gmcgarry 				printf("\b \b");
    850   1.1  gmcgarry 			}
    851   1.1  gmcgarry 			continue;
    852   1.1  gmcgarry 		case '@':
    853   1.1  gmcgarry 		case 'u'&037:
    854   1.1  gmcgarry 			len = 0;
    855   1.1  gmcgarry 			lp = cp;
    856   1.1  gmcgarry 			printf("\n");
    857   1.1  gmcgarry 			continue;
    858   1.1  gmcgarry 		default:
    859   1.1  gmcgarry 			if (len + 1 >= size || c < ' ') {
    860   1.1  gmcgarry 				printf("\007");
    861   1.1  gmcgarry 				continue;
    862   1.1  gmcgarry 			}
    863   1.1  gmcgarry 			printf("%c", c);
    864   1.1  gmcgarry 			++len;
    865   1.1  gmcgarry 			*lp++ = c;
    866   1.1  gmcgarry 		}
    867   1.1  gmcgarry 	}
    868   1.1  gmcgarry }
    869