1#include <dirent.h>
2#include <errno.h>
3#include <fcntl.h>
4#include <stdio.h>
5#include <string.h>
6#include <unistd.h>
7#include <stdbool.h>
8#include <sys/select.h>
9#include <sys/socket.h>
10#include <sys/types.h>
11#include <stdlib.h>
12#include <time.h>
13
14#define formatBool(b) ((b) ? "true" : "false")
15
16void main_ls(char *dir_name, bool repeat) {
17 DIR *d;
18 struct dirent *dir;
19 d = opendir(dir_name);
20 if (d) {
21 while ((dir = readdir(d)) != NULL) {
22 printf("./%s\n", dir->d_name);
23 }
24 if (repeat) {
25 rewinddir(d);
26 while ((dir = readdir(d)) != NULL) {
27 printf("./%s\n", dir->d_name);
28 }
29 }
30 closedir(d);
31 } else if (errno == ENOTDIR) {
32 printf("ENOTDIR\n");
33 } else {
34 printf("%s\n", strerror(errno));
35 }
36}
37
38void main_stat() {
39 printf("stdin isatty: %s\n", formatBool(isatty(0)));
40 printf("stdout isatty: %s\n", formatBool(isatty(1)));
41 printf("stderr isatty: %s\n", formatBool(isatty(2)));
42 printf("/ isatty: %s\n", formatBool(isatty(3)));
43}
44
45void main_poll(int timeout, int millis) {
46 int ret = 0;
47 fd_set rfds;
48 struct timeval tv;
49
50 FD_ZERO(&rfds);
51 FD_SET(0, &rfds);
52
53 tv.tv_sec = timeout;
54 tv.tv_usec = millis*1000;
55 ret = select(1, &rfds, NULL, NULL, &tv);
56 if ((ret > 0) && FD_ISSET(0, &rfds)) {
57 printf("STDIN\n");
58 } else {
59 printf("NOINPUT\n");
60 }
61}
62
63void main_sleepmillis(int millis) {
64 struct timespec tim, tim2;
65 tim.tv_sec = 0;
66 tim.tv_nsec = millis * 1000000;
67
68 if(nanosleep(&tim , &tim2) < 0 ) {
69 printf("ERR\n");
70 return;
71 }
72
73 printf("OK\n");
74}
75
76void main_open_rdonly() {
77 const char *path = "zig-cc.rdonly.test";
78 int fd;
79 char buf[32];
80
81 fd = open(path, O_CREAT|O_TRUNC|O_RDONLY, 0644);
82 if (fd < 0) {
83 perror("ERR: open");
84 goto cleanup;
85 }
86 if (write(fd, "hello world\n", 12) >= 0) {
87 perror("ERR: write");
88 goto cleanup;
89 }
90 if (read(fd, buf, sizeof(buf)) != 0) {
91 perror("ERR: read");
92 goto cleanup;
93 }
94 puts("OK");
95 cleanup:
96 close(fd);
97 unlink(path);
98}
99
100void main_open_wronly() {
101 const char *path = "zig-cc.wronly.test";
102 int fd;
103 char buf[32];
104
105 fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, 0644);
106 if (fd < 0) {
107 perror("ERR: open");
108 goto cleanup;
109 }
110 if (write(fd, "hello world\n", 12) != 12) {
111 perror("ERR: write");
112 goto cleanup;
113 }
114 if (read(fd, buf, sizeof(buf)) >= 0) {
115 perror("ERR: read");
116 goto cleanup;
117 }
118 puts("OK");
119 cleanup:
120 close(fd);
121 unlink(path);
122}
123
124void main_sock() {
125 // Get a listener from the pre-opened file descriptor.
126 // The listener is the first pre-open, with a file-descriptor of 3.
127 int listener_fd = 3;
128
129 int nfd = -1;
130 // Some runtimes set the fd to NONBLOCK
131 // so we loop until we no longer get EAGAIN.
132 while (true) {
133 nfd = accept(listener_fd, NULL, NULL);
134 if (nfd >= 0) {
135 break;
136 }
137 if (errno == EAGAIN) {
138 sleep(1);
139 continue;
140 } else {
141 perror("ERR: accept");
142 return;
143 }
144 }
145
146 // Wait data to be available on nfd for 1 sec.
147 char buf[32];
148 struct timeval tv = {1, 0};
149 fd_set set;
150 FD_ZERO(&set);
151 FD_SET(nfd, &set);
152 int ret = select(nfd+1, &set, NULL, NULL, &tv);
153
154 // If some data is available, read it.
155 if (ret) {
156 // Assume no error: we are about to quit
157 // and we will check `buf` anyway.
158 recv(nfd, buf, sizeof(buf), 0);
159 printf("%s\n", buf);
160 } else {
161 puts("ERR: failed to read data");
162 }
163}
164
165void main_nonblock(char* fpath) {
166 struct timespec tim, tim2;
167 tim.tv_sec = 0;
168 tim.tv_nsec = 100 * 1000000; // 100 msec
169 int fd = open(fpath, O_RDONLY | O_NONBLOCK);
170 char buf[32];
171 ssize_t newLen = 0;
172 while (newLen == 0) {
173 newLen = read(fd, buf, sizeof(buf));
174 if (errno == EAGAIN || newLen == 0) {
175 printf(".");
176 nanosleep(&tim , &tim2) ;
177 continue;
178 }
179 }
180 printf("\n%s\n", buf);
181 close(fd);
182}
183
184int main(int argc, char** argv) {
185 if (strcmp(argv[1],"ls")==0) {
186 bool repeat = false;
187 if (argc > 3) {
188 repeat = strcmp(argv[3],"repeat")==0;
189 }
190 main_ls(argv[2], repeat);
191 } else if (strcmp(argv[1],"stat")==0) {
192 main_stat();
193 } else if (strcmp(argv[1],"poll")==0) {
194 int timeout = 0;
195 int usec = 0;
196 if (argc > 2) {
197 timeout = atoi(argv[2]);
198 }
199 if (argc > 3) {
200 usec = atoi(argv[3]);
201 }
202 main_poll(timeout, usec);
203 } else if (strcmp(argv[1],"sleepmillis")==0) {
204 int timeout = 0;
205 if (argc > 2) {
206 timeout = atoi(argv[2]);
207 }
208 main_sleepmillis(timeout);
209 } else if (strcmp(argv[1],"open-rdonly")==0) {
210 main_open_rdonly();
211 } else if (strcmp(argv[1],"open-wronly")==0) {
212 main_open_wronly();
213 } else if (strcmp(argv[1],"sock")==0) {
214 main_sock();
215 } else if (strcmp(argv[1],"nonblock")==0) {
216 main_nonblock(argv[2]);
217 } else {
218 fprintf(stderr, "unknown command: %s\n", argv[1]);
219 return 1;
220 }
221 return 0;
222}
View as plain text