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


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