iind.c - geomyidae - A small C-based gopherd. Err bitreich.org 70 hgit clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ URL:git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ bitreich.org 70 1Log /scm/geomyidae/log.gph bitreich.org 70 1Files /scm/geomyidae/files.gph bitreich.org 70 1Refs /scm/geomyidae/refs.gph bitreich.org 70 1Tags /scm/geomyidae/tag bitreich.org 70 1README /scm/geomyidae/file/README.gph bitreich.org 70 1LICENSE /scm/geomyidae/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 iind.c (12847B) Err bitreich.org 70 i--- Err bitreich.org 70 i 1 /* Err bitreich.org 70 i 2 * Copy me if you can. Err bitreich.org 70 i 3 * by 20h Err bitreich.org 70 i 4 */ Err bitreich.org 70 i 5 Err bitreich.org 70 i 6 #ifdef __linux__ Err bitreich.org 70 i 7 #define _GNU_SOURCE Err bitreich.org 70 i 8 #endif Err bitreich.org 70 i 9 Err bitreich.org 70 i 10 #include Err bitreich.org 70 i 11 #include Err bitreich.org 70 i 12 #include Err bitreich.org 70 i 13 #include Err bitreich.org 70 i 14 #include Err bitreich.org 70 i 15 #include Err bitreich.org 70 i 16 #include Err bitreich.org 70 i 17 #include Err bitreich.org 70 i 18 #include Err bitreich.org 70 i 19 #include Err bitreich.org 70 i 20 #include Err bitreich.org 70 i 21 #include Err bitreich.org 70 i 22 #include Err bitreich.org 70 i 23 #include Err bitreich.org 70 i 24 #include Err bitreich.org 70 i 25 #include Err bitreich.org 70 i 26 #include Err bitreich.org 70 i 27 #include Err bitreich.org 70 i 28 #include Err bitreich.org 70 i 29 Err bitreich.org 70 i 30 #define PAGE_SHIFT 12 Err bitreich.org 70 i 31 #define PAGE_SIZE (1UL << PAGE_SHIFT) Err bitreich.org 70 i 32 #define BLOCK_SIZE ((PAGE_SIZE * 16) - 1) Err bitreich.org 70 i 33 Err bitreich.org 70 i 34 #include "arg.h" Err bitreich.org 70 i 35 #include "ind.h" Err bitreich.org 70 i 36 #include "handlr.h" Err bitreich.org 70 i 37 Err bitreich.org 70 i 38 /* Err bitreich.org 70 i 39 * Be careful, to look at handlerequest(), in case you add any executing Err bitreich.org 70 i 40 * handler, so nocgi will be valuable. Err bitreich.org 70 i 41 * Err bitreich.org 70 i 42 * All files are handled as binary, without a following ".\r\n". Proper Err bitreich.org 70 i 43 * encoding lines with beginning "." would be a really slow function, not Err bitreich.org 70 i 44 * adding any feature to gopher. Clients can check for the types Err bitreich.org 70 i 45 * requested and assume ".\r\n" or leave it out. Err bitreich.org 70 i 46 * Err bitreich.org 70 i 47 * Geomyidae only adds ".\r\n" in all kind of menus, like dir listings Err bitreich.org 70 i 48 * or dcgi files. There the case of some maybe future "." item type needs Err bitreich.org 70 i 49 * to be handled, if really used. Err bitreich.org 70 i 50 */ Err bitreich.org 70 i 51 Err bitreich.org 70 i 52 #include "filetypes.h" Err bitreich.org 70 i 53 Err bitreich.org 70 i 54 int Err bitreich.org 70 i 55 pendingbytes(int sock) Err bitreich.org 70 i 56 { Err bitreich.org 70 i 57 int pending, rval; Err bitreich.org 70 i 58 Err bitreich.org 70 i 59 pending = 0; Err bitreich.org 70 i 60 rval = 0; Err bitreich.org 70 i 61 #if defined(TIOCOUTQ) && !defined(__OpenBSD__) Err bitreich.org 70 i 62 rval = ioctl(sock, TIOCOUTQ, &pending); Err bitreich.org 70 i 63 #else Err bitreich.org 70 i 64 #ifdef SIOCOUTQ Err bitreich.org 70 i 65 rval = ioctl(sock, SIOCOUTQ, &pending); Err bitreich.org 70 i 66 #endif Err bitreich.org 70 i 67 #endif Err bitreich.org 70 i 68 Err bitreich.org 70 i 69 if (rval != 0) Err bitreich.org 70 i 70 return 0; Err bitreich.org 70 i 71 Err bitreich.org 70 i 72 return pending; Err bitreich.org 70 i 73 } Err bitreich.org 70 i 74 Err bitreich.org 70 i 75 void Err bitreich.org 70 i 76 waitforpendingbytes(int sock) Err bitreich.org 70 i 77 { Err bitreich.org 70 i 78 int npending = 0, opending = 0; Err bitreich.org 70 i 79 useconds_t trytime = 10; Err bitreich.org 70 i 80 Err bitreich.org 70 i 81 /* Err bitreich.org 70 i 82 * Wait until there is nothing pending or the connection stalled Err bitreich.org 70 i 83 * (nothing was sent) for around 40 seconds. Beware, trytime is Err bitreich.org 70 i 84 * an exponential wait. Err bitreich.org 70 i 85 */ Err bitreich.org 70 i 86 while ((npending = pendingbytes(sock)) > 0 && trytime < 20000000) { Err bitreich.org 70 i 87 if (opending != 0) { Err bitreich.org 70 i 88 if (opending != npending) { Err bitreich.org 70 i 89 trytime = 10; Err bitreich.org 70 i 90 } else { Err bitreich.org 70 i 91 /* Err bitreich.org 70 i 92 * Exponentially increase the usleep Err bitreich.org 70 i 93 * waiting time to not waste CPU Err bitreich.org 70 i 94 * resources. Err bitreich.org 70 i 95 */ Err bitreich.org 70 i 96 trytime += trytime; Err bitreich.org 70 i 97 } Err bitreich.org 70 i 98 } Err bitreich.org 70 i 99 opending = npending; Err bitreich.org 70 i 100 Err bitreich.org 70 i 101 usleep(trytime); Err bitreich.org 70 i 102 } Err bitreich.org 70 i 103 } Err bitreich.org 70 i 104 Err bitreich.org 70 i 105 #ifdef __linux__ Err bitreich.org 70 i 106 int Err bitreich.org 70 i 107 xsplice(int fd, int sock) Err bitreich.org 70 i 108 { Err bitreich.org 70 i 109 int pipefd[2], ret = 0; Err bitreich.org 70 i 110 ssize_t nread, nwritten; Err bitreich.org 70 i 111 off_t in_offset = 0; Err bitreich.org 70 i 112 Err bitreich.org 70 i 113 if (pipe(pipefd) < 0) Err bitreich.org 70 i 114 return -1; Err bitreich.org 70 i 115 Err bitreich.org 70 i 116 do { Err bitreich.org 70 i 117 nread = splice(fd, &in_offset, pipefd[1], NULL, Err bitreich.org 70 i 118 BLOCK_SIZE, SPLICE_F_MOVE | SPLICE_F_MORE); Err bitreich.org 70 i 119 Err bitreich.org 70 i 120 if (nread <= 0) { Err bitreich.org 70 i 121 ret = nread < 0 ? -1 : 0; Err bitreich.org 70 i 122 goto out; Err bitreich.org 70 i 123 } Err bitreich.org 70 i 124 Err bitreich.org 70 i 125 nwritten = splice(pipefd[0], NULL, sock, NULL, BLOCK_SIZE, Err bitreich.org 70 i 126 SPLICE_F_MOVE | SPLICE_F_MORE); Err bitreich.org 70 i 127 if (nwritten < 0) { Err bitreich.org 70 i 128 ret = -1; Err bitreich.org 70 i 129 goto out; Err bitreich.org 70 i 130 } Err bitreich.org 70 i 131 } while (nwritten > 0); Err bitreich.org 70 i 132 Err bitreich.org 70 i 133 out: Err bitreich.org 70 i 134 close(pipefd[0]); Err bitreich.org 70 i 135 close(pipefd[1]); Err bitreich.org 70 i 136 Err bitreich.org 70 i 137 return ret; Err bitreich.org 70 i 138 } Err bitreich.org 70 i 139 #endif Err bitreich.org 70 i 140 Err bitreich.org 70 i 141 int Err bitreich.org 70 i 142 xsendfile(int fd, int sock) Err bitreich.org 70 i 143 { Err bitreich.org 70 i 144 struct stat st; Err bitreich.org 70 i 145 char *sendb, *sendi; Err bitreich.org 70 i 146 size_t bufsiz = BUFSIZ; Err bitreich.org 70 i 147 int len, sent, optval; Err bitreich.org 70 i 148 Err bitreich.org 70 i 149 #ifdef splice Err bitreich.org 70 i 150 return xsplice(fd, sock); Err bitreich.org 70 i 151 #endif Err bitreich.org 70 i 152 Err bitreich.org 70 i 153 USED(optval); Err bitreich.org 70 i 154 Err bitreich.org 70 i 155 /* Err bitreich.org 70 i 156 * The story of xsendfile. Err bitreich.org 70 i 157 * Err bitreich.org 70 i 158 * Once upon a time, here you saw a big #ifdef switch source of Err bitreich.org 70 i 159 * many ways how to send files with special functions on Err bitreich.org 70 i 160 * different operating systems. All of this was removed, because Err bitreich.org 70 i 161 * operating systems and kernels got better over time, Err bitreich.org 70 i 162 * simplifying what you need and reducing corner cases. Err bitreich.org 70 i 163 * Err bitreich.org 70 i 164 * For example Linux sendfile(2) sounds nice and faster, but Err bitreich.org 70 i 165 * the function is different on every OS and slower to the now Err bitreich.org 70 i 166 * used approach of read(2) and write(2). Err bitreich.org 70 i 167 * Err bitreich.org 70 i 168 * If you ever consider changing this to some "faster" approach, Err bitreich.org 70 i 169 * consider benchmarks on all platforms. Err bitreich.org 70 i 170 */ Err bitreich.org 70 i 171 Err bitreich.org 70 i 172 if (fstat(fd, &st) >= 0) { Err bitreich.org 70 i 173 if ((bufsiz = st.st_blksize) < BUFSIZ) Err bitreich.org 70 i 174 bufsiz = BUFSIZ; Err bitreich.org 70 i 175 } Err bitreich.org 70 i 176 Err bitreich.org 70 i 177 sendb = xmalloc(bufsiz); Err bitreich.org 70 i 178 while ((len = read(fd, sendb, bufsiz)) > 0) { Err bitreich.org 70 i 179 sendi = sendb; Err bitreich.org 70 i 180 while (len > 0) { Err bitreich.org 70 i 181 if ((sent = write(sock, sendi, len)) < 0) { Err bitreich.org 70 i 182 free(sendb); Err bitreich.org 70 i 183 return -1; Err bitreich.org 70 i 184 } Err bitreich.org 70 i 185 len -= sent; Err bitreich.org 70 i 186 sendi += sent; Err bitreich.org 70 i 187 } Err bitreich.org 70 i 188 } Err bitreich.org 70 i 189 free(sendb); Err bitreich.org 70 i 190 Err bitreich.org 70 i 191 return 0; Err bitreich.org 70 i 192 } Err bitreich.org 70 i 193 Err bitreich.org 70 i 194 void * Err bitreich.org 70 i 195 xcalloc(size_t nmemb, size_t size) Err bitreich.org 70 i 196 { Err bitreich.org 70 i 197 void *p; Err bitreich.org 70 i 198 Err bitreich.org 70 i 199 if (!(p = calloc(nmemb, size))) { Err bitreich.org 70 i 200 perror("calloc"); Err bitreich.org 70 i 201 exit(1); Err bitreich.org 70 i 202 } Err bitreich.org 70 i 203 Err bitreich.org 70 i 204 return p; Err bitreich.org 70 i 205 } Err bitreich.org 70 i 206 Err bitreich.org 70 i 207 void * Err bitreich.org 70 i 208 xmalloc(size_t size) Err bitreich.org 70 i 209 { Err bitreich.org 70 i 210 void *p; Err bitreich.org 70 i 211 Err bitreich.org 70 i 212 if (!(p = malloc(size))) { Err bitreich.org 70 i 213 perror("malloc"); Err bitreich.org 70 i 214 exit(1); Err bitreich.org 70 i 215 } Err bitreich.org 70 i 216 Err bitreich.org 70 i 217 return p; Err bitreich.org 70 i 218 } Err bitreich.org 70 i 219 Err bitreich.org 70 i 220 void * Err bitreich.org 70 i 221 xrealloc(void *ptr, size_t size) Err bitreich.org 70 i 222 { Err bitreich.org 70 i 223 if (!(ptr = realloc(ptr, size))) { Err bitreich.org 70 i 224 perror("realloc"); Err bitreich.org 70 i 225 exit(1); Err bitreich.org 70 i 226 } Err bitreich.org 70 i 227 Err bitreich.org 70 i 228 return ptr; Err bitreich.org 70 i 229 } Err bitreich.org 70 i 230 Err bitreich.org 70 i 231 char * Err bitreich.org 70 i 232 xstrdup(const char *str) Err bitreich.org 70 i 233 { Err bitreich.org 70 i 234 char *ret; Err bitreich.org 70 i 235 Err bitreich.org 70 i 236 if (!(ret = strdup(str))) { Err bitreich.org 70 i 237 perror("strdup"); Err bitreich.org 70 i 238 exit(1); Err bitreich.org 70 i 239 } Err bitreich.org 70 i 240 Err bitreich.org 70 i 241 return ret; Err bitreich.org 70 i 242 } Err bitreich.org 70 i 243 Err bitreich.org 70 i 244 filetype * Err bitreich.org 70 i 245 gettype(char *filename) Err bitreich.org 70 i 246 { Err bitreich.org 70 i 247 char *end; Err bitreich.org 70 i 248 int i; Err bitreich.org 70 i 249 Err bitreich.org 70 i 250 end = strrchr(filename, '.'); Err bitreich.org 70 i 251 if (end == NULL) Err bitreich.org 70 i 252 return &type[0]; Err bitreich.org 70 i 253 end++; Err bitreich.org 70 i 254 Err bitreich.org 70 i 255 for (i = 0; type[i].end != NULL; i++) Err bitreich.org 70 i 256 if (!strcasecmp(end, type[i].end)) Err bitreich.org 70 i 257 return &type[i]; Err bitreich.org 70 i 258 Err bitreich.org 70 i 259 return &type[0]; Err bitreich.org 70 i 260 } Err bitreich.org 70 i 261 Err bitreich.org 70 i 262 void Err bitreich.org 70 i 263 gph_freeelem(gphelem *e) Err bitreich.org 70 i 264 { Err bitreich.org 70 i 265 if (e != NULL) { Err bitreich.org 70 i 266 if (e->e != NULL) { Err bitreich.org 70 i 267 for (;e->num > 0; e->num--) Err bitreich.org 70 i 268 if (e->e[e->num - 1] != NULL) Err bitreich.org 70 i 269 free(e->e[e->num - 1]); Err bitreich.org 70 i 270 free(e->e); Err bitreich.org 70 i 271 } Err bitreich.org 70 i 272 free(e); Err bitreich.org 70 i 273 } Err bitreich.org 70 i 274 return; Err bitreich.org 70 i 275 } Err bitreich.org 70 i 276 Err bitreich.org 70 i 277 void Err bitreich.org 70 i 278 gph_freeindex(gphindex *i) Err bitreich.org 70 i 279 { Err bitreich.org 70 i 280 if (i != NULL) { Err bitreich.org 70 i 281 if (i->n != NULL) { Err bitreich.org 70 i 282 for (;i->num > 0; i->num--) Err bitreich.org 70 i 283 gph_freeelem(i->n[i->num - 1]); Err bitreich.org 70 i 284 free(i->n); Err bitreich.org 70 i 285 } Err bitreich.org 70 i 286 free(i); Err bitreich.org 70 i 287 } Err bitreich.org 70 i 288 Err bitreich.org 70 i 289 return; Err bitreich.org 70 i 290 } Err bitreich.org 70 i 291 Err bitreich.org 70 i 292 void Err bitreich.org 70 i 293 gph_addelem(gphelem *e, char *s) Err bitreich.org 70 i 294 { Err bitreich.org 70 i 295 e->num++; Err bitreich.org 70 i 296 e->e = xrealloc(e->e, sizeof(char *) * e->num); Err bitreich.org 70 i 297 e->e[e->num - 1] = xstrdup(s); Err bitreich.org 70 i 298 Err bitreich.org 70 i 299 return; Err bitreich.org 70 i 300 } Err bitreich.org 70 i 301 Err bitreich.org 70 i 302 gphelem * Err bitreich.org 70 i 303 gph_getadv(char *str) Err bitreich.org 70 i 304 { Err bitreich.org 70 i 305 char *b, *e, *o, *bo; Err bitreich.org 70 i 306 gphelem *ret; Err bitreich.org 70 i 307 Err bitreich.org 70 i 308 ret = xcalloc(1, sizeof(gphelem)); Err bitreich.org 70 i 309 Err bitreich.org 70 i 310 if (strchr(str, '\t')) { Err bitreich.org 70 i 311 gph_addelem(ret, "i"); Err bitreich.org 70 i 312 gph_addelem(ret, "Happy helping ☃ here: You tried to " Err bitreich.org 70 i 313 "output a spurious TAB character. This will " Err bitreich.org 70 i 314 "break gopher. Please review your scripts. " Err bitreich.org 70 i 315 "Have a nice day!"); Err bitreich.org 70 i 316 gph_addelem(ret, "Err"); Err bitreich.org 70 i 317 gph_addelem(ret, "server"); Err bitreich.org 70 i 318 gph_addelem(ret, "port"); Err bitreich.org 70 i 319 Err bitreich.org 70 i 320 return ret; Err bitreich.org 70 i 321 } Err bitreich.org 70 i 322 Err bitreich.org 70 i 323 /* Check for escape sequence. */ Err bitreich.org 70 i 324 if (str[0] == '[' && str[1] != '|') { Err bitreich.org 70 i 325 o = xstrdup(str); Err bitreich.org 70 i 326 b = o + 1; Err bitreich.org 70 i 327 bo = b; Err bitreich.org 70 i 328 while ((e = strchr(bo, '|')) != NULL) { Err bitreich.org 70 i 329 if (e != bo && e[-1] == '\\') { Err bitreich.org 70 i 330 memmove(&e[-1], e, strlen(e)); Err bitreich.org 70 i 331 bo = e; Err bitreich.org 70 i 332 continue; Err bitreich.org 70 i 333 } Err bitreich.org 70 i 334 *e = '\0'; Err bitreich.org 70 i 335 e++; Err bitreich.org 70 i 336 gph_addelem(ret, b); Err bitreich.org 70 i 337 b = e; Err bitreich.org 70 i 338 bo = b; Err bitreich.org 70 i 339 } Err bitreich.org 70 i 340 Err bitreich.org 70 i 341 e = strchr(b, ']'); Err bitreich.org 70 i 342 if (e != NULL) { Err bitreich.org 70 i 343 *e = '\0'; Err bitreich.org 70 i 344 gph_addelem(ret, b); Err bitreich.org 70 i 345 } Err bitreich.org 70 i 346 free(o); Err bitreich.org 70 i 347 Err bitreich.org 70 i 348 if (ret->e != NULL && ret->e[0] != NULL && Err bitreich.org 70 i 349 ret->e[0][0] != '\0' && ret->num == 5) { Err bitreich.org 70 i 350 return ret; Err bitreich.org 70 i 351 } Err bitreich.org 70 i 352 Err bitreich.org 70 i 353 /* Invalid entry: Give back the whole line. */ Err bitreich.org 70 i 354 gph_freeelem(ret); Err bitreich.org 70 i 355 ret = xcalloc(1, sizeof(gphelem)); Err bitreich.org 70 i 356 } Err bitreich.org 70 i 357 Err bitreich.org 70 i 358 gph_addelem(ret, "i"); Err bitreich.org 70 i 359 /* Jump over escape sequence. */ Err bitreich.org 70 i 360 if (str[0] == '[' && str[1] == '|') Err bitreich.org 70 i 361 str += 2; Err bitreich.org 70 i 362 gph_addelem(ret, str); Err bitreich.org 70 i 363 gph_addelem(ret, "Err"); Err bitreich.org 70 i 364 gph_addelem(ret, "server"); Err bitreich.org 70 i 365 gph_addelem(ret, "port"); Err bitreich.org 70 i 366 Err bitreich.org 70 i 367 return ret; Err bitreich.org 70 i 368 } Err bitreich.org 70 i 369 Err bitreich.org 70 i 370 void Err bitreich.org 70 i 371 gph_addindex(gphindex *idx, gphelem *el) Err bitreich.org 70 i 372 { Err bitreich.org 70 i 373 idx->num++; Err bitreich.org 70 i 374 idx->n = xrealloc(idx->n, sizeof(gphelem *) * idx->num); Err bitreich.org 70 i 375 idx->n[idx->num - 1] = el; Err bitreich.org 70 i 376 Err bitreich.org 70 i 377 return; Err bitreich.org 70 i 378 } Err bitreich.org 70 i 379 Err bitreich.org 70 i 380 gphindex * Err bitreich.org 70 i 381 gph_scanfile(char *fname) Err bitreich.org 70 i 382 { Err bitreich.org 70 i 383 char *ln = NULL; Err bitreich.org 70 i 384 size_t linesiz = 0; Err bitreich.org 70 i 385 ssize_t n; Err bitreich.org 70 i 386 FILE *fp; Err bitreich.org 70 i 387 gphindex *ret; Err bitreich.org 70 i 388 gphelem *el; Err bitreich.org 70 i 389 Err bitreich.org 70 i 390 if (!(fp = fopen(fname, "r"))) Err bitreich.org 70 i 391 return NULL; Err bitreich.org 70 i 392 Err bitreich.org 70 i 393 ret = xcalloc(1, sizeof(gphindex)); Err bitreich.org 70 i 394 Err bitreich.org 70 i 395 while ((n = getline(&ln, &linesiz, fp)) > 0) { Err bitreich.org 70 i 396 if (ln[n - 1] == '\n') Err bitreich.org 70 i 397 ln[--n] = '\0'; Err bitreich.org 70 i 398 el = gph_getadv(ln); Err bitreich.org 70 i 399 if (el == NULL) Err bitreich.org 70 i 400 continue; Err bitreich.org 70 i 401 Err bitreich.org 70 i 402 gph_addindex(ret, el); Err bitreich.org 70 i 403 } Err bitreich.org 70 i 404 if (ferror(fp)) Err bitreich.org 70 i 405 perror("getline"); Err bitreich.org 70 i 406 free(ln); Err bitreich.org 70 i 407 fclose(fp); Err bitreich.org 70 i 408 Err bitreich.org 70 i 409 if (ret->n == NULL) { Err bitreich.org 70 i 410 free(ret); Err bitreich.org 70 i 411 return NULL; Err bitreich.org 70 i 412 } Err bitreich.org 70 i 413 Err bitreich.org 70 i 414 return ret; Err bitreich.org 70 i 415 } Err bitreich.org 70 i 416 Err bitreich.org 70 i 417 int Err bitreich.org 70 i 418 gph_printelem(int fd, gphelem *el, char *file, char *base, char *addr, char *port) Err bitreich.org 70 i 419 { Err bitreich.org 70 i 420 char *path, *p, *argbase, buf[PATH_MAX+1], *argp, *realbase, *rpath; Err bitreich.org 70 i 421 int len, blen; Err bitreich.org 70 i 422 Err bitreich.org 70 i 423 if (!strcmp(el->e[3], "server")) { Err bitreich.org 70 i 424 free(el->e[3]); Err bitreich.org 70 i 425 el->e[3] = xstrdup(addr); Err bitreich.org 70 i 426 } Err bitreich.org 70 i 427 if (!strcmp(el->e[4], "port")) { Err bitreich.org 70 i 428 free(el->e[4]); Err bitreich.org 70 i 429 el->e[4] = xstrdup(port); Err bitreich.org 70 i 430 } Err bitreich.org 70 i 431 Err bitreich.org 70 i 432 /* Err bitreich.org 70 i 433 * Ignore if the path is from base, if it might be some h type with Err bitreich.org 70 i 434 * some URL and ignore various types that have different semantics, Err bitreich.org 70 i 435 * do not point to some file or directory. Err bitreich.org 70 i 436 */ Err bitreich.org 70 i 437 if ((el->e[2][0] != '\0' Err bitreich.org 70 i 438 && el->e[2][0] != '/' /* Absolute Request. */ Err bitreich.org 70 i 439 && el->e[0][0] != 'i' /* Informational item. */ Err bitreich.org 70 i 440 && el->e[0][0] != '2' /* CSO server */ Err bitreich.org 70 i 441 && el->e[0][0] != '3' /* Error */ Err bitreich.org 70 i 442 && el->e[0][0] != '8' /* Telnet */ Err bitreich.org 70 i 443 && el->e[0][0] != 'w' /* Selector is direct URI. */ Err bitreich.org 70 i 444 && el->e[0][0] != 'T') && /* tn3270 */ Err bitreich.org 70 i 445 !(el->e[0][0] == 'h' && !strncmp(el->e[2], "URL:", 4))) { Err bitreich.org 70 i 446 path = file + strlen(base); Err bitreich.org 70 i 447 Err bitreich.org 70 i 448 /* Strip off original gph file name. */ Err bitreich.org 70 i 449 if ((p = strrchr(path, '/'))) { Err bitreich.org 70 i 450 len = strlen(path) - strlen(basename(path)); Err bitreich.org 70 i 451 } else { Err bitreich.org 70 i 452 len = strlen(path); Err bitreich.org 70 i 453 } Err bitreich.org 70 i 454 Err bitreich.org 70 i 455 /* Strip off arguments for realpath. */ Err bitreich.org 70 i 456 argbase = strchr(el->e[2], '?'); Err bitreich.org 70 i 457 if (argbase != NULL) { Err bitreich.org 70 i 458 blen = argbase - el->e[2]; Err bitreich.org 70 i 459 } else { Err bitreich.org 70 i 460 blen = strlen(el->e[2]); Err bitreich.org 70 i 461 } Err bitreich.org 70 i 462 Err bitreich.org 70 i 463 /* Err bitreich.org 70 i 464 * Print everything together. Realpath will resolve it. Err bitreich.org 70 i 465 */ Err bitreich.org 70 i 466 snprintf(buf, sizeof(buf), "%s%.*s%.*s", base, len, Err bitreich.org 70 i 467 path, blen, el->e[2]); Err bitreich.org 70 i 468 Err bitreich.org 70 i 469 if ((rpath = realpath(buf, NULL)) && Err bitreich.org 70 i 470 (realbase = realpath(*base? base : "/", NULL)) && Err bitreich.org 70 i 471 !strncmp(realbase, rpath, strlen(realbase))) { Err bitreich.org 70 i 472 p = rpath + (*base? strlen(realbase) : 0); Err bitreich.org 70 i 473 Err bitreich.org 70 i 474 /* Err bitreich.org 70 i 475 * Do not forget to re-add arguments which were Err bitreich.org 70 i 476 * stripped off. Err bitreich.org 70 i 477 */ Err bitreich.org 70 i 478 argp = smprintf("%s%s", *p? p : "/", argbase? argbase : ""); Err bitreich.org 70 i 479 Err bitreich.org 70 i 480 free(el->e[2]); Err bitreich.org 70 i 481 el->e[2] = argp; Err bitreich.org 70 i 482 free(realbase); Err bitreich.org 70 i 483 } Err bitreich.org 70 i 484 if (rpath != NULL) Err bitreich.org 70 i 485 free(rpath); Err bitreich.org 70 i 486 } Err bitreich.org 70 i 487 Err bitreich.org 70 i 488 if (dprintf(fd, "%.1s%s\t%s\t%s\t%s\r\n", el->e[0], el->e[1], el->e[2], Err bitreich.org 70 i 489 el->e[3], el->e[4]) < 0) { Err bitreich.org 70 i 490 perror("printgphelem: dprintf"); Err bitreich.org 70 i 491 return -1; Err bitreich.org 70 i 492 } Err bitreich.org 70 i 493 return 0; Err bitreich.org 70 i 494 } Err bitreich.org 70 i 495 Err bitreich.org 70 i 496 char * Err bitreich.org 70 i 497 smprintf(char *fmt, ...) Err bitreich.org 70 i 498 { Err bitreich.org 70 i 499 va_list fmtargs; Err bitreich.org 70 i 500 char *ret; Err bitreich.org 70 i 501 int size; Err bitreich.org 70 i 502 Err bitreich.org 70 i 503 va_start(fmtargs, fmt); Err bitreich.org 70 i 504 size = vsnprintf(NULL, 0, fmt, fmtargs); Err bitreich.org 70 i 505 va_end(fmtargs); Err bitreich.org 70 i 506 Err bitreich.org 70 i 507 ret = xcalloc(1, ++size); Err bitreich.org 70 i 508 va_start(fmtargs, fmt); Err bitreich.org 70 i 509 vsnprintf(ret, size, fmt, fmtargs); Err bitreich.org 70 i 510 va_end(fmtargs); Err bitreich.org 70 i 511 Err bitreich.org 70 i 512 return ret; Err bitreich.org 70 i 513 } Err bitreich.org 70 i 514 Err bitreich.org 70 i 515 char * Err bitreich.org 70 i 516 reverselookup(char *host) Err bitreich.org 70 i 517 { Err bitreich.org 70 i 518 struct in_addr hoststr; Err bitreich.org 70 i 519 struct hostent *client; Err bitreich.org 70 i 520 char *rethost; Err bitreich.org 70 i 521 Err bitreich.org 70 i 522 rethost = NULL; Err bitreich.org 70 i 523 Err bitreich.org 70 i 524 if (inet_pton(AF_INET, host, &hoststr)) { Err bitreich.org 70 i 525 client = gethostbyaddr((const void *)&hoststr, Err bitreich.org 70 i 526 sizeof(hoststr), AF_INET); Err bitreich.org 70 i 527 if (client != NULL) Err bitreich.org 70 i 528 rethost = xstrdup(client->h_name); Err bitreich.org 70 i 529 } Err bitreich.org 70 i 530 Err bitreich.org 70 i 531 if (rethost == NULL) Err bitreich.org 70 i 532 rethost = xstrdup(host); Err bitreich.org 70 i 533 Err bitreich.org 70 i 534 return rethost; Err bitreich.org 70 i 535 } Err bitreich.org 70 i 536 Err bitreich.org 70 i 537 void Err bitreich.org 70 i 538 setcgienviron(char *file, char *path, char *port, char *base, char *args, Err bitreich.org 70 i 539 char *sear, char *ohost, char *chost, char *bhost, int istls, Err bitreich.org 70 i 540 char *sel, char *traverse) Err bitreich.org 70 i 541 { Err bitreich.org 70 i 542 /* Err bitreich.org 70 i 543 * TODO: Clean environment from possible unsafe environment variables. Err bitreich.org 70 i 544 * But then it is the responsibility of the script writer. Err bitreich.org 70 i 545 */ Err bitreich.org 70 i 546 unsetenv("AUTH_TYPE"); Err bitreich.org 70 i 547 unsetenv("CONTENT_LENGTH"); Err bitreich.org 70 i 548 unsetenv("CONTENT_TYPE"); Err bitreich.org 70 i 549 setenv("GATEWAY_INTERFACE", "CGI/1.1", 1); Err bitreich.org 70 i 550 /* TODO: Separate, if run like rest.dcgi. */ Err bitreich.org 70 i 551 setenv("PATH_INFO", path+strlen(base), 1); Err bitreich.org 70 i 552 setenv("PATH_TRANSLATED", path, 1); Err bitreich.org 70 i 553 Err bitreich.org 70 i 554 setenv("QUERY_STRING", args, 1); Err bitreich.org 70 i 555 setenv("SELECTOR", sel, 1); Err bitreich.org 70 i 556 setenv("REQUEST", sel, 1); Err bitreich.org 70 i 557 setenv("TRAVERSAL", traverse, 1); Err bitreich.org 70 i 558 Err bitreich.org 70 i 559 setenv("REMOTE_ADDR", chost, 1); Err bitreich.org 70 i 560 /* Err bitreich.org 70 i 561 * Don't do a reverse lookup on every call. Only do when needed, in Err bitreich.org 70 i 562 * the script. The RFC allows us to set the IP to the value. Err bitreich.org 70 i 563 */ Err bitreich.org 70 i 564 setenv("REMOTE_HOST", chost, 1); Err bitreich.org 70 i 565 /* Please do not implement identd here. */ Err bitreich.org 70 i 566 unsetenv("REMOTE_IDENT"); Err bitreich.org 70 i 567 unsetenv("REMOTE_USER"); Err bitreich.org 70 i 568 /* Make PHP happy. */ Err bitreich.org 70 i 569 setenv("REDIRECT_STATUS", "", 1); Err bitreich.org 70 i 570 /* Err bitreich.org 70 i 571 * Only GET is possible in gopher. POST emulation would be really Err bitreich.org 70 i 572 * ugly. Err bitreich.org 70 i 573 */ Err bitreich.org 70 i 574 setenv("REQUEST_METHOD", "GET", 1); Err bitreich.org 70 i 575 setenv("SCRIPT_NAME", file, 1); Err bitreich.org 70 i 576 setenv("SERVER_NAME", ohost, 1); Err bitreich.org 70 i 577 setenv("SERVER_PORT", port, 1); Err bitreich.org 70 i 578 setenv("SERVER_LISTEN_NAME", bhost, 1); Err bitreich.org 70 i 579 if (istls) { Err bitreich.org 70 i 580 setenv("SERVER_PROTOCOL", "gophers/1.0", 1); Err bitreich.org 70 i 581 } else { Err bitreich.org 70 i 582 setenv("SERVER_PROTOCOL", "gopher/1.0", 1); Err bitreich.org 70 i 583 } Err bitreich.org 70 i 584 setenv("SERVER_SOFTWARE", "geomyidae", 1); Err bitreich.org 70 i 585 Err bitreich.org 70 i 586 setenv("X_GOPHER_SEARCH", sear, 1); Err bitreich.org 70 i 587 /* legacy compatibility */ Err bitreich.org 70 i 588 setenv("SEARCHREQUEST", sear, 1); Err bitreich.org 70 i 589 Err bitreich.org 70 i 590 if (istls) { Err bitreich.org 70 i 591 setenv("GOPHERS", "on", 1); Err bitreich.org 70 i 592 setenv("HTTPS", "on", 1); Err bitreich.org 70 i 593 } else { Err bitreich.org 70 i 594 unsetenv("GOPHERS"); Err bitreich.org 70 i 595 unsetenv("HTTPS"); Err bitreich.org 70 i 596 } Err bitreich.org 70 i 597 Err bitreich.org 70 i 598 } Err bitreich.org 70 i 599 Err bitreich.org 70 i 600 char * Err bitreich.org 70 i 601 humansize(off_t n) Err bitreich.org 70 i 602 { Err bitreich.org 70 i 603 static char buf[16]; Err bitreich.org 70 i 604 const char postfixes[] = "BKMGTPE"; Err bitreich.org 70 i 605 double size; Err bitreich.org 70 i 606 int i = 0; Err bitreich.org 70 i 607 Err bitreich.org 70 i 608 for (size = n; size >= 1024 && i < strlen(postfixes); i++) Err bitreich.org 70 i 609 size /= 1024; Err bitreich.org 70 i 610 Err bitreich.org 70 i 611 if (!i) { Err bitreich.org 70 i 612 snprintf(buf, sizeof(buf), "%ju%c", (uintmax_t)n, Err bitreich.org 70 i 613 postfixes[i]); Err bitreich.org 70 i 614 } else { Err bitreich.org 70 i 615 snprintf(buf, sizeof(buf), "%.1f%c", size, postfixes[i]); Err bitreich.org 70 i 616 } Err bitreich.org 70 i 617 Err bitreich.org 70 i 618 return buf; Err bitreich.org 70 i 619 } Err bitreich.org 70 i 620 Err bitreich.org 70 i 621 char * Err bitreich.org 70 i 622 humantime(const time_t *clock) Err bitreich.org 70 i 623 { Err bitreich.org 70 i 624 static char buf[32]; Err bitreich.org 70 i 625 struct tm *tm; Err bitreich.org 70 i 626 Err bitreich.org 70 i 627 tm = localtime(clock); Err bitreich.org 70 i 628 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M %Z", tm); Err bitreich.org 70 i 629 Err bitreich.org 70 i 630 return buf; Err bitreich.org 70 i 631 } Err bitreich.org 70 i 632 Err bitreich.org 70 i 633 void Err bitreich.org 70 i 634 lingersock(int sock) Err bitreich.org 70 i 635 { Err bitreich.org 70 i 636 struct linger lingerie; Err bitreich.org 70 i 637 int j; Err bitreich.org 70 i 638 Err bitreich.org 70 i 639 /* Err bitreich.org 70 i 640 * On close only wait for at maximum 60 seconds for all data to be Err bitreich.org 70 i 641 * transmitted before forcefully closing the connection. Err bitreich.org 70 i 642 */ Err bitreich.org 70 i 643 lingerie.l_onoff = 1; Err bitreich.org 70 i 644 lingerie.l_linger = 60; Err bitreich.org 70 i 645 setsockopt(sock, SOL_SOCKET, SO_LINGER, Err bitreich.org 70 i 646 &lingerie, sizeof(lingerie)); Err bitreich.org 70 i 647 Err bitreich.org 70 i 648 /* Err bitreich.org 70 i 649 * Force explicit flush of buffers using TCP_NODELAY. Err bitreich.org 70 i 650 */ Err bitreich.org 70 i 651 j = 1; Err bitreich.org 70 i 652 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &j, sizeof(int)); Err bitreich.org 70 i 653 waitforpendingbytes(sock); Err bitreich.org 70 i 654 j = 0; Err bitreich.org 70 i 655 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &j, sizeof(int)); Err bitreich.org 70 i 656 Err bitreich.org 70 i 657 return; Err bitreich.org 70 i 658 } Err bitreich.org 70 i 659 Err bitreich.org 70 .