don't free an array on the stack
[gregoa/bti.git] / bti.c
diff --git a/bti.c b/bti.c
index 2968936..02332c4 100644 (file)
--- a/bti.c
+++ b/bti.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008 Greg Kroah-Hartman <greg@kroah.com>
  * Copyright (C) 2009 Bart Trojanowski <bart@jukie.net>
 /*
  * Copyright (C) 2008 Greg Kroah-Hartman <greg@kroah.com>
  * Copyright (C) 2009 Bart Trojanowski <bart@jukie.net>
+ * Copyright (C) 2009 Amir Mohammad Saied <amirsaied@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -37,6 +38,7 @@
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <pcre.h>
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <pcre.h>
+#include <termios.h>
 
 
 #define zalloc(size)   calloc(size, 1)
 
 
 #define zalloc(size)   calloc(size, 1)
@@ -64,7 +66,8 @@ enum action {
        ACTION_USER    = 2,
        ACTION_REPLIES = 4,
        ACTION_PUBLIC  = 8,
        ACTION_USER    = 2,
        ACTION_REPLIES = 4,
        ACTION_PUBLIC  = 8,
-       ACTION_UNKNOWN = 16
+       ACTION_GROUP   = 16,
+       ACTION_UNKNOWN = 32
 };
 
 struct session {
 };
 
 struct session {
@@ -76,6 +79,7 @@ struct session {
        char *homedir;
        char *logfile;
        char *user;
        char *homedir;
        char *logfile;
        char *user;
+       char *group;
        char *hosturl;
        int bash;
        int shrink_urls;
        char *hosturl;
        int bash;
        int shrink_urls;
@@ -101,9 +105,10 @@ static void display_help(void)
        fprintf(stdout, "  --account accountname\n");
        fprintf(stdout, "  --password password\n");
        fprintf(stdout, "  --action action\n");
        fprintf(stdout, "  --account accountname\n");
        fprintf(stdout, "  --password password\n");
        fprintf(stdout, "  --action action\n");
-       fprintf(stdout, "    ('update', 'friends', 'public', 'replies' "
-               "or 'user')\n");
+       fprintf(stdout, "    ('update', 'friends', 'public', 'replies', "
+               "'group' or 'user')\n");
        fprintf(stdout, "  --user screenname\n");
        fprintf(stdout, "  --user screenname\n");
+       fprintf(stdout, "  --group groupname\n");
        fprintf(stdout, "  --proxy PROXY:PORT\n");
        fprintf(stdout, "  --host HOST\n");
        fprintf(stdout, "  --logfile logfile\n");
        fprintf(stdout, "  --proxy PROXY:PORT\n");
        fprintf(stdout, "  --host HOST\n");
        fprintf(stdout, "  --logfile logfile\n");
@@ -143,6 +148,7 @@ static void session_free(struct session *session)
        free(session->time);
        free(session->homedir);
        free(session->user);
        free(session->time);
        free(session->homedir);
        free(session->user);
+       free(session->group);
        free(session->hosturl);
        free(session);
 }
        free(session->hosturl);
        free(session);
 }
@@ -183,6 +189,7 @@ static const char *update_uri  = "/update.xml";
 static const char *public_uri  = "/public_timeline.xml";
 static const char *friends_uri = "/friends_timeline.xml";
 static const char *replies_uri = "/replies.xml";
 static const char *public_uri  = "/public_timeline.xml";
 static const char *friends_uri = "/friends_timeline.xml";
 static const char *replies_uri = "/replies.xml";
+static const char *group_uri = "/../laconica/groups/timeline/";
 
 static CURL *curl_init(void)
 {
 
 static CURL *curl_init(void)
 {
@@ -349,7 +356,7 @@ static int send_request(struct session *session)
                curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
                slist = curl_slist_append(slist, "Expect:");
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
                curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
                slist = curl_slist_append(slist, "Expect:");
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
-               
+
                sprintf(endpoint, "%s%s", session->hosturl, update_uri);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
                curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
                sprintf(endpoint, "%s%s", session->hosturl, update_uri);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
                curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
@@ -365,21 +372,29 @@ static int send_request(struct session *session)
 
                break;
        case ACTION_USER:
 
                break;
        case ACTION_USER:
-               sprintf(endpoint, "%s%s%s.xml?page=%d", session->hosturl, user_uri,
-                               session->user, session->page);
+               sprintf(endpoint, "%s%s%s.xml?page=%d", session->hosturl,
+                       user_uri, session->user, session->page);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
 
                break;
        case ACTION_REPLIES:
                snprintf(user_password, sizeof(user_password), "%s:%s",
                         session->account, session->password);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
 
                break;
        case ACTION_REPLIES:
                snprintf(user_password, sizeof(user_password), "%s:%s",
                         session->account, session->password);
-               sprintf(endpoint, "%s%s?page=%d", session->hosturl, replies_uri, session->page);
+               sprintf(endpoint, "%s%s?page=%d", session->hosturl, replies_uri,
+                       session->page);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
                curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
 
                break;
        case ACTION_PUBLIC:
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
                curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
 
                break;
        case ACTION_PUBLIC:
-               sprintf(endpoint, "%s%s?page=%d", session->hosturl, public_uri, session->page);
+               sprintf(endpoint, "%s%s?page=%d", session->hosturl, public_uri,
+                       session->page);
+               curl_easy_setopt(curl, CURLOPT_URL, endpoint);
+
+               break;
+       case ACTION_GROUP:
+               sprintf(endpoint, "%s%s%s.xml?page=%d", session->hosturl,
+                               group_uri, session->group, session->page);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
 
                break;
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
 
                break;
@@ -500,14 +515,13 @@ static void parse_configfile(struct session *session)
                        if (!strncasecmp(c, "true", 4) ||
                                        !strncasecmp(c, "yes", 3))
                                shrink_urls = 1;
                        if (!strncasecmp(c, "true", 4) ||
                                        !strncasecmp(c, "yes", 3))
                                shrink_urls = 1;
-               }
-               else if (!strncasecmp(c, "verbose", 7) &&
+               } else if (!strncasecmp(c, "verbose", 7) &&
                                (c[7] == '=')) {
                        c += 8;
                        if (!strncasecmp(c, "true", 4) ||
                                        !strncasecmp(c, "yes", 3))
                                verbose = 1;
                                (c[7] == '=')) {
                        c += 8;
                        if (!strncasecmp(c, "true", 4) ||
                                        !strncasecmp(c, "yes", 3))
                                verbose = 1;
-               }       
+               }
        } while (!feof(config_file));
 
        if (password)
        } while (!feof(config_file));
 
        if (password)
@@ -545,6 +559,8 @@ static void parse_configfile(struct session *session)
                        session->action = ACTION_REPLIES;
                else if (strcasecmp(action, "public") == 0)
                        session->action = ACTION_PUBLIC;
                        session->action = ACTION_REPLIES;
                else if (strcasecmp(action, "public") == 0)
                        session->action = ACTION_PUBLIC;
+               else if (strcasecmp(action, "group") == 0)
+                       session->action = ACTION_GROUP;
                else
                        session->action = ACTION_UNKNOWN;
                free(action);
                else
                        session->action = ACTION_UNKNOWN;
                free(action);
@@ -613,6 +629,10 @@ static void log_session(struct session *session, int retval)
                fprintf(log_file, "%s: host=%s retrieving public timeline\n",
                        session->time, host);
                break;
                fprintf(log_file, "%s: host=%s retrieving public timeline\n",
                        session->time, host);
                break;
+       case ACTION_GROUP:
+               fprintf(log_file, "%s: host=%s retrieving group timeline\n",
+                       session->time, host);
+               break;
        default:
                break;
        }
        default:
                break;
        }
@@ -636,6 +656,29 @@ static char *get_string_from_stdin(void)
        return string;
 }
 
        return string;
 }
 
+void read_password(char *buf, size_t len)
+{
+       char pwd[80];
+       struct termios old;
+       struct termios tp;
+
+       tcgetattr(0, &tp);
+       old = tp;
+
+       tp.c_lflag &= (~ECHO);
+       tcsetattr(0, TCSANOW, &tp);
+
+       fprintf(stdout, "Enter twitter password: ");
+       fflush(stdout);
+       scanf("%79s", pwd);
+       fprintf(stdout, "\n");
+
+       tcsetattr(0, TCSANOW, &old);
+
+       strncpy(buf, pwd, len);
+       buf[len-1] = '\0';
+}
+
 static int find_urls(const char *tweet, int **pranges)
 {
        /*
 static int find_urls(const char *tweet, int **pranges)
 {
        /*
@@ -909,6 +952,7 @@ int main(int argc, char *argv[], char *envp[])
                { "proxy", 1, NULL, 'P' },
                { "action", 1, NULL, 'A' },
                { "user", 1, NULL, 'u' },
                { "proxy", 1, NULL, 'P' },
                { "action", 1, NULL, 'A' },
                { "user", 1, NULL, 'u' },
+               { "group", 1, NULL, 'G' },
                { "logfile", 1, NULL, 'L' },
                { "shrink-urls", 0, NULL, 's' },
                { "help", 0, NULL, 'h' },
                { "logfile", 1, NULL, 'L' },
                { "shrink-urls", 0, NULL, 's' },
                { "help", 0, NULL, 'h' },
@@ -921,6 +965,7 @@ int main(int argc, char *argv[], char *envp[])
        struct session *session;
        pid_t child;
        char *tweet;
        struct session *session;
        pid_t child;
        char *tweet;
+       static char password[80];
        int retval = 0;
        int option;
        char *http_proxy;
        int retval = 0;
        int option;
        char *http_proxy;
@@ -959,7 +1004,7 @@ int main(int argc, char *argv[], char *envp[])
        parse_configfile(session);
 
        while (1) {
        parse_configfile(session);
 
        while (1) {
-               option = getopt_long_only(argc, argv, "dp:P:H:a:A:u:hg:snVv",
+               option = getopt_long_only(argc, argv, "dp:P:H:a:A:u:hg:G:snVv",
                                          options, NULL);
                if (option == -1)
                        break;
                                          options, NULL);
                if (option == -1)
                        break;
@@ -1004,6 +1049,8 @@ int main(int argc, char *argv[], char *envp[])
                                session->action = ACTION_REPLIES;
                        else if (strcasecmp(optarg, "public") == 0)
                                session->action = ACTION_PUBLIC;
                                session->action = ACTION_REPLIES;
                        else if (strcasecmp(optarg, "public") == 0)
                                session->action = ACTION_PUBLIC;
+                       else if (strcasecmp(optarg, "group") == 0)
+                               session->action = ACTION_GROUP;
                        else
                                session->action = ACTION_UNKNOWN;
                        dbg("action = %d\n", session->action);
                        else
                                session->action = ACTION_UNKNOWN;
                        dbg("action = %d\n", session->action);
@@ -1014,6 +1061,13 @@ int main(int argc, char *argv[], char *envp[])
                        session->user = strdup(optarg);
                        dbg("user = %s\n", session->user);
                        break;
                        session->user = strdup(optarg);
                        dbg("user = %s\n", session->user);
                        break;
+
+               case 'G':
+                       if (session->group)
+                               free(session->group);
+                       session->group = strdup(optarg);
+                       dbg("group = %s\n", session->group);
+                       break;
                case 'L':
                        if (session->logfile)
                                free(session->logfile);
                case 'L':
                        if (session->logfile)
                                free(session->logfile);
@@ -1060,24 +1114,36 @@ int main(int argc, char *argv[], char *envp[])
         * Show the version to make it easier to determine what
         * is going on here
         */
         * Show the version to make it easier to determine what
         * is going on here
         */
-       if (debug)
+       if (debug) {
                display_version();
                display_version();
+               fprintf(stderr, "%s", session->group);
+       }
 
        if (session->action == ACTION_UNKNOWN) {
                fprintf(stderr, "Unknown action, valid actions are:\n");
                fprintf(stderr, "'update', 'friends', 'public', "
 
        if (session->action == ACTION_UNKNOWN) {
                fprintf(stderr, "Unknown action, valid actions are:\n");
                fprintf(stderr, "'update', 'friends', 'public', "
-                       "'replies' or 'user'.\n");
+                       "'replies', 'group' or 'user'.\n");
+               goto exit;
+       }
+
+       if (session->host == HOST_TWITTER && session->action == ACTION_GROUP) {
+               fprintf(stderr, "Groups only work in Identi.ca.\n");
                goto exit;
        }
 
                goto exit;
        }
 
+       if (session->action == ACTION_GROUP && !session->group) {
+               fprintf(stdout, "Enter group name: ");
+               session->group = readline(NULL);
+       }
+
        if (!session->account) {
                fprintf(stdout, "Enter twitter account: ");
                session->account = readline(NULL);
        }
 
        if (!session->password) {
        if (!session->account) {
                fprintf(stdout, "Enter twitter account: ");
                session->account = readline(NULL);
        }
 
        if (!session->password) {
-               fprintf(stdout, "Enter twitter password: ");
-               session->password = readline(NULL);
+               read_password(password, sizeof(password));
+               session->password = strdup(password);
        }
 
        if (session->action == ACTION_UPDATE) {
        }
 
        if (session->action == ACTION_UPDATE) {
@@ -1095,7 +1161,8 @@ int main(int argc, char *argv[], char *envp[])
 
                session->tweet = zalloc(strlen(tweet) + 10);
                if (session->bash)
 
                session->tweet = zalloc(strlen(tweet) + 10);
                if (session->bash)
-                       sprintf(session->tweet, "%c %s", getuid() ? '$' : '#', tweet);
+                       sprintf(session->tweet, "%c %s",
+                               getuid() ? '$' : '#', tweet);
                else
                        sprintf(session->tweet, "%s", tweet);
 
                else
                        sprintf(session->tweet, "%s", tweet);