source: help.c @ 13fa2db

Last change on this file since 13fa2db was e5d8d21, checked in by Wilmer van der Gaast <wilmer@…>, at 2009-11-25T00:45:27Z

Added in-memory help info, which I wanted to implement for ages already.
Sadly the way I'm using it now doesn't work yet since nogaim_init() is
called before help_init(). I'll fix that later. (Have to do that anyway
to at least make ForkDaemon mode work..)

  • Property mode set to 100644
File size: 4.0 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2009 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., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#define BITLBEE_CORE
27#include "bitlbee.h"
28#undef read
29#undef write
30
31#define BUFSIZE 1100
32
33help_t *help_init( help_t **help, const char *helpfile )
34{
35        int i, buflen = 0;
36        help_t *h;
37        char *s, *t;
38        time_t mtime;
39        struct stat stat[1];
40       
41        *help = h = g_new0 ( help_t, 1 );
42       
43        h->fd = open( helpfile, O_RDONLY
44#ifdef _WIN32
45                                  | O_BINARY
46#endif
47                                  );
48       
49        if( h->fd == -1 )
50        {
51                g_free( h );
52                return( *help = NULL );
53        }
54       
55        if( fstat( h->fd, stat ) != 0 )
56        {
57                g_free( h );
58                return( *help = NULL );
59        }
60        mtime = stat->st_mtime;
61       
62        s = g_new (char, BUFSIZE + 1 );
63        s[BUFSIZE] = 0;
64       
65        while( ( ( i = read( h->fd, s + buflen, BUFSIZE - buflen ) ) > 0 ) ||
66               ( i == 0 && strstr( s, "\n%\n" ) ) )
67        {
68                buflen += i;
69                memset( s + buflen, 0, BUFSIZE - buflen );
70                if( !( t = strstr( s, "\n%\n" ) ) || s[0] != '?' )
71                {
72                        /* FIXME: Clean up */
73                        help_free( help );
74                        g_free( s );
75                        return NULL;
76                }
77                i = strchr( s, '\n' ) - s;
78               
79                if( h->title )
80                {
81                        h = h->next = g_new0( help_t, 1 );
82                }
83                h->title = g_new ( char, i );
84               
85                strncpy( h->title, s + 1, i - 1 );
86                h->title[i-1] = 0;
87                h->fd = (*help)->fd;
88                h->offset.file_offset = lseek( h->fd, 0, SEEK_CUR ) - buflen + i + 1;
89                h->length = t - s - i - 1;
90                h->mtime = mtime;
91               
92                buflen -= ( t + 3 - s );
93                t = g_strdup( t + 3 );
94                g_free( s );
95                s = g_renew( char, t, BUFSIZE + 1 );
96                s[BUFSIZE] = 0;
97        }
98       
99        g_free( s );
100       
101        return( *help );
102}
103
104void help_free( help_t **help )
105{
106        help_t *h, *oh;
107        int last_fd = -1; /* Weak de-dupe */
108       
109        if( help == NULL || *help == NULL )
110                return;
111       
112        h = *help;
113        while( h )
114        {
115                if( h->fd != last_fd )
116                {
117                        close( h->fd );
118                        last_fd = h->fd;
119                }
120                g_free( h->title );
121                h = (oh=h)->next;
122                g_free( oh );
123        }
124       
125        *help = NULL;
126}
127
128char *help_get( help_t **help, char *title )
129{
130        time_t mtime;
131        struct stat stat[1];
132        help_t *h;
133
134        for( h = *help; h; h = h->next )
135        {
136                if( h->title != NULL && g_strcasecmp( h->title, title ) == 0 )
137                        break;
138        }
139        if( h && h->length > 0 )
140        {
141                char *s = g_new( char, h->length + 1 );
142               
143                s[h->length] = 0;
144                if( h->fd >= 0 )
145                {
146                        if( fstat( h->fd, stat ) != 0 )
147                        {
148                                g_free( s );
149                                return NULL;
150                        }
151                        mtime = stat->st_mtime;
152               
153                        if( mtime > h->mtime )
154                        {
155                                g_free( s );
156                                return NULL;
157                        }
158                       
159                        lseek( h->fd, h->offset.file_offset, SEEK_SET );
160                        read( h->fd, s, h->length );
161                }
162                else
163                {
164                        strncpy( s, h->offset.mem_offset, h->length );
165                }
166                return s;
167        }
168       
169        return NULL;
170}
171
172int help_add_mem( help_t **help, const char *title, const char *content )
173{
174        help_t *h, *l = NULL;
175       
176        for( h = *help; h; h = h->next )
177        {
178                if( g_strcasecmp( h->title, title ) == 0 )
179                        return 0;
180               
181                l = h;
182        }
183       
184        if( l )
185                h = l->next = g_new0( struct help, 1 );
186        else
187                *help = h = g_new0( struct help, 1 );
188        h->fd = -1;
189        h->title = g_strdup( title );
190        h->length = strlen( content );
191        h->offset.mem_offset = g_strdup( content );
192       
193        return 1;
194}
Note: See TracBrowser for help on using the repository browser.