home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8709 / 12 < prev    next >
Encoding:
Text File  |  1990-07-13  |  7.3 KB  |  275 lines

  1. Path: uunet!seismo!sundc!pitstop!sun!decwrl!decvax!ima!necntc!ncoast!allbery
  2. From: eric@ms.uky.edu@mandrill.CWRU.Edu (Eric Herrin)
  3. Newsgroups: comp.sources.misc
  4. Subject: System V session recorder (uses ptys)
  5. Keywords: session recorder, pty
  6. Message-ID: <4555@ncoast.UUCP>
  7. Date: 24 Sep 87 00:45:15 GMT
  8. Sender: allbery@ncoast.UUCP
  9. Organization: U of Ky, Math. Sciences, Lexington KY
  10. Lines: 261
  11. Approved: allbery@ncoast.UUCP
  12. X-Archive: comp.sources.misc/8709/12
  13.  
  14. Here's a cute little utility I had to write to allow students to 
  15. record terminal sessions.  It works with the System V pty driver I 
  16. posted earlier for the UnixPC, but should work on any System V box
  17. with ptys.  Hope it can be useful to someone else.
  18.  
  19.             eric
  20.  
  21.  
  22. |                                          | 
  23. |    Eric Herrin II                         cbosgd!ukma!eric      |
  24. |    "'tis better to be silent                             eric@UKMA.BITNET      |
  25. |     and be THOUGHT a fool, than to open                  eric@ms.uky.csnet     |
  26. |     one's mouth and remove all doubt."                eric@ms.uky.edu       |
  27.  
  28. ______________________ cut here _________________________
  29. #! /bin/sh
  30. : This is a shell archive, meaning:
  31. : 1. Remove everything above the '#! /bin/sh' line.
  32. : 2. Save the resulting text in a file.
  33. : 3. Execute the file with /bin/sh '(not csh)' to create the files:
  34. :    'session.c'
  35. :    'session.mk'
  36. : This archive created: 'Sun Sep 20 12:02:40 1987
  37. '
  38. export PATH; PATH=/bin:$PATH
  39. echo shar: extracting "'session.c'" '(4397 characters)'
  40. if test -f 'session.c'
  41. then
  42.     echo shar: will not over-write existing file "'session.c'"
  43. else
  44. sed 's/^X//'  >'session.c' <<'SHAR_EOF'
  45. X/* Copyright (c) 1987 University of Kentucky Mathematical Sciences
  46. X * Eric H. Herrin II
  47. X * eric@ms.uky.edu, eric@ms.uky.csnet, !cbosgd!ukma!eric
  48. X * 
  49. X * Permission is hereby granted to modify and redistribute
  50. X * this program for non-commercial use, provided this copyright
  51. X * notice is retained in all versions.
  52. X */
  53. X
  54. X/* session.c - record a terminal session into a file for UNIX System V.
  55. X * 
  56. X * Usage: session [filename]
  57. X */
  58. X#include <stdio.h>
  59. X#include <fcntl.h>
  60. X#include <errno.h>
  61. X#include <signal.h>
  62. X#include <termio.h>
  63. X#include <sys/ttold.h>
  64. X
  65. X#define SHELL         "/bin/ksh"
  66. X#define SHELLARG     "ksh"
  67. X#define BYTES        1
  68. X
  69. XFILE        *recordfile, *fopen();
  70. Xint        pty, tty;
  71. Xstruct sgttyb    savesgbuf;
  72. Xchar        *slave="/dev/ttyXX", *master="/dev/ptyXX";
  73. X
  74. Xmain(argc, argv)
  75. X    int        argc;
  76. X    char        *argv[];
  77. X{
  78. X    int        p, s;
  79. X    int        bytes;
  80. X    char        buf[BYTES];
  81. X    char        *filename;
  82. X    struct sgttyb    sgbuf;
  83. X    void        cleanup();
  84. X
  85. X    if (argc > 2) {
  86. X        fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
  87. X        exit(1);
  88. X    } else if (argc == 2)
  89. X        filename = argv[1];
  90. X    else
  91. X        filename = "session_file";
  92. X
  93. X    if ((recordfile = fopen(filename, "w")) == NULL) {
  94. X        fprintf(stderr, "%s: cannot open %s.\n", argv[0], filename);
  95. X        exit(1);
  96. X    }
  97. X    signal(SIGTERM, cleanup);
  98. X    OpenPtys(slave, master, &tty, &pty);
  99. X    /* fork off a process to handle the setup of the tty for the
  100. X     * shell and execing the shell.
  101. X     */
  102. X    if (fork() == 0) {
  103. X        struct termio    tio;
  104. X
  105. X        close(pty);
  106. X        /* setpgrp to associate the process with the pty.
  107. X         */
  108. X        setpgrp();
  109. X        if ((tty = open(slave, O_RDWR)) < 0) {
  110. X            printf("ERROR: open slave: errno = %d\n", errno);
  111. X            exit(1);
  112. X        }
  113. X        /* set up the tty end of the pty to be the std[in,out,err]
  114. X         * of the new shell.
  115. X         */
  116. X        close(0); dup(tty);
  117. X        close(1); dup(tty);
  118. X        close(2); dup(tty);
  119. X        /* set up some reasonable parameters for the pty, ie.
  120. X         * let the shell have a normal environment.
  121. X         */
  122. X            ioctl(0, TCGETA, &tio);
  123. X            tio.c_cc[VINTR] = '';
  124. X        tio.c_cc[VERASE] = '';
  125. X            tio.c_cc[VKILL] = '';
  126. X            tio.c_cc[VEOF] = '';
  127. X            tio.c_iflag &= ~(IGNBRK | PARMRK | INPCK | INLCR | IGNCR | IUCLC);
  128. X        tio.c_iflag |= (BRKINT | IGNPAR | ISTRIP | ICRNL | IXON);
  129. X            tio.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL);
  130. X            tio.c_oflag |= (OPOST);
  131. X            tio.c_oflag |= (ONLCR); /*?*/
  132. X            tio.c_lflag |= (ISIG | ICANON | ECHO | ECHOK);
  133. X            tio.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | PARODD | HUPCL | CLOCAL);
  134. X            tio.c_cflag |= (B9600 | CS7 | CREAD | PARENB);
  135. X            ioctl(0, TCSETAW, &tio);
  136. X        /* exec the shell
  137. X         */
  138. X        execl(SHELL, SHELLARG, "-i", 0);
  139. X        fprintf(stderr, "exec of /bin/sh failed\n");
  140. X        exit(1);
  141. X    }
  142. X    close(tty);
  143. X    /* master process, device end of tty 
  144. X     */
  145. X    ioctl(0, TIOCGETP, &savesgbuf);
  146. X    sgbuf = savesgbuf;
  147. X    sgbuf.sg_flags |= O_RAW;
  148. X    sgbuf.sg_flags &= ~O_ECHO;
  149. X    ioctl(0, TIOCSETP, &sgbuf);
  150. X    /* fork off a reader of the pty master end.
  151. X     */
  152. X    if (fork() ==  0) {
  153. X        while ((bytes=read(pty, buf, BYTES)) > 0) {
  154. X            fwrite(buf, 1, bytes, stdout);
  155. X            fwrite(buf, 1, bytes, recordfile);
  156. X            fflush(stdout);
  157. X        }
  158. X        exit(0);
  159. X    }
  160. X    /* fork off a writer of the pty master end.
  161. X     */
  162. X    if (fork() == 0) {
  163. X        while ((bytes=read(0, buf, BYTES)) > 0)
  164. X            write(pty, buf, bytes);
  165. X        exit(0);
  166. X    }
  167. X    /* The shell is the only process which will exit on its own.
  168. X     * wait for it.
  169. X     */
  170. X    wait((int *)0); 
  171. X    /* terminate last line, ^D from shell won't do it.
  172. X     */
  173. X    fprintf(recordfile, "\n");
  174. X    /* shell is already dead, so kill everybody else after cleanup.
  175. X     */
  176. X    kill(0, SIGTERM);
  177. X    close(pty);
  178. X    fclose(recordfile);
  179. X}
  180. X
  181. Xvoid cleanup()
  182. X{
  183. X    fclose(recordfile);
  184. X    close(tty);
  185. X    close(pty);
  186. X    ioctl(0, TIOCSETP, &savesgbuf);
  187. X    exit(0);
  188. X}
  189. X
  190. XOpenPtys(slave, master, tty, pty)
  191. X    char        *slave, *master;
  192. X    int        *tty, *pty;
  193. X{
  194. X    int        i, j;
  195. X    int        tmaster;
  196. X    int        letcnt=0, numcnt=0;
  197. X    static char    *letters = "pqrstuvwxyz",
  198. X            *numbers = "0123456789abcdef";
  199. X    static int    letmax, nummax;
  200. X
  201. X    letmax=strlen(letters)-1, nummax=strlen(numbers)-1;
  202. X    do {
  203. X        master[strlen("/dev/pty")] = letters[letcnt];
  204. X        master[strlen("/dev/ptyX")] = numbers[numcnt];
  205. X        if (letcnt > letmax) {
  206. X            fprintf(stderr, "ERROR: all ptys in use\n");
  207. X            exit(1);
  208. X        } else if (++numcnt > nummax) {
  209. X            letcnt++;
  210. X            numcnt = 0;
  211. X        } 
  212. X    } while ((*pty=open(master, O_RDWR)) < 0);
  213. X    /* got a free pty. 
  214. X     */
  215. X    slave[8] = master[8];
  216. X    slave[9] = master[9];
  217. X    if ((*tty = open(slave, O_RDWR)) < 0) {
  218. X        fprintf(stderr, "ERROR: opening slave: errno = %d\n", errno);
  219. X        exit(1);
  220. X    }
  221. X}
  222. SHAR_EOF
  223. echo shar: 4 control characters may be missing from "'session.c'"
  224. if test 4397 -ne "`wc -c < 'session.c'`"
  225. then
  226.     echo shar: error transmitting "'session.c'" '(should have been 4397 characters)'
  227. fi
  228. fi # end of overwriting check
  229. echo shar: extracting "'session.mk'" '(642 characters)'
  230. if test -f 'session.mk'
  231. then
  232.     echo shar: will not over-write existing file "'session.mk'"
  233. else
  234. sed 's/^X//'  >'session.mk' <<'SHAR_EOF'
  235. X# session.mk
  236. X# Copyright (c) 1987 University of Kentucky Mathematical Sciences
  237. X# Eric H. Herrin II
  238. X# eric@ms.uky.edu, eric@ms.uky.csnet, !cbosgd!ukma!eric
  239. X# 
  240. X# Permission is hereby granted to modify and redistribute
  241. X# this program for non-commercial use, provided this copyright
  242. X# notice is retained in all versions.
  243. X#
  244. X
  245. XSRCS = session.c
  246. XOBJS = session.o
  247. XINSDIR = /usr/local/bin
  248. XCFLAGS = -O -c
  249. X
  250. X.c.o:
  251. X    ${CC} ${CFLAGS} $<
  252. X
  253. Xsession: session.o
  254. X    ${CC} ${OBJS} -o session
  255. X
  256. Xinstall: session
  257. X    cp session ${INSDIR}
  258. X    chown bin ${INSDIR}/session
  259. X    chgrp bin ${INSDIR}/session    
  260. X    chmod 555 ${INSDIR}/session
  261. X
  262. Xclean:
  263. X    rm -f *.o
  264. X
  265. Xclobber:
  266. X    rm -f *.o session
  267. SHAR_EOF
  268. if test 642 -ne "`wc -c < 'session.mk'`"
  269. then
  270.     echo shar: error transmitting "'session.mk'" '(should have been 642 characters)'
  271. fi
  272. fi # end of overwriting check
  273. :    End of shell archive
  274. exit 0
  275.