1*72d5dedfSKonstantin Belousov /*
2*72d5dedfSKonstantin Belousov * Initially written by Yar Tikhiy <yar@freebsd.org> in PR 76398.
3*72d5dedfSKonstantin Belousov * Bug fixes and instrumentation by kib@freebsd.org.
4*72d5dedfSKonstantin Belousov */
5*72d5dedfSKonstantin Belousov
6*72d5dedfSKonstantin Belousov #include <sys/types.h>
7*72d5dedfSKonstantin Belousov #include <sys/socket.h>
8*72d5dedfSKonstantin Belousov #include <sys/stat.h>
9*72d5dedfSKonstantin Belousov #include <sys/wait.h>
10*72d5dedfSKonstantin Belousov #include <err.h>
11*72d5dedfSKonstantin Belousov #include <errno.h>
12*72d5dedfSKonstantin Belousov #include <fcntl.h>
13*72d5dedfSKonstantin Belousov #include <md5.h>
14*72d5dedfSKonstantin Belousov #include <signal.h>
15*72d5dedfSKonstantin Belousov #include <stdio.h>
16*72d5dedfSKonstantin Belousov #include <stdlib.h>
17*72d5dedfSKonstantin Belousov #include <string.h>
18*72d5dedfSKonstantin Belousov #include <unistd.h>
19*72d5dedfSKonstantin Belousov
20*72d5dedfSKonstantin Belousov #include <atf-c.h>
21*72d5dedfSKonstantin Belousov
22*72d5dedfSKonstantin Belousov #define NDATA 1000
23*72d5dedfSKonstantin Belousov #define DELAY 2
24*72d5dedfSKonstantin Belousov
25*72d5dedfSKonstantin Belousov static void
hup(int signo __unused)26*72d5dedfSKonstantin Belousov hup(int signo __unused)
27*72d5dedfSKonstantin Belousov {
28*72d5dedfSKonstantin Belousov }
29*72d5dedfSKonstantin Belousov
30*72d5dedfSKonstantin Belousov static int ndata, seq;
31*72d5dedfSKonstantin Belousov
32*72d5dedfSKonstantin Belousov static void
setdata(int n)33*72d5dedfSKonstantin Belousov setdata(int n)
34*72d5dedfSKonstantin Belousov {
35*72d5dedfSKonstantin Belousov ndata = n;
36*72d5dedfSKonstantin Belousov seq = 0;
37*72d5dedfSKonstantin Belousov }
38*72d5dedfSKonstantin Belousov
39*72d5dedfSKonstantin Belousov static char *
getdata(void)40*72d5dedfSKonstantin Belousov getdata(void)
41*72d5dedfSKonstantin Belousov {
42*72d5dedfSKonstantin Belousov static char databuf[256];
43*72d5dedfSKonstantin Belousov static char xeof[] = "#";
44*72d5dedfSKonstantin Belousov
45*72d5dedfSKonstantin Belousov if (seq > ndata)
46*72d5dedfSKonstantin Belousov return (NULL);
47*72d5dedfSKonstantin Belousov if (seq == ndata) {
48*72d5dedfSKonstantin Belousov seq++;
49*72d5dedfSKonstantin Belousov return (xeof);
50*72d5dedfSKonstantin Belousov }
51*72d5dedfSKonstantin Belousov sprintf(databuf, "%08d xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", seq++);
52*72d5dedfSKonstantin Belousov return (databuf);
53*72d5dedfSKonstantin Belousov }
54*72d5dedfSKonstantin Belousov
55*72d5dedfSKonstantin Belousov ATF_TC_WITHOUT_HEAD(eintr_test);
ATF_TC_BODY(eintr_test,tc)56*72d5dedfSKonstantin Belousov ATF_TC_BODY(eintr_test, tc)
57*72d5dedfSKonstantin Belousov {
58*72d5dedfSKonstantin Belousov char c, digest0[33], digest[33], *p;
59*72d5dedfSKonstantin Belousov FILE *fp;
60*72d5dedfSKonstantin Belousov int i, s[2], total0, total;
61*72d5dedfSKonstantin Belousov MD5_CTX md5;
62*72d5dedfSKonstantin Belousov pid_t child;
63*72d5dedfSKonstantin Belousov struct sigaction sa;
64*72d5dedfSKonstantin Belousov
65*72d5dedfSKonstantin Belousov MD5Init(&md5);
66*72d5dedfSKonstantin Belousov setdata(NDATA);
67*72d5dedfSKonstantin Belousov for (total0 = 0; (p = getdata()) != NULL; total0 += strlen(p))
68*72d5dedfSKonstantin Belousov MD5Update(&md5, p, strlen(p));
69*72d5dedfSKonstantin Belousov p = MD5End(&md5, digest0);
70*72d5dedfSKonstantin Belousov
71*72d5dedfSKonstantin Belousov sa.sa_handler = hup;
72*72d5dedfSKonstantin Belousov sigemptyset(&sa.sa_mask);
73*72d5dedfSKonstantin Belousov sa.sa_flags = 0;
74*72d5dedfSKonstantin Belousov ATF_REQUIRE(sigaction(SIGHUP, &sa, NULL) == 0);
75*72d5dedfSKonstantin Belousov
76*72d5dedfSKonstantin Belousov ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, s) == 0);
77*72d5dedfSKonstantin Belousov
78*72d5dedfSKonstantin Belousov switch (child = fork()) {
79*72d5dedfSKonstantin Belousov case -1:
80*72d5dedfSKonstantin Belousov atf_tc_fail("fork failed %s", strerror(errno));
81*72d5dedfSKonstantin Belousov break;
82*72d5dedfSKonstantin Belousov
83*72d5dedfSKonstantin Belousov case 0:
84*72d5dedfSKonstantin Belousov ATF_REQUIRE((fp = fdopen(s[0], "w")) != NULL);
85*72d5dedfSKonstantin Belousov close(s[1]);
86*72d5dedfSKonstantin Belousov setdata(NDATA);
87*72d5dedfSKonstantin Belousov while ((p = getdata())) {
88*72d5dedfSKonstantin Belousov for (; *p;) {
89*72d5dedfSKonstantin Belousov if (fputc(*p, fp) == EOF) {
90*72d5dedfSKonstantin Belousov if (errno == EINTR) {
91*72d5dedfSKonstantin Belousov clearerr(fp);
92*72d5dedfSKonstantin Belousov } else {
93*72d5dedfSKonstantin Belousov atf_tc_fail("fputc errno %s",
94*72d5dedfSKonstantin Belousov strerror(errno));
95*72d5dedfSKonstantin Belousov }
96*72d5dedfSKonstantin Belousov } else {
97*72d5dedfSKonstantin Belousov p++;
98*72d5dedfSKonstantin Belousov }
99*72d5dedfSKonstantin Belousov }
100*72d5dedfSKonstantin Belousov }
101*72d5dedfSKonstantin Belousov fclose(fp);
102*72d5dedfSKonstantin Belousov break;
103*72d5dedfSKonstantin Belousov
104*72d5dedfSKonstantin Belousov default:
105*72d5dedfSKonstantin Belousov close(s[0]);
106*72d5dedfSKonstantin Belousov ATF_REQUIRE((fp = fdopen(s[1], "r")) != NULL);
107*72d5dedfSKonstantin Belousov sleep(DELAY);
108*72d5dedfSKonstantin Belousov ATF_REQUIRE(kill(child, SIGHUP) != -1);
109*72d5dedfSKonstantin Belousov sleep(DELAY);
110*72d5dedfSKonstantin Belousov MD5Init(&md5);
111*72d5dedfSKonstantin Belousov for (total = 0;;) {
112*72d5dedfSKonstantin Belousov i = fgetc(fp);
113*72d5dedfSKonstantin Belousov if (i == EOF) {
114*72d5dedfSKonstantin Belousov if (errno == EINTR) {
115*72d5dedfSKonstantin Belousov clearerr(fp);
116*72d5dedfSKonstantin Belousov } else {
117*72d5dedfSKonstantin Belousov atf_tc_fail("fgetc errno %s",
118*72d5dedfSKonstantin Belousov strerror(errno));
119*72d5dedfSKonstantin Belousov }
120*72d5dedfSKonstantin Belousov continue;
121*72d5dedfSKonstantin Belousov }
122*72d5dedfSKonstantin Belousov total++;
123*72d5dedfSKonstantin Belousov c = i;
124*72d5dedfSKonstantin Belousov MD5Update(&md5, &c, 1);
125*72d5dedfSKonstantin Belousov if (i == '#')
126*72d5dedfSKonstantin Belousov break;
127*72d5dedfSKonstantin Belousov }
128*72d5dedfSKonstantin Belousov MD5End(&md5, digest);
129*72d5dedfSKonstantin Belousov fclose(fp);
130*72d5dedfSKonstantin Belousov ATF_REQUIRE_MSG(total == total0,
131*72d5dedfSKonstantin Belousov "Total number of bytes read does not match: %d %d",
132*72d5dedfSKonstantin Belousov total, total0);
133*72d5dedfSKonstantin Belousov ATF_REQUIRE_MSG(strcmp(digest, digest0) == 0,
134*72d5dedfSKonstantin Belousov "Digests do not match %s %s", digest, digest0);
135*72d5dedfSKonstantin Belousov break;
136*72d5dedfSKonstantin Belousov }
137*72d5dedfSKonstantin Belousov }
138*72d5dedfSKonstantin Belousov
ATF_TP_ADD_TCS(tp)139*72d5dedfSKonstantin Belousov ATF_TP_ADD_TCS(tp)
140*72d5dedfSKonstantin Belousov {
141*72d5dedfSKonstantin Belousov ATF_TP_ADD_TC(tp, eintr_test);
142*72d5dedfSKonstantin Belousov return (atf_no_error());
143*72d5dedfSKonstantin Belousov }
144