source: help.c @ ac6855b3

Last change on this file since ac6855b3 was e6f47fb, checked in by dequis <dx@…>, at 2015-03-04T23:01:39Z

help: Increase read buffer size from 1100 to 2048

This fixes "Error opening helpfile." that was introduced by the rawreply
commit, which made the help string for "help set commands" larger than
1100 bytes, making the strstr(s, "\n%\n") condition fail

I have absolutely no idea why it was 1100 to begin with. It's been like
that since the first revision. 2048 is arbitrary too, but it's nicer.

Needless to say, the help.c code needs to be reviewed more deeply, at
least. Could also use that opportunity to get rid of the xmlto/xslt crap.
Not going to do that right now, i don't want to add more bugs.

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Help file control                                                    */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
23  Fifth Floor, Boston, MA  02110-1301  USA
24*/
25
26#define BITLBEE_CORE
27#include "bitlbee.h"
28#include "help.h"
29#undef read
30#undef write
31
32#define BUFSIZE 2048
33
34help_t *help_init(help_t **help, const char *helpfile)
35{
36        int i, buflen = 0;
37        help_t *h;
38        char *s, *t;
39        time_t mtime;
40        struct stat stat[1];
41
42        *help = h = g_new0(help_t, 1);
43
44        h->fd = open(helpfile, O_RDONLY);
45
46        if (h->fd == -1) {
47                g_free(h);
48                return(*help = NULL);
49        }
50
51        if (fstat(h->fd, stat) != 0) {
52                g_free(h);
53                return(*help = NULL);
54        }
55        mtime = stat->st_mtime;
56
57        s = g_new(char, BUFSIZE + 1);
58        s[BUFSIZE] = 0;
59
60        while (((i = read(h->fd, s + buflen, BUFSIZE - buflen)) > 0) ||
61               (i == 0 && strstr(s, "\n%\n"))) {
62                buflen += i;
63                memset(s + buflen, 0, BUFSIZE - buflen);
64                if (!(t = strstr(s, "\n%\n")) || s[0] != '?') {
65                        /* FIXME: Clean up */
66                        help_free(help);
67                        g_free(s);
68                        return NULL;
69                }
70                i = strchr(s, '\n') - s;
71
72                if (h->title) {
73                        h = h->next = g_new0(help_t, 1);
74                }
75                h->title = g_new(char, i);
76
77                strncpy(h->title, s + 1, i - 1);
78                h->title[i - 1] = 0;
79                h->fd = (*help)->fd;
80                h->offset.file_offset = lseek(h->fd, 0, SEEK_CUR) - buflen + i + 1;
81                h->length = t - s - i - 1;
82                h->mtime = mtime;
83
84                buflen -= (t + 3 - s);
85                t = g_strdup(t + 3);
86                g_free(s);
87                s = g_renew(char, t, BUFSIZE + 1);
88                s[BUFSIZE] = 0;
89        }
90
91        g_free(s);
92
93        return(*help);
94}
95
96void help_free(help_t **help)
97{
98        help_t *h, *oh;
99        int last_fd = -1; /* Weak de-dupe */
100
101        if (help == NULL || *help == NULL) {
102                return;
103        }
104
105        h = *help;
106        while (h) {
107                if (h->fd != last_fd) {
108                        close(h->fd);
109                        last_fd = h->fd;
110                }
111                g_free(h->title);
112                h = (oh = h)->next;
113                g_free(oh);
114        }
115
116        *help = NULL;
117}
118
119char *help_get(help_t **help, char *title)
120{
121        time_t mtime;
122        struct stat stat[1];
123        help_t *h;
124
125        for (h = *help; h; h = h->next) {
126                if (h->title != NULL && g_strcasecmp(h->title, title) == 0) {
127                        break;
128                }
129        }
130        if (h && h->length > 0) {
131                char *s = g_new(char, h->length + 1);
132
133                s[h->length] = 0;
134                if (h->fd >= 0) {
135                        if (fstat(h->fd, stat) != 0) {
136                                g_free(s);
137                                return NULL;
138                        }
139                        mtime = stat->st_mtime;
140
141                        if (mtime > h->mtime) {
142                                g_free(s);
143                                return NULL;
144                        }
145
146                        if (lseek(h->fd, h->offset.file_offset, SEEK_SET) == -1 ||
147                            read(h->fd, s, h->length) != h->length) {
148                                return NULL;
149                        }
150                } else {
151                        strncpy(s, h->offset.mem_offset, h->length);
152                }
153                return s;
154        }
155
156        return NULL;
157}
158
159int help_add_mem(help_t **help, const char *title, const char *content)
160{
161        help_t *h, *l = NULL;
162
163        for (h = *help; h; h = h->next) {
164                if (g_strcasecmp(h->title, title) == 0) {
165                        return 0;
166                }
167
168                l = h;
169        }
170
171        if (l) {
172                h = l->next = g_new0(struct help, 1);
173        } else {
174                *help = h = g_new0(struct help, 1);
175        }
176        h->fd = -1;
177        h->title = g_strdup(title);
178        h->length = strlen(content);
179        h->offset.mem_offset = g_strdup(content);
180
181        return 1;
182}
183
184char *help_get_whatsnew(help_t **help, int old)
185{
186        GString *ret = NULL;
187        help_t *h;
188        int v;
189
190        for (h = *help; h; h = h->next) {
191                if (h->title != NULL && strncmp(h->title, "whatsnew", 8) == 0 &&
192                    sscanf(h->title + 8, "%x", &v) == 1 && v > old) {
193                        char *s = help_get(&h, h->title);
194                        if (ret == NULL) {
195                                ret = g_string_new(s);
196                        } else {
197                                g_string_append_printf(ret, "\n\n%s", s);
198                        }
199                        g_free(s);
200                }
201        }
202
203        return ret ? g_string_free(ret, FALSE) : NULL;
204}
Note: See TracBrowser for help on using the repository browser.