sfeed_gopher.c - sfeed - RSS and Atom parser | |
git clone git://git.codemadness.org/sfeed | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
sfeed_gopher.c (4404B) | |
--- | |
1 #include <stdio.h> | |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 #include <time.h> | |
5 | |
6 #include "util.h" | |
7 | |
8 static char *prefixpath = "/", *host = "127.0.0.1", *port = "70"; /* def… | |
9 static char *line; | |
10 static size_t linesize; | |
11 static time_t comparetime; | |
12 | |
13 /* Escape characters in gopher, CR and LF are ignored */ | |
14 static void | |
15 gophertext(FILE *fp, const char *s) | |
16 { | |
17 for (; *s; s++) { | |
18 switch (*s) { | |
19 case '\r': /* ignore CR */ | |
20 case '\n': /* ignore LF */ | |
21 break; | |
22 case '\t': | |
23 fputs(" ", fp); | |
24 break; | |
25 default: | |
26 putc(*s, fp); | |
27 break; | |
28 } | |
29 } | |
30 } | |
31 | |
32 static void | |
33 printfeed(FILE *fpitems, FILE *fpin, struct feed *f) | |
34 { | |
35 struct uri u; | |
36 char *fields[FieldLast]; | |
37 char *itemhost, *itemport, *itempath, *itemquery, *itemfragment; | |
38 ssize_t linelen; | |
39 unsigned int isnew; | |
40 struct tm rtm, *tm; | |
41 time_t parsedtime; | |
42 int itemtype; | |
43 | |
44 if (f->name[0]) { | |
45 fprintf(fpitems, "i%s\t\t%s\t%s\r\n", f->name, host, por… | |
46 fprintf(fpitems, "i\t\t%s\t%s\r\n", host, port); | |
47 } | |
48 | |
49 while ((linelen = getline(&line, &linesize, fpin)) > 0 && | |
50 !ferror(fpitems)) { | |
51 if (line[linelen - 1] == '\n') | |
52 line[--linelen] = '\0'; | |
53 parseline(line, fields); | |
54 | |
55 itemhost = host; | |
56 itemport = port; | |
57 itemtype = 'i'; | |
58 itempath = fields[FieldLink]; | |
59 itemquery = ""; | |
60 itemfragment = ""; | |
61 | |
62 if (fields[FieldLink][0]) { | |
63 itemtype = 'h'; | |
64 /* if it is a gopher URL then change it into a D… | |
65 if (!strncmp(fields[FieldLink], "gopher://", 9) … | |
66 uri_parse(fields[FieldLink], &u) != -1) { | |
67 itemhost = u.host; | |
68 itemport = u.port[0] ? u.port : "70"; | |
69 itemtype = '1'; | |
70 itempath = u.path; | |
71 itemquery = u.query; | |
72 itemfragment = u.fragment; | |
73 | |
74 if (itempath[0] == '/') { | |
75 itempath++; | |
76 if (*itempath) { | |
77 itemtype = *itempath; | |
78 itempath++; | |
79 } | |
80 } | |
81 } | |
82 } | |
83 | |
84 parsedtime = 0; | |
85 if (!strtotime(fields[FieldUnixTimestamp], &parsedtime) … | |
86 (tm = localtime_r(&parsedtime, &rtm))) { | |
87 isnew = (parsedtime >= comparetime) ? 1 : 0; | |
88 f->totalnew += isnew; | |
89 | |
90 fprintf(fpitems, "%c%c %04d-%02d-%02d %02d:%02d … | |
91 itemtype, | |
92 isnew ? 'N' : ' ', | |
93 tm->tm_year + 1900, tm->tm_mon + 1, tm->… | |
94 tm->tm_hour, tm->tm_min); | |
95 } else { | |
96 fprintf(fpitems, "%c ", itemty… | |
97 } | |
98 f->total++; | |
99 | |
100 gophertext(fpitems, fields[FieldTitle]); | |
101 fputs("\t", fpitems); | |
102 if (itemtype == 'h' && fields[FieldLink] == itempath) | |
103 fputs("URL:", fpitems); | |
104 gophertext(fpitems, itempath); | |
105 if (itemquery[0]) { | |
106 fputs("?", fpitems); | |
107 gophertext(fpitems, itemquery); | |
108 } | |
109 if (itemfragment[0]) { | |
110 fputs("#", fpitems); | |
111 gophertext(fpitems, itemfragment); | |
112 } | |
113 fprintf(fpitems, "\t%s\t%s\r\n", itemhost, itemport); | |
114 } | |
115 fputs(".\r\n", fpitems); | |
116 } | |
117 | |
118 int | |
119 main(int argc, char *argv[]) | |
120 { | |
121 struct feed f = { 0 }; | |
122 FILE *fpitems, *fpindex, *fp; | |
123 char *name, *p; | |
124 int i; | |
125 | |
126 if (argc == 1) { | |
127 if (pledge("stdio", NULL) == -1) | |
128 err(1, "pledge"); | |
129 } else { | |
130 if (unveil("/", "r") == -1) | |
131 err(1, "unveil: /"); | |
132 if (unveil(".", "rwc") == -1) | |
133 err(1, "unveil: ."); | |
134 if (pledge("stdio rpath wpath cpath", NULL) == -1) | |
135 err(1, "pledge"); | |
136 } | |
137 | |
138 if ((comparetime = getcomparetime()) == (time_t)-1) | |
139 errx(1, "getcomparetime"); | |
140 | |
141 if ((p = getenv("SFEED_GOPHER_HOST"))) | |
142 host = p; | |
143 if ((p = getenv("SFEED_GOPHER_PORT"))) | |
144 port = p; | |
145 | |
146 if (argc == 1) { | |
147 f.name = ""; | |
148 printfeed(stdout, stdin, &f); | |
149 checkfileerror(stdin, "<stdin>", 'r'); | |
150 checkfileerror(stdout, "<stdout>", 'w'); | |
151 } else { | |
152 if ((p = getenv("SFEED_GOPHER_PATH"))) | |
153 prefixpath = p; | |
154 | |
155 /* write main index page */ | |
156 if (!(fpindex = fopen("index", "wb"))) | |
157 err(1, "fopen: index"); | |
158 | |
159 for (i = 1; i < argc; i++) { | |
160 memset(&f, 0, sizeof(f)); | |
161 name = ((name = strrchr(argv[i], '/'))) ? name +… | |
162 f.name = name; | |
163 | |
164 if (!(fp = fopen(argv[i], "r"))) | |
165 err(1, "fopen: %s", argv[i]); | |
166 if (!(fpitems = fopen(name, "wb"))) | |
167 err(1, "fopen"); | |
168 printfeed(fpitems, fp, &f); | |
169 checkfileerror(fp, argv[i], 'r'); | |
170 checkfileerror(fpitems, name, 'w'); | |
171 fclose(fp); | |
172 fclose(fpitems); | |
173 | |
174 /* append directory item to index */ | |
175 fputs("1", fpindex); | |
176 gophertext(fpindex, name); | |
177 fprintf(fpindex, " (%lu/%lu)\t", f.totalnew, f.t… | |
178 gophertext(fpindex, prefixpath); | |
179 gophertext(fpindex, name); | |
180 fprintf(fpindex, "\t%s\t%s\r\n", host, port); | |
181 } | |
182 fputs(".\r\n", fpindex); | |
183 checkfileerror(fpindex, "index", 'w'); | |
184 fclose(fpindex); | |
185 } | |
186 | |
187 return 0; | |
188 } |