/[debian]/bti/branches/upstream/current/bti.c
ViewVC logotype

Diff of /bti/branches/upstream/current/bti.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1985 by gregoa, Wed Dec 2 15:43:36 2009 UTC revision 1986 by gregoa, Sun Jan 10 00:18:24 2010 UTC
# Line 33  Line 33 
33  #include <sys/types.h>  #include <sys/types.h>
34  #include <sys/wait.h>  #include <sys/wait.h>
35  #include <curl/curl.h>  #include <curl/curl.h>
 #include <readline/readline.h>  
36  #include <libxml/xmlmemory.h>  #include <libxml/xmlmemory.h>
37  #include <libxml/parser.h>  #include <libxml/parser.h>
38  #include <libxml/tree.h>  #include <libxml/tree.h>
39  #include <pcre.h>  #include <pcre.h>
40  #include <termios.h>  #include <termios.h>
41    #include <dlfcn.h>
42    
43    
44  #define zalloc(size)    calloc(size, 1)  #define zalloc(size)    calloc(size, 1)
# Line 81  struct session { Line 81  struct session {
81          char *user;          char *user;
82          char *group;          char *group;
83          char *hosturl;          char *hosturl;
84            char *hostname;
85          int bash;          int bash;
86          int shrink_urls;          int shrink_urls;
87          int dry_run;          int dry_run;
88          int page;          int page;
89          enum host host;          enum host host;
90          enum action action;          enum action action;
91            void *readline_handle;
92            char *(*readline)(const char *);
93  };  };
94    
95  struct bti_curl_buffer {  struct bti_curl_buffer {
# Line 127  static void display_version(void) Line 130  static void display_version(void)
130          fprintf(stdout, "bti - version %s\n", VERSION);          fprintf(stdout, "bti - version %s\n", VERSION);
131  }  }
132    
133    static char *get_string(const char *name)
134    {
135            char *temp;
136            char *string;
137    
138            string = zalloc(1000);
139            if (!string)
140                    exit(1);
141            if (name != NULL)
142                    fprintf(stdout, "%s", name);
143            if (!fgets(string, 999, stdin))
144                    return NULL;
145            temp = strchr(string, '\n');
146            *temp = '\0';
147            return string;
148    }
149    
150    /*
151     * Try to get a handle to a readline function from a variety of different
152     * libraries.  If nothing is present on the system, then fall back to an
153     * internal one.
154     *
155     * Logic originally based off of code in the e2fsutils package in the
156     * lib/ss/get_readline.c file, which is licensed under the MIT license.
157     *
158     * This keeps us from having to relicense the bti codebase if readline
159     * ever changes its license, as there is no link-time dependancy.
160     * It is a run-time thing only, and we handle any readline-like library
161     * in the same manner, making bti not be a derivative work of any
162     * other program.
163     */
164    static void session_readline_init(struct session *session)
165    {
166            /* Libraries we will try to use for readline/editline functionality */
167            const char *libpath = "libreadline.so.6:libreadline.so.5:"
168                                    "libreadline.so.4:libreadline.so:libedit.so.2:"
169                                    "libedit.so:libeditline.so.0:libeditline.so";
170            void *handle = NULL;
171            char *tmp, *cp, *next;
172            int (*bind_key)(int, void *);
173            void (*insert)(void);
174    
175            /* default to internal function if we can't find anything */
176            session->readline = get_string;
177    
178            tmp = malloc(strlen(libpath)+1);
179            if (!tmp)
180                    return;
181            strcpy(tmp, libpath);
182            for (cp = tmp; cp; cp = next) {
183                    next = strchr(cp, ':');
184                    if (next)
185                            *next++ = 0;
186                    if (*cp == 0)
187                            continue;
188                    if ((handle = dlopen(cp, RTLD_NOW))) {
189                            dbg("Using %s for readline library\n", cp);
190                            break;
191                    }
192            }
193            free(tmp);
194            if (!handle) {
195                    dbg("No readline library found.\n");
196                    return;
197            }
198    
199            session->readline_handle = handle;
200            session->readline = (char *(*)(const char *))dlsym(handle, "readline");
201            if (session->readline == NULL) {
202                    /* something odd happened, default back to internal stuff */
203                    session->readline_handle = NULL;
204                    session->readline = get_string;
205                    return;
206            }
207    
208            /*
209             * If we found a library, turn off filename expansion
210             * as that makes no sense from within bti.
211             */
212            bind_key = (int (*)(int, void *))dlsym(handle, "rl_bind_key");
213            insert = (void (*)(void))dlsym(handle, "rl_insert");
214            if (bind_key && insert)
215                    bind_key('\t', insert);
216    }
217    
218    static void session_readline_cleanup(struct session *session)
219    {
220            if (session->readline_handle)
221                    dlclose(session->readline_handle);
222    }
223    
224  static struct session *session_alloc(void)  static struct session *session_alloc(void)
225  {  {
226          struct session *session;          struct session *session;
# Line 134  static struct session *session_alloc(voi Line 228  static struct session *session_alloc(voi
228          session = zalloc(sizeof(*session));          session = zalloc(sizeof(*session));
229          if (!session)          if (!session)
230                  return NULL;                  return NULL;
231            session_readline_init(session);
232          return session;          return session;
233  }  }
234    
# Line 141  static void session_free(struct session Line 236  static void session_free(struct session
236  {  {
237          if (!session)          if (!session)
238                  return;                  return;
239            session_readline_cleanup(session);
240          free(session->password);          free(session->password);
241          free(session->account);          free(session->account);
242          free(session->tweet);          free(session->tweet);
# Line 150  static void session_free(struct session Line 246  static void session_free(struct session
246          free(session->user);          free(session->user);
247          free(session->group);          free(session->group);
248          free(session->hosturl);          free(session->hosturl);
249            free(session->hostname);
250          free(session);          free(session);
251  }  }
252    
# Line 183  static void bti_curl_buffer_free(struct Line 280  static void bti_curl_buffer_free(struct
280    
281  static const char *twitter_host  = "https://twitter.com/statuses";  static const char *twitter_host  = "https://twitter.com/statuses";
282  static const char *identica_host = "https://identi.ca/api/statuses";  static const char *identica_host = "https://identi.ca/api/statuses";
283    static const char *twitter_name  = "twitter";
284    static const char *identica_name = "identi.ca";
285    
286  static const char *user_uri    = "/user_timeline/";  static const char *user_uri    = "/user_timeline/";
287  static const char *update_uri  = "/update.xml";  static const char *update_uri  = "/update.xml";
# Line 338  static int send_request(struct session * Line 437  static int send_request(struct session *
437          if (!curl)          if (!curl)
438                  return -EINVAL;                  return -EINVAL;
439    
440            if (!session->hosturl)
441                    session->hosturl = strdup(twitter_host);
442    
443          switch (session->action) {          switch (session->action) {
444          case ACTION_UPDATE:          case ACTION_UPDATE:
445                  snprintf(user_password, sizeof(user_password), "%s:%s",                  snprintf(user_password, sizeof(user_password), "%s:%s",
# Line 532  static void parse_configfile(struct sess Line 634  static void parse_configfile(struct sess
634                  if (strcasecmp(host, "twitter") == 0) {                  if (strcasecmp(host, "twitter") == 0) {
635                          session->host = HOST_TWITTER;                          session->host = HOST_TWITTER;
636                          session->hosturl = strdup(twitter_host);                          session->hosturl = strdup(twitter_host);
637                            session->hostname = strdup(twitter_name);
638                  } else if (strcasecmp(host, "identica") == 0) {                  } else if (strcasecmp(host, "identica") == 0) {
639                          session->host = HOST_IDENTICA;                          session->host = HOST_IDENTICA;
640                          session->hosturl = strdup(identica_host);                          session->hosturl = strdup(identica_host);
641                            session->hostname = strdup(identica_name);
642                  } else {                  } else {
643                          session->host = HOST_CUSTOM;                          session->host = HOST_CUSTOM;
644                          session->hosturl = strdup(host);                          session->hosturl = strdup(host);
645                            session->hostname = strdup(host);
646                  }                  }
647                  free(host);                  free(host);
648          }          }
# Line 578  static void log_session(struct session * Line 683  static void log_session(struct session *
683  {  {
684          FILE *log_file;          FILE *log_file;
685          char *filename;          char *filename;
         char *host;  
686    
687          /* Only log something if we have a log file set */          /* Only log something if we have a log file set */
688          if (!session->logfile)          if (!session->logfile)
# Line 592  static void log_session(struct session * Line 696  static void log_session(struct session *
696          log_file = fopen(filename, "a+");          log_file = fopen(filename, "a+");
697          if (log_file == NULL)          if (log_file == NULL)
698                  return;                  return;
         switch (session->host) {  
         case HOST_TWITTER:  
                 host = "twitter";  
                 break;  
         case HOST_IDENTICA:  
                 host = "identi.ca";  
                 break;  
         default:  
                 host = session->hosturl;  
                 break;  
         }  
699    
700          switch (session->action) {          switch (session->action) {
701          case ACTION_UPDATE:          case ACTION_UPDATE:
702                  if (retval)                  if (retval)
703                          fprintf(log_file, "%s: host=%s tweet failed\n",                          fprintf(log_file, "%s: host=%s tweet failed\n",
704                                  session->time, host);                                  session->time, session->hostname);
705                  else                  else
706                          fprintf(log_file, "%s: host=%s tweet=%s\n",                          fprintf(log_file, "%s: host=%s tweet=%s\n",
707                                  session->time, host, session->tweet);                                  session->time, session->hostname, session->tweet);
708                  break;                  break;
709          case ACTION_FRIENDS:          case ACTION_FRIENDS:
710                  fprintf(log_file, "%s: host=%s retrieving friends timeline\n",                  fprintf(log_file, "%s: host=%s retrieving friends timeline\n",
711                          session->time, host);                          session->time, session->hostname);
712                  break;                  break;
713          case ACTION_USER:          case ACTION_USER:
714                  fprintf(log_file, "%s: host=%s retrieving %s's timeline\n",                  fprintf(log_file, "%s: host=%s retrieving %s's timeline\n",
715                          session->time, host, session->user);                          session->time, session->hostname, session->user);
716                  break;                  break;
717          case ACTION_REPLIES:          case ACTION_REPLIES:
718                  fprintf(log_file, "%s: host=%s retrieving replies\n",                  fprintf(log_file, "%s: host=%s retrieving replies\n",
719                          session->time, host);                          session->time, session->hostname);
720                  break;                  break;
721          case ACTION_PUBLIC:          case ACTION_PUBLIC:
722                  fprintf(log_file, "%s: host=%s retrieving public timeline\n",                  fprintf(log_file, "%s: host=%s retrieving public timeline\n",
723                          session->time, host);                          session->time, session->hostname);
724                  break;                  break;
725          case ACTION_GROUP:          case ACTION_GROUP:
726                  fprintf(log_file, "%s: host=%s retrieving group timeline\n",                  fprintf(log_file, "%s: host=%s retrieving group timeline\n",
727                          session->time, host);                          session->time, session->hostname);
728                  break;                  break;
729          default:          default:
730                  break;                  break;
# Line 656  static char *get_string_from_stdin(void) Line 749  static char *get_string_from_stdin(void)
749          return string;          return string;
750  }  }
751    
752  static void read_password(char *buf, size_t len)  static void read_password(char *buf, size_t len, char *host)
753  {  {
754          char pwd[80];          char pwd[80];
755          int retval;          int retval;
# Line 669  static void read_password(char *buf, siz Line 762  static void read_password(char *buf, siz
762          tp.c_lflag &= (~ECHO);          tp.c_lflag &= (~ECHO);
763          tcsetattr(0, TCSANOW, &tp);          tcsetattr(0, TCSANOW, &tp);
764    
765          fprintf(stdout, "Enter twitter password: ");          fprintf(stdout, "Enter password for %s: ", host);
766          fflush(stdout);          fflush(stdout);
767          tcflow(0, TCOOFF);          tcflow(0, TCOOFF);
768          retval = scanf("%79s", pwd);          retval = scanf("%79s", pwd);
# Line 977  int main(int argc, char *argv[], char *e Line 1070  int main(int argc, char *argv[], char *e
1070    
1071          debug = 0;          debug = 0;
1072          verbose = 0;          verbose = 0;
         rl_bind_key('\t', rl_insert);  
1073    
1074          session = session_alloc();          session = session_alloc();
1075          if (!session) {          if (!session) {
# Line 1083  int main(int argc, char *argv[], char *e Line 1175  int main(int argc, char *argv[], char *e
1175                  case 'H':                  case 'H':
1176                          if (session->hosturl)                          if (session->hosturl)
1177                                  free(session->hosturl);                                  free(session->hosturl);
1178                            if (session->hostname)
1179                                    free(session->hostname);
1180                          if (strcasecmp(optarg, "twitter") == 0) {                          if (strcasecmp(optarg, "twitter") == 0) {
1181                                  session->host = HOST_TWITTER;                                  session->host = HOST_TWITTER;
1182                                  session->hosturl = strdup(twitter_host);                                  session->hosturl = strdup(twitter_host);
1183                                    session->hostname = strdup(twitter_name);
1184                          } else if (strcasecmp(optarg, "identica") == 0) {                          } else if (strcasecmp(optarg, "identica") == 0) {
1185                                  session->host = HOST_IDENTICA;                                  session->host = HOST_IDENTICA;
1186                                  session->hosturl = strdup(identica_host);                                  session->hosturl = strdup(identica_host);
1187                                    session->hostname = strdup(identica_name);
1188                          } else {                          } else {
1189                                  session->host = HOST_CUSTOM;                                  session->host = HOST_CUSTOM;
1190                                  session->hosturl = strdup(optarg);                                  session->hosturl = strdup(optarg);
1191                                    session->hostname = strdup(optarg);
1192                          }                          }
1193                          dbg("host = %d\n", session->host);                          dbg("host = %d\n", session->host);
1194                          break;                          break;
# Line 1134  int main(int argc, char *argv[], char *e Line 1231  int main(int argc, char *argv[], char *e
1231    
1232          if (session->action == ACTION_GROUP && !session->group) {          if (session->action == ACTION_GROUP && !session->group) {
1233                  fprintf(stdout, "Enter group name: ");                  fprintf(stdout, "Enter group name: ");
1234                  session->group = readline(NULL);                  session->group = session->readline(NULL);
1235          }          }
1236    
1237          if (!session->account) {          if (!session->account) {
1238                  fprintf(stdout, "Enter twitter account: ");                  fprintf(stdout, "Enter account for %s: ", session->hostname);
1239                  session->account = readline(NULL);                  session->account = session->readline(NULL);
1240          }          }
1241    
1242          if (!session->password) {          if (!session->password) {
1243                  read_password(password, sizeof(password));                  read_password(password, sizeof(password), session->hostname);
1244                  session->password = strdup(password);                  session->password = strdup(password);
1245          }          }
1246    
# Line 1151  int main(int argc, char *argv[], char *e Line 1248  int main(int argc, char *argv[], char *e
1248                  if (session->bash)                  if (session->bash)
1249                          tweet = get_string_from_stdin();                          tweet = get_string_from_stdin();
1250                  else                  else
1251                          tweet = readline("tweet: ");                          tweet = session->readline("tweet: ");
1252                  if (!tweet || strlen(tweet) == 0) {                  if (!tweet || strlen(tweet) == 0) {
1253                          dbg("no tweet?\n");                          dbg("no tweet?\n");
1254                          return -1;                          return -1;

Legend:
Removed from v.1985  
changed lines
  Added in v.1986

  ViewVC Help
Powered by ViewVC 1.1.26