home *** CD-ROM | disk | FTP | other *** search
- /*
- * force.c - v1.3 - by Brendan Kehoe (brendan@cs.widener.edu)
- *
- * v1.0 - 10/15/90 - force execution of a command on the user's command line
- * v1.1 - 11/19/90 - allow a pseudo-interactive session, of sorts
- * v1.2 - 11/20/90 - made the thing error check itself into oblivion
- * v1.3 - 7/16/91 - Ported to SGI by Dan Watts
- *
- * Usage: force [ -n ] [ -l /dev/ttyxx ]
- * -n - use this if you don't want the command to echo
- * -l /dev/ttyxx - the line to hit; use the full name (e.g. /dev/ttyp0)
- *
- * Compiles under SGI Irix, SunOS 4.1, Ultrix 3.1D, and Ultrix 4.1. No
- * promises are made for other OS's or systems.
- *
- * It won't work under System V Release anything until an alternative
- * to the TIOCSTI ioctl comes around. (Or you use SVR4, I'm told.)
- *
- * (Yes, this requires you be root to use it.)
- *
- * To use it, just type whatever at the Force> prompt, and when you
- * hit return, that line will get sent onto the user's input queue,
- * so it's like they typed it. Use Control-V to quote control characters
- * like Control-C. Type -X- on an empty line to quit out.
- *
- * You're welcome to do whatever you want with this, as long as you note
- * its origin somewhere. (Namely "This Was Written By Brendan Kehoe", for
- * starters.) (A 19-page writeup would be cool, too, but maybe it's too much.)
- */
-
- #include <stdio.h>
- #include <sys/types.h> /* for stat(2) */
- #include <sys/stat.h> /* for stat(2) */
- #include <fcntl.h>
- #ifdef sgi
- # include <sys/termio.h>
- # define termios termio
- # define TCGETS TCGETA
- # define TCSETS TCSETA
- #else
- #include <sys/termios.h>
- #endif
-
- #ifdef ultrix
- # include <sys/ioctl.h>
- # define TCGETS TCGETP
- # define TCSETS TCSANOW
- #endif /* ultrix */
-
- void push(), devchk();
-
- extern char *optarg;
- extern int optind;
- short no_echo = 0;
-
- #define USAGE "usage: %s [-n] [-l /dev/ttyxx]\n",*argv
- #define COMMAND_LIM 100
-
- int
- main(argc, argv)
- int argc;
- char **argv;
- {
- int f, cnt;
- short true = 1, no_cmd = 0;
- char *device, *buf, *trail, chr;
-
- if (argc > 4) {
- fprintf(stderr, USAGE);
- exit(1);
- }
-
- if ((device = (char *)malloc(40)) == (char *)NULL) {
- perror("malloc 1");
- exit(1);
- }
-
- if ((buf = (char *) malloc(COMMAND_LIM)) == (char *)NULL) {
- perror("malloc 1a");
- exit(1);
- }
-
- while ((chr = getopt(argc, argv, "nl:")) != -1)
- switch (chr) {
- case 'n':
- no_echo = 1;
- break;
- case 'l':
- (void) devchk(optarg, *argv);
- device = optarg;
- break;
- default:
- fprintf(stderr, USAGE);
- exit(1);
- }
-
- if (strlen(device) < 2) {
- printf("Device [form: /dev/ttyxx]: ");
- fflush(stdout);
- fgets(device, 39, stdin);
- /* cut off the trailing return that fgets leaves on */
- if ((*device) && (*(trail=(char *)(device + strlen(device) - 1)) == '\n'))
- *trail = '\0';
- if (strlen(device) > 7)
- (void) devchk(device, *argv);
- else {
- fprintf(stderr, "%s: give full name [e.g. /dev/ttyp0].\n", *argv);
- exit(1);
- }
- }
-
- printf("Terminate with '-X-' on a line by itself.\n");
- while (true) {
- no_cmd = cnt = 0;
- chr = *buf = '\0';
- printf("Force> ");
- rewind(stdin);
- while (((chr=getchar()) != '\n') && (chr != EOF) && (cnt < COMMAND_LIM))
- *(buf + cnt++) = chr;
- if (cnt == COMMAND_LIM) {
- printf("Limit of %d characters per command line.\n", COMMAND_LIM);
- no_cmd = 1;
- }
- if (chr == EOF) {
- putc('\n', stdout);
- exit(0);
- }
- if (!no_cmd) {
- *(buf + cnt) = '\0';
- if (!strcmp(buf, "-X-"))
- true = 0;
- else if ((*buf != '\n') && (*buf != '\0')) {
- if ((f = open(device, O_NDELAY | O_RDWR)) < 0) {
- perror("open");
- exit(1);
- }
- push(f, buf);
- close(f);
- }
- }
- }
- }
-
- void
- push(f, s)
- int f;
- char *s;
- {
- register int i;
- char ret='\n';
- struct termios termios;
-
- if (no_echo) {
- if (ioctl(f, TCGETS, &termios) < 0) {
- perror("ioctl 1");
- exit(1);
- }
- termios.c_lflag &= ~ECHO;
- if (ioctl(f, TCSETS, &termios) < 0) {
- perror("ioctl 2");
- exit(1);
- }
- }
-
- if (ioctl(f, TCFLSH, 0) < 0) { /* flush the input queue */
- perror("ioctl 3");
- exit(1);
- }
-
- for (i = 0; i < strlen(s); i++) /* give 'em the command */
- ioctl(f, TIOCSTI, s + i);
- ioctl(f, TIOCSTI, &ret); /* including a return */
-
- if (no_echo) {
- ioctl(f, TCGETS, &termios);
- termios.c_lflag |= ECHO;
- ioctl(f, TCSETS, &termios);
-
- ioctl(f, TCFLSH, 1); /* flush the output queue */
- }
- }
-
- void
- devchk(device, prg)
- char *device, *prg;
- {
- struct stat sb;
-
- if (strncmp(device, "/dev/tt", 7) && strncmp(device, "/dev/co", 7)) {
- fprintf(stderr, "%s: give full name [e.g. /dev/ttyp0].\n", prg);
- exit(1);
- }
- if (!strcmp(device, ttyname(0))) {
- fprintf(stderr, "%s: you can't force yourself, you masochist.\n",
- prg);
- exit(1);
- }
- if (strlen(device) > 40) {
- fprintf(stderr, "%s: terminal name too long.\n", prg);
- exit(1);
- }
-
- /*
- * there's probably a cleaner way to do this (not having the struct down
- * here at all); I considered using alloca, then decided not to. I'm open
- * to suggestions. - BK 11/20
- */
- if (stat(device, (struct stat *)&sb) < 0) {
- perror(prg);
- exit(1);
- }
- }
-