fix compiler warning with bti_output_line
[gregoa/bti.git] / config.c
1 /*
2  * Copyright (C) 2008-2011 Greg Kroah-Hartman <greg@kroah.com>
3  * Copyright (C) 2009 Bart Trojanowski <bart@jukie.net>
4  * Copyright (C) 2009-2010 Amir Mohammad Saied <amirsaied@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19
20 #define _GNU_SOURCE
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <string.h>
26 #include <getopt.h>
27 #include <errno.h>
28 #include <ctype.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <time.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <curl/curl.h>
36 #include <libxml/xmlmemory.h>
37 #include <libxml/parser.h>
38 #include <libxml/tree.h>
39 #include <pcre.h>
40 #include <termios.h>
41 #include <dlfcn.h>
42 #include <oauth.h>
43 #include "bti.h"
44
45
46
47 /*
48  * get_key function
49  *
50  * Read a line from the config file and assign it a key and a value.
51  *
52  * This logic taken almost identically from taken from udev's rule file parsing
53  * logic in the file udev-rules.c, written by Kay Sievers and licensed under
54  * the GPLv2+.  I hate writing parsers, so it makes sense to borrow working
55  * logic from those smarter than I...
56  */
57 static int get_key(struct session *session, char *line, char **key, char **value)
58 {
59         char *linepos;
60         char *temp;
61         char terminator;
62
63         linepos = line;
64         if (linepos == NULL || linepos[0] == '\0')
65                 return -1;
66
67         /* skip whitespace */
68         while (isspace(linepos[0]) || linepos[0] == ',')
69                 linepos++;
70         if (linepos[0] == '\0')
71                 return -1;
72
73         *key = linepos;
74
75         for (;;) {
76                 linepos++;
77                 if (linepos[0] == '\0')
78                         return -1;
79                 if (isspace(linepos[0]))
80                         break;
81                 if (linepos[0] == '=')
82                         break;
83         }
84
85         /* remember the end of the key */
86         temp = linepos;
87
88         /* skip whitespace after key */
89         while (isspace(linepos[0]))
90                 linepos++;
91         if (linepos[0] == '\0')
92                 return -1;
93
94         /* make sure this is a = operation */
95         /*
96          * udev likes to check for += and == and lots of other complex
97          * assignments that we don't care about.
98          */
99         if (linepos[0] == '=')
100                 linepos++;
101         else
102                 return -1;
103
104         /* terminate key */
105         temp[0] = '\0';
106
107         /* skip whitespace after opearator */
108         while (isspace(linepos[0]))
109                 linepos++;
110         if (linepos[0] == '\0')
111                 return -1;
112
113         /*
114          * if the value is quoted, then terminate on a ", otherwise space is
115          * the terminator.
116          * */
117         if (linepos[0] == '"') {
118                 terminator = '"';
119                 linepos++;
120         } else
121                 terminator = ' ';
122
123         /* get the value */
124         *value = linepos;
125
126         /* terminate */
127         temp = strchr(linepos, terminator);
128         if (temp) {
129                 temp[0] = '\0';
130                 temp++;
131         } else {
132                 /*
133                  * perhaps we just hit the end of the line, so there would not
134                  * be a terminator, so just use the whole rest of the string as
135                  * the value.
136                  */
137         }
138         printf("%s = %s\n", *key, *value);
139         return 0;
140 }
141
142 typedef int (*config_function_callback)(struct session *session, char *value);
143
144 struct config_table {
145         const char *key;
146         config_function_callback callback;
147 };
148
149
150 int account_callback(struct session *session, char *value)
151 {
152         return 0;
153 }
154
155 static struct config_table config_table[] = {
156         { "account", account_callback },
157         { NULL, NULL }
158 };
159
160
161
162 void bti_parse_configfile(struct session *session)
163 {
164         FILE *config_file;
165         char *line = NULL;
166         size_t len = 0;
167         char *account = NULL;
168         char *password = NULL;
169         char *consumer_key = NULL;
170         char *consumer_secret = NULL;
171         char *access_token_key = NULL;
172         char *access_token_secret = NULL;
173         char *host = NULL;
174         char *proxy = NULL;
175         char *logfile = NULL;
176         char *action = NULL;
177         char *user = NULL;
178         char *replyto = NULL;
179         char *retweet = NULL;
180         int shrink_urls = 0;
181
182         config_file = fopen(session->configfile, "r");
183
184         /* No error if file does not exist or is unreadable.  */
185         if (config_file == NULL)
186                 return;
187
188         do {
189                 char *key;
190                 char *value;
191                 ssize_t n = getline(&line, &len, config_file);
192                 if (n < 0)
193                         break;
194                 if (line[n - 1] == '\n')
195                         line[n - 1] = '\0';
196                 /* Parse file.  Format is the usual value pairs:
197                    account=name
198                    passwort=value
199                    # is a comment character
200                 */
201                 *strchrnul(line, '#') = '\0';
202                 char *c = line;
203                 while (isspace(*c))
204                         c++;
205                 /* Ignore blank lines.  */
206                 if (c[0] == '\0')
207                         continue;
208
209                 get_key(session, line, &key, &value);
210
211                 if (!strncasecmp(c, "account", 7) && (c[7] == '=')) {
212                         c += 8;
213                         if (c[0] != '\0')
214                                 account = strdup(c);
215                 } else if (!strncasecmp(c, "password", 8) &&
216                            (c[8] == '=')) {
217                         c += 9;
218                         if (c[0] != '\0')
219                                 password = strdup(c);
220                 } else if (!strncasecmp(c, "consumer_key", 12) &&
221                            (c[12] == '=')) {
222                         c += 13;
223                         if (c[0] != '\0')
224                                 consumer_key = strdup(c);
225                 } else if (!strncasecmp(c, "consumer_secret", 15) &&
226                            (c[15] == '=')) {
227                         c += 16;
228                         if (c[0] != '\0')
229                                 consumer_secret = strdup(c);
230                 } else if (!strncasecmp(c, "access_token_key", 16) &&
231                            (c[16] == '=')) {
232                         c += 17;
233                         if (c[0] != '\0')
234                                 access_token_key = strdup(c);
235                 } else if (!strncasecmp(c, "access_token_secret", 19) &&
236                            (c[19] == '=')) {
237                         c += 20;
238                         if (c[0] != '\0')
239                                 access_token_secret = strdup(c);
240                 } else if (!strncasecmp(c, "host", 4) &&
241                            (c[4] == '=')) {
242                         c += 5;
243                         if (c[0] != '\0')
244                                 host = strdup(c);
245                 } else if (!strncasecmp(c, "proxy", 5) &&
246                            (c[5] == '=')) {
247                         c += 6;
248                         if (c[0] != '\0')
249                                 proxy = strdup(c);
250                 } else if (!strncasecmp(c, "logfile", 7) &&
251                            (c[7] == '=')) {
252                         c += 8;
253                         if (c[0] != '\0')
254                                 logfile = strdup(c);
255                 } else if (!strncasecmp(c, "replyto", 7) &&
256                            (c[7] == '=')) {
257                         c += 8;
258                         if (c[0] != '\0')
259                                 replyto = strdup(c);
260                 } else if (!strncasecmp(c, "action", 6) &&
261                            (c[6] == '=')) {
262                         c += 7;
263                         if (c[0] != '\0')
264                                 action = strdup(c);
265                 } else if (!strncasecmp(c, "user", 4) &&
266                                 (c[4] == '=')) {
267                         c += 5;
268                         if (c[0] != '\0')
269                                 user = strdup(c);
270                 } else if (!strncasecmp(c, "shrink-urls", 11) &&
271                                 (c[11] == '=')) {
272                         c += 12;
273                         if (!strncasecmp(c, "true", 4) ||
274                                         !strncasecmp(c, "yes", 3))
275                                 shrink_urls = 1;
276                 } else if (!strncasecmp(c, "verbose", 7) &&
277                                 (c[7] == '=')) {
278                         c += 8;
279                         if (!strncasecmp(c, "true", 4) ||
280                                         !strncasecmp(c, "yes", 3))
281                                 session->verbose = 1;
282                 } else if (!strncasecmp(c,"retweet", 7) &&
283                                 (c[7] == '=')) {
284                         c += 8;
285                         if (c[0] != '\0')
286                                 retweet = strdup(c);
287                 }
288         } while (!feof(config_file));
289
290         if (password)
291                 session->password = password;
292         if (account)
293                 session->account = account;
294         if (consumer_key)
295                 session->consumer_key = consumer_key;
296         if (consumer_secret)
297                 session->consumer_secret = consumer_secret;
298         if (access_token_key)
299                 session->access_token_key = access_token_key;
300         if (access_token_secret)
301                 session->access_token_secret = access_token_secret;
302         if (host) {
303                 if (strcasecmp(host, "twitter") == 0) {
304                         session->host = HOST_TWITTER;
305                         session->hosturl = strdup(twitter_host);
306                         session->hostname = strdup(twitter_name);
307                 } else if (strcasecmp(host, "identica") == 0) {
308                         session->host = HOST_IDENTICA;
309                         session->hosturl = strdup(identica_host);
310                         session->hostname = strdup(identica_name);
311                 } else {
312                         session->host = HOST_CUSTOM;
313                         session->hosturl = strdup(host);
314                         session->hostname = strdup(host);
315                 }
316                 free(host);
317         }
318         if (proxy) {
319                 if (session->proxy)
320                         free(session->proxy);
321                 session->proxy = proxy;
322         }
323         if (logfile)
324                 session->logfile = logfile;
325         if (replyto)
326                 session->replyto = replyto;
327         if (retweet)
328                 session->retweet = retweet;
329         if (action) {
330                 if (strcasecmp(action, "update") == 0)
331                         session->action = ACTION_UPDATE;
332                 else if (strcasecmp(action, "friends") == 0)
333                         session->action = ACTION_FRIENDS;
334                 else if (strcasecmp(action, "user") == 0)
335                         session->action = ACTION_USER;
336                 else if (strcasecmp(action, "replies") == 0)
337                         session->action = ACTION_REPLIES;
338                 else if (strcasecmp(action, "public") == 0)
339                         session->action = ACTION_PUBLIC;
340                 else if (strcasecmp(action, "group") == 0)
341                         session->action = ACTION_GROUP;
342                 else
343                         session->action = ACTION_UNKNOWN;
344                 free(action);
345         }
346         if (user)
347                 session->user = user;
348         session->shrink_urls = shrink_urls;
349
350         /* Free buffer and close file.  */
351         free(line);
352         fclose(config_file);
353 }
354
355