1 #ifndef lint 2 static char *sccsid = "@(#)script.c 4.6 (Berkeley) 84/12/23"; 3 #endif 4 5 /* 6 * script 7 */ 8 #include <stdio.h> 9 #include <signal.h> 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 #include <sys/ioctl.h> 13 #include <sgtty.h> 14 #include <sys/time.h> 15 #include <sys/file.h> 16 17 char *getenv(); 18 char *ctime(); 19 char *shell; 20 FILE *fscript; 21 int master; 22 int slave; 23 int child; 24 char *fname = "typescript"; 25 int finish(); 26 27 struct sgttyb b; 28 struct tchars tc; 29 struct ltchars lc; 30 int lb; 31 int l; 32 char *line = "/dev/ptyXX"; 33 int aflg; 34 35 main(argc, argv) 36 int argc; 37 char *argv[]; 38 { 39 int f; 40 41 shell = getenv("SHELL"); 42 if (shell == 0) 43 shell = "/bin/sh"; 44 argc--, argv++; 45 while (argc > 0 && argv[0][0] == '-') { 46 switch (argv[0][1]) { 47 48 case 'a': 49 aflg++; 50 break; 51 52 default: 53 fprintf(stderr, 54 "usage: script [ -a ] [ typescript ]\n"); 55 exit(1); 56 } 57 argc--, argv++; 58 } 59 if (argc > 0) 60 fname = argv[0]; 61 if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 62 perror(fname); 63 fail(); 64 } 65 getmaster(); 66 printf("Script started, file is %s\n", fname); 67 fixtty(); 68 69 (void) signal(SIGCHLD, finish); 70 child = fork(); 71 if (child < 0) { 72 perror("fork"); 73 fail(); 74 } 75 if (child == 0) { 76 f = fork(); 77 if (f < 0) { 78 perror("fork"); 79 fail(); 80 } 81 if (f) 82 dooutput(); 83 else 84 doshell(); 85 } 86 doinput(); 87 } 88 89 doinput() 90 { 91 char ibuf[BUFSIZ]; 92 int cc; 93 94 (void) fclose(fscript); 95 while ((cc = read(0, ibuf, BUFSIZ)) > 0) 96 (void) write(master, ibuf, cc); 97 done(); 98 } 99 100 #include <sys/wait.h> 101 102 finish() 103 { 104 union wait status; 105 106 if (wait3(&status, WNOHANG, 0) != child) 107 return; 108 done(); 109 } 110 111 dooutput() 112 { 113 time_t tvec; 114 char obuf[BUFSIZ]; 115 int cc; 116 117 (void) close(0); 118 tvec = time((time_t *)0); 119 fprintf(fscript, "Script started on %s", ctime(&tvec)); 120 for (;;) { 121 cc = read(master, obuf, sizeof (obuf)); 122 if (cc <= 0) 123 break; 124 (void) write(1, obuf, cc); 125 (void) fwrite(obuf, 1, cc, fscript); 126 } 127 tvec = time((time_t *)0); 128 fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 129 (void) fclose(fscript); 130 (void) close(master); 131 exit(0); 132 } 133 134 doshell() 135 { 136 int t; 137 138 t = open("/dev/tty", O_RDWR); 139 if (t >= 0) { 140 ioctl(t, TIOCNOTTY, (char *)0); 141 (void) close(t); 142 } 143 getslave(); 144 (void) close(master); 145 (void) fclose(fscript); 146 dup2(slave, 0); 147 dup2(slave, 1); 148 dup2(slave, 2); 149 (void) close(slave); 150 execl(shell, "sh", "-i", 0); 151 perror(shell); 152 fail(); 153 } 154 155 fixtty() 156 { 157 struct sgttyb sbuf; 158 159 sbuf = b; 160 sbuf.sg_flags |= RAW; 161 sbuf.sg_flags &= ~ECHO; 162 ioctl(0, TIOCSETP, (char *)&sbuf); 163 } 164 165 fail() 166 { 167 168 (void) kill(0, SIGTERM); 169 done(); 170 } 171 172 done() 173 { 174 175 ioctl(0, TIOCSETP, (char *)&b); 176 printf("Script done, file is %s\n", fname); 177 exit(0); 178 } 179 180 getmaster() 181 { 182 char *pty, *bank, *cp; 183 struct stat stb; 184 int i; 185 186 pty = &line[strlen("/dev/ptyp")]; 187 for (bank = "pqrs"; *bank; bank++) { 188 line[strlen("/dev/pty")] = *bank; 189 *pty = '0'; 190 if (stat(line, &stb) < 0) 191 break; 192 for (cp = "0123456789abcdef"; *cp; cp++) { 193 *pty = *cp; 194 master = open(line, O_RDWR); 195 if (master >= 0) { 196 char *tp = &line[strlen("/dev/")]; 197 int ok; 198 199 /* verify slave side is usable */ 200 *tp = 't'; 201 ok = access(line, R_OK|W_OK) == 0; 202 *tp = 'p'; 203 if (ok) { 204 ioctl(0, TIOCGETP, (char *)&b); 205 ioctl(0, TIOCGETC, (char *)&tc); 206 ioctl(0, TIOCGETD, (char *)&l); 207 ioctl(0, TIOCGLTC, (char *)&lc); 208 ioctl(0, TIOCLGET, (char *)&lb); 209 return; 210 } 211 close(master); 212 } 213 } 214 } 215 fprintf(stderr, "Out of pty's\n"); 216 fail(); 217 } 218 219 getslave() 220 { 221 222 line[strlen("/dev/")] = 't'; 223 slave = open(line, O_RDWR); 224 if (slave < 0) { 225 perror(line); 226 fail(); 227 } 228 ioctl(slave, TIOCSETP, (char *)&b); 229 ioctl(slave, TIOCSETC, (char *)&tc); 230 ioctl(slave, TIOCSLTC, (char *)&lc); 231 ioctl(slave, TIOCLSET, (char *)&lb); 232 ioctl(slave, TIOCSETD, (char *)&l); 233 } 234