Introduction
Introduction Statistics Contact Development Disclaimer Help
tresp.c - quark - quark web server
git clone git://git.suckless.org/quark
Log
Files
Refs
LICENSE
---
tresp.c (2539B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <dirent.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/stat.h>
7 #include <time.h>
8 #include <unistd.h>
9
10 #include "http.h"
11 #include "resp.h"
12 #include "util.h"
13
14 static int
15 compareent(const struct dirent **d1, const struct dirent **d2)
16 {
17 int v;
18
19 v = ((*d2)->d_type == DT_DIR ? 1 : -1) -
20 ((*d1)->d_type == DT_DIR ? 1 : -1);
21 if (v) {
22 return v;
23 }
24
25 return strcmp((*d1)->d_name, (*d2)->d_name);
26 }
27
28 static char *
29 suffix(int t)
30 {
31 switch (t) {
32 case DT_FIFO: return "|";
33 case DT_DIR: return "/";
34 case DT_LNK: return "@";
35 case DT_SOCK: return "=";
36 }
37
38 return "";
39 }
40
41 enum status
42 resp_dir(int fd, const struct response *res)
43 {
44 enum status ret;
45 struct dirent **e;
46 size_t i;
47 int dirlen;
48 char esc[PATH_MAX /* > NAME_MAX */ * 6]; /* strlen("&...;") <= 6…
49
50 /* read directory */
51 if ((dirlen = scandir(res->path, &e, NULL, compareent)) < 0) {
52 return S_FORBIDDEN;
53 }
54
55 /* listing */
56 for (i = 0; i < (size_t)dirlen; i++) {
57 /* skip hidden files, "." and ".." */
58 if (e[i]->d_name[0] == '.') {
59 continue;
60 }
61
62 /* entry line */
63 html_escape(e[i]->d_name, esc, sizeof(esc));
64 if (dprintf(fd, "<br />\n\t\t<a href=\"%s%s\">%s%s</a>",
65 esc,
66 (e[i]->d_type == DT_DIR) ? "/" : "",
67 esc,
68 suffix(e[i]->d_type)) < 0) {
69 ret = S_REQUEST_TIMEOUT;
70 goto cleanup;
71 }
72 }
73
74 /* listing footer */
75 if (dprintf(fd, "\n\t</body>\n</html>\n") < 0) {
76 ret = S_REQUEST_TIMEOUT;
77 goto cleanup;
78 }
79
80 cleanup:
81 while (dirlen--) {
82 free(e[dirlen]);
83 }
84 free(e);
85
86 return ret;
87 }
88
89 enum status
90 resp_file(int fd, const struct response *res)
91 {
92 FILE *fp;
93 enum status ret = 0;
94 ssize_t bread, bwritten;
95 size_t remaining;
96 static char buf[BUFSIZ], *p;
97
98 /* open file */
99 if (!(fp = fopen(res->path, "r"))) {
100 ret = S_FORBIDDEN;
101 goto cleanup;
102 }
103
104 /* seek to lower bound */
105 if (fseek(fp, res->file.lower, SEEK_SET)) {
106 ret = S_INTERNAL_SERVER_ERROR;
107 goto cleanup;
108 }
109
110 /* write data until upper bound is hit */
111 remaining = res->file.upper - res->file.lower + 1;
112
113 while ((bread = fread(buf, 1, MIN(sizeof(buf),
114 remaining), fp))) {
115 if (bread < 0) {
116 ret = S_INTERNAL_SERVER_ERROR;
117 goto cleanup;
118 }
119 remaining -= bread;
120 p = buf;
121 while (bread > 0) {
122 bwritten = write(fd, p, bread);
123 if (bwritten <= 0) {
124 ret = S_REQUEST_TIMEOUT;
125 goto cleanup;
126 }
127 bread -= bwritten;
128 p += bwritten;
129 }
130 }
131 cleanup:
132 if (fp) {
133 fclose(fp);
134 }
135
136 return ret;
137 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.