/* * acm : an aerial combat simulator for X * Copyright (C) 1991-1994 Riley Rainey * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 dated June, 1991. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave., Cambridge, MA 02139, USA. */ #include "manifest.h" #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_STDLIB_H) #include #ifndef bcopy #define bcopy(s, d, n) memcpy ((d), (s), (n)) #endif #endif extern char *getenv (); extern struct servent *getservent(); jmp_buf dead; #ifdef SIGVOID void #endif done () { longjmp (dead, 0); } main (argc, argv) int argc; char *argv[]; { char *display; char *host; char *user; char *plane; char myhost[64]; char args[256]; int s, n = 1; #ifdef _POSIX_VERSION pid_t pid; #else int pid; #endif struct passwd *pwent, *getpwuid(); struct sockaddr_in sin; struct hostent *h = (struct hostent *) NULL; (void) gethostname (myhost, sizeof(myhost)); if ((host = getenv("ACMSERVER")) == NULL) if (argc >= 2 && *argv[1] != '-') { host = argv[1]; n = 2; } else { host = malloc (strlen(myhost) + 1); (void) strcpy (host, myhost); n = 1; } if ((pwent = getpwuid(getuid())) == NULL) { (void) fprintf (stderr, "Yow!\n"); exit (1); } if ((user = getenv("ACM_HANDLE")) != NULL) { if (strncmp (user, "drone", 5) != 0) pwent->pw_name = user; } plane = getenv ("ACM_PLANE"); if ((display = getenv("DISPLAY")) == NULL) { (void) fprintf (stderr, "Excuse me, but you have no DISPLAY.\n\ How do you use X, anyway?\n"); exit (1); } /* * Sometimes we end up with a DISPLAY value that won't jive on the * network (e.g. ":0.0") -- fix these cases. Also, from Michael Pall, * if the acm server is running on the local system, allow "unix:*" and * "local:*" connections. */ if (*display == ':') { (void) strcat (myhost, display); display = myhost; } else if (strcmp (myhost, host)) { if (strncmp ("unix:", display, 5) == 0) { (void) strcat (myhost, display+4); display = myhost; } else if (strncmp ("local:", display, 6) == 0) { (void) strcat (myhost, display+5); display = myhost; } } if ((sin.sin_addr.s_addr = inet_addr (host)) != -1) { sin.sin_family = AF_INET; } else if ((h = gethostbyname (host)) != 0) { sin.sin_family = h->h_addrtype; bcopy (h->h_addr, (char *) &sin.sin_addr, h->h_length); } else { (void) fprintf (stderr, "Unknown host \"%s\"\n", host); exit (1); } sin.sin_port = htons(ACM_PORT); signal (SIGPIPE, done); reconnect: if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) { perror ("can't get a socket"); exit (1); } if (connect (s, (struct sockaddr *) &sin, sizeof (sin)) < 0) { (void) close (s); pid = fork(); if (pid == 0) { (void) fprintf (stderr, "Automatically starting server ...\n"); (void) execl ("/bin/sh", "sh", "-c", "exec acms", (char *) 0); perror ("exec of acms failed"); exit (1); } else if (pid > 0) { sleep (3); goto reconnect; } perror ("can't connect to server"); (void) close (s); exit (1); } if (argv[n] != (char *) NULL) (void) strcpy (args, argv[n++]); else (void) strcpy (args, ""); for (; argv[n] != (char *) NULL; ++n) { (void) strcat (args, "|"); (void) strcat (args, argv[n]); } if (plane) { (void) strcat (args, "|-plane|"); (void) strcat (args, plane); } if (setjmp (dead) == 0) (void) handshake (s, display, pwent->pw_name, args); exit (0); } handshake (s, dpy, name, args) int s; char *dpy, *name, *args; { char info[256]; int n; (void) sprintf (info, "%s %s %s\n", dpy, name, args); (void) write (s, info, strlen (info)); while ((n = read (s, info, sizeof (info))) > 0) (void) write (fileno (stdout), info, n); (void) shutdown (s, 2); return 0; }