coding style cleanups
[gregoa/bti.git] / bti.c
diff --git a/bti.c b/bti.c
index ea464f1..3bcf055 100644 (file)
--- a/bti.c
+++ b/bti.c
 #include <ctype.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <time.h>
 #include <sys/stat.h>
 #include <curl/curl.h>
+#include <readline/readline.h>
 #include "bti_version.h"
 
 
 #define dbg(format, arg...)                                            \
        do {                                                            \
                if (debug)                                              \
-                       printf("%s: " format , __func__ , ## arg );     \
+                       printf("%s: " format , __func__ , ## arg);      \
        } while (0)
 
 
-static int debug = 0;
+static int debug;
 
 enum host {
        HOST_TWITTER = 0,
@@ -49,6 +51,10 @@ struct session {
        char *password;
        char *account;
        char *tweet;
+       char *proxy;
+       char *time;
+       char *homedir;
+       char *logfile;
        int bash;
        enum host host;
 };
@@ -67,7 +73,9 @@ static void display_help(void)
        fprintf(stdout, "options are:\n");
        fprintf(stdout, "  --account accountname\n");
        fprintf(stdout, "  --password password\n");
+       fprintf(stdout, "  --proxy PROXY:PORT\n");
        fprintf(stdout, "  --host HOST\n");
+       fprintf(stdout, "  --logfile logfile\n");
        fprintf(stdout, "  --bash\n");
        fprintf(stdout, "  --debug\n");
        fprintf(stdout, "  --version\n");
@@ -81,17 +89,14 @@ static void display_version(void)
 
 static char *get_string_from_stdin(void)
 {
-       char *temp;
-       char *string;
+       static char *string = (char *)NULL;
+       if (string) {
+               free(string);
+               string = (char *)NULL;
+       }
 
-       string = zalloc(1000);
-       if (!string)
-               return NULL;
+       string = readline("tweet: ");
 
-       if (!fgets(string, 999, stdin))
-               return NULL;
-       temp = strchr(string, '\n');
-       *temp = '\0';
        return string;
 }
 
@@ -112,6 +117,9 @@ static void session_free(struct session *session)
        free(session->password);
        free(session->account);
        free(session->tweet);
+       free(session->proxy);
+       free(session->time);
+       free(session->homedir);
        free(session);
 }
 
@@ -194,6 +202,7 @@ static int send_tweet(struct session *session)
        CURLcode res;
        struct curl_httppost *formpost = NULL;
        struct curl_httppost *lastptr = NULL;
+       struct curl_slist *slist = NULL;
 
        if (!session)
                return -EINVAL;
@@ -215,23 +224,38 @@ static int send_tweet(struct session *session)
                     CURLFORM_COPYCONTENTS, session->tweet,
                     CURLFORM_END);
 
+       curl_formadd(&formpost, &lastptr,
+                    CURLFORM_COPYNAME, "source",
+                    CURLFORM_COPYCONTENTS, "bti",
+                    CURLFORM_END);
+
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
 
        switch (session->host) {
        case HOST_TWITTER:
                curl_easy_setopt(curl, CURLOPT_URL, twitter_url);
+               /*
+                * twitter doesn't like the "Expect: 100-continue" header
+                * anymore, so turn it off.
+                */
+               slist = curl_slist_append(slist, "Expect:");
+               curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
                break;
        case HOST_IDENTICA:
                curl_easy_setopt(curl, CURLOPT_URL, identica_url);
                break;
        }
 
+       if (session->proxy)
+               curl_easy_setopt(curl, CURLOPT_PROXY, session->proxy);
+
        if (debug)
                curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
 
        dbg("user_password = %s\n", user_password);
        dbg("data = %s\n", data);
+       dbg("proxy = %s\n", session->proxy);
 
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl_buf);
@@ -255,13 +279,14 @@ static void parse_configfile(struct session *session)
        char *account = NULL;
        char *password = NULL;
        char *host = NULL;
+       char *proxy = NULL;
+       char *logfile = NULL;
        char *file;
-       char *home = getenv("HOME");
 
        /* config file is ~/.bti  */
-       file = alloca(strlen(home) + 7);
+       file = alloca(strlen(session->homedir) + 7);
 
-       sprintf(file, "%s/.bti", home);
+       sprintf(file, "%s/.bti", session->homedir);
 
        config_file = fopen(file, "r");
 
@@ -302,6 +327,16 @@ static void parse_configfile(struct session *session)
                        c += 5;
                        if (c[0] != '\0')
                                host = strdup(c);
+               } else if (!strncasecmp(c, "proxy", 5) &&
+                          (c[5] == '=')) {
+                       c += 6;
+                       if (c[0] != '\0')
+                               proxy = strdup(c);
+               } else if (!strncasecmp(c, "logfile", 7) &&
+                          (c[7] == '=')) {
+                       c += 8;
+                       if (c[0] != '\0')
+                               logfile = strdup(c);
                }
        } while (!feof(config_file));
 
@@ -316,12 +351,59 @@ static void parse_configfile(struct session *session)
                        session->host = HOST_IDENTICA;
                free(host);
        }
+       if (proxy) {
+               if (session->proxy)
+                       free(session->proxy);
+               session->proxy = proxy;
+       }
+       if (logfile)
+               session->logfile = logfile;
 
        /* Free buffer and close file.  */
        free(line);
        fclose(config_file);
 }
 
+static void log_session(struct session *session, int retval)
+{
+       FILE *log_file;
+       char *filename;
+       char *host;
+
+       /* Only log something if we have a log file set */
+       if (!session->logfile)
+               return;
+
+       filename = alloca(strlen(session->homedir) +
+                         strlen(session->logfile) + 3);
+
+       sprintf(filename, "%s/%s", session->homedir, session->logfile);
+
+       log_file = fopen(filename, "a+");
+       if (log_file == NULL)
+               return;
+       switch (session->host) {
+       case HOST_TWITTER:
+               host = "twitter";
+               break;
+       case HOST_IDENTICA:
+               host = "identi.ca";
+               break;
+       default:
+               host = "unknown";
+               break;
+       }
+
+       if (retval)
+               fprintf(log_file, "%s: host=%s tweet failed\n",
+                       session->time, host);
+       else
+               fprintf(log_file, "%s: host=%s tweet=%s\n",
+                       session->time, host, session->tweet);
+
+       fclose(log_file);
+}
+
 int main(int argc, char *argv[], char *envp[])
 {
        static const struct option options[] = {
@@ -329,6 +411,8 @@ int main(int argc, char *argv[], char *envp[])
                { "account", 1, NULL, 'a' },
                { "password", 1, NULL, 'p' },
                { "host", 1, NULL, 'H' },
+               { "proxy", 1, NULL, 'P' },
+               { "logfile", 1, NULL, 'L' },
                { "help", 0, NULL, 'h' },
                { "bash", 0, NULL, 'b' },
                { "version", 0, NULL, 'v' },
@@ -337,24 +421,43 @@ int main(int argc, char *argv[], char *envp[])
        struct session *session;
        pid_t child;
        char *tweet;
-       int retval;
+       int retval = 0;
        int option;
-#if 0
-       char *home = getenv("HOME");
-       char *pwd = getenv("PWD");
-       char *dir;
-#endif
+       char *http_proxy;
+       time_t t;
+
+       debug = 0;
+       rl_bind_key('\t', rl_insert);
+
        session = session_alloc();
        if (!session) {
                fprintf(stderr, "no more memory...\n");
                return -1;
        }
 
+       /* get the current time so that we can log it later */
+       time(&t);
+       session->time = strdup(ctime(&t));
+       session->time[strlen(session->time)-1] = 0x00;
+
+       session->homedir = strdup(getenv("HOME"));
+
        curl_global_init(CURL_GLOBAL_ALL);
+
+       /* Set environment variables first, before reading command line options
+        * or config file values. */
+       http_proxy = getenv("http_proxy");
+       if (http_proxy) {
+               if (session->proxy)
+                       free(session->proxy);
+               session->proxy = strdup(http_proxy);
+               dbg("http_proxy = %s\n", session->proxy);
+       }
+
        parse_configfile(session);
 
        while (1) {
-               option = getopt_long_only(argc, argv, "dqe:p:H:a:h",
+               option = getopt_long_only(argc, argv, "dqe:p:P:H:a:h",
                                          options, NULL);
                if (option == -1)
                        break;
@@ -374,6 +477,18 @@ int main(int argc, char *argv[], char *envp[])
                        session->password = strdup(optarg);
                        dbg("password = %s\n", session->password);
                        break;
+               case 'P':
+                       if (session->proxy)
+                               free(session->proxy);
+                       session->proxy = strdup(optarg);
+                       dbg("proxy = %s\n", session->proxy);
+                       break;
+               case 'L':
+                       if (session->logfile)
+                               free(session->logfile);
+                       session->logfile = strdup(optarg);
+                       dbg("logfile = %s\n", session->logfile);
+                       break;
                case 'H':
                        if (strcasecmp(optarg, "twitter") == 0)
                                session->host = HOST_TWITTER;
@@ -382,7 +497,7 @@ int main(int argc, char *argv[], char *envp[])
                        dbg("host = %d\n", session->host);
                        break;
                case 'b':
-                       session->bash= 1;
+                       session->bash = 1;
                        break;
                case 'h':
                        display_help();
@@ -405,31 +520,18 @@ int main(int argc, char *argv[], char *envp[])
                fprintf(stdout, "Enter twitter password: ");
                session->password = get_string_from_stdin();
        }
-#if 0
-       /* get the current working directory basename */
-       if (strcmp(pwd, home) == 0)
-               dir = "~";
-       else {
-               dir = strrchr(pwd, '/');
-               if (dir)
-                       dir++;
-               else
-                       dir = "?";
-       }
-#endif
+
        tweet = get_string_from_stdin();
-       if (strlen(tweet) == 0) {
+       if (!tweet || strlen(tweet) == 0) {
                dbg("no tweet?\n");
                return -1;
        }
 
-//     session->tweet = zalloc(strlen(tweet) + strlen(dir) + 10);
        session->tweet = zalloc(strlen(tweet) + 10);
 
        /* if --bash is specified, add the "PWD $ " to
         * the start of the tweet. */
        if (session->bash)
-//             sprintf(session->tweet, "%s $ %s", dir, tweet);
                sprintf(session->tweet, "$ %s", tweet);
        else
                sprintf(session->tweet, "%s", tweet);
@@ -452,12 +554,11 @@ int main(int argc, char *argv[], char *envp[])
        }
 
        retval = send_tweet(session);
-       if (retval && !session->bash) {
+       if (retval && !session->bash)
                fprintf(stderr, "tweet failed\n");
-               return -1;
-       }
 
-       session_free(session);
+       log_session(session, retval);
 exit:
-       return 0;
+       session_free(session);
+       return retval;;
 }