github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/imports/wasi_snapshot_preview1/testdata/zig-cc/wasi.c (about) 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 16 void 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 38 void 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 45 void 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 63 void 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 76 void 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 100 void 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 124 void 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 165 void 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 an empty string is read, newLen might be 1, 175 // causing the loop to terminate. 176 if (strlen(buf) == 0) { 177 newLen = 0; 178 } 179 if (errno == EAGAIN || newLen == 0) { 180 printf("."); 181 nanosleep(&tim , &tim2) ; 182 continue; 183 } 184 } 185 printf("\n%s\n", buf); 186 close(fd); 187 } 188 189 int main(int argc, char** argv) { 190 if (strcmp(argv[1],"ls")==0) { 191 bool repeat = false; 192 if (argc > 3) { 193 repeat = strcmp(argv[3],"repeat")==0; 194 } 195 main_ls(argv[2], repeat); 196 } else if (strcmp(argv[1],"stat")==0) { 197 main_stat(); 198 } else if (strcmp(argv[1],"poll")==0) { 199 int timeout = 0; 200 int usec = 0; 201 if (argc > 2) { 202 timeout = atoi(argv[2]); 203 } 204 if (argc > 3) { 205 usec = atoi(argv[3]); 206 } 207 main_poll(timeout, usec); 208 } else if (strcmp(argv[1],"sleepmillis")==0) { 209 int timeout = 0; 210 if (argc > 2) { 211 timeout = atoi(argv[2]); 212 } 213 main_sleepmillis(timeout); 214 } else if (strcmp(argv[1],"open-rdonly")==0) { 215 main_open_rdonly(); 216 } else if (strcmp(argv[1],"open-wronly")==0) { 217 main_open_wronly(); 218 } else if (strcmp(argv[1],"sock")==0) { 219 main_sock(); 220 } else if (strcmp(argv[1],"nonblock")==0) { 221 main_nonblock(argv[2]); 222 } else { 223 fprintf(stderr, "unknown command: %s\n", argv[1]); 224 return 1; 225 } 226 return 0; 227 }