Logo Search packages:      
Sourcecode: jove version File versions

portsrv.c

/**************************************************************************
 * This program is Copyright (C) 1986-2002 by Jonathan Payne.  JOVE is    *
 * provided by Jonathan and Jovehacks without charge and without          *
 * warranty.  You may copy, modify, and/or distribute JOVE, provided that *
 * this notice is included in all the source files and documentation.     *
 **************************************************************************/

/* This program is invoked by JOVE for two purposes related to PIPEPROCS:
 * - "kbd": gather tty input into lumps and send them to JOVE proper.
 * - "portsrv": gather process output into lumps and send them to JOVE
 * These functions are gathered into one program to reduce the number
 * of misc. programs to install.  The resulting program is small anyway.
 */

#include "jove.h"

#ifdef PIPEPROCS  /* almost the whole file! */

#include <signal.h>
#include <errno.h>

#include "sysprocs.h"
#include "iproc.h"

private struct lump     lump;

/* JOVE sends KBDSIG whenever it wants the kbd process (this program)
 * to stop competing for input from the keyboard.  JOVE does this when
 * JOVE realizes that there are no more interactive processes running.
 * The reason we go through all this trouble is that JOVE slows down
 * a lot when it's getting its keyboard input via a pipe.
 */

private SIGRESTYPE strt_read proto((int));

private SIGRESTYPE
hold_read(junk)
int   junk; /* passed in when invoked by a signal; of no interest */
{
      signal(KBDSIG, strt_read);
      pause();
      return SIGRESVALUE;
}

private SIGRESTYPE
strt_read(junk)
int   junk;
{
      signal(KBDSIG, hold_read);
      return SIGRESVALUE;
}

private void
kbd_process()
{
      int   pid,
            n;

      signal(SIGINT, SIG_IGN);
      pid = getpid();
      lump.header.pid = pid;

      strt_read(0);
      for (;;) {
            n = read(0, (UnivPtr) lump.data, sizeof(lump.data));
            if (n == -1) {
                  if (errno != EINTR)
                        break;

                  continue;
            }
            lump.header.nbytes = n;
            /* It is not clear what we can do if this write fails */
            do ; while (write(1, (UnivPtr) &lump, sizeof(struct header) + n) < 0
                  && errno == EINTR);
      }
}

/* This is a server for jove sub processes.  By the time we get here, our
 * standard output goes to jove's process input.
 */

private int tty_fd;

private void
proc_write(ptr, n)
UnivConstPtr      ptr;
size_t      n;
{
      /* It is not clear what we can do if this write fails */
      do ; while (write(1, ptr, n) < 0 && errno == EINTR);
}

private void
read_pipe(fd)
int   fd;
{
      register size_t   n;

      while ((lump.header.nbytes = read(fd, (UnivPtr) lump.data, sizeof lump.data)) > 0) {
            n = sizeof(struct header) + lump.header.nbytes;
            proc_write((UnivConstPtr) &lump, n);
      }
}

private void
proc_error(str)
char  *str;
{
      lump.header.pid = getpid();
      lump.header.nbytes = strlen(str);
      strcpy(lump.data, str);
      proc_write((UnivConstPtr) &lump, sizeof(struct header) + lump.header.nbytes);
      /* It is not clear what we can do if this write fails */
      do ; while (write(tty_fd, (UnivConstPtr)str, strlen(str)) < 0 && errno == EINTR);
      exit(-2);
}

private void
portsrv_process(argc, argv)
int   argc;
char  **argv;
{
      int   p[2];
      pid_t pid;

      if (pipe(p) == -1)
            proc_error("Cannot pipe jove portsrv.\n");

      switch (pid = fork()) {
      case -1:
            proc_error("portsrv: cannot fork.\n");
            /*NOTREACHED*/

      case 0:
            /* We'll intercept child's output in p[0] */
            (void) dup2(p[1], 1);
            (void) dup2(p[1], 2);
            (void) close(p[0]);
            (void) close(p[1]);

            NEWPG();
            execv(argv[1], &argv[2]);
            _exit(-4);
            /*NOTREACHED*/

      default:
            (void) close(0);
            tty_fd = open("/dev/tty", O_WRONLY | O_BINARY);

            (void) signal(SIGINT, SIG_IGN);
            (void) signal(SIGQUIT, SIG_IGN);
            (void) close(p[1]);

            /* tell jove the pid of the real child as opposed to us */
            lump.header.pid = getpid();
            lump.header.nbytes = sizeof (pid_t);
            byte_copy((UnivConstPtr) &pid, (UnivPtr) lump.data, sizeof(pid_t));
            /* It is not clear what we can do if this write fails */
            do ; while (write(1, (UnivConstPtr) &lump, sizeof(struct header) + sizeof(pid_t)) < 0
                  && errno == EINTR);

            /* read proc's output and send it to jove */
            read_pipe(p[0]);

            /* received EOF - wait for child to die and then write the
             * child's status to JOVE.
             *
             * Notice that we use a byte count of -1 (an otherwise
             * impossible value) as a marker.  JOVE "knows" the real
             * length is sizeof(wait_status_t).
             */

            (void) close(p[0]);
            lump.header.pid = getpid();
            lump.header.nbytes = -1;      /* tell jove we are finished */
            /* try to exit like our child did ... */
            {
                  wait_status_t     status;

                  do ; while (wait(&status) != pid);
                  byte_copy((UnivPtr)&status, (UnivPtr)lump.data,
                        sizeof(status));
            }
            /* It is not clear what we can do if this write fails */
            do ; while (write(1, (UnivConstPtr) &lump,
                  sizeof(struct header) + sizeof(wait_status_t)) < 0
                        && errno == EINTR);
      }
}

int
main(argc, argv)
int   argc;
char  **argv;
{
      if (strcmp(argv[0], "kbd") == 0)
            kbd_process();
      else
            portsrv_process(argc, argv);
      return 0;
}

#else /* !PIPEPROCS */
int
main()
{
      return 0;
}
#endif /* !PIPEPROCS */

Generated by  Doxygen 1.6.0   Back to index