home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / script / script.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  5.8 KB  |  286 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)script.c    5.13 (Berkeley) 3/5/91";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * script
  46.  */
  47. #include <sys/types.h>
  48. #include <sys/stat.h>
  49. #include <termios.h>
  50. #include <sys/ioctl.h>
  51. #include <sys/time.h>
  52. #include <sys/file.h>
  53. #include <sys/signal.h>
  54. #include <stdio.h>
  55. #include <paths.h>
  56.  
  57. char    *shell;
  58. FILE    *fscript;
  59. int    master;
  60. int    slave;
  61. int    child;
  62. int    subchild;
  63. char    *fname;
  64.  
  65. struct    termios tt;
  66. struct    winsize win;
  67. int    lb;
  68. int    l;
  69. char    line[] = "/dev/ptyXX";
  70. int    aflg;
  71.  
  72. main(argc, argv)
  73.     int argc;
  74.     char *argv[];
  75. {
  76.     extern char *optarg;
  77.     extern int optind;
  78.     int ch;
  79.     void finish();
  80.     char *getenv();
  81.  
  82.     while ((ch = getopt(argc, argv, "a")) != EOF)
  83.         switch((char)ch) {
  84.         case 'a':
  85.             aflg++;
  86.             break;
  87.         case '?':
  88.         default:
  89.             fprintf(stderr, "usage: script [-a] [file]\n");
  90.             exit(1);
  91.         }
  92.     argc -= optind;
  93.     argv += optind;
  94.  
  95.     if (argc > 0)
  96.         fname = argv[0];
  97.     else
  98.         fname = "typescript";
  99.     if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) {
  100.         perror(fname);
  101.         fail();
  102.     }
  103.  
  104.     shell = getenv("SHELL");
  105.     if (shell == NULL)
  106.         shell = _PATH_BSHELL;
  107.  
  108.     getmaster();
  109.     printf("Script started, file is %s\n", fname);
  110.     fixtty();
  111.  
  112.     (void) signal(SIGCHLD, finish);
  113.     child = fork();
  114.     if (child < 0) {
  115.         perror("fork");
  116.         fail();
  117.     }
  118.     if (child == 0) {
  119.         subchild = child = fork();
  120.         if (child < 0) {
  121.             perror("fork");
  122.             fail();
  123.         }
  124.         if (child)
  125.             dooutput();
  126.         else
  127.             doshell();
  128.     }
  129.     doinput();
  130. }
  131.  
  132. doinput()
  133. {
  134.     register int cc;
  135.     char ibuf[BUFSIZ];
  136.  
  137.     (void) fclose(fscript);
  138.     while ((cc = read(0, ibuf, BUFSIZ)) > 0)
  139.         (void) write(master, ibuf, cc);
  140.     done();
  141. }
  142.  
  143. #include <sys/wait.h>
  144.  
  145. void
  146. finish()
  147. {
  148.     union wait status;
  149.     register int pid;
  150.     register int die = 0;
  151.  
  152.     while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0)
  153.         if (pid == child)
  154.             die = 1;
  155.  
  156.     if (die)
  157.         done();
  158. }
  159.  
  160. dooutput()
  161. {
  162.     register int cc;
  163.     time_t tvec, time();
  164.     char obuf[BUFSIZ], *ctime();
  165.  
  166.     (void) close(0);
  167.     tvec = time((time_t *)NULL);
  168.     fprintf(fscript, "Script started on %s", ctime(&tvec));
  169.     for (;;) {
  170.         cc = read(master, obuf, sizeof (obuf));
  171.         if (cc <= 0)
  172.             break;
  173.         (void) write(1, obuf, cc);
  174.         (void) fwrite(obuf, 1, cc, fscript);
  175.     }
  176.     done();
  177. }
  178.  
  179. doshell()
  180. {
  181.     int t;
  182.  
  183.     /***
  184.     t = open(_PATH_TTY, O_RDWR);
  185.     if (t >= 0) {
  186.         (void) ioctl(t, TIOCNOTTY, (char *)0);
  187.         (void) close(t);
  188.     }
  189.     ***/
  190.     getslave();
  191.     (void) close(master);
  192.     (void) fclose(fscript);
  193.     (void) dup2(slave, 0);
  194.     (void) dup2(slave, 1);
  195.     (void) dup2(slave, 2);
  196.     (void) close(slave);
  197.     execl(shell, "sh", "-i", 0);
  198.     perror(shell);
  199.     fail();
  200. }
  201.  
  202. fixtty()
  203. {
  204.     struct termios rtt;
  205.  
  206.     rtt = tt;
  207.     cfmakeraw(&rtt);
  208.     rtt.c_lflag &= ~ECHO;
  209.     (void) tcsetattr(0, TCSAFLUSH, &rtt);
  210. }
  211.  
  212. fail()
  213. {
  214.  
  215.     (void) kill(0, SIGTERM);
  216.     done();
  217. }
  218.  
  219. done()
  220. {
  221.     time_t tvec, time();
  222.     char *ctime();
  223.  
  224.     if (subchild) {
  225.         tvec = time((time_t *)NULL);
  226.         fprintf(fscript,"\nScript done on %s", ctime(&tvec));
  227.         (void) fclose(fscript);
  228.         (void) close(master);
  229.     } else {
  230.         (void) tcsetattr(0, TCSAFLUSH, &tt);
  231.         printf("Script done, file is %s\n", fname);
  232.     }
  233.     exit(0);
  234. }
  235.  
  236. getmaster()
  237. {
  238.     char *pty, *bank, *cp;
  239.     struct stat stb;
  240.  
  241.     pty = &line[strlen("/dev/ptyp")];
  242.     for (bank = "pqrs"; *bank; bank++) {
  243.         line[strlen("/dev/pty")] = *bank;
  244.         *pty = '0';
  245.         if (stat(line, &stb) < 0)
  246.             break;
  247.         for (cp = "0123456789abcdef"; *cp; cp++) {
  248.             *pty = *cp;
  249.             master = open(line, O_RDWR);
  250.             if (master >= 0) {
  251.                 char *tp = &line[strlen("/dev/")];
  252.                 int ok;
  253.  
  254.                 /* verify slave side is usable */
  255.                 *tp = 't';
  256.                 ok = access(line, R_OK|W_OK) == 0;
  257.                 *tp = 'p';
  258.                 if (ok) {
  259.                     (void) tcgetattr(0, &tt);
  260.                         (void) ioctl(0, TIOCGWINSZ, 
  261.                         (char *)&win);
  262.                     return;
  263.                 }
  264.                 (void) close(master);
  265.             }
  266.         }
  267.     }
  268.     fprintf(stderr, "Out of pty's\n");
  269.     fail();
  270. }
  271.  
  272. getslave()
  273. {
  274.  
  275.     line[strlen("/dev/")] = 't';
  276.     slave = open(line, O_RDWR);
  277.     if (slave < 0) {
  278.         perror(line);
  279.         fail();
  280.     }
  281.     (void) tcsetattr(slave, TCSAFLUSH, &tt);
  282.     (void) ioctl(slave, TIOCSWINSZ, (char *)&win);
  283.     (void) setsid();
  284.     (void) ioctl(slave, TIOCSCTTY, 0);
  285. }
  286.