File:  [MW Coherent from dump] / coherent / b / kernel / tools / kbmain.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:37 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * driver routine for loadable keyboard tables.
 *
 * prior to firing off the ioctl() which loads the new keyboard tables,
 * permform some simple validity checks on the table.
 * if errors are found, bail out without setting the new table.
 *
 * this version removes all references to stdio since we need to put over
 * a dozen cooked keyboard tables on the boot disk - space is at a premium.
 *
 * Version 1.1, 6/25/91
 */

#include <sgtty.h>
#include <sys/kb.h>
#include <sys/kbscan.h>
#include <errno.h>
#include <sys/mdata.h>

#define	VERSION	"1.1"
#define	FALSE	(0 != 0)
#define	TRUE	(0 == 0)
#define NULL ((char *)0)
#define putchar(c) { char b = c; write(1, &b, 1); }

/*
 * globals
 */
char	*argv0;				/* name of this executable */
int	errors;				/* for exit status */
char	verbose;			/* step-by-step details */
char	debug;				/* print out cooked table & exit */
KBTBL	table[MAX_KEYS];		/* cooked table for ioctl() */
FNKEY	*arena;				/* function key arena */
unsigned char	fnbuffer[(sizeof(FNKEY) + MAX_FCHAR)]; /* function key area */

/*
 * The following table maps the specified key number to
 * a scan code set 3 value.
 * Note that K_14, K_65 through K_74 and K_107
 * are provided for compatibility with
 * the old XT layout AT keyboards.
 */
unsigned char	keyval[] = {		/* code set 3 mapped value */
none, K_1, K_2, K_3, K_4, K_5, K_6, K_7,
K_8, K_9, K_10, K_11, K_12, K_13, K_14, K_15,
K_16, K_17, K_18, K_19, K_20, K_21, K_22, K_23,
K_24, K_25, K_26, K_27, K_28, K_29, K_30, K_31,
K_32, K_33, K_34, K_35, K_36, K_37, K_38, K_39,
K_40, K_41, K_42, K_43, K_44, K_45, K_46, K_47,
K_48, K_49, K_50, K_51, K_52, K_53, K_54, K_55,
none, K_57, K_58, none, K_60, K_61, K_62, none,
K_64, K_65, K_66, K_67, K_68, K_69, K_70, K_71,
K_72, K_73, K_74, K_75, K_76, none, none, K_79,
K_80, K_81, none, K_83, K_84, K_85, K_86, none,
none, K_89, K_90, K_91, K_92, K_93, none, K_95,
K_96, K_97, K_98, K_99, K_100, K_101, K_102, K_103,
K_104, K_105, K_106, K_107, K_108, none, K_110, none,
K_112, K_113, K_114, K_115, K_116, K_117, K_118, K_119,
K_120, K_121, K_122, K_123, K_124, K_125, K_126, none
};

/*
 * externs from user-defined keyboard table
 */
extern	KBTBL	kbtbl[];			/* actual table */
extern	char	tbl_name[];			/* name of table as text */
extern	unsigned char *funkey[];		/* function key definitions */
extern	int	numfun;				/* # of function keys in tbl */
extern	int	numkey;				/* number of keys in kbtbl[] */

main(argc, argv)
char *argv[];
{
	unsigned char *cp, *ncp;
	int i, j;
	int fd;					/* console file descriptor */

	argv0 = argv[0];
	arena = (FNKEY *) fnbuffer;

	if (argc > 1) {
		if (strcmp(argv[1], "-V") == 0)
			printf("Version %s\n", VERSION);
		else if (strcmp(argv[1], "-D") == 0)
			++debug;
		else
			usage();
	}

	if ((fd = open("/dev/console", 2)) < 0) {
		err("unable to access console");
		exit(errors);
	}

	/*
	 * loop through the user's keyboard table validating each entry.
	 * if the entry is good, copy it to the destination table.
	 */
	for (i = 0; i < numkey; ++i) {		/* loop thru user's keys */
		if (ok_entry(i)) {
			j = kbtbl[i].k_key;		/* map key */
			table[j] = kbtbl[i];		/* copy entry */
		} else
			++errors;
	}

	if (errors)
		exit(errors);
	/*
	 * build a function key arena consisting of the user defined
	 * special and function keys.
	 */
	ncp = arena->k_fnval;
	for (i = 0; i < numfun; ++i) {
		cp = funkey[i];
		do {
			if (ncp >= &arena->k_fnval[MAX_FCHAR]) {
				err("function key table overflow");
				exit(errors);
			}
			*ncp++ = *cp;
		} while (*cp++ != DELIM);
	}
	arena->k_nfkeys = numfun;

	if (debug) {
		dump();				/* print out cooked table */
		exit(0);
	}

	/*
	 * load the cooked keyboard table into the driver via a
	 * special ioctl() call.
	 */
	ioctl(fd, TIOCSETKBT, table);
	if (errno) {
		err("keyboard table ioctl() failed, errno=%d", errno);
		exit(errors);
	}

	/*
	 * load the cooked function key table into the driver via a
	 * special ioctl() call.
	 */
	ioctl(fd, TIOCSETF, arena);
	if (errno) {
		err("function key ioctl() failed, errno=%d", errno);
		exit(errors);
	}

	printf("Loaded %s\n", tbl_name);
	close(fd);
	exit(errors);
}

/*
 * validate a table entry
 */
ok_entry(n)
register int n;
{
	int i;
	int key = lookup(kbtbl[n].k_key);
	unsigned char kval;

	if (!key) {
		err("invalid key #0x%x in kbtbl[%d]", kbtbl[n].k_key, n);
		return FALSE;
	}
	if ((kbtbl[n].k_flags & (S|F)) == (S|F)) {
		err("invalid flag field for key K_%d", key);
		return FALSE;
	}
	if (kbtbl[n].k_flags & S) {
		for (i = BASE; i <= ALT_GR; ++i) {
			kval = kbtbl[n].k_val[i];
			if (kval != kbtbl[n].k_val[BASE]) {
				err("inconsistent shift key entry for K_%d",
				    key);
				return FALSE;
			}
			if (kval < scroll || kval > altgr) {
				err("bad shift key entry for K_%d",
				    key);
				return FALSE;
			}
		} /* for */
	} else if (kbtbl[n].k_flags & F) {
		for (i = BASE; i <= ALT_GR; ++i) {
			kval = kbtbl[n].k_val[i];
			if (kval != none)
				if (kval >= numfun
				  && !VTKEY(kval) /* && kval != fgk*/) {
					printf("val=%d\n", kval);
					err("bad function key entry K_%d",
					    key);
					return FALSE;
				}
		} /* for */
	} /* flag key */

	if (table[kbtbl[n].k_key].k_key != 0) {
		err("multiple entries for K_%d", key);
		return FALSE;
	}
	return TRUE;
}

/*
 * lookup the physical key number associated with a given
 * code set 3 scan code.
 *
 * return 0 if not found.
 */
lookup(sc)
unsigned sc;
{
	register int i;

	if (sc == none)
		return 0;
	for (i = 0; i < sizeof(keyval)/sizeof(keyval[0]); ++i)
		if (keyval[i] == (unsigned char)sc)
			return (i);
	return 0;
}

usage()
{
	printf("usage:\t%s [-V]\n", argv0);
	exit(1);
}

err(msg)
char *msg;
{
	printf("%s: ERROR: %r\n", argv0, &msg);
	++errors;
}

/*
 * dump the cooked keyboard table to stdout
 */
dump()
{
	int i, j;

	for (i = 0; i < MAX_KEYS; ++i) {
		printf("%02x: %02x ", i, table[i].k_key);
		for (j = 0; j < 9; ++j)
			printf("%02x ", table[i].k_val[j]);
		printf("(%02x)\n", table[i].k_flags);
	}
}


/*
 * Simple standard output printf() using single character writes to stdout.
 *
 * Non-portable things:
 * 1) alignment of arguments is assumed to be completely contiguous.
 * 2) the smallest number is assumed to negate to itself.
 *    be held in an exact number of ints.
 */
union	alltypes {
	char	c;
	int	i;
	unsigned u;
	char	*s;
};

#define	bump(p,s)	(p+=sizeof(s)/sizeof(int))

char	*printi();

static	char	null[] = "{NULL}";

printf(args)
union alltypes args;
{
	xprintf(&args);
}
xprintf(argp)
union alltypes *argp;
{
	register char *cbp;
	int *iap;
	register c;
	char *s;
	char *cbs;
	char adj, pad;
	int prec;
	int fwidth;
	int pwidth;
	register char *fmt;
	union alltypes elem;
	char cbuf[64];

	iap = (int *)argp;
	fmt = *(char **)iap;
	bump(iap, char*);
	for (;;) {
		while((c = *fmt++) != '%') {
			if(c == '\0') {
				return;
			}
			putchar(c);
		}
		pad = ' ';
		fwidth = -1;
		prec = -1;
		c = *fmt++;
		if (c == '-') {
			adj = 1;
			c = *fmt++;
		} else
			adj = 0;
		if (c == '0') {
			pad = '0';
			c = *fmt++;
		}
		if (c == '*') {
			fwidth = *iap++;
			c = *fmt++;
		} else
			for (fwidth = 0; c>='0' && c<='9'; c = *fmt++)
				fwidth = fwidth*10 + c-'0';
		if (c == '.') {
			c = *fmt++;
			if (c == '*') {
				prec = *iap++;
				c = *fmt++;
			} else
				for (prec=0; c >= '0' && c <= '9'; c = *fmt++)
					prec = prec*10 + c-'0';
		}
		cbp = cbs = cbuf;
		switch (c) {

		case 'd':
			elem.i = *iap++;
			if (elem.i < 0) {
				elem.i = -elem.i;
				*cbp++ = '-';
			}
			cbp = printi(cbp, elem.i, 10);
			break;

		case 'u':
			cbp = printi(cbp, *iap++, 10);
			break;
	
		case 'o':
			cbp = printi(cbp, *iap++, 8);
			break;

		case 'x':
			cbp = printi(cbp, *iap++, 16);
			break;

		case 's':
			if ((s = *(char **)iap) == NULL)
				s = null;
			bump(iap, char*);
			/*
			 * Do %s specially so it can be longer.
			 */
			cbp = cbs = s;
			while (*cbp++ != '\0')
				if (prec>=0 && cbp-s>prec)
					break;
			cbp--;
			break;
	
		case 'c':
			elem.c = *iap++;
			*cbp++ = elem.c;
			break;
	
		case 'r':
			xprintf(*(char ***)iap);
			bump(iap, char**);
			break;
	
		default:
			putchar(c);
			continue;
		}
		if ((pwidth = fwidth + cbs-cbp) < 0)
			pwidth = 0;
		if (!adj)
			while (pwidth-- != 0)
				putchar(pad);
		while (cbs < cbp)
			putchar(*cbs++);
		if (adj)
			while (pwidth-- != 0)
				putchar(pad);
	}
}

static	char	digits[] = {
	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
	'A', 'B', 'C', 'D', 'E', 'F'
};

/*
 * Print an unsigned integer in base b.
 */
static
char *
printi(cp, n, b)
char *cp;
register unsigned n;
{
	register a;
	register char *ep;
	char pbuf[10];

	ep = &pbuf[10];
	*--ep = 0;
	for ( ; a = n/b; n=a)
		*--ep = digits[n%b];
	*--ep = digits[n];
	while (*ep)
		*cp++ = *ep++;
	return (cp);
}

/* end of kbmain.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.