1
0
Files
irix-657m-src/eoe/cmd/kbdpipe/kbdpipe.c
2022-09-29 17:59:04 +03:00

385 lines
8.6 KiB
C

/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/* #ident "@(#)kbdpipe:kbdpipe.c 1.3" */
#ident "$Revision: 1.1 $"
/*
* kbdpipe.c Uses "kbd" tables in a pipeline.
*
* Usage:
*
* kbdpipe -t table [-f loadfile] [-F] [-o outfile] [infile]
*
* The process forks, with the child handling final output and
* reading a pipeline.
* The parent pushes "kbd" into the "read" pipeline.
* If the table is not publicly resident, an attempt is made
* to load & attach the table. Load is from trusted dir.
* The parent sends stdin to the pipe, the child reads it and
* writes the output.
*
* -t table Tries to attach "table". If it fails, it tries
* to do kbdmap on file named /usr/lib/kbd/table.
* then attach that table.
*
* -f file If "table" can't be attached, tries to load
* "file" via kbdmap, then attach "table". If the
* filename begins with "/", it is tried. If it
* does NOT begin with "/", then "/usr/lib/kbd" is
* pre-pended, and that is tried. If it succeeds in
* loading "file", it still tries to attach "table".
*
* -F Forces outfile to be overwritten if it exists.
*
* -o outfile Output goes to "outfile" instead of stdout.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stropts.h>
#include <fcntl.h>
#include <errno.h>
#include <locale.h>
#include <signal.h>
#include <sys/kbdm.h>
/* #include <sys/kbd.h> */
#include <pfmt.h>
#include <string.h>
#define assuming(x) if (x) { while (x)
#define otherwise } else
#define loop
extern int optind, opterr;
extern char *optarg;
char *prog;
int opttrunc;
#ifdef DEBUG
char trusted[256] = "./";
#else
char trusted[256] = "/usr/lib/kbd/"; /* THE trusted place */
#endif
#define LOADER "kbdload" /* name of loader program */
#define READSIDE 0
#define WRITESIDE 1
int pfd[2]; /* pipe fds */
main(argc, argv)
int argc;
char **argv;
{
register char *path, *table, *output, *fname;
register int c, chile;
struct stat st;
(void)setlocale(LC_ALL, "");
(void)setlabel("UX:pipe");
(void)setcat("uxmesg");
table = output = path = fname = (char *) 0;
opttrunc = opterr = 0;
prog = *argv;
while ((c = getopt(argc, argv, "f:t:o:F")) != EOF) {
switch (c) {
case 'f': fname = optarg; break;
case 't': table = optarg; break;
case 'o': output = optarg; break;
case 'F': opttrunc = 1; break;
default:
usage(0);
}
}
if (! table)
usage(1);
if (output) {
if (! opttrunc) { /* don't overwrite */
if (stat(output, &st) == 0) { /* file exists */
pfmt(stderr, MM_ERROR, ":129:%s: file exists.\n",
output);
exit(1);
}
}
if (!freopen(output, "w", stdout)) {
pfmt(stderr, MM_ERROR, ":130:Cannot re-open stdout: %s\n",
strerror(errno));
exit(1);
}
}
/*
* open pipes & try to push stuff
*/
dopipes(table, fname);
switch (chile = fork()) {
case 0: /* child */
close(pfd[WRITESIDE]);
doread(optind < argc ? 512 : 1);
exit(0);
case -1: /* failure */
pfmt(stderr, MM_ERROR, ":131:fork() failed: %s\n",
strerror(errno));
exit(1);
default: /* parent */
break;
}
/*
* Parent gets this far; child stops above.
*/
close(pfd[READSIDE]); /* parent doesn't need READSIDE */
assuming (optind < argc) loop {
if (! freopen(argv[optind], "r", stdin)) {
kill(chile, SIGKILL);
pfmt(stderr, MM_ERROR, ":132:Cannot reopen stdin on %s: %s\n",
argv[optind], strerror(errno));
exit(1);
}
dowrite();
++optind;
}
otherwise {
dowrite();
}
close(pfd[WRITESIDE]);
exit(0);
}
usage(complain)
int complain;
{
if (complain)
pfmt(stderr, MM_ERROR, ":26:Incorrect usage\n");
pfmt(stderr, MM_ACTION,
":133:Usage: %s -t table [-f path] [-o outfile] [-F] [infile(s)]\n", prog);
exit(1);
}
/*
* read stdin, write pfd[WRITESIDE]
*/
dowrite()
{
register int c;
char ch; /* no register */
while ((c = getchar()) != EOF) {
ch = c;
write(pfd[WRITESIDE], &ch, 1);
}
}
/*
* Child: read pfd[READSIDE], write stdout. Try to do
* reasonable chunks... This produces the final output.
*/
char rbuf[514];
doread(n)
int n;
{
register int i, j;
while ((i = read(pfd[READSIDE], rbuf, n)) > 0) {
j = 0;
while (i--) {
putchar(rbuf[j]);
++j;
}
}
}
char cmd[512];
/*
* dopipes sets up the pipe (or Stream Pipe) so we can WRITE
* to one and READ from the other.
*/
dopipes(t, fn)
register unsigned char *t; /* table name */
register unsigned char *fn; /* file name if can't attach */
{
register int i;
struct strioctl sb;
int rval; /* for child return */
#ifdef SVR4
if (pipe(&pfd[0])) {
pfmt(stderr, MM_ERROR, ":134:pipe() failed: %s\n", strerror(errno));
exit(1);
}
if (ioctl(pfd[READSIDE], I_PUSH, "kbd")) { /* push kbd */
pfmt(stderr, MM_ERROR, ":135:Cannot push \"kbd\" module: %s\n",
strerror(errno));
exit(1);
}
#else
/*
* On SVR 3.x, use "/dev/spx" (the SP driver); push just after
* open, before link, so don't do PUSH here.
*/
if (spipe(&pfd[0])) {
pfmt(stderr, MM_ERROR, ":134:pipe() failed: %s\n", strerror(errno));
exit(1);
}
#endif
if (tach(t, pfd[READSIDE])) {
/*
* If we can attach the table, no sweat.
*/
if (turnon(pfd[READSIDE]))
return;
pfmt(stderr, MM_ERROR, ":136:Cannot turn on \"kbd\" module.\n");
exit(1);
}
/*
* Otherwise, try to load and then attach. It's a pain
* because we need stdin/stdout to be the pipe when we call
* the loader. We fork and let a child take care of it.
*/
switch(fork()) {
case 0: break; /* child continues */
case -1: pfmt(stderr, MM_ERROR, ":131:fork() failed: %s\n",
strerror(errno));
exit(1);
default: if ((wait(&rval) == (-1)) && (errno != ECHILD)) {
pfmt(stderr, MM_NOSTD, ":137:(Interrupted)");
exit(2);
}
if ((rval != 0) && (errno != ECHILD)) {
/* fprintf(stderr, "Unknown error %d\n", */
/* prog, errno); */
exit(1);
}
return; /* whew! */
}
/*
* The child gets this far; the parent is waiting
* above, and will NEVER get this far.
*/
close(0); close(1);
if ((dup(pfd[READSIDE]) == (-1)) || (dup(pfd[WRITESIDE]) == (-1))) {
pfmt(stderr, MM_ERROR, ":138:dup() failed: %s\n", strerror(errno));
exit(1);
}
fprintf(stderr, "step 1.\n");
close(pfd[READSIDE]);
close(pfd[WRITESIDE]);
fprintf(stderr, "step 11.\n");
/*
* Use "system" here so we don't have to fork, exec, and wait
* around for the return value, which simplifies things considerably
* at this juncture. "exec" would probably speed it up, but
* would complicate things. Use of "tach" and "turnon" directly
* instead of calling "kbdkey" reduces out one "system()" call;
* if the system is set up to cater to its user community, we'll
* rarely get this far...right?
*/
sprintf(cmd, "%s %s%s", LOADER, (fn[0] == '/' ? "" : trusted),
(fn ? fn : t));
fprintf(stderr, "step 2.\n");
if (system(cmd)) {
pfmt(stderr, MM_ERROR, ":139:Cannot load\n");
exit(1);
}
fprintf(stderr, "step 3.\n");
if (tach(t, 0))
turnon(0);
else {
pfmt(stderr, MM_ERROR, ":140:Cannot attach %s\n", t);
exit(1);
}
fprintf(stderr, "step 4.\n");
exit(0); /* child must exit */
}
#ifndef SVR4
/*
* spipe Open "/dev/spx" and obtain a Streams Pipe. This function
* "borrowed" from UTS library source with some mods. You
* only need it on SVR3.?.
*/
#define SPCLONE "/dev/spx"
spipe(fds)
int *fds;
{
struct strfdinsert fdi;
long dummy;
if ((fds[0] = open(SPCLONE, O_RDWR)) < 0)
return(-1);
if (ioctl(fds[0], I_PUSH, "kbd")) {
pfmt(stderr, MM_ERROR, ":135:Cannot push \"kbd\" module: %s\n",
strerror(errno));
exit(1);
}
if ((fds[1] = open(SPCLONE, O_RDWR)) < 0)
return(-1);
fdi.databuf.maxlen = fdi.databuf.len = -1;
fdi.databuf.buf = NULL;
fdi.ctlbuf.maxlen = fdi.ctlbuf.len = sizeof(long);
fdi.ctlbuf.buf = (caddr_t)&dummy;
fdi.offset = 0;
fdi.fildes = fds[1];
fdi.flags = 0;
if (ioctl(fds[0], I_FDINSERT, &fdi) < 0)
return(-1);
return(0);
}
#endif /* ! SVR4 */
tach(name, fd)
char *name;
int fd;
{
struct strioctl sb;
struct kbd_tach t;
register int rval;
sb.ic_cmd = KBD_ATTACH;
sb.ic_timout = 15;
sb.ic_len = sizeof(struct kbd_tach);
sb.ic_dp = (char *) &t;
strcpy((char *)t.t_table, name);
t.t_type = Z_UP;
rval = ioctl(fd, I_STR, &sb);
if (rval)
return(0); /* tach failed */
return(1);
}
turnon(fd)
int fd;
{
struct strioctl sb;
struct kbd_ctl c;
register int rval;
sb.ic_cmd = KBD_ON;
sb.ic_timout = 15;
sb.ic_len = sizeof(struct kbd_ctl);
sb.ic_dp = (char *) &c;
c.c_type = Z_UP;
rval = ioctl(fd, I_STR, &sb);
if (rval) {
pfmt(stderr, MM_ERROR, ":141:Cannot turn on mapping: %s\n",
strerror(errno));
return(0);
}
return(1);
}