source: web/old/remctl-2.14/tests/util/fdflag-t.c @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 3.1 KB
Line 
1/*
2 * fdflag test suite.
3 *
4 * Written by Russ Allbery <rra@stanford.edu>
5 * Copyright 2008, 2009 Board of Trustees, Leland Stanford Jr. University
6 *
7 * See LICENSE for licensing terms.
8 */
9
10#include <config.h>
11#include <portable/system.h>
12#include <portable/socket.h>
13
14#include <errno.h>
15#include <sys/wait.h>
16
17#include <tests/tap/basic.h>
18#include <util/util.h>
19
20
21int
22main(void)
23{
24    int master, data, out1, out2;
25    socklen_t size;
26    ssize_t status;
27    struct sockaddr_in sin;
28    pid_t child;
29    char buffer[] = "D";
30
31    plan(8);
32
33    /* Parent will create the socket first to get the port number. */
34    memset(&sin, '\0', sizeof(sin));
35    sin.sin_family = AF_INET;
36    master = socket(AF_INET, SOCK_STREAM, 0);
37    if (master == -1)
38        sysbail("socket creation failed");
39    if (bind(master, (struct sockaddr *) &sin, sizeof(sin)) < 0)
40        sysbail("bind failed");
41    size = sizeof(sin);
42    if (getsockname(master, (struct sockaddr *) &sin, &size) < 0)
43        sysbail("getsockname failed");
44    if (listen(master, 1) < 0)
45        sysbail("listen failed");
46
47    /* Duplicate standard output to test close-on-exec. */
48    out1 = 8;
49    out2 = 9;
50    if (dup2(fileno(stdout), out1) < 0)
51        sysbail("cannot dup stdout to fd 8");
52    if (dup2(fileno(stdout), out2) < 0)
53        sysbail("cannot dup stdout to fd 9");
54    ok(fdflag_close_exec(out1, true), "set fd 8 to close-on-exec");
55    ok(fdflag_close_exec(out2, true), "set fd 9 to close-on-exec");
56    ok(fdflag_close_exec(out2, false), "set fd 9 back to regular");
57
58    /*
59     * Fork, child closes the open socket and then tries to connect, parent
60     * calls listen() and accept() on it.  Parent will then set the socket
61     * non-blocking and try to read from it to see what happens, then write to
62     * the socket and close it, triggering the child close and exit.
63     *
64     * Before the child exits, it will exec a shell that will print "no" to
65     * the duplicate of stdout that the parent created and then the ok to
66     * regular stdout.
67     */
68    child = fork();
69    if (child < 0) {
70        sysbail("fork failed");
71    } else if (child != 0) {
72        size = sizeof(sin);
73        data = accept(master, (struct sockaddr *) &sin, &size);
74        close(master);
75        if (data < 0)
76            sysbail("accept failed");
77        ok(fdflag_nonblocking(data, true), "set socket non-blocking");
78        status = read(data, buffer, sizeof(buffer));
79        is_int(-1, status, "got -1 from non-blocking read");
80        is_int(EAGAIN, errno, "...with EAGAIN errno");
81        write(data, buffer, sizeof(buffer));
82        close(data);
83    } else {
84        data = socket(AF_INET, SOCK_STREAM, 0);
85        if (data < 0)
86            sysbail("child socket failed");
87        if (connect(data, (struct sockaddr *) &sin, sizeof(sin)) < 0)
88            sysbail("child connect failed");
89        read(data, buffer, sizeof(buffer));
90        fclose(stderr);
91        execlp("sh", "sh", "-c",
92               "printf 'not ' >&8; echo ok 7; echo 'ok 8' >&9", (char *) 0);
93        sysbail("exec failed");
94    }
95    waitpid(child, NULL, 0);
96    exit(0);
97}
Note: See TracBrowser for help on using the repository browser.