URI: 
       handlr.c - geomyidae - A small C-based gopherd.
  HTML git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
       handlr.c (5663B)
       ---
            1 /*
            2  * Copy me if you can.
            3  * by 20h
            4  */
            5 
            6 #include <unistd.h>
            7 #include <memory.h>
            8 #include <netdb.h>
            9 #include <netinet/in.h>
           10 #include <fcntl.h>
           11 #include <stdio.h>
           12 #include <stdlib.h>
           13 #include <string.h>
           14 #include <sys/socket.h>
           15 #include <sys/types.h>
           16 #include <sys/stat.h>
           17 #include <dirent.h>
           18 #include <sys/wait.h>
           19 #include <errno.h>
           20 #include <libgen.h>
           21 
           22 #include "ind.h"
           23 #include "arg.h"
           24 
           25 void
           26 handledir(int sock, char *path, char *port, char *base, char *args,
           27                 char *sear, char *ohost, char *chost, char *bhost, int istls,
           28                 char *sel, char *traverse)
           29 {
           30         char *pa, *file, *e, *par;
           31         struct dirent **dirent;
           32         int ndir, i, ret = 0;
           33         struct stat st;
           34         filetype *type;
           35 
           36         USED(args);
           37         USED(sear);
           38         USED(bhost);
           39         USED(sel);
           40         USED(traverse);
           41 
           42         pa = xstrdup(path);
           43 
           44         /* Is there any directory below the request? */
           45         if (strlen(pa+strlen(base)) > 1) {
           46                 par = xstrdup(pa+strlen(base));
           47                 e = strrchr(par, '/');
           48                 *e = '\0';
           49                 dprintf(sock, "1..\t%s\t%s\t%s\r\n",
           50                         par, ohost, port);
           51                 free(par);
           52         }
           53 
           54         ndir = scandir(pa, &dirent, 0, alphasort);
           55         if (ndir < 0) {
           56                 perror("scandir");
           57                 free(pa);
           58                 return;
           59         } else {
           60                 for (i = 0; i < ndir && ret >= 0; i++) {
           61                         if (dirent[i]->d_name[0] == '.')
           62                                 continue;
           63 
           64                         type = gettype(dirent[i]->d_name);
           65 
           66                         file = smprintf("%s%s%s",
           67                                         pa,
           68                                         pa[strlen(pa)-1] == '/'? "" : "/",
           69                                         dirent[i]->d_name);
           70                         if (stat(file, &st) >= 0 && S_ISDIR(st.st_mode))
           71                                 type = gettype("index.gph");
           72                         ret = dprintf(sock,
           73                                         "%c%-50.50s %10s %16s\t%s\t%s\t%s\r\n",
           74                                         *type->type,
           75                                         dirent[i]->d_name,
           76                                         humansize(st.st_size),
           77                                         humantime(&(st.st_mtime)),
           78                                         file + strlen(base), ohost, port);
           79                         free(file);
           80                 }
           81                 for (i = 0; i < ndir; i++)
           82                         free(dirent[i]);
           83                 free(dirent);
           84         }
           85         dprintf(sock, ".\r\n");
           86 
           87         free(pa);
           88 }
           89 
           90 void
           91 handlegph(int sock, char *file, char *port, char *base, char *args,
           92                 char *sear, char *ohost, char *chost, char *bhost, int istls,
           93                 char *sel, char *traverse)
           94 {
           95         gphindex *act;
           96         int i, ret = 0;
           97 
           98         USED(args);
           99         USED(sear);
          100         USED(bhost);
          101         USED(sel);
          102         USED(traverse);
          103 
          104         act = gph_scanfile(file);
          105         if (act != NULL) {
          106                 for (i = 0; i < act->num && ret >= 0; i++)
          107                         ret = gph_printelem(sock, act->n[i], file, base, ohost, port);
          108                 dprintf(sock, ".\r\n");
          109 
          110                 for (i = 0; i < act->num; i++) {
          111                         gph_freeelem(act->n[i]);
          112                         act->n[i] = NULL;
          113                 }
          114                 gph_freeindex(act);
          115         }
          116 }
          117 
          118 void
          119 handlebin(int sock, char *file, char *port, char *base, char *args,
          120                 char *sear, char *ohost, char *chost, char *bhost, int istls,
          121                 char *sel, char *traverse)
          122 {
          123         int fd;
          124 
          125         USED(port);
          126         USED(base);
          127         USED(args);
          128         USED(sear);
          129         USED(ohost);
          130         USED(bhost);
          131         USED(sel);
          132         USED(traverse);
          133 
          134         fd = open(file, O_RDONLY);
          135         if (fd >= 0) {
          136                 if (xsendfile(fd, sock) < 0)
          137                         perror("sendfile");
          138                 close(fd);
          139         }
          140 }
          141 
          142 /*
          143  * See RFC3875 5 NPH Scripts
          144  *
          145  * In gopher, with no header parsing, this allows bi-directional
          146  * long-running communications. One example would be raw HTTP emulation.
          147  */
          148 void
          149 handlecgi(int sock, char *file, char *port, char *base, char *args,
          150                 char *sear, char *ohost, char *chost, char *bhost, int istls,
          151                 char *sel, char *traverse)
          152 {
          153         char *script, *path, *filec, *scriptc;
          154 
          155         USED(base);
          156         USED(port);
          157 
          158         filec = xstrdup(file);
          159         scriptc = xstrdup(file);
          160         path = dirname(filec);
          161         script = basename(scriptc);
          162 
          163         if (sear == NULL)
          164                 sear = "";
          165         if (args == NULL)
          166                 args = "";
          167 
          168         while (dup2(sock, 0) < 0 && errno == EINTR);
          169         while (dup2(sock, 1) < 0 && errno == EINTR);
          170         while (dup2(sock, 2) < 0 && errno == EINTR);
          171         switch (fork()) {
          172         case 0:
          173                 if (path != NULL) {
          174                         if (chdir(path) < 0)
          175                                 break;
          176                 }
          177 
          178                 setcgienviron(script, file, port, base, args, sear, ohost, chost,
          179                                 bhost, istls, sel, traverse);
          180 
          181                 if (execl(file, script, sear, args, ohost, port, traverse, sel,
          182                                 (char *)NULL) == -1) {
          183                         perror("execl");
          184                         _exit(1);
          185                 }
          186         case -1:
          187                 perror("fork");
          188                 break;
          189         default:
          190                 wait(NULL);
          191                 free(filec);
          192                 free(scriptc);
          193                 break;
          194         }
          195 }
          196 
          197 /*
          198  * This is RFC3875 NPH Scripts
          199  * plus parsing of GPH syntax for easier gophermap portability.
          200  */
          201 void
          202 handledcgi(int sock, char *file, char *port, char *base, char *args,
          203                 char *sear, char *ohost, char *chost, char *bhost, int istls,
          204                 char *sel, char *traverse)
          205 {
          206         FILE *fp;
          207         char *script, *path, *filec, *scriptc, *ln = NULL;
          208         size_t linesiz = 0;
          209         ssize_t n;
          210         int outsocks[2], ret = 0;
          211         gphelem *el;
          212 
          213         if (socketpair(AF_LOCAL, SOCK_STREAM, 0, outsocks) < 0)
          214                 return;
          215 
          216         filec = xstrdup(file);
          217         scriptc = xstrdup(file);
          218         path = dirname(filec);
          219         script = basename(scriptc);
          220 
          221         if (sear == NULL)
          222                 sear = "";
          223         if (args == NULL)
          224                 args = "";
          225 
          226         while (dup2(sock, 0) < 0 && errno == EINTR);
          227         while (dup2(sock, 2) < 0 && errno == EINTR);
          228         switch (fork()) {
          229         case 0:
          230                 while (dup2(outsocks[1], 1) < 0 && errno == EINTR);
          231                 close(outsocks[0]);
          232                 if (path != NULL) {
          233                         if (chdir(path) < 0)
          234                                 break;
          235                 }
          236 
          237                 setcgienviron(script, file, port, base, args, sear, ohost, chost,
          238                                 bhost, istls, sel, traverse);
          239 
          240                 if (execl(file, script, sear, args, ohost, port, traverse, sel,
          241                                 (char *)NULL) == -1) {
          242                         perror("execl");
          243                         _exit(1);
          244                 }
          245                 break;
          246         case -1:
          247                 perror("fork");
          248                 break;
          249         default:
          250                 while (dup2(sock, 1) < 0 && errno == EINTR);
          251                 close(outsocks[1]);
          252 
          253                 if (!(fp = fdopen(outsocks[0], "r"))) {
          254                         perror("fdopen");
          255                         close(outsocks[0]);
          256                         break;
          257                 }
          258 
          259                 while ((n = getline(&ln, &linesiz, fp)) > 0 && ret >= 0) {
          260                         if (ln[n - 1] == '\n')
          261                                 ln[--n] = '\0';
          262 
          263                         el = gph_getadv(ln);
          264                         if (el == NULL)
          265                                 continue;
          266 
          267                         ret = gph_printelem(sock, el, file, base, ohost, port);
          268                         gph_freeelem(el);
          269                 }
          270                 if (ferror(fp))
          271                         perror("getline");
          272                 dprintf(sock, ".\r\n");
          273 
          274                 free(ln);
          275                 fclose(fp);
          276                 wait(NULL);
          277                 free(filec);
          278                 free(scriptc);
          279                 break;
          280         }
          281 }
          282