1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)script.c 5.14 (Berkeley) 07/03/91"; 16 #endif /* not lint */ 17 18 /* 19 * script 20 */ 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 #include <termios.h> 24 #include <sys/ioctl.h> 25 #include <sys/time.h> 26 #include <sys/file.h> 27 #include <sys/signal.h> 28 #include <stdio.h> 29 #include <paths.h> 30 31 char *shell; 32 FILE *fscript; 33 int master; 34 int slave; 35 int child; 36 int subchild; 37 char *fname; 38 39 struct termios tt; 40 struct winsize win; 41 int lb; 42 int l; 43 char line[] = "/dev/ptyXX"; 44 int aflg; 45 46 main(argc, argv) 47 int argc; 48 char *argv[]; 49 { 50 extern char *optarg; 51 extern int optind; 52 int ch; 53 void finish(); 54 char *getenv(); 55 56 while ((ch = getopt(argc, argv, "a")) != EOF) 57 switch((char)ch) { 58 case 'a': 59 aflg++; 60 break; 61 case '?': 62 default: 63 fprintf(stderr, "usage: script [-a] [file]\n"); 64 exit(1); 65 } 66 argc -= optind; 67 argv += optind; 68 69 if (argc > 0) 70 fname = argv[0]; 71 else 72 fname = "typescript"; 73 if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 74 perror(fname); 75 fail(); 76 } 77 78 shell = getenv("SHELL"); 79 if (shell == NULL) 80 shell = _PATH_BSHELL; 81 82 (void) tcgetattr(0, &tt); 83 (void) ioctl(0, TIOCGWINSZ, (char *)&win); 84 if (openpty(&master, &slave, NULL, &tt, &win) == -1) { 85 perror("openpty"); 86 exit(1); 87 } 88 89 printf("Script started, file is %s\n", fname); 90 fixtty(); /* go raw */ 91 92 (void) signal(SIGCHLD, finish); 93 child = fork(); 94 if (child < 0) { 95 perror("fork"); 96 fail(); 97 } 98 if (child == 0) { 99 subchild = child = fork(); 100 if (child < 0) { 101 perror("fork"); 102 fail(); 103 } 104 if (child) 105 dooutput(); 106 else 107 doshell(); 108 } 109 doinput(); 110 } 111 112 doinput() 113 { 114 register int cc; 115 char ibuf[BUFSIZ]; 116 117 (void) fclose(fscript); 118 while ((cc = read(0, ibuf, BUFSIZ)) > 0) 119 (void) write(master, ibuf, cc); 120 done(); 121 } 122 123 #include <sys/wait.h> 124 125 void 126 finish() 127 { 128 union wait status; 129 register int pid; 130 register int die = 0; 131 132 while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) 133 if (pid == child) 134 die = 1; 135 136 if (die) 137 done(); 138 } 139 140 dooutput() 141 { 142 register int cc; 143 time_t tvec, time(); 144 char obuf[BUFSIZ], *ctime(); 145 146 (void) close(0); 147 tvec = time((time_t *)NULL); 148 fprintf(fscript, "Script started on %s", ctime(&tvec)); 149 for (;;) { 150 cc = read(master, obuf, sizeof (obuf)); 151 if (cc <= 0) 152 break; 153 (void) write(1, obuf, cc); 154 (void) fwrite(obuf, 1, cc, fscript); 155 } 156 done(); 157 } 158 159 doshell() 160 { 161 162 close(master); 163 (void) fclose(fscript); 164 login_tty(slave); 165 execl(shell, "sh", "-i", 0); 166 perror(shell); 167 fail(); 168 } 169 170 fixtty() 171 { 172 struct termios rtt; 173 174 rtt = tt; 175 cfmakeraw(&rtt); 176 rtt.c_lflag &= ~ECHO; 177 (void) tcsetattr(0, TCSAFLUSH, &rtt); 178 } 179 180 fail() 181 { 182 183 (void) kill(0, SIGTERM); 184 done(); 185 } 186 187 done() 188 { 189 time_t tvec, time(); 190 char *ctime(); 191 192 if (subchild) { 193 tvec = time((time_t *)NULL); 194 fprintf(fscript,"\nScript done on %s", ctime(&tvec)); 195 (void) fclose(fscript); 196 (void) close(master); 197 } else { 198 (void) tcsetattr(0, TCSAFLUSH, &tt); 199 printf("Script done, file is %s\n", fname); 200 } 201 exit(0); 202 } 203