home *** CD-ROM | disk | FTP | other *** search
- /* ACS - Auto Console Switching */
- /* What this does is allows you to specify VTs (virtual terminals, */
- /* also known as consoles) to watch. When it detects new data on */
- /* this tty it will automatically switch. */
- /* */
- /* This allows you to do many things at once such as: */
- /* 1.) IRC on one VT */
- /* 2.) IRC on a different IRC network on another */
- /* 3.) wait for a web page to load up on another */
- /* 4.) wait for telnet to connect to a site on another */
- /* */
- /* Compile with -DBEEPONLY to cause a beep on new activity, rather */
- /* than switching to the console with new activity. */
- /* */
- /* Note: This should work on Linux and *BSD systems. */
- /* */
- /* So you can see the uses of this. Enjoy. */
- /* Shok (Matt Conover), shok@dataforce.net */
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <signal.h>
- #include <sys/stat.h>
- #include <linux/vt.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
-
- #define ERROR -1
- #define MAXVTNUM 63
-
- struct vcs {
- int fd;
- char curbuf[6666], prevbuf[6666];
- } vcs[MAXVTNUM];
-
- int fd;
-
- void clean(int val);
- void syntax(char **argv);
- void parse(int argc, char **argv);
-
- void sighandler(int signum);
-
- void main(int argc, char **argv)
- {
- char buf[512];
- register int i;
- register int tty;
-
- memset(buf, 0, sizeof(buf));
-
- for (i = 0 ; i < MAXVTNUM; i++)
- {
- vcs[i].fd = -1, vcs[i].curbuf[0] = 0;
-
- bzero(vcs[i].curbuf, sizeof(vcs[i].curbuf));
- bzero(vcs[i].prevbuf, sizeof(vcs[i].prevbuf));
- }
-
- /* --------------- */
-
- parse(argc, argv); /* Take care of arguments (such as the VTs), */
- /* as well as open the files. */
-
- /* Turn into a daemon, exit the parent. */
- if (fork() != 0) exit(0);
-
- /* Need to switch to the active console. tty is what we pass */
- /* to ioctl() with VT_ACTIVATE. */
- if ((tty = open("/dev/tty", O_RDWR)) == ERROR)
- {
- fprintf(stderr, "error with open(): %s\n", strerror(errno));
- exit(ERROR);
- }
-
- /* Used so that when we receive a signal to abort, we close up */
- /* all the open file descriptors, and give them a message that */
- /* we are aborting. If this is run as a daemon, then you would */
- /* have to send it with kill -2, -3 or -15. */
- signal(SIGINT, sighandler);
- signal(SIGTERM, sighandler);
- signal(SIGQUIT, sighandler);
-
- while (1)
- {
- for (i = 0; i < MAXVTNUM; i++)
- {
- if (vcs[i].fd != -1)
- {
- /* Copy the current buffer into the previous one, */
- /* for later use. */
- strcpy(vcs[i].prevbuf, vcs[i].curbuf);
-
- /* Get to the beginning of the screen. */
- lseek(vcs[i].fd, 0, SEEK_SET);
-
- if ((read(vcs[i].fd, vcs[i].curbuf, sizeof(vcs[i].curbuf)))
- == ERROR) {
- perror("read");
- clean(ERROR);
- }
-
- /* Compare the buffer of the previous screen dumb with */
- /* this one. If they are different, new data has been */
- /* received and we switch consoles. */
-
- if ((strcmp(vcs[i].curbuf, vcs[i].prevbuf) != 0)
- && (vcs[i].prevbuf[0] != 0))
- {
- # ifdef BEEPONLY
- ioctl(tty, VT_ACTIVATE, i+1);
- # else
- write(tty, '\a', 1);
- # endif
- usleep(500000);
- }
- }
- }
- }
- }
-
- void parse(int argc, char **argv)
- {
- int i;
- char *p;
- char buf[512], bfa[512];
-
- if (argc < 2) syntax(argv);
-
- sprintf(buf, "Watching ");
-
- for (argc--; argc; argc--)
- {
- if (strcasecmp(argv[argc], "all") == 0)
- {
- for (i = 0; i < MAXVTNUM; i++)
- {
- sprintf(buf, "/dev/vcs%d", i+1);
-
- vcs[i].fd = open(buf, O_RDONLY | O_NOCTTY);
- if (vcs[i].fd == ERROR)
- {
- fprintf(stderr, "error with open(): %s\n", strerror(errno));
- clean(ERROR);
- }
- }
-
- printf("Watching all tty's...\n");
- return;
- }
-
- if (strncasecmp(argv[argc], "tty", 3) != 0) syntax(argv);
-
- strcat(buf, argv[argc]), strcat(buf, " ");
- p = (argv[argc]+3);
-
- sprintf(bfa, "/dev/vcs%d", atoi(p));
- vcs[atoi(p) - 1].fd = i = open(bfa, O_RDONLY | O_NOCTTY);
-
- if (vcs[atoi(p) - 1].fd == ERROR)
- {
- fprintf(stderr, "error with open(): %s\n", strerror(errno));
- clean(ERROR);
- }
- }
-
- buf[strlen(buf) - 1] = 0;
-
- strcat(buf, "...\n");
- printf(buf);
- }
-
- void syntax(char **argv)
- {
- printf("Syntax: %s <all | tty2 tty3 ttyX ...>\n", argv[0]);
- exit(ERROR);
- }
-
- void clean(int val)
- {
- register int i;
-
- for (i = 0; i < MAXVTNUM; i++)
- if (vcs[i].fd != -1) close(vcs[i].fd);
-
- close(fd);
- exit(val);
- }
-
- void sighandler(int signum)
- {
- char msg[] = "Received signal to abort. Now exiting.\n";
-
- close(fd);
-
- fd = open("/dev/tty", O_NOCTTY | O_WRONLY);
- if (fd == ERROR)
- {
- printf(msg);
- clean(signum);
- }
-
- /* Give aborting message to current VT. */
- write(fd, msg, sizeof(msg));
-
- clean(signum);
- }
-