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