|
|
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.