m4ly

C Yahoo Quotes

Jul 24th, 2013
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.54 KB | None | 0 0
  1. /*
  2. C Yahoo Quotes 0.1 alpha version
  3.  
  4. Req.: libmysql(MySQL), libcurl
  5. Compilation: gcc `mysql_config --libs --cflags` `curl-config --libs --cflags`  cyahooquotes.c  -o cyahooquotes
  6.  
  7. Copyright (C) 2013 Dawid Mocek <dawid.mocek@gmail.com>
  8.  
  9. This program is free software; you can redistribute it and/or
  10. modify it under the terms of the GNU General Public License
  11. as published by the Free Software Foundation; either version 2
  12. of the License, or (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  22.  
  23. */
  24.  
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <curl/curl.h>
  29. #include <time.h>
  30. #include <my_global.h>
  31. #include <mysql.h>
  32.  
  33. #define YH_MAX_SYMBOLS      10000
  34. #define YH_BASE_URL     "http://download.finance.yahoo.com/d/quotes.csv?"
  35. #define YH_S_PARAM_GLUE     "+"
  36. #define YH_S_PARAM_NAME     "&s="
  37. #define YH_F_PARAM_NAME     "f="
  38.  
  39. #define MYSQL_DB        "dawid_market"
  40. #define MYSQL_HOST      "localhost"
  41. #define MYSQL_USER      "dawid"
  42. #define MYSQL_PASS      ""
  43. #define MYSQL_QUERY     "SELECT symbol_from_db(ticker, companyname) FROM market_data WHERE type != 'Test'"
  44.  
  45. int read_symbols_from_file(char *symbols_filename, char ***symbols_arr);
  46. void perror_exit_failure(const char *mesg);
  47. void sql_exit_failure(MYSQL *con);
  48. void sql_free_res(MYSQL_RES *result);
  49.  
  50. typedef struct CURLResult
  51. {
  52.         char *memory;
  53.         size_t size;
  54. };
  55.  
  56.  
  57. void sql_free_res(MYSQL_RES *result)
  58. {
  59.     mysql_free_result(result);
  60. }
  61.  
  62. static int add_symbols_to_list_sql(MYSQL_RES *result, MYSQL *con, struct curl_slist **slist)
  63. {
  64.     if(result == NULL)
  65.     {
  66.     sql_exit_failure(con);
  67.     }
  68.     MYSQL_ROW row;
  69.     int cnt = 0;
  70.     int num = mysql_num_fields(result);
  71.     while((row = mysql_fetch_row(result)))
  72.     {
  73.     int i;
  74.     for(i = 0; i < num; i++)
  75.     {
  76.         //printf("%d, %s\n", cnt, row[i]);
  77.         *slist = curl_slist_append(*slist, row[i]);
  78.     }
  79.     cnt++;
  80.     }
  81.     sql_free_res(result);
  82.     return cnt;
  83. }
  84.  
  85. void sql_con(MYSQL *con, const char *host, const char *db, const char *user, const char *pass)
  86. {
  87.     if(mysql_real_connect(con, host, user, pass, db, 0, NULL, 0) == NULL)
  88.     {
  89.     sql_exit_failure(con);
  90.     }
  91. }
  92.  
  93. MYSQL_RES *sql_query(MYSQL *con, const char *query)
  94. {
  95.     if(mysql_query(con, query))
  96.     {
  97.     sql_exit_failure(con);
  98.     }
  99.     MYSQL_RES *result;
  100.     result = mysql_store_result(con);
  101.    
  102.     return result;
  103. }
  104.  
  105. void sql_close(MYSQL *con)
  106. {
  107.     mysql_close(con);
  108. }
  109.  
  110. void sql_exit_failure(MYSQL *con)
  111. {
  112.     fprintf(stderr, "%s\n", mysql_error(con));
  113.     mysql_close(con);
  114.     exit(EXIT_FAILURE);
  115.  
  116. }
  117. /*
  118. Function reads symbols from file to dynamic array
  119. */
  120. static int add_symbols_to_list_file(const char *symbols_filename, struct curl_slist **slist)
  121. {  
  122.  
  123.     FILE *symbols_file = fopen(symbols_filename, "r");
  124.     if(!symbols_file)
  125.     {
  126.     printf("Error occured while opening file: %s\n", symbols_filename);
  127.     exit(EXIT_FAILURE);
  128.     }
  129.  
  130.     char buffLine[BUFSIZ];
  131.     int cnt = 0;
  132.     /* Read line by line */
  133.     while(fgets(buffLine, sizeof(buffLine), symbols_file))
  134.     {
  135.     if(cnt >= YH_MAX_SYMBOLS)
  136.         break;
  137.    
  138.     char *symbol = strchr(buffLine,'\n');
  139.     if(symbol) *symbol = 0;
  140.     symbol = strdup(buffLine);
  141.  
  142.     // Add new symbol to list
  143.     *slist = curl_slist_append(*slist, symbol);
  144.     free(symbol);
  145.     cnt++;
  146.     }
  147.    
  148.     fclose(symbols_file);
  149.     return cnt;
  150. }
  151.  
  152. char *construct_s_param(struct curl_slist *symbols_list)
  153. {
  154.     char *s_param = (char*)malloc(sizeof(char));
  155.     s_param[0]  = '\0';
  156.     int len = 0;
  157.    
  158.     while(symbols_list != NULL)
  159.     {
  160.         len =  strlen(s_param) + strlen(symbols_list->data) + strlen((char*)YH_S_PARAM_GLUE) + 1;
  161.    
  162.         char *s_param_tmp = (char*)realloc(s_param,  len * sizeof(char));
  163.         if(!s_param_tmp)
  164.         {
  165.         free(s_param_tmp);
  166.         perror("Not enough memory [ Function: construct_s_param() Var: s_param_tmp ]\n");
  167.         exit(EXIT_FAILURE);
  168.         }
  169.         s_param = s_param_tmp;
  170.         strcat(s_param, symbols_list->data);
  171.         strcat(s_param, (char*)YH_S_PARAM_GLUE);
  172.    
  173.         symbols_list = symbols_list->next;
  174.     }
  175.     s_param[len-2] = '\0';
  176.     return s_param;
  177. }
  178.  
  179. char *construct_url(const char *f_param, const char *s_param)
  180. {
  181.  
  182.     char *full_url = (char*)malloc(((strlen((const char*)YH_BASE_URL) + strlen(s_param) + strlen((const char*)YH_F_PARAM_NAME) + strlen((const char*)YH_S_PARAM_NAME) + strlen(f_param))) * sizeof(char*));
  183.     if(!full_url)
  184.     {
  185.         free(full_url);
  186.         perror_exit_failure("Memory allocation failure. [ Function: construct_url() Var: full_url ]\n");
  187.     }
  188.     strcpy(full_url, (const char*)YH_BASE_URL);
  189.     strcat(full_url, (const char*)YH_F_PARAM_NAME);
  190.     strcat(full_url, f_param);
  191.     strcat(full_url, (const char*)YH_S_PARAM_NAME);
  192.     strcat(full_url, s_param);
  193.  
  194.     return full_url;
  195. }
  196.  
  197. void  perror_exit_failure(const char *mesg)
  198. {
  199.     perror(mesg);
  200.     exit(EXIT_FAILURE);
  201. }
  202.  
  203. int construct_urls_list(struct curl_slist *symbols_list, struct curl_slist **urls_list, const char *f_param)
  204. {
  205.     int i = 1;
  206.     int urls_list_size = 0;
  207.     struct curl_slist *list_temp = NULL;
  208.  
  209.     while(symbols_list != NULL)
  210.     {
  211.  
  212.     list_temp = curl_slist_append(list_temp, symbols_list->data);
  213.     if(!list_temp)
  214.         perror_exit_failure("Memory allocation failure. [ Function: construct_urls_list() Var: list_temp ]\n");
  215.    
  216.     if(i % 200 == 0)
  217.     {
  218.         char *s_param = construct_s_param(list_temp);
  219.         char *url =  construct_url(f_param, s_param);
  220.        
  221.         *urls_list = curl_slist_append(*urls_list, url);
  222.  
  223.         if(!urls_list)
  224.         perror_exit_failure("Memory allocation failure. [ Function: construct_urls_list() Var #1: *urls_list ]\n");
  225.    
  226.         curl_slist_free_all(list_temp);
  227.         list_temp = NULL;
  228.         free(url);
  229.         free(s_param);
  230.         urls_list_size++;
  231.         i = 0;
  232.     }
  233.     i++;
  234.     symbols_list = symbols_list->next;
  235.    
  236.     }
  237.  
  238.     if(i > 0 && list_temp != NULL)
  239.     {
  240.         char *s_param = construct_s_param(list_temp);
  241.         char *url =  construct_url(f_param, s_param);
  242.  
  243.         *urls_list = curl_slist_append(*urls_list, url);
  244.  
  245.         if(!urls_list)
  246.         perror_exit_failure("Memory allocation failure. [ Function: construct_urls_list() Var #2: *urls_list ]\n");
  247.        
  248.         curl_slist_free_all(list_temp);
  249.         list_temp = NULL;
  250.         free(url);
  251.         free(s_param);
  252.         urls_list_size++;
  253.    
  254.     }
  255.     return urls_list_size;
  256. }
  257.  
  258. void construct_curl_results_arr(struct CURLResult ***curl_results, int urls_list_size)
  259. {
  260.         int i = 0, cnt = 0;
  261.         for(i = 0; i < urls_list_size; i++)
  262.         {
  263.             //Zwiekszam dynamiczna tablice curl_results
  264.             struct  CURLResult **curl_results_tmp = (struct CURLResult**)realloc(*curl_results, ++cnt * sizeof(struct CURLResult*));
  265.             *curl_results = curl_results_tmp;
  266.        
  267.            // Tworze nowa strukture mem
  268.             struct CURLResult *mem = (struct CURLResult*)malloc(sizeof(struct CURLResult));
  269.  
  270.            // Przypisuje jej domyslne wartosci
  271.            mem->memory = (char*)malloc(1);
  272.            mem->size = 0;
  273.  
  274.            (*curl_results)[i] = mem;
  275.         }
  276. }
  277. void free_curl_results_arr(struct CURLResult ***curl_results, int urls_list_size)
  278. {
  279.     int i = 0;
  280.     for(i = 0; i < urls_list_size; i++)
  281.     {
  282.     free((*curl_results)[i]->memory);
  283.     (*curl_results)[i]->memory = NULL;
  284.     free((*curl_results)[i]);
  285.     }
  286.     free(*curl_results);
  287.     *curl_results = NULL;
  288. }
  289.  
  290. static size_t write_to_memory(void *contents, size_t size, size_t nmemb, void *userp)
  291. {
  292.     size_t realsize = 0;
  293.     realsize = size * nmemb;
  294.  
  295.     struct CURLResult *mem = (struct CURLResult *)userp;
  296.    
  297.     mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1);
  298.  
  299.     memcpy(&(mem->memory[mem->size]), contents, realsize);
  300.     mem->size += realsize;
  301.     mem->memory[mem->size] = 0;
  302.  
  303.     return realsize;
  304. }
  305.  
  306. void prepare_curl_handles(CURL ***curl_handlers, struct CURLResult ***curl_results, struct curl_slist *urls_list)
  307. {
  308.     int i = 0;
  309.         while(urls_list != NULL)
  310.         {
  311.             CURL *http_handle;
  312.             http_handle = curl_easy_init();
  313.  
  314.          
  315.            curl_easy_setopt(http_handle, CURLOPT_URL,  urls_list->data);
  316.  
  317.      
  318.            curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, (void*)(*curl_results)[i]);
  319.  
  320.            curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, write_to_memory);
  321.  
  322.            CURL **curl_handlers_tmp = (CURL**)realloc(*curl_handlers, ++i * sizeof(CURL*));
  323.            *curl_handlers = curl_handlers_tmp;
  324.  
  325.            (*curl_handlers)[i-1] = http_handle;
  326.            urls_list = urls_list->next;
  327.            
  328.  
  329.         }
  330.  
  331. }
  332.  
  333. void cleanup_curl_handles(CURL ***curl_handles, int urls_list_size)
  334. {
  335.     int i = 0;
  336.     for(i = 0; i < urls_list_size; i++)
  337.     {
  338.         curl_easy_cleanup((*curl_handles)[i]);
  339.     }
  340.     free(*curl_handles);
  341.     *curl_handles = NULL;
  342. }
  343.  
  344. void print_curl_slist(struct curl_slist *slist)
  345. {
  346.     while(slist != NULL)
  347.     {
  348.     printf("%s\n\n", slist->data);
  349.     slist = slist->next;
  350.     }
  351. }
  352. void print_curl_results(struct CURLResult **curl_results, int urls_list_size)
  353. {
  354.     int i;
  355.     for(i = 0; i < urls_list_size; i++)
  356.     {
  357.     printf("%s", curl_results[i]->memory);
  358.     }
  359. }
  360.  
  361. void curl_finish(CURLM *multi_handle, CURL ***curl_handles, int urls_list_size)
  362. {
  363.     int i;
  364.  
  365.     curl_multi_cleanup(multi_handle);
  366.     multi_handle = NULL;
  367.  
  368.     for(i= 0; i < urls_list_size; i++)
  369.     {
  370.         curl_easy_cleanup((*curl_handles)[i]);
  371.         (*curl_handles)[i] = NULL;
  372.     }
  373.  
  374.     free((*curl_handles));
  375.     curl_handles = NULL;
  376.  
  377. }
  378.  
  379. int main(void)
  380. {
  381.     MYSQL *con = NULL;
  382.     MYSQL_RES *result = NULL;
  383.  
  384.     struct curl_slist *symbols_list = NULL;
  385.     struct curl_slist *urls_list = NULL;
  386.     struct CURLResult **curl_results = NULL;
  387.     CURLM *multi_handle;
  388.     int still_running = 0;
  389.     CURL **curl_handles = NULL;
  390.  
  391.     char f_param[] = "svp2ghjkpol1na2";
  392.  
  393.     con = mysql_init(NULL);
  394.     sql_con(con, (const char*)MYSQL_HOST, (const char*)MYSQL_DB, (const char*)MYSQL_USER, (const char*)MYSQL_PASS);
  395.     result = sql_query(con, (const char*)MYSQL_QUERY);
  396.     add_symbols_to_list_sql(result, con, &symbols_list);
  397.     sql_close(con);
  398.  
  399.  
  400.     int urls_list_size = construct_urls_list(symbols_list, &urls_list, f_param);
  401.     construct_curl_results_arr(&curl_results, urls_list_size);
  402.  
  403.     prepare_curl_handles(&curl_handles, &curl_results, urls_list);
  404.    
  405.     curl_global_init(CURL_GLOBAL_ALL);
  406.     multi_handle = curl_multi_init();
  407.     int i;
  408.     for(i = 0; i < urls_list_size; i++)
  409.     {
  410.     curl_multi_add_handle(multi_handle, curl_handles[i]);
  411.     }
  412.  
  413.  
  414.     curl_multi_perform(multi_handle, &still_running);
  415.  
  416.     do {
  417.     struct timeval timeout;
  418.     int rc; // select() return code
  419.  
  420.     fd_set fdread;
  421.     fd_set fdwrite;
  422.     fd_set fdexcep;
  423.     int maxfd = -1;
  424.  
  425.     long curl_timeo = -1;
  426.  
  427.     FD_ZERO(&fdread);
  428.     FD_ZERO(&fdwrite);
  429.     FD_ZERO(&fdexcep);
  430.  
  431.     //set a suitable timeout to play around with
  432.     timeout.tv_sec = 1;
  433.     timeout.tv_usec = 0;
  434.  
  435.     curl_multi_timeout(multi_handle, &curl_timeo);
  436.     if(curl_timeo >= 0)
  437.     {
  438.         timeout.tv_sec = curl_timeo / 1000;
  439.         if(timeout.tv_sec > 1)
  440.         timeout.tv_sec = 1;
  441.         else
  442.         timeout.tv_usec = (curl_timeo % 1000) * 1000;
  443.     }
  444.  
  445.     // get file descriptors from the transfers
  446.     curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
  447.  
  448.     // In a real-world program you OF COURSE check the return code of the
  449.     //  function calls.  On success, the value of maxfd is guaranteed to be
  450.     //  greater or equal than -1.  We call select(maxfd + 1, ...), specially in
  451.     //  case of (maxfd == -1), we call select(0, ...), which is basically equal
  452.     //  to sleep.
  453.     if((maxfd != -1 ))
  454.     {
  455.         rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
  456.     }
  457.     else
  458.     {
  459. #ifdef _WIN32
  460.             Sleep(timeout.tv_sec * 1000);
  461. #else
  462.             select(0 , NULL, NULL, NULL, &timeout);
  463. #endif
  464.             rc =1;
  465.     }
  466.     switch(rc)
  467.     {
  468.         case -1:
  469.         printf("%d\n", rc);
  470.         break;
  471.         case 0:
  472.         default:
  473.         // timeout or readable/writable sockets
  474.         curl_multi_perform(multi_handle, &still_running);
  475.         break;
  476.     }
  477.     } while(still_running);
  478.  
  479.     curl_multi_cleanup(multi_handle);
  480.     cleanup_curl_handles(&curl_handles, urls_list_size);
  481.     curl_global_cleanup();
  482.     print_curl_results(curl_results, urls_list_size);
  483.     free_curl_results_arr(&curl_results, urls_list_size);
  484.     curl_slist_free_all(symbols_list);
  485.     curl_slist_free_all(urls_list);
  486.  
  487. return 0;
  488. }
Add Comment
Please, Sign In to add comment