hebraize.c (16496B)
1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 2012-11-17 Antoine Amarilli <a3nm@a3nm.net> 35 * created from ttyrec 36 */ 37 38 /* 39 * script 40 */ 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 #include <termios.h> 44 #include <sys/ioctl.h> 45 #include <sys/time.h> 46 #include <sys/file.h> 47 #include <sys/signal.h> 48 #include <stdio.h> 49 #include <time.h> 50 #include <unistd.h> 51 #include <string.h> 52 #include <stdlib.h> 53 54 #if defined(SVR4) 55 #include <fcntl.h> 56 #endif /* SVR4 */ 57 58 #include <sys/time.h> 59 60 #define HAVE_inet_aton 61 #define HAVE_scsi_h 62 #define HAVE_kd_h 63 64 #define _(FOO) FOO 65 66 #ifdef HAVE_openpty 67 #include <libutil.h> 68 #endif 69 70 #if defined(SVR4) && !defined(CDEL) 71 #if defined(_POSIX_VDISABLE) 72 #define CDEL _POSIX_VDISABLE 73 #elif defined(CDISABLE) 74 #define CDEL CDISABLE 75 #else /* not _POSIX_VISIBLE && not CDISABLE */ 76 #define CDEL 255 77 #endif /* not _POSIX_VISIBLE && not CDISABLE */ 78 #endif /* SVR4 && ! CDEL */ 79 80 void done(void); 81 void fail(void); 82 void fixtty(void); 83 void getmaster(void); 84 void getslave(void); 85 void doinput(void); 86 void dooutput(void); 87 void doshell(const char*); 88 void spawnshell(); 89 90 char *shell; 91 int master; 92 int slave; 93 int child; 94 int subchild; 95 int freq; 96 97 struct termios tt; 98 struct winsize win; 99 int lb; 100 int l; 101 #if !defined(SVR4) 102 #ifndef HAVE_openpty 103 char line[] = "/dev/ptyXX"; 104 #endif 105 #endif /* !SVR4 */ 106 int aflg; 107 int force; 108 int limit; 109 char *command = NULL; 110 111 static void 112 resize(int dummy) { 113 /* transmit window change information to the child */ 114 (void) ioctl(0, TIOCGWINSZ, (char *)&win); 115 (void) ioctl(master, TIOCSWINSZ, (char *)&win); 116 } 117 118 int 119 main(argc, argv) 120 int argc; 121 char *argv[]; 122 { 123 struct sigaction sa; 124 extern int optind; 125 int ch; 126 void finish(); 127 char *getenv(); 128 129 freq = 1; 130 131 while ((ch = getopt(argc, argv, "f:h?")) != EOF) 132 switch((char)ch) { 133 case 'f': 134 freq = atoi(optarg); 135 break; 136 case 'h': 137 case '?': 138 default: 139 //fprintf(stderr, _("usage: hebraize [-u] [-e command] [-a] [-f] [-l limit] [file]\n")); 140 fprintf(stderr, _("usage: hebraize TODO\n")); 141 exit(1); 142 } 143 argc -= optind; 144 argv += optind; 145 146 shell = getenv("SHELL"); 147 if (shell == NULL) 148 shell = "/bin/sh"; 149 150 getmaster(); 151 fixtty(); 152 153 sigemptyset(&sa.sa_mask); 154 sa.sa_flags = 0; 155 sa.sa_handler = finish; 156 sigaction(SIGCHLD, &sa, NULL); 157 child = fork(); 158 if (child < 0) { 159 if (!force) perror("fork"); 160 fail(); 161 } 162 if (child == 0) { 163 subchild = child = fork(); 164 if (child < 0) { 165 if (!force) perror("fork"); 166 fail(); 167 } 168 if (child) { 169 sa.sa_flags = SA_RESTART; 170 sigaction(SIGCHLD, &sa, NULL); 171 dooutput(); 172 } else 173 doshell(command); 174 } 175 sa.sa_handler = resize; 176 sa.sa_flags = SA_RESTART; 177 sigaction(SIGWINCH, &sa, NULL); 178 doinput(); 179 180 return 0; 181 } 182 183 void 184 doinput() 185 { 186 register int cc; 187 char ibuf[BUFSIZ]; 188 189 #ifdef HAVE_openpty 190 (void) close(slave); 191 #endif 192 while ((cc = read(0, ibuf, BUFSIZ)) > 0) 193 (void) write(master, ibuf, cc); 194 done(); 195 } 196 197 #include <sys/wait.h> 198 199 void 200 finish() 201 { 202 #if defined(SVR4) 203 int status; 204 #else /* !SVR4 */ 205 union wait status; 206 #endif /* !SVR4 */ 207 register int pid; 208 209 while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) 210 if (pid == child) 211 break; 212 } 213 214 struct linebuf { 215 char str[BUFSIZ + 1]; /* + 1 for an additional NULL character.*/ 216 int len; 217 }; 218 219 220 inline int soft(unsigned char c) { 221 return c == 'e' || c == 'i' || c == 'y' || c == 'E' || c == 'I' || c == 'Y'; 222 } 223 int vowel(unsigned char c) { 224 return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y' 225 || c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' || c == 'Y'; 226 } 227 inline int final_changes(unsigned char c) { 228 return c == 0xA7 || c == 0x9E || c == 0xA0 || c == 0xA4; 229 } 230 231 void 232 dooutput() 233 { 234 int cc; 235 int i; 236 int escape = 0; 237 int ncc; 238 unsigned char last = 0; 239 unsigned char lastw = 0; 240 int may_voice = 0; 241 char obuf[BUFSIZ]; 242 char nobuf[9*BUFSIZ]; 243 int count = 0; 244 245 setbuf(stdout, NULL); 246 (void) close(0); 247 #ifdef HAVE_openpty 248 (void) close(slave); 249 #endif 250 for (;;) { 251 252 cc = read(master, obuf, BUFSIZ); 253 if (cc <= 0) 254 break; 255 ncc = 0; 256 for (i = 0; i < cc; i++) { 257 char c = obuf[i]; 258 if (escape == 0) { 259 if (last == 'c' || last == 'C') { 260 if (soft(c)) { 261 nobuf[ncc++] = 0x08; 262 nobuf[ncc++] = 0xD7; 263 nobuf[ncc++] = 0xA1; 264 } 265 } 266 if (last == 'c' || last == 'C') { 267 if (soft(c)) { 268 nobuf[ncc++] = 0x08; 269 nobuf[ncc++] = 0xD7; 270 nobuf[ncc++] = 0xA1; 271 } 272 } 273 if (last == 'g' || last == 'G') { 274 if (soft(c)) { 275 nobuf[ncc++] = 0x08; 276 nobuf[ncc++] = 0xD7; 277 nobuf[ncc++] = 0x96; 278 } 279 } 280 if ((last == 's' || last == 'S') && may_voice) { 281 if (vowel(c)) { 282 nobuf[ncc++] = 0x08; 283 nobuf[ncc++] = 0xD7; 284 nobuf[ncc++] = 0x96; 285 } 286 } 287 if (final_changes(lastw)) { 288 //printf("%c %d\n", lastw, lastw == 0x9E); 289 // nobuf[ncc++] = 'A'; 290 // nobuf[ncc++] = 'A'; 291 // nobuf[ncc++] = 'A'; 292 if (c == ' ') { 293 nobuf[ncc++] = 0x08; 294 nobuf[ncc++] = 0xD7; 295 nobuf[ncc++] = lastw - 1; 296 } 297 } 298 may_voice = 0; 299 if (!(count++ % freq)) { 300 switch (c) { 301 case 'a': 302 case 'A': 303 nobuf[ncc++] = 0xD7; 304 nobuf[ncc++] = 0x90; 305 break; 306 case 'b': 307 case 'B': 308 nobuf[ncc++] = 0xD7; 309 nobuf[ncc++] = 0x91; 310 break; 311 case 'g': 312 case 'G': 313 nobuf[ncc++] = 0xD7; 314 nobuf[ncc++] = 0x92; 315 break; 316 case 'd': 317 case 'D': 318 nobuf[ncc++] = 0xD7; 319 nobuf[ncc++] = 0x93; 320 break; 321 case 'e': 322 case 'E': 323 case 'h': 324 case 'H': 325 nobuf[ncc++] = 0xD7; 326 nobuf[ncc++] = 0x94; 327 break; 328 case 'v': 329 case 'V': 330 case 'u': 331 case 'U': 332 case 'w': 333 case 'W': 334 nobuf[ncc++] = 0xD7; 335 nobuf[ncc++] = 0x95; 336 break; 337 case 'z': 338 case 'Z': 339 case 'j': 340 case 'J': 341 // geresh, but it will make it move 342 nobuf[ncc++] = 0xD7; 343 nobuf[ncc++] = 0x96; 344 break; 345 346 case 't': 347 case 'T': 348 nobuf[ncc++] = 0xD7; 349 nobuf[ncc++] = 0x98; 350 break; 351 case 'i': 352 case 'I': 353 nobuf[ncc++] = 0xD7; 354 nobuf[ncc++] = 0x99; 355 break; 356 357 case 'l': 358 case 'L': 359 nobuf[ncc++] = 0xD7; 360 nobuf[ncc++] = 0x9C; 361 break; 362 case 'm': 363 case 'M': 364 nobuf[ncc++] = 0xD7; 365 nobuf[ncc++] = 0x9E; 366 nobuf[ncc-1] = 0x9E; 367 break; 368 case 'n': 369 case 'N': 370 nobuf[ncc++] = 0xD7; 371 nobuf[ncc++] = 0xA0; 372 break; 373 case 's': 374 case 'S': 375 nobuf[ncc++] = 0xD7; 376 nobuf[ncc++] = 0xA1; 377 may_voice = (vowel(last)); 378 break; 379 380 case 'f': 381 case 'F': 382 case 'p': 383 case 'P': 384 nobuf[ncc++] = 0xD7; 385 nobuf[ncc++] = 0xA4; 386 break; 387 388 case 'c': 389 case 'C': 390 case 'k': 391 case 'K': 392 case 'q': 393 case 'Q': 394 nobuf[ncc++] = 0xD7; 395 nobuf[ncc++] = 0xA7; 396 break; 397 case 'r': 398 case 'R': 399 nobuf[ncc++] = 0xD7; 400 nobuf[ncc++] = 0xA8; 401 break; 402 403 // schwa 404 // case 'e': 405 // case 'E': 406 nobuf[ncc++] = 0xC6; 407 nobuf[ncc++] = 0x8F; 408 break; 409 410 case 0x1B: 411 escape = 1; 412 default: 413 nobuf[ncc++] = c; 414 } 415 } else { 416 switch (c) { 417 case 0x1B: 418 escape = 1; 419 default: 420 nobuf[ncc++] = c; 421 } 422 } 423 count = count % freq; 424 last = c; 425 if (ncc) { 426 lastw = nobuf[ncc-1]; 427 //printf("set lastw to %x because read %d, eqauls %d\n", lastw, c, lastw == 0x9E); 428 } 429 } else { 430 nobuf[ncc++] = c; 431 if (escape == 1) { 432 if (c == '[') { 433 escape = 2; 434 } else { 435 if (c >= 64 && c <= 95) { 436 escape = 0; 437 } 438 } 439 } else if (escape == 2) { 440 if (c >= 64 && c <= 126) 441 escape = 0; 442 } 443 } 444 } 445 446 (void) write(1, nobuf, ncc); 447 } 448 done(); 449 } 450 451 void 452 doshell(const char* command) 453 { 454 /*** 455 int t; 456 457 t = open(_PATH_TTY, O_RDWR); 458 if (t >= 0) { 459 (void) ioctl(t, TIOCNOTTY, (char *)0); 460 (void) close(t); 461 } 462 ***/ 463 getslave(); 464 (void) close(master); 465 (void) dup2(slave, 0); 466 (void) dup2(slave, 1); 467 (void) dup2(slave, 2); 468 (void) close(slave); 469 470 spawnshell(); 471 perror(shell); 472 fail(); 473 } 474 475 void 476 fixtty() 477 { 478 struct termios rtt; 479 480 rtt = tt; 481 #if defined(SVR4) 482 #if !defined(XCASE) 483 #define XCASE 0 484 #endif 485 rtt.c_iflag = 0; 486 rtt.c_lflag &= ~(ISIG|ICANON|XCASE|ECHO|ECHOE|ECHOK|ECHONL); 487 rtt.c_oflag = OPOST; 488 rtt.c_cc[VINTR] = CDEL; 489 rtt.c_cc[VQUIT] = CDEL; 490 rtt.c_cc[VERASE] = CDEL; 491 rtt.c_cc[VKILL] = CDEL; 492 rtt.c_cc[VEOF] = 1; 493 rtt.c_cc[VEOL] = 0; 494 #else /* !SVR4 */ 495 cfmakeraw(&rtt); 496 rtt.c_lflag &= ~ECHO; 497 #endif /* !SVR4 */ 498 (void) tcsetattr(0, TCSAFLUSH, &rtt); 499 } 500 501 void 502 fail() 503 { 504 if (force) { 505 spawnshell(); 506 perror(shell); 507 } 508 (void) kill(0, SIGTERM); 509 done(); 510 } 511 512 void 513 done() 514 { 515 if (subchild) { 516 (void) close(master); 517 } else { 518 (void) tcsetattr(0, TCSAFLUSH, &tt); 519 } 520 exit(0); 521 } 522 523 void 524 getmaster() 525 { 526 #if defined(SVR4) 527 (void) tcgetattr(0, &tt); 528 (void) ioctl(0, TIOCGWINSZ, (char *)&win); 529 if ((master = open("/dev/ptmx", O_RDWR)) < 0) { 530 if (!force) perror("open(\"/dev/ptmx\", O_RDWR)"); 531 fail(); 532 } 533 #else /* !SVR4 */ 534 #ifdef HAVE_openpty 535 (void) tcgetattr(0, &tt); 536 (void) ioctl(0, TIOCGWINSZ, (char *)&win); 537 if (openpty(&master, &slave, NULL, &tt, &win) < 0) { 538 fprintf(stderr, _("openpty failed\n")); 539 fail(); 540 } 541 #else 542 #ifdef HAVE_getpt 543 if ((master = getpt()) < 0) { 544 if (!force) perror("getpt()"); 545 fail(); 546 } 547 #else 548 char *pty, *bank, *cp; 549 struct stat stb; 550 551 pty = &line[strlen("/dev/ptyp")]; 552 for (bank = "pqrs"; *bank; bank++) { 553 line[strlen("/dev/pty")] = *bank; 554 *pty = '0'; 555 if (stat(line, &stb) < 0) 556 break; 557 for (cp = "0123456789abcdef"; *cp; cp++) { 558 *pty = *cp; 559 master = open(line, O_RDWR); 560 if (master >= 0) { 561 char *tp = &line[strlen("/dev/")]; 562 int ok; 563 564 /* verify slave side is usable */ 565 *tp = 't'; 566 ok = access(line, R_OK|W_OK) == 0; 567 *tp = 'p'; 568 if (ok) { 569 (void) tcgetattr(0, &tt); 570 (void) ioctl(0, TIOCGWINSZ, 571 (char *)&win); 572 return; 573 } 574 (void) close(master); 575 } 576 } 577 } 578 fprintf(stderr, _("Out of pty's\n")); 579 fail(); 580 #endif /* not HAVE_getpt */ 581 #endif /* not HAVE_openpty */ 582 #endif /* !SVR4 */ 583 } 584 585 void 586 getslave() 587 { 588 #if defined(SVR4) 589 (void) setsid(); 590 grantpt( master); 591 unlockpt(master); 592 if ((slave = open((const char *)ptsname(master), O_RDWR)) < 0) { 593 if (!force) perror("open(fd, O_RDWR)"); 594 fail(); 595 } 596 (void) tcsetattr(slave, TCSAFLUSH, &tt); 597 (void) ioctl(slave, TIOCSWINSZ, (char *)&win); 598 (void) ioctl(slave, TIOCSCTTY, 0); 599 #else /* !SVR4 */ 600 #ifndef HAVE_openpty 601 line[strlen("/dev/")] = 't'; 602 slave = open(line, O_RDWR); 603 if (slave < 0) { 604 if (!force) perror(line); 605 fail(); 606 } 607 (void) tcsetattr(slave, TCSAFLUSH, &tt); 608 (void) ioctl(slave, TIOCSWINSZ, (char *)&win); 609 #endif 610 (void) setsid(); 611 (void) ioctl(slave, TIOCSCTTY, 0); 612 #endif /* SVR4 */ 613 } 614 615 void 616 spawnshell() 617 { 618 force = 0; 619 620 if (!command) { 621 execl(shell, strrchr(shell, '/') + 1, "-i", NULL); 622 } else { 623 execl(shell, strrchr(shell, '/') + 1, "-c", command, NULL); 624 } 625 }