int main(int argc, char* argv[]) { struct connection conn; iopoll_fd fds[2]; int selfpipe; int i; msg_debug_init(); testmode = getenv("TESTMODE") != 0; if ((shell_argv = malloc((argc + 3) * sizeof *argv)) == 0) die_oom(111); for (i = 1; i < argc; ++i) shell_argv[i-1] = argv[i]; for (; i < argc + 4; ++i) shell_argv[i-1] = 0; shell_argc = argc - 1; if ((path = getenv("PATH")) == 0) die1(111, "No PATH is set"); if ((devnull = open("/dev/null", O_RDWR)) == -1) die1sys(111, "Could not open \"/dev/null\""); if (!nonblock_on(0)) die1sys(111, "Could not set non-blocking status"); if ((selfpipe = selfpipe_init()) == -1) die1sys(111, "Could not create self-pipe"); init_slots(); connection_init(&conn, 0, 0); fds[0].fd = 0; fds[0].events = IOPOLL_READ; fds[1].fd = selfpipe; fds[1].events = IOPOLL_READ; for (;;) { if (iopoll_restart(fds, 2, -1) == -1) die1sys(111, "Poll failed"); if (fds[0].revents) if (connection_read(&conn, handle_packet) <= 0) break; if (fds[1].revents) { read(selfpipe, &i, 1); handle_child(WNOHANG); } } msg1("Waiting for remaining slots to complete"); while (slots_used > 0) handle_child(0); return 0; }
/** Connect a socket to an IPv4 address, honouring a timeout. * * \note The socket will have nonblocking mode turned on on return from * this function. */ int socket_connect4_timeout(int sock, const ipv4addr* ip, ipv4port port, int timeout) { iopoll_fd pf; if (!nonblock_on(sock)) return 0; if (socket_connect4(sock, ip, port)) return 1; if (errno != EINPROGRESS && errno != EWOULDBLOCK) return 0; pf.fd = sock; pf.events = IOPOLL_WRITE; switch (iopoll_restart(&pf, 1, timeout)) { case 0: errno = ETIMEDOUT; return 0; case 1: if (socket_connected(sock)) return 1; /* No break, fall through */ default: return 0; } }
int main(int ac, char **av) { const char * const fifoname = "./fio.fifo"; const char * const filename = "./fio.file"; const mode_t mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH; FILE *file; char line[BUFSIZ]; const int lock = 1; int errors = 0; int fd, wfd; if (ac == 2 && !strcmp(av[1], "help")) { printf("usage: %s\n", *av); return EXIT_SUCCESS; } printf("Testing: %s\n", "fio"); umask(0); if ((fd = fifo_open(fifoname, mode, lock, &wfd)) == -1) { ++errors, printf("Test1: fifo_open(\"%s\", %d, %d) failed (%s)\n", fifoname, (int)mode, lock, strerror(errno)); #ifndef HAVE_FCNTL_THAT_CAN_LOCK_FIFOS printf("\n Can your system lock fifos?\n\n"); #endif } else { if ((fcntl_lock(fd, F_SETLK, F_WRLCK, SEEK_SET, 0, 0)) != -1) ++errors, printf("Test2: fcntl_lock(wrlock) failed\n"); /* Should really test that the following non-blocking changes do occur */ if (nonblock_on(fd) == -1) ++errors, printf("Test3: nonblock_on() failed (%s)\n", strerror(errno)); if (nonblock_off(fd) == -1) ++errors, printf("Test4: nonblock_off() failed (%s)\n", strerror(errno)); if (fcntl_set_flag(fd, O_NONBLOCK) == -1) ++errors, printf("Test5: fcntl_set_flag() failed (%s)\n", strerror(errno)); if (fcntl_clear_flag(fd, O_NONBLOCK) == -1) ++errors, printf("Test6: fcntl_clear_flag() failed (%s)\n", strerror(errno)); close(fd); close(wfd); unlink(fifoname); } #define CHECK_FGETLINE(i, size, expected) \ if ((expected) && !fgetline(line, (size), file)) \ ++errors, printf("Test%d: fgetline() failed\n", (i)); \ else if ((expected) && strcmp(line, ((expected) ? (expected) : ""))) \ ++errors, printf("Test%d: fgetline() read \"%s\", not \"%s\"\n", (i), line, (expected ? expected : "(null)")); #define TEST_FGETLINE(i, buf, size, contents, line1, line2, line3) \ if (!(file = fopen(filename, "wb"))) \ ++errors, printf("Test%d: failed to run test: failed to create test file\n", (i)); \ else \ { \ if (fwrite((contents), 1, strlen(contents), file) != strlen(contents)) \ ++errors, printf("Test%d: failed to run test: failed to write to test file\n", (i)); \ else \ { \ fclose(file); \ if (!(file = fopen(filename, "r"))) \ ++errors, printf("Test%d: failed to run test: failed to open test file for reading\n", (i)); \ else \ { \ CHECK_FGETLINE((i), (size), (line1)) \ CHECK_FGETLINE((i), (size), (line2)) \ CHECK_FGETLINE((i), (size), (line3)) \ if (fgetline(buf, BUFSIZ, file)) \ ++errors, printf("Test%d: fgetline() failed to return NULL at end of file\n", (i)); \ } \ } \ fclose(file); \ unlink(filename); \ } TEST_FGETLINE(7, line, BUFSIZ, "abc\ndef\r\nghi\r", "abc\n", "def\n", "ghi\n") TEST_FGETLINE(8, line, BUFSIZ, "abc\rdef\nghi\r\n", "abc\n", "def\n", "ghi\n") TEST_FGETLINE(9, line, BUFSIZ, "abc\r\ndef\rghi\n", "abc\n", "def\n", "ghi\n") TEST_FGETLINE(10, line, BUFSIZ, "abc\ndef\rghi", "abc\n", "def\n", "ghi") TEST_FGETLINE(11, line, BUFSIZ, "", (char *)NULL, (char *)NULL, (char *)NULL) TEST_FGETLINE(12, line, 5, "abc", "abc", (char *)NULL, (char *)NULL) TEST_FGETLINE(13, line, 5, "abc\n", "abc\n", (char *)NULL, (char *)NULL) TEST_FGETLINE(14, line, 5, "abc\r\n", "abc\n", (char *)NULL, (char *)NULL) TEST_FGETLINE(15, line, 5, "abc\r", "abc\n", (char *)NULL, (char *)NULL) TEST_FGETLINE(16, line, 3, "abc\r", "ab", "c\n", (char *)NULL) TEST_FGETLINE(17, NULL, 0, "abc\r", (char *)NULL, (char *)NULL, (char *)NULL) /* Test read_timeout() and write_timeout() */ if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, S_IRUSR | S_IWUSR)) == -1) ++errors, printf("Test19: failed to create %s (%s)\n", filename, strerror(errno)); else { char buf[12] = "0123456789\n"; if (write_timeout(fd, 1, 0) == -1) ++errors, printf("Test18: write_timeout(fd, 1, 0) failed (%s)\n", strerror(errno)); else if (write(fd, buf, 11) != 11) ++errors, printf("Test18: write(fd, \"0123456789\\n\", 11) failed (%s)\n", strerror(errno)); else { close(fd); if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) ++errors, printf("Test19: failed to open %s for reading (%s)\n", filename, strerror(errno)); else if (read_timeout(fd, 1, 0) == -1) ++errors, printf("Test19: read_timeout(fd, 1, 0) failed (%s)\n", strerror(errno)); else if (read(fd, buf, 11) != 11) ++errors, printf("Test19: read(fd) failed (%s)\n", strerror(errno)); } close(fd); } unlink(filename); /* Test error handling */ #define TEST_ERR(i, func) \ if ((func) != -1) \ ++errors, printf("Test%d: %s failed to return -1\n", (i), (#func)); \ else if (errno != EINVAL) \ ++errors, printf("Test%d: %s failed (errno = %s, not %s)\n", (i), (#func), strerror(errno), strerror(EINVAL)); TEST_ERR(20, read_timeout(-1, 0, 0)) TEST_ERR(21, read_timeout(0, -1, 0)) TEST_ERR(22, read_timeout(0, 0, -1)) TEST_ERR(23, write_timeout(-1, 0, 0)) TEST_ERR(24, write_timeout(0, -1, 0)) TEST_ERR(25, write_timeout(0, 0, -1)) TEST_ERR(26, rw_timeout(-1, 0, 0)) TEST_ERR(27, rw_timeout(0, -1, 0)) TEST_ERR(28, rw_timeout(0, 0, -1)) TEST_ERR(29, nap(-1, 0)) TEST_ERR(30, nap(0, -1)) if (errors) printf("%d/30 tests failed\n", errors); else printf("All tests passed\n"); #ifndef HAVE_FCNTL_THAT_CAN_LOCK_FIFOS printf("\n"); printf(" Note: Some systems (e.g. FreeBSD) can't lock fifos so fifo_open()\n"); printf(" can't guarantee a unique reader.\n"); #endif return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE; }
int nonblock_set(int fd, int arg) { return (arg) ? nonblock_on(fd) : nonblock_off(fd); }