/* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: main.c,v 1.5 1998/09/30 23:58:17 itojun Exp $ */ /* * Most of X11 code was derived from twiddler driver. */ #include #include #include #include #include #include #include #include #include #include #ifdef X_DISPLAY_MISSING # error this program cannot be compiled without X11. #endif #ifndef REMOTE_DEVICE # define REMOTE_DEVICE "/dev/tty02" /*biased to VAIO505 :-P*/ #endif static char *remote = REMOTE_DEVICE; static int debug = 0; #define dprintf(x) { if (debug) fprintf x; } static int verbose = 0; #define verbmsg(x) { if (verbose) fprintf x; } Display *display = NULL; static uid_t uid, euid; static gid_t gid, egid; static int uidswapped = 0; static void usage __P((void)); static void mainloop __P((int)); static void buttonpress __P((int, int)); static int uucplock __P((char *)); static int uucpunlock __P((char *)); static RETSIGTYPE sigtrap __P((int)); static void daemonuid __P((void)); static void useruid __P((void)); #define EFFECT 0x15 #define LEFT 0x16 #define RIGHT 0x17 #define RELEASE 0x55 int main(argc, argv) int argc; char **argv; { int fd; struct termios old, raw; int ch; extern int optind; extern char *optarg; uid = getuid(); euid = geteuid(); gid = getgid(); egid = getegid(); useruid(); while ((ch = getopt(argc, argv, "df:v")) != EOF) { switch (ch) { case 'd': debug++; break; case 'f': remote = optarg; break; case 'v': verbose++; break; default: usage(); /*NOTREACHED*/ } } argc -= optind; argv += optind; fprintf(stderr, "initializing...\r"); verbmsg((stderr, "initializing X11... ")); display = XOpenDisplay(getenv("DISPLAY")); if (!display) errx(1, "opening X11 display"); verbmsg((stderr, "done.\n")); verbmsg((stderr, "initializing serial port %s... ", remote)); daemonuid(); if (!strchr(remote, '/')) { char *p; p = (char *)malloc(strlen("/dev/") + strlen(remote) + 1); if (!p) err(1, "malloc"); sprintf(p, "/dev/%s", remote); remote = p; } if (uucplock(remote) < 0) { errx(1, "cannot lock %s", remote); /*NOTREACHED*/ } signal(SIGINT, sigtrap); signal(SIGHUP, sigtrap); fd = open(remote, O_NONBLOCK); if (fd < 0) { uucpunlock(remote); err(1, "%s", remote); /*NOTREACHED*/ } tcgetattr(fd, &old); raw = old; cfmakeraw(&raw); cfsetspeed(&raw, B1200); raw.c_cflag &= ~(CSIZE|PARENB|CSTOPB|MDMBUF); raw.c_cflag |= CS8|CREAD|CLOCAL; tcsetattr(fd, TCSANOW, &raw); sleep(1); close(fd); sleep(1); fd = open(remote, O_RDONLY); if (fd < 0) { uucpunlock(remote); err(1, "%s", remote); /*NOTREACHED*/ } useruid(); verbmsg((stderr, "done.\n")); fprintf(stderr, "xmindpath ready.\n"); fprintf(stderr, "\007"); mainloop(fd); uucpunlock(remote); exit(0); } static void usage() { fprintf(stderr, "usage: xmindpath [-dv] [-f dev]\n"); exit(0); } static void mainloop(fd) int fd; { struct timeval tv; struct fd_set rfd; u_char buf[BUFSIZ]; int nfd; int len; int heartbeat = 0; int i; int keystate; keystate = 0; while (1) { tv.tv_sec = 0; tv.tv_usec = 500*1000; FD_ZERO(&rfd); FD_SET(fd, &rfd); nfd = select(fd + 1, &rfd, 0, 0, &tv); if (nfd < 0) { uucpunlock(remote); err(1, "select"); /*NOTREACHED*/ } switch (nfd) { case 0: /*timeout*/ dprintf((stderr, "%c\r", "\\|/-"[heartbeat++ % 4])); break; case 1: len = read(fd, buf, sizeof(buf)); for (i = 0; i < len; i++) { /* filter out bogus remote commander code */ switch (buf[i]) { case LEFT: case RIGHT: case EFFECT: case RELEASE: break; default: dprintf((stderr, "bogus char: %02x\n", buf[i])); continue; } switch (buf[i]) { case LEFT: dprintf((stderr, "left\n")); buttonpress(Button3, 1); break; case RIGHT: dprintf((stderr, "right\n")); buttonpress(Button1, 1); break; case EFFECT: dprintf((stderr, "effect\n")); buttonpress(Button2, 1); break; case RELEASE: dprintf((stderr, "release\n")); buttonpress(Button1, 0); buttonpress(Button2, 0); buttonpress(Button3, 0); break; default: dprintf((stderr, "%02x\n", buf[i])); continue; } } break; default: dprintf((stderr, "select=%d\n", nfd)); break; } } } /* fake mouse button press */ static void buttonpress(button, state) int button; int state; { int offset; static int buttonstate[5]; /* X11 defines 5 buttons */ offset = button - Button1; if (offset < 0 || sizeof(buttonstate)/sizeof(buttonstate[0]) <= offset) return; /* edge trigger */ if ((buttonstate[offset] && state) || (!buttonstate[offset] && !state)) return; XTestFakeButtonEvent(display, button, state ? True : False, 0); buttonstate[offset] = state; XFlush(display); } static int uucplock(name) char *name; { return uu_lock(strrchr(name, '/') + 1); } static int uucpunlock(name) char *name; { return uu_unlock(strrchr(name, '/') + 1); } static RETSIGTYPE sigtrap(no) int no; { uucpunlock(remote); exit(1); } static void daemonuid() { if (uidswapped == 0) return; #ifdef HAVE_SETREUID setreuid(uid, euid); setregid(gid, egid); #else setuid(uid); seteuid(euid); setgid(gid); setegid(egid); #endif uidswapped = 0; } static void useruid() { if (uidswapped == 1) return; #ifdef HAVE_SETREUID setregid(egid, gid); setreuid(euid, uid); #else setgid(egid); setegid(gid); setuid(euid); seteuid(uid); #endif uidswapped = 1; }