geomyidae

A small C-based gopherd. (gopher://bitreich.org/1/scm/geomyidae)
git clone git://r-36.net/geomyidae
Log | Files | Refs | README | LICENSE

handlr.c (4761B)


      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 
     21 #include "ind.h"
     22 #include "arg.h"
     23 
     24 void
     25 handledir(int sock, char *path, char *port, char *base, char *args,
     26 		char *sear, char *ohost, char *chost, int istls)
     27 {
     28 	char *pa, *file, *e, *par, *b;
     29 	struct dirent **dirent;
     30 	int ndir, i, ret = 0;
     31 	struct stat st;
     32 	filetype *type;
     33 
     34 	USED(args);
     35 	USED(sear);
     36 
     37 	pa = xstrdup(path);
     38 	e = pa + strlen(pa) - 1;
     39 	if (e[0] == '/')
     40 		*e = '\0';
     41 
     42 	par = xstrdup(pa);
     43 	b = strrchr(par + strlen(base), '/');
     44 	if (b != NULL) {
     45 		*b = '\0';
     46 		dprintf(sock, "1..\t%s\t%s\t%s\r\n",
     47 			par + strlen(base), ohost, port);
     48 	}
     49 	free(par);
     50 
     51 	ndir = scandir(pa[0] ? pa : ".", &dirent, 0, alphasort);
     52 	if (ndir < 0) {
     53 		perror("scandir");
     54 		free(pa);
     55 		return;
     56 	} else {
     57 		for (i = 0; i < ndir && ret >= 0; i++) {
     58 			if (dirent[i]->d_name[0] == '.') {
     59 				free(dirent[i]);
     60 				continue;
     61 			}
     62 
     63 			type = gettype(dirent[i]->d_name);
     64 			file = smprintf("%s/%s", pa,
     65 					dirent[i]->d_name);
     66 			if (stat(file, &st) >= 0 && S_ISDIR(st.st_mode))
     67 				type = gettype("index.gph");
     68 			e = file + strlen(base);
     69 			ret = dprintf(sock,
     70 					"%c%-50.50s %10s %16s\t%s\t%s\t%s\r\n",
     71 					*type->type,
     72 					dirent[i]->d_name,
     73 					humansize(st.st_size),
     74 					humantime(&(st.st_mtim.tv_sec)),
     75 					e, ohost, port);
     76 			free(file);
     77 			free(dirent[i]);
     78 		}
     79 		free(dirent);
     80 	}
     81 	dprintf(sock, ".\r\n");
     82 
     83 	free(pa);
     84 }
     85 
     86 void
     87 handlegph(int sock, char *file, char *port, char *base, char *args,
     88 		char *sear, char *ohost, char *chost, int istls)
     89 {
     90 	Indexs *act;
     91 	int i, ret = 0;
     92 
     93 	USED(args);
     94 	USED(sear);
     95 
     96 	act = scanfile(file);
     97 	if (act != NULL) {
     98 		for (i = 0; i < act->num && ret >= 0; i++) {
     99 			ret = printelem(sock, act->n[i], file, base, ohost, port);
    100 			freeelem(act->n[i]);
    101 			act->n[i] = NULL;
    102 		}
    103 		dprintf(sock, ".\r\n");
    104 
    105 		freeindex(act);
    106 	}
    107 }
    108 
    109 void
    110 handlebin(int sock, char *file, char *port, char *base, char *args,
    111 		char *sear, char *ohost, char *chost, int istls)
    112 {
    113 	int fd;
    114 
    115 	USED(port);
    116 	USED(base);
    117 	USED(args);
    118 	USED(sear);
    119 	USED(ohost);
    120 
    121 	fd = open(file, O_RDONLY);
    122 	if (fd >= 0) {
    123 		if (xsendfile(fd, sock) < 0)
    124 			perror("sendfile");
    125 		close(fd);
    126 	}
    127 }
    128 
    129 void
    130 handlecgi(int sock, char *file, char *port, char *base, char *args,
    131 		char *sear, char *ohost, char *chost, int istls)
    132 {
    133 	char *p, *path;
    134 
    135 	USED(base);
    136 	USED(port);
    137 
    138 	path = xstrdup(file);
    139 	p = strrchr(path, '/');
    140 	if (p != NULL)
    141 		p[1] = '\0';
    142 	else {
    143 		free(path);
    144 		path = NULL;
    145 	}
    146 
    147 	p = strrchr(file, '/');
    148 	if (p == NULL)
    149 		p = file;
    150 
    151 	if (sear == NULL)
    152 		sear = "";
    153 	if (args == NULL)
    154 		args = "";
    155 
    156 	dup2(sock, 0);
    157 	dup2(sock, 1);
    158 	dup2(sock, 2);
    159 	switch (fork()) {
    160 	case 0:
    161 		if (path != NULL) {
    162 			if (chdir(path) < 0)
    163 				break;
    164 		}
    165 
    166 		setcgienviron(p, file, port, base, args, sear, ohost, chost,
    167 				istls);
    168 
    169 		if (execl(file, p, sear, args, ohost, port,
    170 				(char *)NULL) == -1) {
    171 			perror("execl");
    172 			_exit(1);
    173 		}
    174 	case -1:
    175 		perror("fork");
    176 		break;
    177 	default:
    178 		wait(NULL);
    179 		free(path);
    180 		break;
    181 	}
    182 }
    183 
    184 void
    185 handledcgi(int sock, char *file, char *port, char *base, char *args,
    186 		char *sear, char *ohost, char *chost, int istls)
    187 {
    188 	FILE *fp;
    189 	char *p, *path, *ln = NULL;
    190 	size_t linesiz = 0;
    191 	ssize_t n;
    192 	int outpipe[2], ret = 0;
    193 	Elems *el;
    194 
    195 	if (pipe(outpipe) < 0)
    196 		return;
    197 
    198 	path = xstrdup(file);
    199 	p = strrchr(path, '/');
    200 	if (p != NULL)
    201 		p[1] = '\0';
    202 	else {
    203 		free(path);
    204 		path = NULL;
    205 	}
    206 
    207 	p = strrchr(file, '/');
    208 	if (p == NULL)
    209 		p = file;
    210 
    211 	if (sear == NULL)
    212 		sear = "";
    213 	if (args == NULL)
    214 		args = "";
    215 
    216 	while (dup2(sock, 0) < 0 && errno == EINTR);
    217 	while (dup2(sock, 2) < 0 && errno == EINTR);
    218 	switch (fork()) {
    219 	case 0:
    220 		while(dup2(outpipe[1], 1) < 0 && errno == EINTR);
    221 		close(outpipe[0]);
    222 		if (path != NULL) {
    223 			if (chdir(path) < 0)
    224 				break;
    225 		}
    226 
    227 		setcgienviron(p, file, port, base, args, sear, ohost, chost,
    228 				istls);
    229 
    230 		if (execl(file, p, sear, args, ohost, port,
    231 				(char *)NULL) == -1) {
    232 			perror("execl");
    233 			_exit(1);
    234 		}
    235 		break;
    236 	case -1:
    237 		perror("fork");
    238 		break;
    239 	default:
    240 		while(dup2(sock, 1) < 0 && errno == EINTR);
    241 		close(outpipe[1]);
    242 
    243 		if (!(fp = fdopen(outpipe[0], "r"))) {
    244 			perror("fdopen");
    245 			break;
    246 		}
    247 
    248 		while ((n = getline(&ln, &linesiz, fp)) > 0 && ret >= 0) {
    249 			if (ln[n - 1] == '\n')
    250 				ln[--n] = '\0';
    251 
    252 			el = getadv(ln);
    253 			if (el == NULL)
    254 				continue;
    255 
    256 			ret = printelem(sock, el, file, base, ohost, port);
    257 			freeelem(el);
    258 		}
    259 		if (ferror(fp))
    260 			perror("getline");
    261 		dprintf(sock, ".\r\n");
    262 
    263 		free(ln);
    264 		free(path);
    265 		fclose(fp);
    266 		wait(NULL);
    267 		break;
    268 	}
    269 }
    270