Viewing file: client_example.c (31.31 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* File: client_example.c * This file contains an simple example program illustratin * how to interact with the Cloudmark Authority Server using * the libcurl library. * * For detailed information about libcurl see the documentation * at <a href='http://curl.haxx.se/libcurl/'>http://curl.haxx.se/libcurl/</a>. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <curl/curl.h> #include "mbox_subs.h" #include "json_parser.h"
/* * Configuration Globals */ int g_raw_output = 0; /* If non-zero display raw JSON responses. */ char *g_ip = NULL; /* If non-NULL points to an IP address to score */ char *g_mbox_file = NULL; /* If non-NULL is the path to a mbox file to score. */ char *g_score_message_func; /* The method to use for scoring messages */ char *g_analysis_file = NULL; /* If non-NULL is the path to a file of analyisis strings to score. */
/* ******************************************************************************/ /* * libcurl helpers. */
/* libcurl callback support. * * These routines support the libcurl write callback, as described * <a href='http://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html'>here</a> * in the lib curl documentation. */
/* * Curl response buffer. * * This is the structure that the callback function passed to curl uses to * accumlate the response. */ typedef struct response_buffer { size_t allocated; /* Space allocated. */ char * buffer; /* Pointer to the buffer. */ }response_buffer_t;
/* The curl callback. * This routine is passed to curl as CUROPT_WRITEFUNCTION. The library calls it * when data comes back from the server, and the routine accumulates the data into * the passed in response_buffer_t. Note that the actuall size of the passed in data * is size * nmemb . * * Parameters: * ptr - Pointer to the data. * size - Size of a data block * nmemb - Number of data blocks. * userdata - Pointer to the response_buffer_t into which we're accumulating the response. * * Returns: The number of bytes processed. */ size_t response_callback(char *ptr, size_t size, size_t nmemb, void *userdata) { response_buffer_t *rbp = (response_buffer_t *)userdata; size_t data_len = size*nmemb; size_t newsize = rbp->allocated + data_len; // always allocate an extra byte so we can NUL-terminate. char *newbuf = realloc(rbp->buffer, newsize+1); if (newbuf) { memcpy(newbuf + rbp->allocated, ptr, data_len); rbp->allocated = newsize; rbp->buffer = newbuf; return data_len; } else { return 0; } }
/* Allocate and initialize a new response_buffer_t. * * Returns: A pointer to a newly allocated response_buffer_t. */ response_buffer_t *new_response_buf() { return (response_buffer_t *)calloc(sizeof(response_buffer_t), 1); }
/* Dispose of a response_buffer_t. * Deallocate a response_buffer_t allocated by new_response_buf(). * * Parameter: * buf - The response_buffer_t to deallocate. */ void release_response_buf(response_buffer_t *buf) { if (buf) { free(buf->buffer); free(buf); } }
/* Dispose of a response_buffer_t and return the data. * Deallocate a response_buffer_t allocated by new_response_buf(). * This routine differs from release_response_buf() in that * it returns the data from the buffer (as a nul-terminated <tt>char*</tt>) * Note that the returned data must be explicitly free'd by * the caller. * * Parameter: * buf - The response_buffer_t to deallocate. * * Returns: The data from the response_buffer_t. */ char *release_response_buf_string(response_buffer_t *buf) { char *str = NULL; if (buf && buf->allocated) { str = buf->buffer; str[buf->allocated] = '\0'; } free(buf); return str; }
/* ******************************************************************************/ /* * libcurl form part support. * * These routines just abstract and simplify the process of adding a form section * prior to POSTing. */
/* form parts list * This struct keeps track of the pointers that libcurl uses for its form parts list. */ typedef struct formargs { struct curl_httppost *formpost; /* The beginning of the list */ struct curl_httppost *lastpost; /* The end of the list */ }formargs_t;
/* Allocate and initialize a new formargs_t. * * Returns: A pointer to a newly allocated formargs_t. */ formargs_t *new_formargs() { return (formargs_t *)calloc(sizeof(formargs_t), 1); }
/* Dispose of a formargs_t. * Deallocate a formargs_t allocated by new_formargs(). * * Parameter: * args - The formargs_t to deallocate. */ void release_formargs(formargs_t *args) { curl_formfree(args->formpost); free(args); }
/* Add a form part. * Add a form part to the list. Note that this takes a part as * a NUL-terminated C-string. * * Parameters: * args - The formargs_t we're going to add the part to. * name - The name of the part * value - The content of the part * * Returns: Result of the curl_formadd call. */ CURLFORMcode form_addarg(formargs_t *args, char *name, char*value) { return curl_formadd(&(args->formpost), &(args->lastpost), CURLFORM_COPYNAME, name, CURLFORM_COPYCONTENTS, value, CURLFORM_END); }
/* ******************************************************************************/
/* libcurl submission routines. * * These routines just abstract and simplify the process if submitting a request to * the server and fetching the response. */
/* * Send a GET request to the server and return the response. * * The routine assembles a GET request, sends it to the server and returns the response * as a C-string. * * Parameters: * curl - The curl handle. * url - The URL of the server, including port number if necessary * req - The name of the request * arg - If non-NULL is an argument to the request * respstr - A pointer to a <TT>char *</tt> to receive the response string * * Returns: a response from curl. On success will be CURLE_OK. */ CURLcode do_GET_request(CURL* curl, char *url, char* req, char *arg, long *httpcode, char **respstr) { /* allocate the response buffer. */ response_buffer_t *rbuf = new_response_buf(); size_t url_len = strlen(url)+1; size_t req_len = strlen(req); size_t arg_len = arg ? strlen(arg) : 0; size_t total_len = 0; char *full_req = NULL; CURLcode res = CURLE_OK; *httpcode = 0; size_t i; /* allocate memory for the request string */ total_len = url_len + req_len + arg_len +5; full_req = (char*)malloc(total_len); /* start with the url */ strcpy(full_req, url); /* then the request */ strcat(full_req, req); /* and finally, any args */ if (arg) { strcat(full_req, "/"); strcat(full_req, arg); }
/* pass the address of our callback to curl */ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, response_callback); /* and the buffer for the resonse */ curl_easy_setopt(curl, CURLOPT_WRITEDATA, rbuf); /* and finally, the request */ curl_easy_setopt(curl, CURLOPT_URL, full_req);
/* The let curl do its magic. */ res = curl_easy_perform(curl);
/* get our HTTP response code */ if (res == CURLE_OK) { long response_code; if(CURLE_OK == curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code)) { *httpcode = response_code; } } /* done with this */ free(full_req);
/* pass the response string back to the caller */ *respstr = release_response_buf_string(rbuf);
/* and return the result*/ return res; }
/* * Send a POST request to the server and return the response. * * The routine assembles a POST request, sends it to the server and returns the response * as a C-string. * * Parameters: * curl - The curl handle. * url - The URL of the server, including port number if necessary * req - The name of the request * args - Is our list of POST parts. * respstr - A pointer to a <TT>char *</TT> to receive the response string * * Returns: a response from curl. On success will be CURLE_OK. */ CURLcode do_POST_request(CURL* curl, char *url, char* req, formargs_t *args, long *httpcode, char **respstr) { /* allocate the response buffer. */ response_buffer_t *rbuf = new_response_buf(); size_t url_len = strlen(url)+1; size_t req_len = strlen(req); size_t total_len = 0; char *full_req = NULL; CURLcode res = CURLE_OK; *httpcode = 0;
/* allocate memory for the request string */ total_len = url_len + req_len + 5; full_req = (char*)malloc(total_len); /* start with the url */ strcpy(full_req, url); /* then the request */ strcat(full_req, req);
/* pass the address of our callback to curl */ res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, response_callback); /* and the buffer for the resonse */ res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, rbuf); /* and the request */ res = curl_easy_setopt(curl, CURLOPT_URL, full_req); /* finally and the POST parts. Note that this will also inform libcurl * that this request is to a multipart formpost */ res = curl_easy_setopt(curl, CURLOPT_HTTPPOST, (args->formpost));
/* let curl do its magic */ res = curl_easy_perform(curl);
/* get our HTTP response code */ if (res == CURLE_OK) { long response_code; if(CURLE_OK == curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code)) { *httpcode = response_code; } }
/* done with this */ free(full_req);
/* pass the response string back to the caller */ *respstr = release_response_buf_string(rbuf);
/* return the result */ return res; }
/* ******************************************************************************/ /* * Check a response for errors. * * Given a JSON object returned from the server, examine it for an * HTTP error. If an error is found, report the error. * * Parameter: * obj - The object to examine. * * Returns: 1 if no error, 0 if error found. */ int check_JSON_response(JSON_Object_t *obj) { int code = -1; char *code_string = ""; int ret= 1;
/* see if we have an http_error field */ JSON_Value_t *hep = Find(obj, "http_error"); if (hep) { /* if so, report the error */ JSON_Value_t *erp = Find(hep->u.obj, "error"); if (erp) { printf("Authority Server returned HTTP error: %s", erp->u.string); JSON_Value_t *dtp = Find(hep->u.obj, "details"); if (dtp) { printf(" details: %s", dtp->u.string); } puts("\r"); ret = 0; } } return ret; }
/* * Print the raw response from the server * * Parameters: * func - The corresponding function call * response - The response from the server */ void print_raw_response(char *func, char *response) { printf("%s response: %s\n", func, response); }
/******************************************************************************/ /* * GET Requests * * These functions handle the various GET requests we can send to the server * */
/* ping. * * Send a ping to the server. Display the response. * * Parameters: * curl - The curl handle. * host - The server url * * Returns: The CURLcode returned by libcurl */
CURLcode do_ping(CURL *curl, char *host) { char *response = NULL; long httpcode; CURLcode res = do_GET_request(curl, host, "/score/v2/ping", NULL, &httpcode, &response); if (res == CURLE_OK) { if (httpcode >= 400 ) { printf("HTTP Response: %ld\n %s\n ", httpcode, response); } else if (response) { if (g_raw_output) { print_raw_response("ping", response); } else { char *resp2 = response; JSON_Object_t *obj = ParseJSONObject(&resp2); if (obj) { if (check_JSON_response(obj)) printf("ping OK\n"); } else { fprintf(stderr, "Invalid JSON string returned from ping call\n"); } } } else { printf("ping response: (Empty)\n"); } } else { fprintf(stderr, "Curl Error: (%d) - %s \n", res, curl_easy_strerror(res)); } free(response); return res; }
/* max_message_size. * * Fetch the maximum message size from the server. Display the response. * * Parameters: * curl - The curl handle. * host - The server url * * Returns: The CURLcode returned by libcurl */ CURLcode do_max_message_size(CURL *curl, char *host) { char *response = NULL; long httpcode; CURLcode res = do_GET_request(curl, host, "/score/v2/max-message-size", NULL, &httpcode, &response); if (res == CURLE_OK) { if (httpcode >= 400 ) { printf("HTTP Response: %ld\n %s\n ", httpcode, response); } else if (response) { if (g_raw_output) { print_raw_response("max-message-size", response); } else { char *resp2 = response; JSON_Object_t *obj = ParseJSONObject(&resp2); if (obj) { if (check_JSON_response(obj)) { JSON_Value_t *val = Find(obj, "maxMessageSize"); if (val) printf("max message size: %d\n", (int)val->u.number); else printf("no field in response\n"); } FreeJSONObject(obj); } else { fprintf(stderr, "Invalid JSON string returned from max_message_size call\n"); } } } else { printf("max-message-size response: (Empty)\n"); } } else { fprintf(stderr, "Curl Error: (%d) - %s \n", res, curl_easy_strerror(res)); } free(response); return res; }
/* license. * * Fetch the license from the server. Display the response. * * Parameters: * curl - The curl handle. * host - The server url * * Returns: The CURLcode returned by libcurl */ CURLcode do_license(CURL *curl, char *host) { char *response = NULL; long httpcode; CURLcode res = do_GET_request(curl, host, "/score/v2/license", NULL, &httpcode, &response); if (res == CURLE_OK) { if (httpcode >= 400 ) { printf("HTTP Response: %ld\n %s\n ", httpcode, response); } else if (response) { if (g_raw_output) { print_raw_response("license", response); } else { char *resp2 = response; JSON_Object_t *obj = ParseJSONObject(&resp2); if (obj) { printf("license"); if (check_JSON_response(obj)) { unsigned i = 0; while(1) { JSON_Pair_t *pp = GetPairFromObject(obj, i); if ( pp ) { printf(" %s: ", pp->name); DisplayJSONValue(stdout, pp->value); printf("\n"); } else { break; } ++i; } } FreeJSONObject(obj); } else { fprintf(stderr, "Invalid JSON string returned from license call\n"); } } } else { printf("license"); } } else { fprintf(stderr, "Curl Error: (%d) - %s \n", res, curl_easy_strerror(res)); } free(response); return res; }
/* microupdate_versions. * * Fetch the microupdate version information from the server. Display the response. * * Parameters: * curl - The curl handle. * host - The server url * * Returns: The CURLcode returned by libcurl */ CURLcode do_microupdate_versions(CURL *curl, char *host) { char *response = NULL; long httpcode; CURLcode res = do_GET_request(curl, host, "/score/v2/microupdate-versions", NULL, &httpcode, &response); if (res == CURLE_OK) { if (httpcode >= 400 ) { printf("HTTP Response: %ld\n %s\n ", httpcode, response); } else if (response) { if (g_raw_output) { print_raw_response("microupdate-versions", response); } else { char *resp2 = response; JSON_Object_t *obj = ParseJSONObject(&resp2); if (obj) { printf("microupdate-versions:\n"); if (check_JSON_response(obj)) { unsigned i = 0; while(1) { JSON_Pair_t *pp = GetPairFromObject(obj, i); if ( pp ) { printf(" %s: ", pp->name); DisplayJSONValue(stdout, pp->value); printf("\n"); } else { break; } ++i; } } FreeJSONObject(obj); } else { fprintf(stderr, "Invalid JSON string returned from microupdate-versions call\n"); } } } else { printf("microupdate-versions response: (Empty)\n"); } } else { fprintf(stderr, "Curl Error: (%d) - %s \n", res, curl_easy_strerror(res)); } free(response); return res; }
/* supported_attributes. * * Fetch the list of supported attributes from the server. Display the response. * * Parameters: * curl - The curl handle. * host - The server url * * Returns: The CURLcode returned by libcurl */ CURLcode do_supported_attributes(CURL *curl, char *host) { char *response = NULL; long httpcode; CURLcode res = do_GET_request(curl, host, "/score/v2/supported-attributes", NULL, &httpcode, &response); if (res == CURLE_OK) { if (httpcode >= 400 ) { printf("HTTP Response: %ld\n %s\n ", httpcode, response); } else if (response) { if (g_raw_output) { print_raw_response("supported-attributes", response); } else { char *resp2 = response; JSON_Object_t *obj = ParseJSONObject(&resp2); if (obj) { printf("supported-attributes: \n"); if (check_JSON_response(obj)) { unsigned i = 0; while(1) { JSON_Pair_t *pp = GetPairFromObject(obj, i); if ( pp ) { printf(" %s: ", pp->name); DisplayJSONValue(stdout, pp->value); printf("\n"); } else { break; } ++i; } } FreeJSONObject(obj); } else { fprintf(stderr, "Invalid JSON string returned from supported-attributes call\n"); } } } else { printf("supported-attributes response: (Empty)\n"); } } else { fprintf(stderr, "Curl Error: (%d) - %s \n", res, curl_easy_strerror(res)); } free(response); return res; }
/* runtime. * * Fetch the runtime information from the server. Display the response. * * Parameters: * curl - The curl handle. * host - The server url * * Returns: The CURLcode returned by libcurl */ CURLcode do_runtime(CURL *curl, char *host) { char *response = NULL; long httpcode; CURLcode res = do_GET_request(curl, host, "/score/v2/runtime", NULL, &httpcode, &response); if (res == CURLE_OK) { if (httpcode >= 400 ) { printf("HTTP Response: %ld\n %s\n ", httpcode, response); } else if (response) { if (g_raw_output) { print_raw_response("runtime information", response); } else { char *resp2 = response; JSON_Object_t *obj = ParseJSONObject(&resp2); if (obj) { printf("runtime: \n"); if (check_JSON_response(obj)) { unsigned i = 0; while(1) { JSON_Pair_t *pp = GetPairFromObject(obj, i); if ( pp ) { printf(" %s: ", pp->name); DisplayJSONValue(stdout, pp->value); printf("\n"); } else { break; } ++i; } } FreeJSONObject(obj); } else { fprintf(stderr, "Invalid JSON string returned from microupdate-versions call\n"); } } } else { printf("runtimeresponse: (Empty)\n"); } } else { fprintf(stderr, "Curl Error: (%d) - %s \n", res, curl_easy_strerror(res)); } free(response); return res; }
/******************************************************************************/ /* * Scoring Routines * * These routines handle the various scoring calls to the server, all of which * are sent as POSTs * */
/* Score an ip address * * Call the server with an ip address, print the returned score * * Parameters: * curl - The curl handle * host - The server url * ip - The string contianing the IP address to score * * Returns: The CURLcode returned by libcurl */ CURLcode do_score_ip(CURL *curl, char *host, char *ip) { char *response = NULL; formargs_t *args = new_formargs(); CURLcode res = CURLE_OK; long httpcode;
res = do_GET_request(curl, host, "/score/v2/ip", ip, &httpcode, &response); if (res == CURLE_OK) { if (httpcode >= 400 ) { printf("HTTP Response: %ld\n %s\n ", httpcode, response); } else if (response) { if (g_raw_output) { print_raw_response("score/ip", response); } else { char *resp2 = response; JSON_Object_t *obj = ParseJSONObject(&resp2); if (obj) { if (check_JSON_response(obj)) { JSON_Value_t *sp = Find(obj, "score"); printf("score/ip response - score: "); DisplayJSONValue(stdout, sp); } printf("\n"); } else { fprintf(stderr, "Invalid JSON string returned from score/ip call\n"); } } } else { printf("score/ip response: (Empty)\n"); } } else { fprintf(stderr, "Curl Error: (%d) - %s \n", res, curl_easy_strerror(res)); } release_formargs(args); free(response); return res; } /* Score an analysis string * * Call the server with an analysis string, print the returned score * * Parameters: * curl - The curl handle * host - The server url * analysis - The analyis string to score * * Returns: The CURLcode returned by libcurl */ CURLcode do_score_analysis(CURL *curl, char *host, char *analysis) { char *response = NULL; formargs_t *args = new_formargs(); CURLcode res = CURLE_OK; long httpcode;
form_addarg(args, "analysis", analysis); res = do_POST_request(curl, host, "/score/v2/analysis", args, &httpcode, &response); if (res == CURLE_OK) { if (httpcode >= 400 ) { printf("HTTP Response: %ld\n %s\n ", httpcode, response); } else if (response) { if (g_raw_output) { print_raw_response("score/analysis", response); } else { char *resp2 = response; JSON_Object_t *obj = ParseJSONObject(&resp2); if (obj) { if (check_JSON_response(obj)) { JSON_Value_t *sp = Find(obj, "score"); printf("score/analysis response - score: "); DisplayJSONValue(stdout, sp); } printf("\n"); } else { fprintf(stderr, "Invalid JSON string returned from score/analysis call\n"); } } } else { printf("score/analysis response: (Empty)\n"); } } else { fprintf(stderr, "Curl Error: (%d) - %s \n", res, curl_easy_strerror(res)); } release_formargs(args); free(response); return res;
} /* Score an message * * This is a general message scoring routine. The actual scoring function * which may be \c score/message, \c score/content or \c score/sender * is passed in the \c func parameter. * * * Parameters: * curl - The curl handle * host - The server url * func - The actual scoring call to the server * rfc822 - The entire mail, as a single C-string * helo_domain - The HELO domain from the envelope. (Optional) * mail_from - The MAIL FROM field from the envelope. (Optional) * receipt_to - rAa list of receipt_to from the the RCPT TO field in the envelope. (Optional) * connip - The connecting IP address. (Optional) * * Returns: The CURLcode returned by libcurl */ CURLcode do_score_general(CURL *curl, char *host, char* func, char *rfc822, char* helo_domain, char* mail_from, char* receipt_to, char* connip) { char *response = NULL; formargs_t *args = new_formargs(); CURLcode res = CURLE_OK; long httpcode;
form_addarg(args, "rfc822", rfc822); if (helo_domain) form_addarg(args, "helo_domain", helo_domain); if (mail_from) form_addarg(args, "mail_from", mail_from); if (receipt_to) form_addarg(args, "rcpt_to", receipt_to); if (connip) form_addarg(args, "connip", connip);
res = do_POST_request(curl, host, func, args, &httpcode, &response);
if (res == CURLE_OK) { if (httpcode >= 400 ) { printf("HTTP Response: %ld\n %s\n ", httpcode, response); }else if (response) { if (g_raw_output) { print_raw_response(func, response); } else { char *resp2 = response; JSON_Object_t *obj = ParseJSONObject(&resp2); if (obj) { if (check_JSON_response(obj)) { JSON_Value_t *sp = Find(obj, "score"); JSON_Value_t *ap = Find(obj, "analysis"); printf("%s response - score: ", func); DisplayJSONValue(stdout, sp); printf(" analysis: "); DisplayJSONValue(stdout, ap); } printf("\n"); } else { fprintf(stderr, "Invalid JSON string returned from %s call\n", func); } } } else { printf("%s response: (Empty)\n", func); } } else { fprintf(stderr, "Curl Error: (%d) - %s \n", res, curl_easy_strerror(res)); } release_formargs(args); free(response); return res;
}
/******************************************************************************/
/* Usage message. * Called when a bum parameter is seen. Print the usage message and quit. */ void usage() { fprintf(stderr, "usage: client_example [-r] [-I ip] [-a file] [-m file] [-C type] host\n"); exit(1); }
/* The mainline * * Parameters: * argc - The number of command line arguments * argv - The list of command line arguments */ int main(int argc, char **argv) { mail_t *mail; mbox_t *box; char *score_method = NULL; char *host=NULL; int argchar; CURL *curl = NULL;
while(-1 < (argchar = getopt(argc, argv, "rI:a:C:m:"))) { switch(argchar) { case 'r' : g_raw_output = 1; break; case 'I' : g_ip = optarg; break; case 'C' : score_method = optarg; break; case 'm' : g_mbox_file = optarg; break; case 'a' : g_analysis_file = optarg; break; default : usage(); break; }
}
if (optind <argc) host = strdup(argv[optind]); else usage();
if (g_mbox_file) { if (score_method) { if (!strcmp(score_method, "message")) { g_score_message_func = "/score/v2/message"; } else if (!strcmp(score_method, "content")) { g_score_message_func = "/score/v2/content"; } else if (!strcmp(score_method, "sender")) { g_score_message_func = "/score/v2/sender"; } else { fprintf(stderr, "Arg to -C must be message, content or sender\n"); usage(); } } else { g_score_message_func = "/score/v2/message"; } } else if (score_method) { fprintf(stderr, "-C can only be used with -m\n"); usage(); }
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
// If nothing else specified, just fetch status and config info if ( !g_ip && !g_mbox_file && !g_analysis_file) { if (CURLE_OK == do_ping(curl, host)) { printf("\n"); if (CURLE_OK == do_max_message_size(curl, host)) { printf("\n"); if (CURLE_OK == do_license(curl, host)) { printf("\n"); if (CURLE_OK == do_microupdate_versions(curl, host)) { printf("\n"); if (CURLE_OK == do_supported_attributes(curl, host)) { printf("\n"); do_runtime(curl, host); printf("\n"); } } } } } }
if ( g_ip ) do_score_ip(curl, host, g_ip); if (g_mbox_file) { box = new_mbox(g_mbox_file); if (box) { printf("\n"); while ((mail = next_mail(box))) { char *subj = get_header(mail, "Subject: "); if (subj) printf("%s\n", subj); do_score_general(curl, host, g_score_message_func, mail->mail_text, NULL, NULL, NULL, NULL); free_mail(mail); free(subj); printf("\n\n"); } free_mbox(box); } else { fprintf(stderr, "Could not open mbox file: %s\n", g_mbox_file); exit(1); } }
if (g_analysis_file) { FILE *af = fopen(g_analysis_file, "r"); if (af) { char buf[2048]; while(fgets(buf, sizeof(buf), af)) { printf("%s", buf); do_score_analysis(curl, host, buf); printf("\n"); } fclose(af); } else { fprintf(stderr, "Could not open analysis file: %s\n", g_analysis_file); exit(1); } }
curl_easy_cleanup(curl); exit(0); }
|