|
|
1.1 ! root 1: /* tstuu.c ! 2: Test the uucp package on a UNIX system. ! 3: ! 4: Copyright (C) 1991, 1992 Ian Lance Taylor ! 5: ! 6: This file is part of the Taylor UUCP package. ! 7: ! 8: This program is free software; you can redistribute it and/or ! 9: modify it under the terms of the GNU General Public License as ! 10: published by the Free Software Foundation; either version 2 of the ! 11: License, or (at your option) any later version. ! 12: ! 13: This program is distributed in the hope that it will be useful, but ! 14: WITHOUT ANY WARRANTY; without even the implied warranty of ! 15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 16: General Public License for more details. ! 17: ! 18: You should have received a copy of the GNU General Public License ! 19: along with this program; if not, write to the Free Software ! 20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 21: ! 22: The author of the program may be contacted at [email protected] or ! 23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. ! 24: */ ! 25: ! 26: #include "uucp.h" ! 27: ! 28: #if USE_RCS_ID ! 29: const char tstuu_rcsid[] = "$Id: tstuu.c,v 1.1 93/07/30 07:54:26 bin Exp Locker: bin $"; ! 30: #endif ! 31: ! 32: #include "sysdep.h" ! 33: #include "system.h" ! 34: #include "getopt.h" ! 35: ! 36: #include <stdio.h> ! 37: #include <ctype.h> ! 38: #include <errno.h> ! 39: ! 40: #if HAVE_SYS_TIMES_H ! 41: #include <sys/times.h> ! 42: #endif ! 43: ! 44: #if HAVE_SYS_IOCTL_H ! 45: #include <sys/ioctl.h> ! 46: #endif ! 47: ! 48: #if HAVE_SELECT ! 49: #include <sys/time.h> ! 50: #if HAVE_SYS_SELECT_H ! 51: #include <sys/select.h> ! 52: #endif ! 53: #endif ! 54: ! 55: #if HAVE_POLL ! 56: #if HAVE_STROPTS_H ! 57: #include <stropts.h> ! 58: #endif ! 59: #if HAVE_POLL_H ! 60: #include <poll.h> ! 61: #endif ! 62: #endif ! 63: ! 64: #if HAVE_FCNTL_H ! 65: #include <fcntl.h> ! 66: #else ! 67: #if HAVE_SYS_FILE_H ! 68: #include <sys/file.h> ! 69: #endif ! 70: #endif ! 71: ! 72: #ifndef O_RDONLY ! 73: #define O_RDONLY 0 ! 74: #define O_WRONLY 1 ! 75: #define O_RDWR 2 ! 76: #endif ! 77: ! 78: #if HAVE_TIME_H && (HAVE_SYS_TIME_AND_TIME_H || ! HAVE_SELECT) ! 79: #include <time.h> ! 80: #endif ! 81: ! 82: #if HAVE_SYS_WAIT_H ! 83: #include <sys/wait.h> ! 84: #endif ! 85: ! 86: #if HAVE_UNION_WAIT ! 87: typedef union wait wait_status; ! 88: #else ! 89: typedef int wait_status; ! 90: #endif ! 91: ! 92: #if HAVE_STREAMS_PTYS ! 93: #include <termio.h> ! 94: extern char *ptsname (); ! 95: #endif ! 96: ! 97: /* Get definitions for both O_NONBLOCK and O_NDELAY. */ ! 98: ! 99: #ifndef O_NDELAY ! 100: #ifdef FNDELAY ! 101: #define O_NDELAY FNDELAY ! 102: #else /* ! defined (FNDELAY) */ ! 103: #define O_NDELAY 0 ! 104: #endif /* ! defined (FNDELAY) */ ! 105: #endif /* ! defined (O_NDELAY) */ ! 106: ! 107: #ifndef O_NONBLOCK ! 108: #ifdef FNBLOCK ! 109: #define O_NONBLOCK FNBLOCK ! 110: #else /* ! defined (FNBLOCK) */ ! 111: #define O_NONBLOCK 0 ! 112: #endif /* ! defined (FNBLOCK) */ ! 113: #endif /* ! defined (O_NONBLOCK) */ ! 114: ! 115: #if O_NDELAY == 0 && O_NONBLOCK == 0 ! 116: #error No way to do nonblocking I/O ! 117: #endif ! 118: ! 119: /* Get definitions for EAGAIN, EWOULDBLOCK and ENODATA. */ ! 120: #ifndef EAGAIN ! 121: #ifndef EWOULDBLOCK ! 122: #define EAGAIN (-1) ! 123: #define EWOULDBLOCK (-1) ! 124: #else /* defined (EWOULDBLOCK) */ ! 125: #define EAGAIN EWOULDBLOCK ! 126: #endif /* defined (EWOULDBLOCK) */ ! 127: #else /* defined (EAGAIN) */ ! 128: #ifndef EWOULDBLOCK ! 129: #define EWOULDBLOCK EAGAIN ! 130: #endif /* ! defined (EWOULDBLOCK) */ ! 131: #endif /* defined (EAGAIN) */ ! 132: ! 133: #ifndef ENODATA ! 134: #define ENODATA EAGAIN ! 135: #endif ! 136: ! 137: /* Make sure we have a CLK_TCK definition, even if it makes no sense. ! 138: This is in case TIMES_TICK is defined as CLK_TCK. */ ! 139: #ifndef CLK_TCK ! 140: #define CLK_TCK (60) ! 141: #endif ! 142: ! 143: /* Don't try too hard to get a TIMES_TICK value; it doesn't matter ! 144: that much. */ ! 145: #if TIMES_TICK == 0 ! 146: #undef TIMES_TICK ! 147: #define TIMES_TICK CLK_TCK ! 148: #endif ! 149: ! 150: #if TIMES_DECLARATION_OK ! 151: extern long times (); ! 152: #endif ! 153: ! 154: #ifndef SIGCHLD ! 155: #define SIGCHLD SIGCLD ! 156: #endif ! 157: ! 158: #if 1 ! 159: #define ZUUCICO_CMD "login uucp" ! 160: #define UUCICO_EXECL "/bin/login", "login", "uucp" ! 161: #else ! 162: #define ZUUCICO_CMD "su - nuucp" ! 163: #define UUCICO_EXECL "/bin/su", "su", "-", "nuucp" ! 164: #endif ! 165: ! 166: #if ! HAVE_SELECT && ! HAVE_POLL ! 167: #error You need select or poll ! 168: #endif ! 169: ! 170: #if ! HAVE_REMOVE ! 171: #undef remove ! 172: #define remove unlink ! 173: #endif ! 174: ! 175: /* Buffer chain to hold data read from a uucico. */ ! 176: ! 177: #define BUFCHARS (512) ! 178: ! 179: struct sbuf ! 180: { ! 181: struct sbuf *qnext; ! 182: int cstart; ! 183: int cend; ! 184: char ab[BUFCHARS]; ! 185: }; ! 186: ! 187: /* Local functions. */ ! 188: ! 189: static void umake_file P((const char *zfile, int cextra)); ! 190: static void uprepare_test P((boolean fmake, int itest, ! 191: boolean fcall_uucico, ! 192: const char *zsys)); ! 193: static void ucheck_file P((const char *zfile, const char *zerr, ! 194: int cextra)); ! 195: static void ucheck_test P((int itest, boolean fcall_uucico)); ! 196: static RETSIGTYPE uchild P((int isig)); ! 197: static int cpshow P((char *z, int bchar)); ! 198: static void uchoose P((int *po1, int *po2)); ! 199: static long cread P((int o, struct sbuf **)); ! 200: static boolean fsend P((int o, int oslave, struct sbuf **)); ! 201: static boolean fwritable P((int o)); ! 202: static void xsystem P((const char *zcmd)); ! 203: static FILE *xfopen P((const char *zname, const char *zmode)); ! 204: ! 205: static char *zDebug; ! 206: static int iTest; ! 207: static boolean fCall_uucico; ! 208: static int iPercent; ! 209: static pid_t iPid1, iPid2; ! 210: static int cFrom1, cFrom2; ! 211: static char abLogout1[sizeof "tstout /dev/ptyp0"]; ! 212: static char abLogout2[sizeof "tstout /dev/ptyp0"]; ! 213: static char *zProtocols; ! 214: ! 215: int ! 216: main (argc, argv) ! 217: int argc; ! 218: char **argv; ! 219: { ! 220: int iopt; ! 221: const char *zcmd1, *zcmd2; ! 222: const char *zsys; ! 223: boolean fmake = TRUE; ! 224: int omaster1, oslave1, omaster2, oslave2; ! 225: char abpty1[sizeof "/dev/ptyp0"]; ! 226: char abpty2[sizeof "/dev/ptyp0"]; ! 227: struct sbuf *qbuf1, *qbuf2; ! 228: ! 229: zcmd1 = NULL; ! 230: zcmd2 = NULL; ! 231: zsys = "test2"; ! 232: ! 233: while ((iopt = getopt (argc, argv, "c:np:s:t:ux:1:2:")) != EOF) ! 234: { ! 235: switch (iopt) ! 236: { ! 237: case 'c': ! 238: zProtocols = optarg; ! 239: break; ! 240: case 'n': ! 241: fmake = FALSE; ! 242: break; ! 243: case 'p': ! 244: iPercent = (int) strtol (optarg, (char **) NULL, 10); ! 245: srand ((unsigned int) ixsysdep_time ((long *) NULL)); ! 246: break; ! 247: case 's': ! 248: zsys = optarg; ! 249: break; ! 250: case 't': ! 251: iTest = (int) strtol (optarg, (char **) NULL, 10); ! 252: break; ! 253: case 'u': ! 254: fCall_uucico = TRUE; ! 255: break; ! 256: case 'x': ! 257: zDebug = optarg; ! 258: break; ! 259: case '1': ! 260: zcmd1 = optarg; ! 261: break; ! 262: case '2': ! 263: zcmd2 = optarg; ! 264: break; ! 265: default: ! 266: fprintf (stderr, ! 267: "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n", ! 268: VERSION); ! 269: fprintf (stderr, ! 270: "Usage: tstuu [-xn] [-t #] [-u] [-1 cmd] [-2 cmd]\n"); ! 271: exit (EXIT_FAILURE); ! 272: } ! 273: } ! 274: ! 275: if (fCall_uucico && zcmd2 == NULL) ! 276: zcmd2 = ZUUCICO_CMD; ! 277: ! 278: uprepare_test (fmake, iTest, fCall_uucico, zsys); ! 279: ! 280: (void) remove ("/usr/tmp/tstuu/spool1/core"); ! 281: (void) remove ("/usr/tmp/tstuu/spool2/core"); ! 282: ! 283: omaster1 = -1; ! 284: oslave1 = -1; ! 285: omaster2 = -1; ! 286: oslave2 = -1; ! 287: ! 288: #if ! HAVE_STREAMS_PTYS ! 289: ! 290: { ! 291: char *zptyname; ! 292: const char *zpty; ! 293: ! 294: zptyname = abpty1; ! 295: ! 296: for (zpty = "pqrs"; *zpty != '\0'; ++zpty) ! 297: { ! 298: int ipty; ! 299: ! 300: for (ipty = 0; ipty < 16; ipty++) ! 301: { ! 302: int om, os; ! 303: FILE *e; ! 304: ! 305: sprintf (zptyname, "/dev/pty%c%c", *zpty, ! 306: "0123456789abcdef"[ipty]); ! 307: om = open (zptyname, O_RDWR); ! 308: if (om < 0) ! 309: continue; ! 310: zptyname[5] = 't'; ! 311: os = open (zptyname, O_RDWR); ! 312: if (os < 0) ! 313: { ! 314: (void) close (om); ! 315: continue; ! 316: } ! 317: ! 318: if (omaster1 == -1) ! 319: { ! 320: omaster1 = om; ! 321: oslave1 = os; ! 322: ! 323: e = fopen ("/usr/tmp/tstuu/pty1", "w"); ! 324: if (e == NULL) ! 325: { ! 326: perror ("fopen"); ! 327: exit (EXIT_FAILURE); ! 328: } ! 329: fprintf (e, "%s", zptyname + 5); ! 330: if (fclose (e) != 0) ! 331: { ! 332: perror ("fclose"); ! 333: exit (EXIT_FAILURE); ! 334: } ! 335: ! 336: zptyname = abpty2; ! 337: } ! 338: else ! 339: { ! 340: omaster2 = om; ! 341: oslave2 = os; ! 342: ! 343: e = fopen ("/usr/tmp/tstuu/pty2", "w"); ! 344: if (e == NULL) ! 345: { ! 346: perror ("fopen"); ! 347: exit (EXIT_FAILURE); ! 348: } ! 349: fprintf (e, "%s", zptyname + 5); ! 350: if (fclose (e) != 0) ! 351: { ! 352: perror ("fclose"); ! 353: exit (EXIT_FAILURE); ! 354: } ! 355: break; ! 356: } ! 357: } ! 358: ! 359: if (omaster1 != -1 && omaster2 != -1) ! 360: break; ! 361: } ! 362: } ! 363: ! 364: #else /* HAVE_STREAMS_PTYS */ ! 365: ! 366: { ! 367: int ipty; ! 368: ! 369: for (ipty = 0; ipty < 2; ipty++) ! 370: { ! 371: int om, os; ! 372: FILE *e; ! 373: char *znam; ! 374: struct termio stio; ! 375: ! 376: om = open ((char *) "/dev/ptmx", O_RDWR); ! 377: if (om < 0) ! 378: break; ! 379: znam = ptsname (om); ! 380: if (znam == NULL) ! 381: break; ! 382: if (unlockpt (om) != 0 ! 383: || grantpt (om) != 0) ! 384: break; ! 385: ! 386: os = open (znam, O_RDWR); ! 387: if (os < 0) ! 388: { ! 389: (void) close (om); ! 390: om = -1; ! 391: break; ! 392: } ! 393: ! 394: if (ioctl (os, I_PUSH, "ptem") < 0 ! 395: || ioctl(os, I_PUSH, "ldterm") < 0) ! 396: { ! 397: perror ("ioctl"); ! 398: exit (EXIT_FAILURE); ! 399: } ! 400: ! 401: /* Can this really be right? */ ! 402: memset (&stio, 0, sizeof (stio)); ! 403: stio.c_cflag = B9600 | CS8 | CREAD | HUPCL; ! 404: ! 405: if (ioctl(os, TCSETA, &stio) < 0) ! 406: { ! 407: perror ("TCSETA"); ! 408: exit (EXIT_FAILURE); ! 409: } ! 410: ! 411: if (omaster1 == -1) ! 412: { ! 413: strcpy (abpty1, znam); ! 414: omaster1 = om; ! 415: oslave1 = os; ! 416: e = fopen ("/usr/tmp/tstuu/pty1", "w"); ! 417: if (e == NULL) ! 418: { ! 419: perror ("fopen"); ! 420: exit (EXIT_FAILURE); ! 421: } ! 422: fprintf (e, "%s", znam + 5); ! 423: if (fclose (e) != 0) ! 424: { ! 425: perror ("fclose"); ! 426: exit (EXIT_FAILURE); ! 427: } ! 428: } ! 429: else ! 430: { ! 431: strcpy (abpty2, znam); ! 432: omaster2 = om; ! 433: oslave2 = os; ! 434: e = fopen ("/usr/tmp/tstuu/pty2", "w"); ! 435: if (e == NULL) ! 436: { ! 437: perror ("fopen"); ! 438: exit (EXIT_FAILURE); ! 439: } ! 440: fprintf (e, "%s", znam + 5); ! 441: if (fclose (e) != 0) ! 442: { ! 443: perror ("fclose"); ! 444: exit (EXIT_FAILURE); ! 445: } ! 446: } ! 447: } ! 448: } ! 449: ! 450: #endif /* HAVE_STREAMS_PTYS */ ! 451: ! 452: if (omaster2 == -1) ! 453: { ! 454: fprintf (stderr, "No pseudo-terminals available\n"); ! 455: exit (EXIT_FAILURE); ! 456: } ! 457: ! 458: /* Make sure we can or these into an int for the select call. Most ! 459: systems could use 31 instead of 15, but it should never be a ! 460: problem. */ ! 461: if (omaster1 > 15 || omaster2 > 15) ! 462: { ! 463: fprintf (stderr, "File descriptors are too large\n"); ! 464: exit (EXIT_FAILURE); ! 465: } ! 466: ! 467: /* Prepare to log out the command if it is a login command. On ! 468: Ultrix 4.0 uucico can only be run from login for some reason. */ ! 469: ! 470: if (zcmd1 == NULL ! 471: || strncmp (zcmd1, "login", sizeof "login" - 1) != 0) ! 472: abLogout1[0] = '\0'; ! 473: else ! 474: sprintf (abLogout1, "tstout %s", abpty1); ! 475: ! 476: if (zcmd2 == NULL ! 477: || strncmp (zcmd2, "login", sizeof "login" - 1) != 0) ! 478: abLogout2[0] = '\0'; ! 479: else ! 480: sprintf (abLogout2, "tstout %s", abpty2); ! 481: ! 482: iPid1 = fork (); ! 483: if (iPid1 < 0) ! 484: { ! 485: perror ("fork"); ! 486: exit (EXIT_FAILURE); ! 487: } ! 488: else if (iPid1 == 0) ! 489: { ! 490: if (close (0) < 0 ! 491: || close (1) < 0 ! 492: || close (omaster1) < 0 ! 493: || close (omaster2) < 0 ! 494: || close (oslave2) < 0) ! 495: perror ("close"); ! 496: ! 497: if (dup2 (oslave1, 0) < 0 ! 498: || dup2 (oslave1, 1) < 0) ! 499: perror ("dup2"); ! 500: ! 501: if (close (oslave1) < 0) ! 502: perror ("close"); ! 503: ! 504: if (zDebug != NULL) ! 505: fprintf (stderr, "About to exec first process\n"); ! 506: ! 507: if (zcmd1 != NULL) ! 508: exit (system ((char *) zcmd1)); ! 509: else ! 510: { ! 511: (void) execl ("uucico", "uucico", "-I", "/usr/tmp/tstuu/Config1", ! 512: "-q", "-S", zsys, "-pstdin", (const char *) NULL); ! 513: perror ("execl failed"); ! 514: exit (EXIT_FAILURE); ! 515: } ! 516: } ! 517: ! 518: iPid2 = fork (); ! 519: if (iPid2 < 0) ! 520: { ! 521: perror ("fork"); ! 522: kill (iPid1, SIGTERM); ! 523: exit (EXIT_FAILURE); ! 524: } ! 525: else if (iPid2 == 0) ! 526: { ! 527: if (close (0) < 0 ! 528: || close (1) < 0 ! 529: || close (omaster1) < 0 ! 530: || close (oslave1) < 0 ! 531: || close (omaster2) < 0) ! 532: perror ("close"); ! 533: ! 534: if (dup2 (oslave2, 0) < 0 ! 535: || dup2 (oslave2, 1) < 0) ! 536: perror ("dup2"); ! 537: ! 538: if (close (oslave2) < 0) ! 539: perror ("close"); ! 540: ! 541: if (zDebug != NULL) ! 542: fprintf (stderr, "About to exec second process\n"); ! 543: ! 544: if (fCall_uucico) ! 545: { ! 546: (void) execl (UUCICO_EXECL, (const char *) NULL); ! 547: perror ("execl failed"); ! 548: exit (EXIT_FAILURE); ! 549: } ! 550: else if (zcmd2 != NULL) ! 551: exit (system ((char *) zcmd2)); ! 552: else ! 553: { ! 554: (void) execl ("uucico", "uucico", "-I", "/usr/tmp/tstuu/Config2", ! 555: "-lq", (const char *)NULL); ! 556: perror ("execl failed"); ! 557: exit (EXIT_FAILURE); ! 558: } ! 559: } ! 560: ! 561: signal (SIGCHLD, uchild); ! 562: ! 563: if (fcntl (omaster1, F_SETFL, O_NDELAY | O_NONBLOCK) < 0 ! 564: && errno == EINVAL) ! 565: (void) fcntl (omaster1, F_SETFL, O_NONBLOCK); ! 566: if (fcntl (omaster2, F_SETFL, O_NDELAY | O_NONBLOCK) < 0 ! 567: && errno == EINVAL) ! 568: (void) fcntl (omaster2, F_SETFL, O_NONBLOCK); ! 569: ! 570: qbuf1 = NULL; ! 571: qbuf2 = NULL; ! 572: ! 573: while (TRUE) ! 574: { ! 575: int o1, o2; ! 576: boolean fcont; ! 577: ! 578: o1 = omaster1; ! 579: o2 = omaster2; ! 580: uchoose (&o1, &o2); ! 581: ! 582: if (o1 == -1 && o2 == -1) ! 583: { ! 584: if (zDebug != NULL) ! 585: fprintf (stderr, "Five second pause\n"); ! 586: continue; ! 587: } ! 588: ! 589: if (o1 != -1) ! 590: cFrom1 += cread (omaster1, &qbuf1); ! 591: ! 592: if (o2 != -1) ! 593: cFrom2 += cread (omaster2, &qbuf2); ! 594: ! 595: do ! 596: { ! 597: fcont = FALSE; ! 598: ! 599: if (qbuf1 != NULL ! 600: && fwritable (omaster2) ! 601: && fsend (omaster2, oslave2, &qbuf1)) ! 602: fcont = TRUE; ! 603: ! 604: if (qbuf2 != NULL ! 605: && fwritable (omaster1) ! 606: && fsend (omaster1, oslave1, &qbuf2)) ! 607: fcont = TRUE; ! 608: ! 609: if (! fcont ! 610: && (qbuf1 != NULL || qbuf2 != NULL)) ! 611: { ! 612: long cgot1, cgot2; ! 613: ! 614: cgot1 = cread (omaster1, &qbuf1); ! 615: cFrom1 += cgot1; ! 616: cgot2 = cread (omaster2, &qbuf2); ! 617: cFrom2 += cgot2; ! 618: fcont = TRUE; ! 619: } ! 620: } ! 621: while (fcont); ! 622: } ! 623: ! 624: /*NOTREACHED*/ ! 625: } ! 626: ! 627: /* When a child dies, kill them both. */ ! 628: ! 629: static RETSIGTYPE ! 630: uchild (isig) ! 631: int isig; ! 632: { ! 633: struct tms sbase, s1, s2; ! 634: ! 635: signal (SIGCHLD, SIG_DFL); ! 636: ! 637: /* Give the processes a chance to die on their own. */ ! 638: sleep (2); ! 639: ! 640: (void) kill (iPid1, SIGTERM); ! 641: (void) kill (iPid2, SIGTERM); ! 642: ! 643: (void) times (&sbase); ! 644: ! 645: #if HAVE_WAITPID ! 646: (void) waitpid (iPid1, (pointer) NULL, 0); ! 647: #else /* ! HAVE_WAITPID */ ! 648: #if HAVE_WAIT4 ! 649: (void) wait4 (iPid1, (pointer) NULL, 0, (struct rusage *) NULL); ! 650: #else /* ! HAVE_WAIT4 */ ! 651: (void) wait ((wait_status *) NULL); ! 652: #endif /* ! HAVE_WAIT4 */ ! 653: #endif /* ! HAVE_WAITPID */ ! 654: ! 655: (void) times (&s1); ! 656: ! 657: #if HAVE_WAITPID ! 658: (void) waitpid (iPid2, (pointer) NULL, 0); ! 659: #else /* ! HAVE_WAITPID */ ! 660: #if HAVE_WAIT4 ! 661: (void) wait4 (iPid2, (wait_status *) NULL, 0, (struct rusage *) NULL); ! 662: #else /* ! HAVE_WAIT4 */ ! 663: (void) wait ((wait_status *) NULL); ! 664: #endif /* ! HAVE_WAIT4 */ ! 665: #endif /* ! HAVE_WAITPID */ ! 666: ! 667: (void) times (&s2); ! 668: ! 669: fprintf (stderr, ! 670: " First child: user: %g; system: %g\n", ! 671: (double) (s1.tms_cutime - sbase.tms_cutime) / (double) TIMES_TICK, ! 672: (double) (s1.tms_cstime - sbase.tms_cstime) / (double) TIMES_TICK); ! 673: fprintf (stderr, ! 674: "Second child: user: %g; system: %g\n", ! 675: (double) (s2.tms_cutime - s1.tms_cutime) / (double) TIMES_TICK, ! 676: (double) (s2.tms_cstime - s1.tms_cstime) / (double) TIMES_TICK); ! 677: ! 678: ucheck_test (iTest, fCall_uucico); ! 679: ! 680: if (abLogout1[0] != '\0') ! 681: { ! 682: if (zDebug != NULL) ! 683: fprintf (stderr, "Executing %s\n", abLogout1); ! 684: (void) system (abLogout1); ! 685: } ! 686: if (abLogout2[0] != '\0') ! 687: { ! 688: if (zDebug != NULL) ! 689: fprintf (stderr, "Executing %s\n", abLogout2); ! 690: (void) system (abLogout2); ! 691: } ! 692: ! 693: fprintf (stderr, "Wrote %d bytes from 1 to 2\n", cFrom1); ! 694: fprintf (stderr, "Wrote %d bytes from 2 to 1\n", cFrom2); ! 695: ! 696: if (access ("/usr/tmp/tstuu/spool1/core", R_OK) == 0) ! 697: fprintf (stderr, "core file 1 exists\n"); ! 698: if (access ("/usr/tmp/tstuu/spool2/core", R_OK) == 0) ! 699: fprintf (stderr, "core file 2 exists\n"); ! 700: ! 701: exit (EXIT_SUCCESS); ! 702: } ! 703: ! 704: /* Open a file without error. */ ! 705: ! 706: static FILE * ! 707: xfopen (zname, zmode) ! 708: const char *zname; ! 709: const char *zmode; ! 710: { ! 711: FILE *eret; ! 712: ! 713: eret = fopen (zname, zmode); ! 714: if (eret == NULL) ! 715: { ! 716: perror (zname); ! 717: exit (EXIT_FAILURE); ! 718: } ! 719: return eret; ! 720: } ! 721: ! 722: /* Close a file without error. */ ! 723: ! 724: static void xfclose P((FILE *e)); ! 725: ! 726: static void ! 727: xfclose (e) ! 728: FILE *e; ! 729: { ! 730: if (fclose (e) != 0) ! 731: { ! 732: perror ("fclose"); ! 733: exit (EXIT_FAILURE); ! 734: } ! 735: } ! 736: ! 737: /* Create a test file. */ ! 738: ! 739: static void ! 740: umake_file (z, c) ! 741: const char *z; ! 742: int c; ! 743: { ! 744: int i; ! 745: FILE *e; ! 746: ! 747: e = xfopen (z, "w"); ! 748: ! 749: for (i = 0; i < 256; i++) ! 750: { ! 751: int i2; ! 752: ! 753: for (i2 = 0; i2 < 256; i2++) ! 754: putc (i, e); ! 755: } ! 756: ! 757: for (i = 0; i < c; i++) ! 758: putc (i, e); ! 759: ! 760: xfclose (e); ! 761: } ! 762: ! 763: /* Check a test file. */ ! 764: ! 765: static void ! 766: ucheck_file (z, zerr, c) ! 767: const char *z; ! 768: const char *zerr; ! 769: int c; ! 770: { ! 771: int i; ! 772: FILE *e; ! 773: ! 774: e = xfopen (z, "r"); ! 775: ! 776: for (i = 0; i < 256; i++) ! 777: { ! 778: int i2; ! 779: ! 780: for (i2 = 0; i2 < 256; i2++) ! 781: { ! 782: int bread; ! 783: ! 784: bread = getc (e); ! 785: if (bread == EOF) ! 786: { ! 787: fprintf (stderr, ! 788: "%s: Unexpected EOF at position %d,%d\n", ! 789: zerr, i, i2); ! 790: xfclose (e); ! 791: return; ! 792: } ! 793: if (bread != i) ! 794: fprintf (stderr, ! 795: "%s: At position %d,%d got %d expected %d\n", ! 796: zerr, i, i2, bread, i); ! 797: } ! 798: } ! 799: ! 800: for (i = 0; i < c; i++) ! 801: { ! 802: int bread; ! 803: ! 804: bread = getc (e); ! 805: if (bread == EOF) ! 806: { ! 807: fprintf (stderr, "%s: Unexpected EOF at extra %d\n", zerr, i); ! 808: xfclose (e); ! 809: return; ! 810: } ! 811: if (bread != i) ! 812: fprintf (stderr, "%s: At extra %d got %d expected %d\n", ! 813: zerr, i, bread, i); ! 814: } ! 815: ! 816: if (getc (e) != EOF) ! 817: fprintf (stderr, "%s: File is too long", zerr); ! 818: ! 819: xfclose (e); ! 820: } ! 821: ! 822: /* Prepare all the configuration files for testing. */ ! 823: ! 824: static void ! 825: uprepare_test (fmake, itest, fcall_uucico, zsys) ! 826: boolean fmake; ! 827: int itest; ! 828: boolean fcall_uucico; ! 829: const char *zsys; ! 830: { ! 831: FILE *e; ! 832: const char *zuucp1, *zuucp2; ! 833: const char *zuux1, *zuux2; ! 834: char ab[1000]; ! 835: const char *zfrom; ! 836: const char *zto; ! 837: ! 838: /* We must make /usr/tmp/tstuu world writeable or we won't be able to ! 839: receive files into it. */ ! 840: (void) umask (0); ! 841: ! 842: #ifndef S_IWOTH ! 843: #define S_IWOTH 02 ! 844: #endif ! 845: ! 846: if (mkdir ((char *) "/usr/tmp/tstuu", ! 847: IPUBLIC_DIRECTORY_MODE | S_IWOTH) != 0 ! 848: && errno != EEXIST) ! 849: { ! 850: perror ("mkdir"); ! 851: exit (EXIT_FAILURE); ! 852: } ! 853: ! 854: if (mkdir ((char *) "/usr/tmp/tstuu/spool1", IPUBLIC_DIRECTORY_MODE) != 0 ! 855: && errno != EEXIST) ! 856: { ! 857: perror ("mkdir"); ! 858: exit (EXIT_FAILURE); ! 859: } ! 860: ! 861: if (mkdir ((char *) "/usr/tmp/tstuu/spool2", IPUBLIC_DIRECTORY_MODE) != 0 ! 862: && errno != EEXIST) ! 863: { ! 864: perror ("mkdir"); ! 865: exit (EXIT_FAILURE); ! 866: } ! 867: ! 868: if (fmake) ! 869: { ! 870: e = xfopen ("/usr/tmp/tstuu/Config1", "w"); ! 871: ! 872: fprintf (e, "# First test configuration file\n"); ! 873: fprintf (e, "nodename test1\n"); ! 874: fprintf (e, "spool /usr/tmp/tstuu/spool1\n"); ! 875: fprintf (e, "lockdir /usr/tmp/tstuu/spool1\n"); ! 876: fprintf (e, "sysfile /usr/tmp/tstuu/System1\n"); ! 877: fprintf (e, "sysfile /usr/tmp/tstuu/System1.2\n"); ! 878: fprintf (e, "portfile /usr/tmp/tstuu/Port1\n"); ! 879: (void) remove ("/usr/tmp/tstuu/Log1"); ! 880: #if ! HAVE_HDB_LOGGING ! 881: fprintf (e, "logfile /usr/tmp/tstuu/Log1\n"); ! 882: #else ! 883: fprintf (e, "%s\n", "logfile /usr/tmp/tstuu/Log1/%s/%s"); ! 884: #endif ! 885: fprintf (e, "statfile /usr/tmp/tstuu/Stats1\n"); ! 886: fprintf (e, "debugfile /usr/tmp/tstuu/Debug1\n"); ! 887: fprintf (e, "callfile /usr/tmp/tstuu/Call1\n"); ! 888: fprintf (e, "pubdir /usr/tmp/tstuu\n"); ! 889: #if HAVE_V2_CONFIG ! 890: fprintf (e, "v2-files no\n"); ! 891: #endif ! 892: #if HAVE_HDB_CONFIG ! 893: fprintf (e, "hdb-files no\n"); ! 894: #endif ! 895: if (zDebug != NULL) ! 896: fprintf (e, "debug %s\n", zDebug); ! 897: ! 898: xfclose (e); ! 899: ! 900: e = xfopen ("/usr/tmp/tstuu/System1", "w"); ! 901: ! 902: fprintf (e, "# This file is ignored, to test multiple system files\n"); ! 903: fprintf (e, "time never\n"); ! 904: ! 905: xfclose (e); ! 906: ! 907: e = xfopen ("/usr/tmp/tstuu/System1.2", "w"); ! 908: ! 909: fprintf (e, "# First test system file\n"); ! 910: fprintf (e, "time any\n"); ! 911: fprintf (e, "port stdin\n"); ! 912: fprintf (e, "# That was the defaults\n"); ! 913: fprintf (e, "system %s\n", zsys); ! 914: if (! fcall_uucico) ! 915: { ! 916: FILE *eprog; ! 917: ! 918: eprog = xfopen ("/usr/tmp/tstuu/Chat1", "w"); ! 919: ! 920: /* Wait for the other side to open the port and flush input. */ ! 921: fprintf (eprog, "sleep 2\n"); ! 922: fprintf (eprog, ! 923: "echo password $1 speed $2 1>&2\n"); ! 924: fprintf (eprog, "echo test1\n"); ! 925: fprintf (eprog, "exit 0\n"); ! 926: ! 927: xfclose (eprog); ! 928: ! 929: if (chmod ("/usr/tmp/tstuu/Chat1", ! 930: S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) ! 931: { ! 932: perror ("chmod (/usr/tmp/tstuu/Chat1)"); ! 933: exit (EXIT_FAILURE); ! 934: } ! 935: ! 936: fprintf (e, "chat-program /usr/tmp/tstuu/Chat1 \\P \\S\n"); ! 937: ! 938: fprintf (e, "chat word: \\P\n"); ! 939: fprintf (e, "chat-fail login;\n"); ! 940: fprintf (e, "call-login *\n"); ! 941: fprintf (e, "call-password *\n"); ! 942: } ! 943: else ! 944: fprintf (e, "chat \"\"\n"); ! 945: fprintf (e, "call-transfer yes\n"); ! 946: fprintf (e, "commands cat\n"); ! 947: if (! fcall_uucico && iPercent == 0) ! 948: { ! 949: fprintf (e, "protocol-parameter g window 7\n"); ! 950: fprintf (e, "protocol-parameter g packet-size 4096\n"); ! 951: fprintf (e, "protocol-parameter j avoid \\377\n"); ! 952: } ! 953: if (zProtocols != NULL) ! 954: fprintf (e, "protocol %s\n", zProtocols); ! 955: ! 956: xfclose (e); ! 957: ! 958: e = xfopen ("/usr/tmp/tstuu/Port1", "w"); ! 959: ! 960: fprintf (e, "port stdin\n"); ! 961: fprintf (e, "type stdin\n"); ! 962: fprintf (e, "pty true\n"); ! 963: ! 964: xfclose (e); ! 965: ! 966: e = xfopen ("/usr/tmp/tstuu/Call1", "w"); ! 967: ! 968: fprintf (e, "Call out password file\n"); ! 969: fprintf (e, "%s test1 pass1\n", zsys); ! 970: ! 971: xfclose (e); ! 972: ! 973: if (! fcall_uucico) ! 974: { ! 975: FILE *eprog; ! 976: ! 977: e = xfopen ("/usr/tmp/tstuu/Config2", "w"); ! 978: ! 979: fprintf (e, "# Second test configuration file\n"); ! 980: fprintf (e, "nodename test2\n"); ! 981: fprintf (e, "spool /usr/tmp/tstuu/spool2\n"); ! 982: fprintf (e, "lockdir /usr/tmp/tstuu/spool2\n"); ! 983: fprintf (e, "sysfile /usr/tmp/tstuu/System2\n"); ! 984: (void) remove ("/usr/tmp/tstuu/Log2"); ! 985: #if ! HAVE_HDB_LOGGING ! 986: fprintf (e, "logfile /usr/tmp/tstuu/Log2\n"); ! 987: #else ! 988: fprintf (e, "%s\n", "logfile /usr/tmp/tstuu/Log2/%s/%s"); ! 989: #endif ! 990: fprintf (e, "statfile /usr/tmp/tstuu/Stats2\n"); ! 991: fprintf (e, "debugfile /usr/tmp/tstuu/Debug2\n"); ! 992: fprintf (e, "passwdfile /usr/tmp/tstuu/Pass2\n"); ! 993: fprintf (e, "pubdir /usr/tmp/tstuu\n"); ! 994: #if HAVE_V2_CONFIG ! 995: fprintf (e, "v2-files no\n"); ! 996: #endif ! 997: #if HAVE_HDB_CONFIG ! 998: fprintf (e, "hdb-files no\n"); ! 999: #endif ! 1000: if (zDebug != NULL) ! 1001: fprintf (e, "debug %s\n", zDebug); ! 1002: ! 1003: xfclose (e); ! 1004: ! 1005: e = xfopen ("/usr/tmp/tstuu/System2", "w"); ! 1006: ! 1007: fprintf (e, "# Second test system file\n"); ! 1008: fprintf (e, "system test1\n"); ! 1009: fprintf (e, "called-login test1\n"); ! 1010: fprintf (e, "request true\n"); ! 1011: fprintf (e, "commands cat\n"); ! 1012: if (zProtocols != NULL) ! 1013: fprintf (e, "protocol %s\n", zProtocols); ! 1014: ! 1015: eprog = xfopen ("/usr/tmp/tstuu/Chat2", "w"); ! 1016: ! 1017: fprintf (eprog, ! 1018: "echo port $1 1>&2\n"); ! 1019: fprintf (eprog, "exit 0\n"); ! 1020: ! 1021: xfclose (eprog); ! 1022: ! 1023: if (chmod ("/usr/tmp/tstuu/Chat2", ! 1024: S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) ! 1025: { ! 1026: perror ("chmod (/usr/tmp/tstuu/Chat2"); ! 1027: exit (EXIT_FAILURE); ! 1028: } ! 1029: ! 1030: fprintf (e, "called-chat-program /bin/sh /usr/tmp/tstuu/Chat2 \\Y\n"); ! 1031: fprintf (e, "time any\n"); ! 1032: ! 1033: xfclose (e); ! 1034: ! 1035: e = xfopen ("/usr/tmp/tstuu/Pass2", "w"); ! 1036: ! 1037: fprintf (e, "# Call in password file\n"); ! 1038: fprintf (e, "test1 pass1\n"); ! 1039: ! 1040: xfclose (e); ! 1041: } ! 1042: } ! 1043: ! 1044: zuucp1 = "./uucp -I /usr/tmp/tstuu/Config1 -r"; ! 1045: zuux1 = "./uux -I /usr/tmp/tstuu/Config1 -r"; ! 1046: ! 1047: if (fcall_uucico) ! 1048: { ! 1049: zuucp2 = "/usr/bin/uucp -r"; ! 1050: zuux2 = "/usr/bin/uux -r"; ! 1051: } ! 1052: else ! 1053: { ! 1054: zuucp2 = "./uucp -I /usr/tmp/tstuu/Config2 -r"; ! 1055: zuux2 = "./uux -I /usr/tmp/tstuu/Config2 -r"; ! 1056: } ! 1057: ! 1058: /* Test transferring a file from the first system to the second. */ ! 1059: if (itest == 0 || itest == 1) ! 1060: { ! 1061: zfrom = "/usr/tmp/tstuu/from1"; ! 1062: if (fcall_uucico) ! 1063: zto = "/usr/spool/uucppublic/to1"; ! 1064: else ! 1065: zto = "/usr/tmp/tstuu/to1"; ! 1066: ! 1067: (void) remove (zto); ! 1068: umake_file (zfrom, 0); ! 1069: ! 1070: sprintf (ab, "%s %s %s!%s", zuucp1, zfrom, zsys, zto); ! 1071: xsystem (ab); ! 1072: } ! 1073: ! 1074: /* Test having the first system request a file from the second. */ ! 1075: if (itest == 0 || itest == 2) ! 1076: { ! 1077: if (fcall_uucico) ! 1078: zfrom = "/usr/spool/uucppublic/from2"; ! 1079: else ! 1080: zfrom = "/usr/tmp/tstuu/from2"; ! 1081: zto = "/usr/tmp/tstuu/to2"; ! 1082: ! 1083: (void) remove (zto); ! 1084: umake_file (zfrom, 3); ! 1085: ! 1086: sprintf (ab, "%s %s!%s %s", zuucp1, zsys, zfrom, zto); ! 1087: xsystem (ab); ! 1088: } ! 1089: ! 1090: /* Test having the second system send a file to the first. */ ! 1091: if (itest == 0 || itest == 3) ! 1092: { ! 1093: if (fcall_uucico) ! 1094: zfrom = "/usr/spool/uucppublic/from3"; ! 1095: else ! 1096: zfrom = "/usr/tmp/tstuu/from3"; ! 1097: zto = "/usr/tmp/tstuu/to3"; ! 1098: ! 1099: (void) remove (zto); ! 1100: umake_file (zfrom, 5); ! 1101: ! 1102: sprintf (ab, "%s -c \\~/from3 test1!~/to3", zuucp2); ! 1103: xsystem (ab); ! 1104: } ! 1105: ! 1106: /* Test having the second system request a file from the first. */ ! 1107: if (itest == 0 || itest == 4) ! 1108: { ! 1109: zfrom = "/usr/tmp/tstuu/from4"; ! 1110: if (fcall_uucico) ! 1111: zto = "/usr/spool/uucppublic/to4"; ! 1112: else ! 1113: zto = "/usr/tmp/tstuu/to4"; ! 1114: ! 1115: (void) remove (zto); ! 1116: umake_file (zfrom, 7); ! 1117: ! 1118: sprintf (ab, "%s test1!%s %s", zuucp2, zfrom, zto); ! 1119: xsystem (ab); ! 1120: } ! 1121: ! 1122: /* Test having the second system make an execution request. */ ! 1123: if (itest == 0 || itest == 5) ! 1124: { ! 1125: zfrom = "/usr/tmp/tstuu/from5"; ! 1126: if (fcall_uucico) ! 1127: zto = "/usr/spool/uucppublic/to5"; ! 1128: else ! 1129: zto = "/usr/tmp/tstuu/to5"; ! 1130: ! 1131: (void) remove (zto); ! 1132: umake_file (zfrom, 11); ! 1133: ! 1134: sprintf (ab, "%s test1!cat '<%s' '>%s'", zuux2, zfrom, zto); ! 1135: xsystem (ab); ! 1136: } ! 1137: ! 1138: /* Test having the first system request a wildcard. */ ! 1139: if (itest == 0 || itest == 6) ! 1140: { ! 1141: const char *zfrom1, *zfrom2; ! 1142: ! 1143: if (fcall_uucico) ! 1144: { ! 1145: zfrom = "/usr/spool/uucppublic/to6\\*"; ! 1146: zfrom1 = "/usr/spool/uucppublic/to6.1"; ! 1147: zfrom2 = "/usr/spool/uucppublic/to6.2"; ! 1148: } ! 1149: else ! 1150: { ! 1151: zfrom = "/usr/tmp/tstuu/spool2/to6\\*"; ! 1152: zfrom1 = "/usr/tmp/tstuu/spool2/to6.1"; ! 1153: zfrom2 = "/usr/tmp/tstuu/spool2/to6.2"; ! 1154: } ! 1155: ! 1156: umake_file (zfrom1, 100); ! 1157: umake_file (zfrom2, 101); ! 1158: (void) remove ("/usr/tmp/tstuu/to6.1"); ! 1159: (void) remove ("/usr/tmp/tstuu/to6.2"); ! 1160: ! 1161: sprintf (ab, "%s %s!%s /usr/tmp/tstuu", zuucp1, zsys, zfrom); ! 1162: xsystem (ab); ! 1163: } ! 1164: ! 1165: /* Test having the second system request a wildcard. */ ! 1166: if (itest == 0 || itest == 7) ! 1167: { ! 1168: const char *zto1, *zto2; ! 1169: ! 1170: if (fcall_uucico) ! 1171: { ! 1172: zto = "/usr/spool/uucppublic"; ! 1173: zto1 = "/usr/spool/uucppublic/to7.1"; ! 1174: zto2 = "/usr/spool/uucppublic/to7.2"; ! 1175: } ! 1176: else ! 1177: { ! 1178: zto = "/usr/tmp/tstuu"; ! 1179: zto1 = "/usr/tmp/tstuu/to7.1"; ! 1180: zto2 = "/usr/tmp/tstuu/to7.2"; ! 1181: } ! 1182: ! 1183: umake_file ("/usr/tmp/tstuu/spool1/to7.1", 150); ! 1184: umake_file ("/usr/tmp/tstuu/spool1/to7.2", 155); ! 1185: (void) remove (zto1); ! 1186: (void) remove (zto2); ! 1187: ! 1188: sprintf (ab, "%s test1!/usr/tmp/tstuu/spool1/to7.\\* %s", zuucp2, ! 1189: zto); ! 1190: xsystem (ab); ! 1191: } ! 1192: ! 1193: /* Test an E command. This runs cat, discarding the output. */ ! 1194: if ((itest == 0 || itest == 8) && ! fcall_uucico) ! 1195: { ! 1196: umake_file ("/usr/tmp/tstuu/from8", 30); ! 1197: sprintf (ab, "%s - test2!cat < /usr/tmp/tstuu/from8", zuux1); ! 1198: xsystem (ab); ! 1199: } ! 1200: } ! 1201: ! 1202: /* Try to make sure the file transfers were successful. */ ! 1203: ! 1204: static void ! 1205: ucheck_test (itest, fcall_uucico) ! 1206: int itest; ! 1207: boolean fcall_uucico; ! 1208: { ! 1209: if (itest == 0 || itest == 1) ! 1210: { ! 1211: if (fcall_uucico) ! 1212: ucheck_file ("/usr/spool/uucppublic/to1", "test 1", 0); ! 1213: else ! 1214: ucheck_file ("/usr/tmp/tstuu/to1", "test 1", 0); ! 1215: } ! 1216: ! 1217: if (itest == 0 || itest == 2) ! 1218: ucheck_file ("/usr/tmp/tstuu/to2", "test 2", 3); ! 1219: ! 1220: if (itest == 0 || itest == 3) ! 1221: ucheck_file ("/usr/tmp/tstuu/to3", "test 3", 5); ! 1222: ! 1223: if (itest == 0 || itest == 4) ! 1224: { ! 1225: if (fcall_uucico) ! 1226: ucheck_file ("/usr/spool/uucppublic/to4", "test 4", 7); ! 1227: else ! 1228: ucheck_file ("/usr/tmp/tstuu/to4", "test 4", 7); ! 1229: } ! 1230: ! 1231: if (itest == 0 || itest == 6) ! 1232: { ! 1233: ucheck_file ("/usr/tmp/tstuu/to6.1", "test 6.1", 100); ! 1234: ucheck_file ("/usr/tmp/tstuu/to6.2", "test 6.2", 101); ! 1235: } ! 1236: ! 1237: if (itest == 0 || itest == 7) ! 1238: { ! 1239: const char *zto1, *zto2; ! 1240: ! 1241: if (fcall_uucico) ! 1242: { ! 1243: zto1 = "/usr/spool/uucppublic/to7.1"; ! 1244: zto2 = "/usr/spool/uucppublic/to7.2"; ! 1245: } ! 1246: else ! 1247: { ! 1248: zto1 = "/usr/tmp/tstuu/to7.1"; ! 1249: zto2 = "/usr/tmp/tstuu/to7.2"; ! 1250: } ! 1251: ! 1252: ucheck_file (zto1, "test 7.1", 150); ! 1253: ucheck_file (zto2, "test 7.2", 155); ! 1254: } ! 1255: } ! 1256: ! 1257: /* A debugging routine used when displaying buffers. */ ! 1258: ! 1259: static int ! 1260: cpshow (z, ichar) ! 1261: char *z; ! 1262: int ichar; ! 1263: { ! 1264: if (isprint (BUCHAR (ichar)) && ichar != '\"') ! 1265: { ! 1266: *z = (char) ichar; ! 1267: return 1; ! 1268: } ! 1269: ! 1270: *z++ = '\\'; ! 1271: ! 1272: switch (ichar) ! 1273: { ! 1274: case '\n': ! 1275: *z = 'n'; ! 1276: return 2; ! 1277: case '\r': ! 1278: *z = 'r'; ! 1279: return 2; ! 1280: case '\"': ! 1281: *z = '\"'; ! 1282: return 2; ! 1283: default: ! 1284: sprintf (z, "%03o", (unsigned int)(ichar & 0xff)); ! 1285: return strlen (z) + 1; ! 1286: } ! 1287: } ! 1288: ! 1289: /* Pick one of two file descriptors which is ready for reading, or ! 1290: return in five seconds. If the argument is ready for reading, ! 1291: leave it alone; otherwise set it to -1. */ ! 1292: ! 1293: static void ! 1294: uchoose (po1, po2) ! 1295: int *po1; ! 1296: int *po2; ! 1297: { ! 1298: #if HAVE_SELECT ! 1299: ! 1300: int iread; ! 1301: struct timeval stime; ! 1302: ! 1303: iread = (1 << *po1) | (1 << *po2); ! 1304: stime.tv_sec = 5; ! 1305: stime.tv_usec = 0; ! 1306: ! 1307: if (select ((*po1 > *po2 ? *po1 : *po2) + 1, (pointer) &iread, ! 1308: (pointer) NULL, (pointer) NULL, &stime) < 0) ! 1309: { ! 1310: perror ("select"); ! 1311: uchild (SIGCHLD); ! 1312: } ! 1313: ! 1314: if ((iread & (1 << *po1)) == 0) ! 1315: *po1 = -1; ! 1316: ! 1317: if ((iread & (1 << *po2)) == 0) ! 1318: *po2 = -1; ! 1319: ! 1320: #else /* ! HAVE_SELECT */ ! 1321: ! 1322: #if HAVE_POLL ! 1323: ! 1324: struct pollfd as[2]; ! 1325: ! 1326: as[0].fd = *po1; ! 1327: as[0].events = POLLIN; ! 1328: as[1].fd = *po2; ! 1329: as[1].events = POLLIN; ! 1330: ! 1331: if (poll (as, 2, 5 * 1000) < 0) ! 1332: { ! 1333: perror ("poll"); ! 1334: uchild (SIGCHLD); ! 1335: } ! 1336: ! 1337: if ((as[0].revents & POLLIN) == 0) ! 1338: *po1 = -1; ! 1339: ! 1340: if ((as[1].revents & POLLIN) == 0) ! 1341: *po2 = -1; ! 1342: ! 1343: #endif /* HAVE_POLL */ ! 1344: #endif /* ! HAVE_SELECT */ ! 1345: } ! 1346: ! 1347: /* Read some data from a file descriptor. This keeps reading until ! 1348: one of the reads gets no data. */ ! 1349: ! 1350: static long ! 1351: cread (o, pqbuf) ! 1352: int o; ! 1353: struct sbuf **pqbuf; ! 1354: { ! 1355: long ctotal; ! 1356: ! 1357: while (*pqbuf != NULL && (*pqbuf)->qnext != NULL) ! 1358: pqbuf = &(*pqbuf)->qnext; ! 1359: ! 1360: ctotal = 0; ! 1361: ! 1362: while (TRUE) ! 1363: { ! 1364: int cgot; ! 1365: ! 1366: if (*pqbuf != NULL ! 1367: && (*pqbuf)->cend >= sizeof (*pqbuf)->ab) ! 1368: pqbuf = &(*pqbuf)->qnext; ! 1369: ! 1370: if (*pqbuf == NULL) ! 1371: { ! 1372: *pqbuf = (struct sbuf *) malloc (sizeof (struct sbuf)); ! 1373: if (*pqbuf == NULL) ! 1374: { ! 1375: fprintf (stderr, "Out of memory\n"); ! 1376: uchild (SIGCHLD); ! 1377: } ! 1378: (*pqbuf)->qnext = NULL; ! 1379: (*pqbuf)->cstart = 0; ! 1380: (*pqbuf)->cend = 0; ! 1381: } ! 1382: ! 1383: cgot = read (o, (*pqbuf)->ab + (*pqbuf)->cend, ! 1384: (sizeof (*pqbuf)->ab) - (*pqbuf)->cend); ! 1385: if (cgot < 0) ! 1386: { ! 1387: if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENODATA) ! 1388: cgot = 0; ! 1389: else ! 1390: { ! 1391: perror ("read"); ! 1392: uchild (SIGCHLD); ! 1393: } ! 1394: } ! 1395: ! 1396: if (cgot == 0) ! 1397: return ctotal; ! 1398: ! 1399: ctotal += cgot; ! 1400: ! 1401: if (zDebug != NULL) ! 1402: { ! 1403: char abshow[325]; ! 1404: char *zfrom; ! 1405: char *zshow; ! 1406: int i; ! 1407: ! 1408: zfrom = (*pqbuf)->ab + (*pqbuf)->cend; ! 1409: zshow = abshow; ! 1410: for (i = 0; i < cgot && i < 80; i++, zfrom++) ! 1411: zshow += cpshow (zshow, *zfrom); ! 1412: if (i < cgot) ! 1413: { ! 1414: *zshow++ = '.'; ! 1415: *zshow++ = '.'; ! 1416: *zshow++ = '.'; ! 1417: } ! 1418: *zshow = '\0'; ! 1419: fprintf (stderr, "Read from %d: %d \"%s\"\n", o, cgot, abshow); ! 1420: fflush (stderr); ! 1421: } ! 1422: ! 1423: if (iPercent > 0) ! 1424: { ! 1425: int i; ! 1426: int c; ! 1427: ! 1428: c = 0; ! 1429: for (i = 0; i < cgot; i++) ! 1430: { ! 1431: if (rand () % 1000 < iPercent) ! 1432: { ! 1433: ++(*pqbuf)->ab[(*pqbuf)->cend + i]; ! 1434: ++c; ! 1435: } ! 1436: } ! 1437: if (zDebug != NULL && c > 0) ! 1438: fprintf (stderr, "Clobbered %d bytes\n", c); ! 1439: } ! 1440: ! 1441: (*pqbuf)->cend += cgot; ! 1442: ! 1443: if (ctotal > 256) ! 1444: return ctotal; ! 1445: } ! 1446: } ! 1447: ! 1448: /* Write data to a file descriptor until one of the writes gets no ! 1449: data. */ ! 1450: ! 1451: static boolean ! 1452: fsend (o, oslave, pqbuf) ! 1453: int o; ! 1454: int oslave; ! 1455: struct sbuf **pqbuf; ! 1456: { ! 1457: long ctotal; ! 1458: ! 1459: ctotal = 0; ! 1460: while (*pqbuf != NULL) ! 1461: { ! 1462: int cwrite, cwrote; ! 1463: ! 1464: if ((*pqbuf)->cstart >= (*pqbuf)->cend) ! 1465: { ! 1466: struct sbuf *qfree; ! 1467: ! 1468: qfree = *pqbuf; ! 1469: *pqbuf = (*pqbuf)->qnext; ! 1470: free ((pointer) qfree); ! 1471: continue; ! 1472: } ! 1473: ! 1474: #ifdef FIONREAD ! 1475: { ! 1476: long cunread; ! 1477: ! 1478: if (ioctl (oslave, FIONREAD, &cunread) < 0) ! 1479: { ! 1480: perror ("FIONREAD"); ! 1481: uchild (SIGCHLD); ! 1482: } ! 1483: if (zDebug != NULL) ! 1484: fprintf (stderr, "%ld unread\n", cunread); ! 1485: cwrite = 256 - cunread; ! 1486: if (cwrite <= 0) ! 1487: break; ! 1488: } ! 1489: #else /* ! FIONREAD */ ! 1490: if (! fwritable (o)) ! 1491: break; ! 1492: cwrite = 1; ! 1493: #endif /* ! FIONREAD */ ! 1494: ! 1495: if (cwrite > (*pqbuf)->cend - (*pqbuf)->cstart) ! 1496: cwrite = (*pqbuf)->cend - (*pqbuf)->cstart; ! 1497: ! 1498: cwrote = write (o, (*pqbuf)->ab + (*pqbuf)->cstart, cwrite); ! 1499: if (cwrote < 0) ! 1500: { ! 1501: if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENODATA) ! 1502: cwrote = 0; ! 1503: else ! 1504: { ! 1505: perror ("write"); ! 1506: uchild (SIGCHLD); ! 1507: } ! 1508: } ! 1509: ! 1510: if (cwrote == 0) ! 1511: break; ! 1512: ! 1513: ctotal += cwrote; ! 1514: (*pqbuf)->cstart += cwrote; ! 1515: } ! 1516: ! 1517: if (zDebug != NULL && ctotal > 0) ! 1518: fprintf (stderr, "Wrote %ld to %d\n", ctotal, o); ! 1519: ! 1520: return ctotal > 0; ! 1521: } ! 1522: ! 1523: /* Check whether a file descriptor can be written to. */ ! 1524: ! 1525: static boolean ! 1526: fwritable (o) ! 1527: int o; ! 1528: { ! 1529: #if HAVE_SELECT ! 1530: ! 1531: int iwrite; ! 1532: struct timeval stime; ! 1533: int cfds; ! 1534: ! 1535: iwrite = 1 << o; ! 1536: ! 1537: stime.tv_sec = 0; ! 1538: stime.tv_usec = 0; ! 1539: ! 1540: cfds = select (o + 1, (pointer) NULL, (pointer) &iwrite, ! 1541: (pointer) NULL, &stime); ! 1542: if (cfds < 0) ! 1543: { ! 1544: perror ("select"); ! 1545: uchild (SIGCHLD); ! 1546: } ! 1547: ! 1548: return cfds > 0; ! 1549: ! 1550: #else /* ! HAVE_SELECT */ ! 1551: ! 1552: #if HAVE_POLL ! 1553: ! 1554: struct pollfd s; ! 1555: int cfds; ! 1556: ! 1557: s.fd = o; ! 1558: s.events = POLLOUT; ! 1559: ! 1560: cfds = poll (&s, 1, 0); ! 1561: if (cfds < 0) ! 1562: { ! 1563: perror ("poll"); ! 1564: uchild (SIGCHLD); ! 1565: } ! 1566: ! 1567: return cfds > 0; ! 1568: ! 1569: #endif /* HAVE_POLL */ ! 1570: #endif /* ! HAVE_SELECT */ ! 1571: } ! 1572: ! 1573: /* A version of the system command that checks for errors. */ ! 1574: ! 1575: static void ! 1576: xsystem (zcmd) ! 1577: const char *zcmd; ! 1578: { ! 1579: int istat; ! 1580: ! 1581: istat = system ((char *) zcmd); ! 1582: if (istat != 0) ! 1583: { ! 1584: fprintf (stderr, "Command failed with status %d\n", istat); ! 1585: fprintf (stderr, "%s\n", zcmd); ! 1586: exit (EXIT_FAILURE); ! 1587: } ! 1588: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.