/[debian]/bti/trunk/bti.c
ViewVC logotype

Annotation of /bti/trunk/bti.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1623 - (hide annotations)
Thu Mar 12 15:55:34 2009 UTC (12 years, 3 months ago) by gregoa
File MIME type: text/plain
File size: 19672 byte(s)
New upstream release; from the RELEASE-NOTES:
"--action support, bti now can output data from the twitter
and identica servers".
1 gregoa 1473 /*
2     * Copyright (C) 2008 Greg Kroah-Hartman <greg@kroah.com>
3     *
4     * This program is free software; you can redistribute it and/or modify it
5     * under the terms of the GNU General Public License as published by the
6     * Free Software Foundation version 2 of the License.
7     *
8     * This program is distributed in the hope that it will be useful, but
9     * WITHOUT ANY WARRANTY; without even the implied warranty of
10     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11     * General Public License for more details.
12     *
13     * You should have received a copy of the GNU General Public License along
14     * with this program; if not, write to the Free Software Foundation, Inc.,
15     * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16     */
17    
18     #include <stdio.h>
19     #include <stdlib.h>
20     #include <stddef.h>
21     #include <string.h>
22     #include <getopt.h>
23     #include <errno.h>
24     #include <ctype.h>
25     #include <fcntl.h>
26     #include <unistd.h>
27 gregoa 1526 #include <time.h>
28 gregoa 1473 #include <sys/stat.h>
29     #include <curl/curl.h>
30 gregoa 1526 #include <readline/readline.h>
31 gregoa 1623 #include <libxml/xmlmemory.h>
32     #include <libxml/parser.h>
33     #include <libxml/tree.h>
34 gregoa 1473 #include "bti_version.h"
35    
36    
37     #define zalloc(size) calloc(size, 1)
38    
39     #define dbg(format, arg...) \
40     do { \
41     if (debug) \
42 gregoa 1563 printf("%s: " format , __func__ , ## arg); \
43 gregoa 1473 } while (0)
44    
45    
46 gregoa 1563 static int debug;
47 gregoa 1473
48     enum host {
49     HOST_TWITTER = 0,
50     HOST_IDENTICA = 1,
51     };
52    
53 gregoa 1623 enum action {
54     ACTION_UPDATE = 0,
55     ACTION_FRIENDS = 1,
56     ACTION_USER = 2,
57     ACTION_REPLIES = 4,
58     ACTION_PUBLIC = 8,
59     ACTION_UNKNOWN = 16
60     };
61    
62 gregoa 1473 struct session {
63     char *password;
64     char *account;
65     char *tweet;
66 gregoa 1509 char *proxy;
67 gregoa 1526 char *time;
68     char *homedir;
69 gregoa 1532 char *logfile;
70 gregoa 1623 char *user;
71 gregoa 1473 int bash;
72     enum host host;
73 gregoa 1623 enum action action;
74 gregoa 1473 };
75    
76     struct bti_curl_buffer {
77     char *data;
78 gregoa 1623 enum action action;
79 gregoa 1473 int length;
80     };
81    
82     static void display_help(void)
83     {
84 gregoa 1623 fprintf(stdout, "bti - send tweet to twitter or identi.ca\n");
85 gregoa 1473 fprintf(stdout, "Version: " BTI_VERSION "\n");
86     fprintf(stdout, "Usage:\n");
87     fprintf(stdout, " bti [options]\n");
88     fprintf(stdout, "options are:\n");
89     fprintf(stdout, " --account accountname\n");
90     fprintf(stdout, " --password password\n");
91 gregoa 1623 fprintf(stdout, " --action action\n");
92     fprintf(stdout, " ('update', 'friends', 'public', 'replies' or 'user')\n");
93     fprintf(stdout, " --user screenname\n");
94 gregoa 1509 fprintf(stdout, " --proxy PROXY:PORT\n");
95 gregoa 1473 fprintf(stdout, " --host HOST\n");
96 gregoa 1532 fprintf(stdout, " --logfile logfile\n");
97 gregoa 1473 fprintf(stdout, " --bash\n");
98     fprintf(stdout, " --debug\n");
99     fprintf(stdout, " --version\n");
100     fprintf(stdout, " --help\n");
101     }
102    
103     static void display_version(void)
104     {
105     fprintf(stdout, "bti - version %s\n", BTI_VERSION);
106     }
107    
108     static struct session *session_alloc(void)
109     {
110     struct session *session;
111    
112     session = zalloc(sizeof(*session));
113     if (!session)
114     return NULL;
115     return session;
116     }
117    
118     static void session_free(struct session *session)
119     {
120     if (!session)
121     return;
122     free(session->password);
123     free(session->account);
124     free(session->tweet);
125 gregoa 1509 free(session->proxy);
126 gregoa 1526 free(session->time);
127     free(session->homedir);
128 gregoa 1623 free(session->user);
129 gregoa 1473 free(session);
130     }
131    
132 gregoa 1623 static struct bti_curl_buffer *bti_curl_buffer_alloc(enum action action)
133 gregoa 1473 {
134     struct bti_curl_buffer *buffer;
135    
136     buffer = zalloc(sizeof(*buffer));
137     if (!buffer)
138     return NULL;
139    
140     /* start out with a data buffer of 1 byte to
141     * make the buffer fill logic simpler */
142     buffer->data = zalloc(1);
143     if (!buffer->data) {
144     free(buffer);
145     return NULL;
146     }
147     buffer->length = 0;
148 gregoa 1623 buffer->action = action;
149 gregoa 1473 return buffer;
150     }
151    
152     static void bti_curl_buffer_free(struct bti_curl_buffer *buffer)
153     {
154     if (!buffer)
155     return;
156     free(buffer->data);
157     free(buffer);
158     }
159    
160 gregoa 1623 static const char *twitter_user_url = "http://twitter.com/statuses/user_timeline/";
161     static const char *twitter_update_url = "https://twitter.com/statuses/update.xml";
162     static const char *twitter_public_url = "http://twitter.com/statuses/public_timeline.xml";
163     static const char *twitter_friends_url = "https://twitter.com/statuses/friends_timeline.xml";
164     static const char *twitter_replies_url = "http://twitter.com/statuses/replies.xml";
165 gregoa 1473
166 gregoa 1623 static const char *identica_user_url = "http://identi.ca/api/statuses/user_timeline/";
167     static const char *identica_update_url = "http://identi.ca/api/statuses/update.xml";
168     static const char *identica_public_url = "http://identi.ca/api/statuses/public_timeline.xml";
169     static const char *identica_friends_url = "http://identi.ca/api/statuses/friends_timeline.xml";
170     static const char *identica_replies_url = "http://identi.ca/api/statuses/replies.xml";
171    
172 gregoa 1473 static CURL *curl_init(void)
173     {
174     CURL *curl;
175    
176     curl = curl_easy_init();
177     if (!curl) {
178     fprintf(stderr, "Can not init CURL!\n");
179     return NULL;
180     }
181     /* some ssl sanity checks on the connection we are making */
182     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
183     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
184     return curl;
185     }
186    
187 gregoa 1623 void parse_statuses(xmlDocPtr doc, xmlNodePtr current)
188     {
189     xmlChar *text = NULL;
190     xmlChar *user = NULL;
191     xmlNodePtr userinfo;
192    
193     current = current->xmlChildrenNode;
194     while (current != NULL) {
195     if (current->type == XML_ELEMENT_NODE) {
196     if (!xmlStrcmp(current->name, (const xmlChar *)"text"))
197     text = xmlNodeListGetString(doc, current->xmlChildrenNode, 1);
198     if (!xmlStrcmp(current->name, (const xmlChar *)"user")) {
199     userinfo = current->xmlChildrenNode;
200     while (userinfo != NULL) {
201     if ((!xmlStrcmp(userinfo->name, (const xmlChar *)"screen_name"))) {
202     if (user)
203     xmlFree(user);
204     user = xmlNodeListGetString(doc, userinfo->xmlChildrenNode, 1);
205     }
206     userinfo = userinfo->next;
207     }
208     }
209     if (user && text) {
210     printf("[%s] %s\n", user, text);
211     xmlFree(user);
212     xmlFree(text);
213     user = NULL;
214     text = NULL;
215     }
216     }
217     current = current->next;
218     }
219    
220     return;
221     }
222    
223     static void parse_timeline(char *document)
224     {
225     xmlDocPtr doc;
226     xmlNodePtr current;
227     doc = xmlReadMemory(document, strlen(document), "timeline.xml", NULL, XML_PARSE_NOERROR);
228    
229     if (doc == NULL)
230     return;
231    
232     current = xmlDocGetRootElement(doc);
233     if (current == NULL) {
234     fprintf(stderr, "empty document\n");
235     xmlFreeDoc(doc);
236     return;
237     }
238    
239     if (xmlStrcmp(current->name, (const xmlChar *) "statuses")) {
240     fprintf(stderr, "unexpected document type\n");
241     xmlFreeDoc(doc);
242     return;
243     }
244    
245     current = current->xmlChildrenNode;
246     while (current != NULL) {
247     if ((!xmlStrcmp(current->name, (const xmlChar *)"status")))
248     parse_statuses(doc, current);
249     current = current->next;
250     }
251     xmlFreeDoc(doc);
252    
253     return;
254     }
255    
256 gregoa 1473 size_t curl_callback(void *buffer, size_t size, size_t nmemb, void *userp)
257     {
258     struct bti_curl_buffer *curl_buf = userp;
259     size_t buffer_size = size * nmemb;
260     char *temp;
261    
262     if ((!buffer) || (!buffer_size) || (!curl_buf))
263     return -EINVAL;
264    
265     /* add to the data we already have */
266     temp = zalloc(curl_buf->length + buffer_size + 1);
267     if (!temp)
268     return -ENOMEM;
269    
270     memcpy(temp, curl_buf->data, curl_buf->length);
271     free(curl_buf->data);
272     curl_buf->data = temp;
273     memcpy(&curl_buf->data[curl_buf->length], (char *)buffer, buffer_size);
274     curl_buf->length += buffer_size;
275 gregoa 1623 if (curl_buf->action)
276     parse_timeline(curl_buf->data);
277 gregoa 1473
278     dbg("%s\n", curl_buf->data);
279    
280     return buffer_size;
281     }
282    
283 gregoa 1623 static int send_request(struct session *session)
284 gregoa 1473 {
285     char user_password[500];
286     char data[500];
287 gregoa 1623 /* is there usernames longer than 22 chars? */
288     char user_url[70];
289 gregoa 1473 struct bti_curl_buffer *curl_buf;
290     CURL *curl = NULL;
291     CURLcode res;
292     struct curl_httppost *formpost = NULL;
293     struct curl_httppost *lastptr = NULL;
294 gregoa 1503 struct curl_slist *slist = NULL;
295 gregoa 1473
296     if (!session)
297     return -EINVAL;
298    
299 gregoa 1623 curl_buf = bti_curl_buffer_alloc(session->action);
300 gregoa 1473 if (!curl_buf)
301     return -ENOMEM;
302    
303     curl = curl_init();
304     if (!curl)
305     return -EINVAL;
306    
307 gregoa 1623 switch (session->action) {
308     case ACTION_UPDATE:
309     snprintf(user_password, sizeof(user_password), "%s:%s",
310     session->account, session->password);
311     snprintf(data, sizeof(data), "status=\"%s\"", session->tweet);
312     curl_formadd(&formpost, &lastptr,
313     CURLFORM_COPYNAME, "status",
314     CURLFORM_COPYCONTENTS, session->tweet,
315     CURLFORM_END);
316 gregoa 1473
317 gregoa 1623 curl_formadd(&formpost, &lastptr,
318     CURLFORM_COPYNAME, "source",
319     CURLFORM_COPYCONTENTS, "bti",
320     CURLFORM_END);
321 gregoa 1532
322 gregoa 1623 curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
323 gregoa 1503 slist = curl_slist_append(slist, "Expect:");
324     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
325 gregoa 1623 switch (session->host) {
326     case HOST_TWITTER:
327     curl_easy_setopt(curl, CURLOPT_URL, twitter_update_url);
328     break;
329     case HOST_IDENTICA:
330     curl_easy_setopt(curl, CURLOPT_URL, identica_update_url);
331     break;
332     }
333     curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
334    
335 gregoa 1473 break;
336 gregoa 1623 case ACTION_FRIENDS:
337     snprintf(user_password, sizeof(user_password), "%s:%s",
338     session->account, session->password);
339     switch (session->host) {
340     case HOST_TWITTER:
341     curl_easy_setopt(curl, CURLOPT_URL, twitter_friends_url);
342     break;
343     case HOST_IDENTICA:
344     curl_easy_setopt(curl, CURLOPT_URL, identica_friends_url);
345     break;
346     }
347     curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
348    
349 gregoa 1473 break;
350 gregoa 1623 case ACTION_USER:
351     switch (session->host) {
352     case HOST_TWITTER:
353     sprintf(user_url, "%s%s.xml", twitter_user_url, session->user);
354     curl_easy_setopt(curl, CURLOPT_URL, user_url);
355     break;
356     case HOST_IDENTICA:
357     sprintf(user_url, "%s%s.xml", identica_user_url, session->user);
358     curl_easy_setopt(curl, CURLOPT_URL, user_url);
359     break;
360     }
361    
362     break;
363     case ACTION_REPLIES:
364     snprintf(user_password, sizeof(user_password), "%s:%s",
365     session->account, session->password);
366     switch (session->host) {
367     case HOST_TWITTER:
368     curl_easy_setopt(curl, CURLOPT_URL, twitter_replies_url);
369     break;
370     case HOST_IDENTICA:
371     curl_easy_setopt(curl, CURLOPT_URL, identica_replies_url);
372     break;
373     }
374     curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
375    
376     break;
377     case ACTION_PUBLIC:
378     switch (session->host) {
379     case HOST_TWITTER:
380     curl_easy_setopt(curl, CURLOPT_URL, twitter_public_url);
381     break;
382     case HOST_IDENTICA:
383     curl_easy_setopt(curl, CURLOPT_URL, identica_public_url);
384     break;
385     }
386    
387     break;
388     default:
389     break;
390 gregoa 1473 }
391    
392 gregoa 1509 if (session->proxy)
393     curl_easy_setopt(curl, CURLOPT_PROXY, session->proxy);
394    
395 gregoa 1473 if (debug)
396     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
397    
398     dbg("user_password = %s\n", user_password);
399     dbg("data = %s\n", data);
400 gregoa 1509 dbg("proxy = %s\n", session->proxy);
401 gregoa 1473
402     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_callback);
403     curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl_buf);
404     res = curl_easy_perform(curl);
405     if (res && !session->bash) {
406 gregoa 1623 fprintf(stderr, "error(%d) trying to perform operation\n", res);
407 gregoa 1473 return -EINVAL;
408     }
409    
410     curl_easy_cleanup(curl);
411 gregoa 1623 if (session->action == ACTION_UPDATE)
412     curl_formfree(formpost);
413 gregoa 1473 bti_curl_buffer_free(curl_buf);
414     return 0;
415     }
416    
417     static void parse_configfile(struct session *session)
418     {
419     FILE *config_file;
420     char *line = NULL;
421     size_t len = 0;
422     char *account = NULL;
423     char *password = NULL;
424     char *host = NULL;
425 gregoa 1509 char *proxy = NULL;
426 gregoa 1532 char *logfile = NULL;
427 gregoa 1623 char *action = NULL;
428     char *user = NULL;
429 gregoa 1473 char *file;
430    
431     /* config file is ~/.bti */
432 gregoa 1526 file = alloca(strlen(session->homedir) + 7);
433 gregoa 1473
434 gregoa 1526 sprintf(file, "%s/.bti", session->homedir);
435 gregoa 1473
436     config_file = fopen(file, "r");
437    
438     /* No error if file does not exist or is unreadable. */
439     if (config_file == NULL)
440     return;
441    
442     do {
443     ssize_t n = getline(&line, &len, config_file);
444     if (n < 0)
445     break;
446     if (line[n - 1] == '\n')
447     line[n - 1] = '\0';
448     /* Parse file. Format is the usual value pairs:
449     account=name
450     passwort=value
451     # is a comment character
452     */
453     *strchrnul(line, '#') = '\0';
454     char *c = line;
455     while (isspace(*c))
456     c++;
457     /* Ignore blank lines. */
458     if (c[0] == '\0')
459     continue;
460    
461     if (!strncasecmp(c, "account", 7) && (c[7] == '=')) {
462     c += 8;
463     if (c[0] != '\0')
464     account = strdup(c);
465     } else if (!strncasecmp(c, "password", 8) &&
466     (c[8] == '=')) {
467     c += 9;
468     if (c[0] != '\0')
469     password = strdup(c);
470     } else if (!strncasecmp(c, "host", 4) &&
471     (c[4] == '=')) {
472     c += 5;
473     if (c[0] != '\0')
474     host = strdup(c);
475 gregoa 1509 } else if (!strncasecmp(c, "proxy", 5) &&
476     (c[5] == '=')) {
477     c += 6;
478     if (c[0] != '\0')
479     proxy = strdup(c);
480 gregoa 1532 } else if (!strncasecmp(c, "logfile", 7) &&
481     (c[7] == '=')) {
482     c += 8;
483     if (c[0] != '\0')
484     logfile = strdup(c);
485 gregoa 1623 } else if (!strncasecmp(c, "action", 6) &&
486     (c[6] == '=')) {
487     c += 7;
488     if (c[0] != '\0')
489     action = strdup(c);
490     } else if (!strncasecmp(c, "user", 4) &&
491     (c[4] == '=')) {
492     c += 5;
493     if (c[0] != '\0')
494     user = strdup(c);
495 gregoa 1473 }
496     } while (!feof(config_file));
497    
498     if (password)
499     session->password = password;
500     if (account)
501     session->account = account;
502     if (host) {
503     if (strcasecmp(host, "twitter") == 0)
504     session->host = HOST_TWITTER;
505     if (strcasecmp(host, "identica") == 0)
506     session->host = HOST_IDENTICA;
507     free(host);
508     }
509 gregoa 1513 if (proxy) {
510     if (session->proxy)
511     free(session->proxy);
512 gregoa 1509 session->proxy = proxy;
513 gregoa 1513 }
514 gregoa 1532 if (logfile)
515     session->logfile = logfile;
516 gregoa 1623 if (action) {
517     if (strcasecmp(action, "update") == 0)
518     session->action = ACTION_UPDATE;
519     else if (strcasecmp(action, "friends") == 0)
520     session->action = ACTION_FRIENDS;
521     else if (strcasecmp(action, "user") == 0)
522     session->action = ACTION_USER;
523     else if (strcasecmp(action, "replies") == 0)
524     session->action = ACTION_REPLIES;
525     else if (strcasecmp(action, "public") == 0)
526     session->action = ACTION_PUBLIC;
527     else
528     session->action = ACTION_UNKNOWN;
529     free(action);
530     }
531     if (user) {
532     session->user = user;
533     }
534 gregoa 1473
535     /* Free buffer and close file. */
536     free(line);
537     fclose(config_file);
538     }
539    
540 gregoa 1526 static void log_session(struct session *session, int retval)
541     {
542     FILE *log_file;
543     char *filename;
544     char *host;
545    
546 gregoa 1532 /* Only log something if we have a log file set */
547     if (!session->logfile)
548     return;
549 gregoa 1526
550 gregoa 1532 filename = alloca(strlen(session->homedir) +
551     strlen(session->logfile) + 3);
552 gregoa 1526
553 gregoa 1532 sprintf(filename, "%s/%s", session->homedir, session->logfile);
554    
555 gregoa 1526 log_file = fopen(filename, "a+");
556     if (log_file == NULL)
557     return;
558     switch (session->host) {
559     case HOST_TWITTER:
560     host = "twitter";
561     break;
562     case HOST_IDENTICA:
563     host = "identi.ca";
564     break;
565     default:
566     host = "unknown";
567     break;
568     }
569    
570 gregoa 1623 switch (session->action) {
571     case ACTION_UPDATE:
572     if (retval)
573     fprintf(log_file, "%s: host=%s tweet failed\n",
574     session->time, host);
575     else
576     fprintf(log_file, "%s: host=%s tweet=%s\n",
577     session->time, host, session->tweet);
578     break;
579     case ACTION_FRIENDS:
580     fprintf(log_file, "%s: host=%s retrieving friends timeline\n",
581 gregoa 1563 session->time, host);
582 gregoa 1623 break;
583     case ACTION_USER:
584     fprintf(log_file, "%s: host=%s retrieving %s's timeline\n",
585     session->time, host, session->user);
586     break;
587     case ACTION_REPLIES:
588     fprintf(log_file, "%s: host=%s retrieving replies\n",
589     session->time, host);
590     break;
591     case ACTION_PUBLIC:
592     fprintf(log_file, "%s: host=%s retrieving public timeline\n",
593     session->time, host);
594     break;
595     default:
596     break;
597     }
598 gregoa 1526
599     fclose(log_file);
600     }
601    
602 gregoa 1623 static char *get_string_from_stdin(void)
603     {
604     char *temp;
605     char *string;
606    
607     string = zalloc(1000);
608     if (!string)
609     return NULL;
610    
611     if (!fgets(string, 999, stdin))
612     return NULL;
613     temp = strchr(string, '\n');
614     *temp = '\0';
615     return string;
616     }
617    
618 gregoa 1473 int main(int argc, char *argv[], char *envp[])
619     {
620     static const struct option options[] = {
621     { "debug", 0, NULL, 'd' },
622     { "account", 1, NULL, 'a' },
623     { "password", 1, NULL, 'p' },
624     { "host", 1, NULL, 'H' },
625 gregoa 1513 { "proxy", 1, NULL, 'P' },
626 gregoa 1623 { "action", 1, NULL, 'A' },
627     { "user", 1, NULL, 'u' },
628 gregoa 1532 { "logfile", 1, NULL, 'L' },
629 gregoa 1473 { "help", 0, NULL, 'h' },
630     { "bash", 0, NULL, 'b' },
631     { "version", 0, NULL, 'v' },
632     { }
633     };
634     struct session *session;
635     pid_t child;
636     char *tweet;
637 gregoa 1526 int retval = 0;
638 gregoa 1473 int option;
639 gregoa 1513 char *http_proxy;
640 gregoa 1526 time_t t;
641    
642 gregoa 1563 debug = 0;
643 gregoa 1526 rl_bind_key('\t', rl_insert);
644 gregoa 1563
645 gregoa 1473 session = session_alloc();
646     if (!session) {
647     fprintf(stderr, "no more memory...\n");
648     return -1;
649     }
650    
651 gregoa 1526 /* get the current time so that we can log it later */
652     time(&t);
653     session->time = strdup(ctime(&t));
654     session->time[strlen(session->time)-1] = 0x00;
655    
656     session->homedir = strdup(getenv("HOME"));
657    
658 gregoa 1473 curl_global_init(CURL_GLOBAL_ALL);
659 gregoa 1513
660     /* Set environment variables first, before reading command line options
661     * or config file values. */
662     http_proxy = getenv("http_proxy");
663     if (http_proxy) {
664     if (session->proxy)
665     free(session->proxy);
666     session->proxy = strdup(http_proxy);
667     dbg("http_proxy = %s\n", session->proxy);
668     }
669    
670 gregoa 1473 parse_configfile(session);
671    
672     while (1) {
673 gregoa 1623 option = getopt_long_only(argc, argv, "dqe:p:P:H:a:A:u:h",
674 gregoa 1473 options, NULL);
675     if (option == -1)
676     break;
677     switch (option) {
678     case 'd':
679     debug = 1;
680     break;
681     case 'a':
682     if (session->account)
683     free(session->account);
684     session->account = strdup(optarg);
685     dbg("account = %s\n", session->account);
686     break;
687     case 'p':
688     if (session->password)
689     free(session->password);
690     session->password = strdup(optarg);
691     dbg("password = %s\n", session->password);
692     break;
693 gregoa 1513 case 'P':
694     if (session->proxy)
695     free(session->proxy);
696     session->proxy = strdup(optarg);
697     dbg("proxy = %s\n", session->proxy);
698     break;
699 gregoa 1623 case 'A':
700     if (strcasecmp(optarg, "update") == 0)
701     session->action = ACTION_UPDATE;
702     else if (strcasecmp(optarg, "friends") == 0)
703     session->action = ACTION_FRIENDS;
704     else if (strcasecmp(optarg, "user") == 0)
705     session->action = ACTION_USER;
706     else if (strcasecmp(optarg, "replies") == 0)
707     session->action = ACTION_REPLIES;
708     else if (strcasecmp(optarg, "public") == 0)
709     session->action = ACTION_PUBLIC;
710     else
711     session->action = ACTION_UNKNOWN;
712     dbg("action = %d\n", session->action);
713     break;
714     case 'u':
715     if (session->user)
716     free(session->user);
717     session->user = strdup(optarg);
718     dbg("user = %s\n", session->user);
719     break;
720 gregoa 1532 case 'L':
721     if (session->logfile)
722     free(session->logfile);
723     session->logfile = strdup(optarg);
724     dbg("logfile = %s\n", session->logfile);
725     break;
726 gregoa 1473 case 'H':
727     if (strcasecmp(optarg, "twitter") == 0)
728     session->host = HOST_TWITTER;
729     if (strcasecmp(optarg, "identica") == 0)
730     session->host = HOST_IDENTICA;
731     dbg("host = %d\n", session->host);
732     break;
733     case 'b':
734 gregoa 1563 session->bash = 1;
735 gregoa 1473 break;
736     case 'h':
737     display_help();
738     goto exit;
739     case 'v':
740     display_version();
741     goto exit;
742     default:
743     display_help();
744     goto exit;
745     }
746     }
747    
748 gregoa 1623 if (session->action == ACTION_UNKNOWN) {
749     fprintf(stderr, "Unknown action, valid actions are:\n");
750     fprintf(stderr, "'update', 'friends', 'public', 'replies' or 'user'.\n");
751     goto exit;
752     }
753    
754 gregoa 1473 if (!session->account) {
755     fprintf(stdout, "Enter twitter account: ");
756 gregoa 1574 session->account = readline(NULL);
757 gregoa 1473 }
758    
759     if (!session->password) {
760     fprintf(stdout, "Enter twitter password: ");
761 gregoa 1574 session->password = readline(NULL);
762 gregoa 1473 }
763 gregoa 1563
764 gregoa 1623 if (session->action == ACTION_UPDATE) {
765     if (session->bash)
766     tweet = get_string_from_stdin();
767     else
768     tweet = readline("tweet: ");
769     if (!tweet || strlen(tweet) == 0) {
770     dbg("no tweet?\n");
771     return -1;
772     }
773    
774     session->tweet = zalloc(strlen(tweet) + 10);
775     if (session->bash)
776     sprintf(session->tweet, "$ %s", tweet);
777     else
778     sprintf(session->tweet, "%s", tweet);
779    
780     free(tweet);
781     dbg("tweet = %s\n", session->tweet);
782 gregoa 1473 }
783    
784 gregoa 1623 if (!session->user)
785     session->user = strdup(session->account);
786 gregoa 1473
787     dbg("account = %s\n", session->account);
788     dbg("password = %s\n", session->password);
789     dbg("host = %d\n", session->host);
790 gregoa 1623 dbg("action = %d\n", session->action);
791 gregoa 1473
792     /* fork ourself so that the main shell can get on
793     * with it's life as we try to connect and handle everything
794     */
795     if (session->bash) {
796     child = fork();
797 gregoa 1623 if (child) {
798 gregoa 1473 dbg("child is %d\n", child);
799     exit(0);
800     }
801     }
802    
803 gregoa 1623 retval = send_request(session);
804 gregoa 1526 if (retval && !session->bash)
805 gregoa 1623 fprintf(stderr, "operation failed\n");
806 gregoa 1473
807 gregoa 1532 log_session(session, retval);
808 gregoa 1526 exit:
809 gregoa 1473 session_free(session);
810 gregoa 1526 return retval;;
811 gregoa 1473 }

  ViewVC Help
Powered by ViewVC 1.1.26