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