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 (5384B)


      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 void
    143 handlecgi(int sock, char *file, char *port, char *base, char *args,
    144 		char *sear, char *ohost, char *chost, char *bhost, int istls,
    145 		char *sel, char *traverse)
    146 {
    147 	char *script, *path, *filec, *scriptc;
    148 
    149 	USED(base);
    150 	USED(port);
    151 
    152 	filec = xstrdup(file);
    153 	scriptc = xstrdup(file);
    154 	path = dirname(filec);
    155 	script = basename(scriptc);
    156 
    157 	if (sear == NULL)
    158 		sear = "";
    159 	if (args == NULL)
    160 		args = "";
    161 
    162 	while (dup2(sock, 0) < 0 && errno == EINTR);
    163 	while (dup2(sock, 1) < 0 && errno == EINTR);
    164 	while (dup2(sock, 2) < 0 && errno == EINTR);
    165 	switch (fork()) {
    166 	case 0:
    167 		if (path != NULL) {
    168 			if (chdir(path) < 0)
    169 				break;
    170 		}
    171 
    172 		setcgienviron(script, file, port, base, args, sear, ohost, chost,
    173 				bhost, istls, sel, traverse);
    174 
    175 		if (execl(file, script, sear, args, ohost, port, traverse, sel,
    176 				(char *)NULL) == -1) {
    177 			perror("execl");
    178 			_exit(1);
    179 		}
    180 	case -1:
    181 		perror("fork");
    182 		break;
    183 	default:
    184 		wait(NULL);
    185 		free(filec);
    186 		free(scriptc);
    187 		break;
    188 	}
    189 }
    190 
    191 void
    192 handledcgi(int sock, char *file, char *port, char *base, char *args,
    193 		char *sear, char *ohost, char *chost, char *bhost, int istls,
    194 		char *sel, char *traverse)
    195 {
    196 	FILE *fp;
    197 	char *script, *path, *filec, *scriptc, *ln = NULL;
    198 	size_t linesiz = 0;
    199 	ssize_t n;
    200 	int outsocks[2], ret = 0;
    201 	gphelem *el;
    202 
    203 	if (socketpair(AF_LOCAL, SOCK_STREAM, 0, outsocks) < 0)
    204 		return;
    205 
    206 	filec = xstrdup(file);
    207 	scriptc = xstrdup(file);
    208 	path = dirname(filec);
    209 	script = basename(scriptc);
    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(outsocks[1], 1) < 0 && errno == EINTR);
    221 		close(outsocks[0]);
    222 		if (path != NULL) {
    223 			if (chdir(path) < 0)
    224 				break;
    225 		}
    226 
    227 		setcgienviron(script, file, port, base, args, sear, ohost, chost,
    228 				bhost, istls, sel, traverse);
    229 
    230 		if (execl(file, script, sear, args, ohost, port, traverse, sel,
    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(outsocks[1]);
    242 
    243 		if (!(fp = fdopen(outsocks[0], "r"))) {
    244 			perror("fdopen");
    245 			close(outsocks[0]);
    246 			break;
    247 		}
    248 
    249 		while ((n = getline(&ln, &linesiz, fp)) > 0 && ret >= 0) {
    250 			if (ln[n - 1] == '\n')
    251 				ln[--n] = '\0';
    252 
    253 			el = gph_getadv(ln);
    254 			if (el == NULL)
    255 				continue;
    256 
    257 			ret = gph_printelem(sock, el, file, base, ohost, port);
    258 			gph_freeelem(el);
    259 		}
    260 		if (ferror(fp))
    261 			perror("getline");
    262 		dprintf(sock, ".\r\n");
    263 
    264 		free(ln);
    265 		fclose(fp);
    266 		wait(NULL);
    267 		free(filec);
    268 		free(scriptc);
    269 		break;
    270 	}
    271 }
    272