• R/O
  • SSH
  • HTTPS

ogup: 提交


Commit MetaInfo

修訂36 (tree)
時間2021-12-06 21:04:16
作者mateuszviste

Log Message

moved gopher- and glist-related routines to separate modules for better clarity

Change Summary

差異

--- trunk/gopherjoker/Makefile (revision 35)
+++ trunk/gopherjoker/Makefile (revision 36)
@@ -11,7 +11,7 @@
1111
1212 all: gopherjoker
1313
14-gopherjoker: csv.o gopherjoker.o
14+gopherjoker: csv.o glist.o gopher.o gopherjoker.o
1515
1616 clean:
1717 rm -f gopherjoker *.o
--- trunk/gopherjoker/glist.c (nonexistent)
+++ trunk/gopherjoker/glist.c (revision 36)
@@ -0,0 +1,124 @@
1+/*
2+ * glist-handling routines
3+ * This file is part of the Obsevable Gopherspace Universe Project
4+ * Copyright (C) 2019-2021 Mateusz Viste
5+ */
6+
7+#include <ctype.h> /* tolower() */
8+#include <stdlib.h>
9+#include <string.h> /* strcpy() */
10+#include <time.h>
11+
12+#include "glist.h"
13+
14+
15+/* rotate an uint32_t value by 1 bit left */
16+static void rotl(uint32_t *u) {
17+ uint32_t bit;
18+ bit = *u & 1;
19+ *u <<= 1;
20+ *u |= bit;
21+}
22+
23+
24+/* compute hash of a glist node (ie. a host, port, selector tuple) - used to
25+ * determine the identity of a glist entry. this is a somewhat specialized
26+ * version of a BSD sum. */
27+uint32_t glist_node_hash(const struct gopherlist *node) {
28+ uint32_t res = 0;
29+ int i;
30+ /* start with port */
31+ res = node->port;
32+ /* add host (case-insensitive) */
33+ for (i = 0; node->fqdn[i] != 0; i++) {
34+ rotl(&res);
35+ res ^= (uint32_t)tolower(node->fqdn[i]);
36+ }
37+ /* add selector */
38+ for (i = 0; (node->selector != NULL) && (node->selector[i] != 0); i++) {
39+ rotl(&res);
40+ res ^= (uint32_t)node->selector[i];
41+ }
42+ return(res);
43+}
44+
45+
46+void glist_free(struct gopherlist *glist) {
47+ struct gopherlist *victim;
48+ while (glist) {
49+ free(glist->selector);
50+ victim = glist;
51+ glist = glist->next;
52+ free(victim);
53+ }
54+}
55+
56+
57+struct gopherlist *glist_findhost(struct gopherlist *glist, const char *host, const unsigned short port) {
58+ struct gopherlist *node;
59+ for (node = glist; node != NULL; node = node->next) {
60+ if ((node->port == port) && (strcasecmp(node->fqdn, host) == 0)) return(node);
61+ }
62+ return(NULL);
63+}
64+
65+
66+/* add new host to glist, unless said host:port pair already exists there.
67+ * returns pointer to the new (or already existing) struct. NULL on error. */
68+struct gopherlist *glist_addnewhost(struct gopherlist **glist, unsigned long *glistlen, const char *newhost, unsigned short newport, time_t failedsince) {
69+ struct gopherlist *node;
70+
71+ /* is entry in list already? */
72+ node = glist_findhost(*glist, newhost, newport);
73+ if (node != NULL) return(node);
74+
75+ /* add it */
76+ node = calloc(1, sizeof(struct gopherlist) + strlen(newhost));
77+ if (node == NULL) return(NULL);
78+ /* */
79+ strcpy(node->fqdn, newhost);
80+ node->port = newport;
81+ node->failedsince = failedsince;
82+ node->prev = NULL;
83+ node->next = *glist;
84+ if (*glist != NULL) (*glist)->prev = node;
85+ *glist = node;
86+ *glistlen += 1;
87+ return(*glist);
88+}
89+
90+
91+void glist_node_free(struct gopherlist **node) {
92+ if (*node == NULL) return;
93+ free((*node)->selector);
94+ free(*node);
95+ *node = NULL;
96+}
97+
98+
99+struct gopherlist *glist_node_unchain(struct gopherlist *glist, struct gopherlist *node, unsigned long *glistlen) {
100+ if (node->prev == NULL) {
101+ glist = node->next;
102+ glist->prev = NULL;
103+ *glistlen -= 1;
104+ return(glist);
105+ }
106+ node->prev->next = node->next;
107+ if (node->next != NULL) {
108+ node->next->prev = node->prev;
109+ }
110+ *glistlen -= 1;
111+ return(glist);
112+}
113+
114+
115+struct gopherlist *glist_node_dup(struct gopherlist *node) {
116+ struct gopherlist *res;
117+ if (node == NULL) return(NULL);
118+ res = calloc(1, sizeof(struct gopherlist) + strlen(node->fqdn));
119+ if (res == NULL) return(NULL);
120+
121+ memcpy(res, node, sizeof(struct gopherlist) + strlen(node->fqdn));
122+ if (node->selector != NULL) res->selector = strdup(node->selector);
123+ return(res);
124+}
--- trunk/gopherjoker/glist.h (nonexistent)
+++ trunk/gopherjoker/glist.h (revision 36)
@@ -0,0 +1,41 @@
1+/*
2+ * glist-handling routines
3+ * This file is part of the Obsevable Gopherspace Universe Project
4+ * Copyright (C) 2019-2021 Mateusz Viste
5+ */
6+
7+#ifndef GLIST_H
8+#define GLIST_H
9+
10+#include <stdint.h>
11+
12+struct gopherlist {
13+ time_t failedsince;
14+ struct gopherlist *next;
15+ struct gopherlist *prev;
16+ unsigned short port;
17+ char *selector;
18+ char fqdn[1];
19+};
20+
21+
22+/* compute hash of a glist node (ie. a host, port, selector tuple) - used to
23+ * determine the identity of a glist entry. this is a somewhat specialized
24+ * version of a BSD sum. */
25+uint32_t glist_node_hash(const struct gopherlist *node);
26+
27+void glist_free(struct gopherlist *glist);
28+
29+struct gopherlist *glist_findhost(struct gopherlist *glist, const char *host, const unsigned short port);
30+
31+/* add new host to glist, unless said host:port pair already exists there.
32+ * returns pointer to the new (or already existing) struct. NULL on error. */
33+struct gopherlist *glist_addnewhost(struct gopherlist **glist, unsigned long *glistlen, const char *newhost, unsigned short newport, time_t failedsince);
34+
35+void glist_node_free(struct gopherlist **node);
36+
37+struct gopherlist *glist_node_unchain(struct gopherlist *glist, struct gopherlist *node, unsigned long *glistlen);
38+
39+struct gopherlist *glist_node_dup(struct gopherlist *node);
40+
41+#endif
--- trunk/gopherjoker/gopher.c (nonexistent)
+++ trunk/gopherjoker/gopher.c (revision 36)
@@ -0,0 +1,161 @@
1+/*
2+ * gopher-related routines
3+ * This file is part of the Obsevable Gopherspace Universe Project
4+ * Copyright (C) 2019-2021 Mateusz Viste
5+ */
6+
7+#include <arpa/inet.h> /* inet_pton() */
8+#include <errno.h>
9+#include <fcntl.h>
10+#include <netdb.h> /* gethostbyname() */
11+#include <stdlib.h> /* atoi() */
12+#include <string.h> /* strlen() */
13+#include <sys/types.h>
14+#include <sys/socket.h>
15+#include <time.h> /* ctime(), time_t */
16+#include <unistd.h> /* close() */
17+
18+
19+#include "gopher.h"
20+
21+
22+static int connect_nonblocking(int s, const struct sockaddr *addr, socklen_t addrlen, int timeout) {
23+ int r;
24+ struct timeval t;
25+ fd_set selset;
26+ for (;;) {
27+ r = connect(s, addr, addrlen);
28+ if (r == 0) return(0);
29+ if (errno != EINPROGRESS) return(r);
30+ FD_ZERO(&selset);
31+ FD_SET(s, &selset);
32+ t.tv_sec = timeout;
33+ t.tv_usec = 0;
34+ r = select(s + 1, NULL, &selset, NULL, &t);
35+ if (r < 0) return(-3);
36+ r = connect(s, addr, addrlen);
37+ return(r);
38+ }
39+}
40+
41+
42+long gopher_fetch(char *buff, size_t buffsz, const char *host, unsigned short port, const char *selector, char *ipstr) {
43+ int sock = -1;
44+ size_t len;
45+ int flags;
46+ time_t timeout;
47+ struct addrinfo *addr, *addrptr;
48+
49+ /* resolve host & connect */
50+ if (getaddrinfo(host, NULL, NULL, &addr) != 0) return(-1);
51+ for (addrptr = addr; addrptr != NULL; addrptr = addrptr->ai_next) {
52+ struct sockaddr_in *sin;
53+ sock = socket(addrptr->ai_family, addrptr->ai_socktype, addrptr->ai_protocol);
54+ if (sock < 0) continue;
55+ /* set port */
56+ sin = (void *)(addrptr->ai_addr);
57+ sin->sin_port = htons(port);
58+ /* set socket as non-blocking */
59+ flags = fcntl(sock, F_GETFL);
60+ fcntl(sock, F_SETFL, flags | O_NONBLOCK);
61+ /* try to connect */
62+ if (connect_nonblocking(sock, addrptr->ai_addr, addrptr->ai_addrlen, 10) == 0) {
63+ /* fill ipstr and continue */
64+ inet_ntop(addrptr->ai_family, addrptr->ai_addr, ipstr, addrptr->ai_addrlen);
65+ break;
66+ } else { /* close sock and try next option (if any) */
67+ close(sock);
68+ sock = -1;
69+ }
70+ }
71+ freeaddrinfo(addr);
72+ if (sock < 0) return(-2);
73+
74+ /* send selector, terminated by a CR/LF pair */
75+ if (selector != NULL) send(sock, selector, strlen(selector), MSG_MORE);
76+ send(sock, "\r\n", 2, 0);
77+
78+ /* fetch answer until end of transmission or timeout */
79+ len = 0;
80+ timeout = time(NULL) + 10;
81+ for (;;) {
82+ size_t spaceleft = buffsz - len;
83+ ssize_t rlen;
84+ if (time(NULL) > timeout) {
85+ close(sock);
86+ return(-3);
87+ }
88+ if (spaceleft == 0) break; /* I'm stuffed thank you */
89+ rlen = recv(sock, buff + len, spaceleft, 0);
90+ if (rlen == 0) break; /* orderly shutdown */
91+ if (rlen < 0) { /* sock error */
92+ if ((errno == EWOULDBLOCK) || (errno == EAGAIN)) continue;
93+ close(sock);
94+ return(-4);
95+ }
96+ len += (size_t)rlen;
97+ }
98+
99+ /* close sock and quit */
100+ close(sock);
101+ return((long)len);
102+}
103+
104+
105+/* parse a gopher menu line entry and fill host, port and selector accordingly.
106+ * returns 0 on success, non-zero otherwise. */
107+int gopher_menu_parseline(char *host, unsigned short hostsz, unsigned short *port, char *selector, unsigned short selectorsz, const char *menu, long menulen) {
108+ char portstr[8];
109+ unsigned short i = 0, t;
110+ /* skip first tabs (description) */
111+ for (;;) {
112+ i++;
113+ /* printf("i=%d ['%c']\n", i, menu[i]); */
114+ if (menu[i] == '\t') break;
115+ if (menu[i] == '\r') return(-2);
116+ if (menu[i] == '\n') return(-3);
117+ if (i >= menulen) return(-4);
118+ }
119+ /* read selector */
120+ for (t = 0; ; t++) {
121+ if (t >= selectorsz) return(-5);
122+ i++;
123+ if (i >= menulen) return(-6);
124+ if (menu[i] == '\r') return(-7);
125+ if (menu[i] == '\n') return(-8);
126+ selector[t] = menu[i];
127+ if (selector[t] == '\t') {
128+ selector[t] = 0;
129+ break;
130+ }
131+ }
132+ /* read hostname */
133+ for (t = 0; ; t++) {
134+ if (t >= hostsz) return(-9);
135+ i++;
136+ if (i >= menulen) return(-10);
137+ if (menu[i] == '\r') return(-11);
138+ if (menu[i] == '\n') return(-12);
139+ host[t] = menu[i];
140+ if (host[t] == '\t') {
141+ host[t] = 0;
142+ break;
143+ }
144+ }
145+ /* read port */
146+ for (t = 0; ; t++) {
147+ if (t >= sizeof(portstr)) return(-13);
148+ i++;
149+ if (i >= menulen) return(-14);
150+ portstr[t] = menu[i];
151+ if ((portstr[t] == '\t') || (portstr[t] == '\n')) {
152+ int tport;
153+ portstr[t] = 0;
154+ tport = atoi(portstr);
155+ if ((tport < 1) || (tport > 0xffff)) return(-15);
156+ *port = (unsigned short)tport;
157+ break;
158+ }
159+ }
160+ return(0);
161+}
--- trunk/gopherjoker/gopher.h (nonexistent)
+++ trunk/gopherjoker/gopher.h (revision 36)
@@ -0,0 +1,16 @@
1+/*
2+ * gopher-related routines
3+ * This file is part of the Obsevable Gopherspace Universe Project
4+ * Copyright (C) 2019-2021 Mateusz Viste
5+ */
6+
7+#ifndef GOPHER_H
8+#define GOPHER_H
9+
10+long gopher_fetch(char *buff, size_t buffsz, const char *host, unsigned short port, const char *selector, char *ipstr);
11+
12+/* parse a gopher menu line entry and fill host, port and selector accordingly.
13+ * returns 0 on success, non-zero otherwise. */
14+int gopher_menu_parseline(char *host, unsigned short hostsz, unsigned short *port, char *selector, unsigned short selectorsz, const char *menu, long menulen);
15+
16+#endif
--- trunk/gopherjoker/gopherjoker.c (revision 35)
+++ trunk/gopherjoker/gopherjoker.c (revision 36)
@@ -33,30 +33,19 @@
3333 * DEALINGS IN THE SOFTWARE.
3434 */
3535
36-#include <arpa/inet.h> /* inet_pton() */
37-#include <ctype.h> /* tolower() */
3836 #include <dirent.h> /* opendir() */
3937 #include <errno.h>
40-#include <fcntl.h>
41-#include <netdb.h> /* gethostbyname() */
38+#include <netdb.h> /* INET6_ADDRSTRLEN */
4239 #include <stdio.h> /* printf(), fopen(), ... */
4340 #include <stdlib.h> /* calloc(), rand() */
4441 #include <string.h> /* strcpy() */
45-#include <sys/types.h>
46-#include <sys/socket.h>
4742 #include <time.h> /* ctime(), time_t */
4843 #include <unistd.h> /* sleep() */
4944
5045 #include "csv.h"
46+#include "glist.h"
47+#include "gopher.h"
5148
52-struct gopherlist {
53- time_t failedsince;
54- struct gopherlist *next;
55- struct gopherlist *prev;
56- unsigned short port;
57- char *selector;
58- char fqdn[1];
59-};
6049
6150 #define WAITPERIOD_DEFAULT 20
6251 #define SAVEPERIOD_DEFAULT 3600
@@ -77,37 +66,6 @@
7766 /**************** FUNCTIONS ****************/
7867
7968
80-/* rotate an uint32_t value by 1 bit left */
81-static void rotl(uint32_t *u) {
82- uint32_t bit;
83- bit = *u & 1;
84- *u <<= 1;
85- *u |= bit;
86-}
87-
88-
89-/* compute hash of a glist node (ie. a host, port, selector tuple) - used to
90- * determine the identity of a glist entry. this is a somewhat specialized
91- * version of a BSD sum. */
92-static uint32_t gnodehash(const struct gopherlist *node) {
93- uint32_t res = 0;
94- int i;
95- /* start with port */
96- res = node->port;
97- /* add host (case-insensitive) */
98- for (i = 0; node->fqdn[i] != 0; i++) {
99- rotl(&res);
100- res ^= (uint32_t)tolower(node->fqdn[i]);
101- }
102- /* add selector */
103- for (i = 0; (node->selector != NULL) && (node->selector[i] != 0); i++) {
104- rotl(&res);
105- res ^= (uint32_t)node->selector[i];
106- }
107- return(res);
108-}
109-
110-
11169 /* returns 0 on success (glist added to recent history), -1 on error (entry
11270 * already present) */
11371 static int add_glist_to_recent_history_if_not_present(const struct gopherlist *node) {
@@ -114,7 +72,7 @@
11472 uint32_t hash;
11573 int i;
11674 if (node == NULL) return(-1);
117- hash = gnodehash(node);
75+ hash = glist_node_hash(node);
11876 /* is it in history already? */
11977 for (i = 0; i < RECENT_HISTORY_SZ; i++) {
12078 if (glob_recenthistory[i] == hash) return(-1);
@@ -127,17 +85,6 @@
12785 }
12886
12987
130-static void glist_free(struct gopherlist *glist) {
131- struct gopherlist *victim;
132- while (glist) {
133- free(glist->selector);
134- victim = glist;
135- glist = glist->next;
136- free(victim);
137- }
138-}
139-
140-
14188 /* returns pointer to dbfile name */
14289 static int parseargs(int argc, char **argv, char **dbfile, char **dbcount) {
14390 int i;
@@ -174,40 +121,6 @@
174121 }
175122
176123
177-static struct gopherlist *glist_findhost(struct gopherlist *glist, const char *host, const unsigned short port) {
178- struct gopherlist *node;
179- for (node = glist; node != NULL; node = node->next) {
180- if ((node->port == port) && (strcasecmp(node->fqdn, host) == 0)) return(node);
181- }
182- return(NULL);
183-}
184-
185-
186-/* add new host to glist, unless said host:port pair already exists there.
187- * returns pointer to the new (or already existing) struct. NULL on error. */
188-static struct gopherlist *glist_addnewhost(struct gopherlist **glist, unsigned long *glistlen, char *newhost, unsigned short newport, time_t failedsince) {
189- struct gopherlist *node;
190-
191- /* is entry in list already? */
192- node = glist_findhost(*glist, newhost, newport);
193- if (node != NULL) return(node);
194-
195- /* add it */
196- node = calloc(1, sizeof(struct gopherlist) + strlen(newhost));
197- if (node == NULL) return(NULL);
198- /* */
199- strcpy(node->fqdn, newhost);
200- node->port = newport;
201- node->failedsince = failedsince;
202- node->prev = NULL;
203- node->next = *glist;
204- if (*glist != NULL) (*glist)->prev = node;
205- *glist = node;
206- *glistlen += 1;
207- return(*glist);
208-}
209-
210-
211124 static struct gopherlist *loaddb(const char *fname, unsigned long *glistlen) {
212125 FILE *fd;
213126 int i;
@@ -259,22 +172,6 @@
259172 }
260173
261174
262-static struct gopherlist *dropnode(struct gopherlist *glist, struct gopherlist *node, unsigned long *glistlen) {
263- if (node->prev == NULL) {
264- glist = node->next;
265- glist->prev = NULL;
266- *glistlen -= 1;
267- return(glist);
268- }
269- node->prev->next = node->next;
270- if (node->next != NULL) {
271- node->next->prev = node->prev;
272- }
273- *glistlen -= 1;
274- return(glist);
275-}
276-
277-
278175 /* open fname and read a server name from it, write it to *s. returns
279176 * port number on success, neg value on error */
280177 static int get_server_from_file(char *s, size_t ssz, const char *fname) {
@@ -376,148 +273,6 @@
376273 }
377274
378275
379-static int connect_nonblocking(int s, const struct sockaddr *addr, socklen_t addrlen, int timeout) {
380- int r;
381- struct timeval t;
382- fd_set selset;
383- for (;;) {
384- r = connect(s, addr, addrlen);
385- if (r == 0) return(0);
386- if (errno != EINPROGRESS) return(r);
387- FD_ZERO(&selset);
388- FD_SET(s, &selset);
389- t.tv_sec = timeout;
390- t.tv_usec = 0;
391- r = select(s + 1, NULL, &selset, NULL, &t);
392- if (r < 0) return(-3);
393- r = connect(s, addr, addrlen);
394- return(r);
395- }
396-}
397-
398-
399-static long gopher_fetch(char *buff, size_t buffsz, const char *host, unsigned short port, const char *selector, char *ipstr) {
400- int sock = -1;
401- size_t len;
402- int flags;
403- time_t timeout;
404- struct addrinfo *addr, *addrptr;
405-
406- /* resolve host & connect */
407- if (getaddrinfo(host, NULL, NULL, &addr) != 0) return(-1);
408- for (addrptr = addr; addrptr != NULL; addrptr = addrptr->ai_next) {
409- struct sockaddr_in *sin;
410- sock = socket(addrptr->ai_family, addrptr->ai_socktype, addrptr->ai_protocol);
411- if (sock < 0) continue;
412- /* set port */
413- sin = (void *)(addrptr->ai_addr);
414- sin->sin_port = htons(port);
415- /* set socket as non-blocking */
416- flags = fcntl(sock, F_GETFL);
417- fcntl(sock, F_SETFL, flags | O_NONBLOCK);
418- /* try to connect */
419- if (connect_nonblocking(sock, addrptr->ai_addr, addrptr->ai_addrlen, 10) == 0) {
420- /* fill ipstr and continue */
421- inet_ntop(addrptr->ai_family, addrptr->ai_addr, ipstr, addrptr->ai_addrlen);
422- break;
423- } else { /* close sock and try next option (if any) */
424- close(sock);
425- sock = -1;
426- }
427- }
428- freeaddrinfo(addr);
429- if (sock < 0) return(-2);
430-
431- /* send selector, terminated by a CR/LF pair */
432- if (selector != NULL) send(sock, selector, strlen(selector), MSG_MORE);
433- send(sock, "\r\n", 2, 0);
434-
435- /* fetch answer until end of transmission or timeout */
436- len = 0;
437- timeout = time(NULL) + 10;
438- for (;;) {
439- size_t spaceleft = buffsz - len;
440- ssize_t rlen;
441- if (time(NULL) > timeout) {
442- close(sock);
443- return(-3);
444- }
445- if (spaceleft == 0) break; /* I'm stuffed thank you */
446- rlen = recv(sock, buff + len, spaceleft, 0);
447- if (rlen == 0) break; /* orderly shutdown */
448- if (rlen < 0) { /* sock error */
449- if ((errno == EWOULDBLOCK) || (errno == EAGAIN)) continue;
450- close(sock);
451- return(-4);
452- }
453- len += (size_t)rlen;
454- }
455-
456- /* close sock and quit */
457- close(sock);
458- return((long)len);
459-}
460-
461-
462-/* read a gopher line entry and fill host, port and selector accordingly.
463- * returns 0 on success, non-zero otherwise. */
464-static int readgline(char *host, unsigned short hostsz, unsigned short *port, char *selector, unsigned short selectorsz, const char *menu, long menulen) {
465- char portstr[8];
466- unsigned short i = 0, t;
467- /* skip first tabs (description) */
468- for (;;) {
469- i++;
470- /* printf("i=%d ['%c']\n", i, menu[i]); */
471- if (menu[i] == '\t') break;
472- if (menu[i] == '\r') return(-2);
473- if (menu[i] == '\n') return(-3);
474- if (i >= menulen) return(-4);
475- }
476- /* read selector */
477- for (t = 0; ; t++) {
478- if (t >= selectorsz) return(-5);
479- i++;
480- if (i >= menulen) return(-6);
481- if (menu[i] == '\r') return(-7);
482- if (menu[i] == '\n') return(-8);
483- selector[t] = menu[i];
484- if (selector[t] == '\t') {
485- selector[t] = 0;
486- break;
487- }
488- }
489- /* read hostname */
490- for (t = 0; ; t++) {
491- if (t >= hostsz) return(-9);
492- i++;
493- if (i >= menulen) return(-10);
494- if (menu[i] == '\r') return(-11);
495- if (menu[i] == '\n') return(-12);
496- host[t] = menu[i];
497- if (host[t] == '\t') {
498- host[t] = 0;
499- break;
500- }
501- }
502- /* read port */
503- for (t = 0; ; t++) {
504- if (t >= sizeof(portstr)) return(-13);
505- i++;
506- if (i >= menulen) return(-14);
507- portstr[t] = menu[i];
508- if ((portstr[t] == '\t') || (portstr[t] == '\n')) {
509- int tport;
510- portstr[t] = 0;
511- tport = atoi(portstr);
512- if ((tport < 1) || (tport > 0xffff)) return(-15);
513- *port = (unsigned short)tport;
514- break;
515- }
516- }
517- return(0);
518-}
519-
520-
521276 static int ishostvalid(const char *host) {
522277 unsigned short i;
523278 for (i = 0; host[i] != 0; i++) {
@@ -551,7 +306,7 @@
551306 char selector[128];
552307 unsigned short port;
553308
554- if (readgline(host, sizeof(host), &port, selector, sizeof(selector), menu + i, menulen - i) == 0) {
309+ if (gopher_menu_parseline(host, sizeof(host), &port, selector, sizeof(selector), menu + i, menulen - i) == 0) {
555310 /* validate host name */
556311 if (ishostvalid(host) != 0) continue;
557312 /* */
@@ -581,26 +336,6 @@
581336 }
582337
583338
584-static void gnode_free(struct gopherlist **node) {
585- if (*node == NULL) return;
586- free((*node)->selector);
587- free(*node);
588- *node = NULL;
589-}
590-
591-
592-static struct gopherlist *gnodedup(struct gopherlist *node) {
593- struct gopherlist *res;
594- if (node == NULL) return(NULL);
595- res = calloc(1, sizeof(struct gopherlist) + strlen(node->fqdn));
596- if (res == NULL) return(NULL);
597-
598- memcpy(res, node, sizeof(struct gopherlist) + strlen(node->fqdn));
599- if (node->selector != NULL) res->selector = strdup(node->selector);
600- return(res);
601-}
602-
603-
604339 /**************** MAIN ****************/
605340
606341 int main(int argc, char **argv) {
@@ -661,7 +396,7 @@
661396 if ((--ttl == 0) || (curhost == NULL)) {
662397 printf("TTL expired -> picking new host\n");
663398 curhost = pickrandhostfromlist(glist, glistlen);
664- curhost = gnodedup(curhost);
399+ curhost = glist_node_dup(curhost);
665400 ttl = TTLINIT;
666401 }
667402
@@ -689,11 +424,11 @@
689424 } else if (time(NULL) > curhost->failedsince + MAXFAILTIME) {
690425 /* remove server from the list */
691426 printf("server removed due to long-time failure: %s:%u (failed since %s)\n", gnode->fqdn, gnode->port, ctime(&(gnode->failedsince)));
692- glist = dropnode(glist, gnode, &glistlen);
693- gnode_free(&gnode);
427+ glist = glist_node_unchain(glist, gnode, &glistlen);
428+ glist_node_free(&gnode);
694429 }
695430 }
696- gnode_free(&curhost);
431+ glist_node_free(&curhost);
697432 continue;
698433 }
699434
@@ -711,7 +446,7 @@
711446 }
712447 /* */
713448 glist_free(mlist);
714- gnode_free(&curhost);
449+ glist_node_free(&curhost);
715450 continue;
716451 }
717452
@@ -728,9 +463,9 @@
728463 if (glist_findhost(mlist, curhost->fqdn, curhost->port) == NULL) {
729464 printf("ERR: main menu contains no link to self, dropping hostname '%s'\n", curhost->fqdn);
730465 gnode = glist_findhost(glist, curhost->fqdn, curhost->port);
731- glist = dropnode(glist, gnode, &glistlen);
466+ glist = glist_node_unchain(glist, gnode, &glistlen);
732467 glist_free(mlist);
733- gnode_free(&curhost);
468+ glist_node_free(&curhost);
734469 continue;
735470 }
736471 }
@@ -743,11 +478,11 @@
743478 gnode = pickrandhostfromlist(mlist, i);
744479 if (gnode == NULL) {
745480 printf("pickrandhostfromlist() could not find a node candidate in list\n");
746- gnode_free(&curhost);
481+ glist_node_free(&curhost);
747482 glist_free(mlist);
748483 continue;
749484 }
750- curhost = gnodedup(gnode);
485+ curhost = glist_node_dup(gnode);
751486
752487 glist_free(mlist);
753488 }
Show on old repository browser