searpent/searpent.c

109 lines
2.9 KiB
C

/*
* Copyright (c) 2023 Emma Tebibyte
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <curl/curl.h>
#include <jansson.h>
#define SEARX_QUERY_JSON "search?format=json&q="
typedef struct curl_read_data_t {
size_t len;
char* data;
} curl_read_data_t;
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
curl_read_data_t *data = (curl_read_data_t *)userp;
size_t old_len;
if (data->len == 0) {
data->len = nmemb;
data->data = (char *) malloc(nmemb);
memcpy(data->data, buffer, nmemb);
} else {
old_len = data->len;
data->len += nmemb;
data->data = (char *) realloc(data->data, data->len);
memcpy(data->data + old_len, buffer, nmemb);
}
return nmemb;
}
curl_read_data_t search(char *argv[], char *term) {
char *url = "https://searx.mxchange.org/";
size_t buf_size = sizeof(SEARX_QUERY_JSON) + strlen(url) + strlen(term);
char *search_url = malloc(buf_size);
char *error;
CURL *handle;
CURLcode res;
snprintf(search_url, buf_size, "%s%s%s", url, SEARX_QUERY_JSON, term);
curl_read_data_t json;
json.len = 0;
json.data = NULL;
handle = curl_easy_init();
if (handle) {
error[CURL_ERROR_SIZE];
curl_easy_setopt(handle, CURLOPT_URL, search_url);
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &json);
curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, error);
res = curl_easy_perform(handle);
curl_easy_cleanup(handle);
fprintf(stderr, "%s: %s", argv[0], error);
} else {
fprintf(stderr, "%s: failed to initialize curl.\n");
}
return json;
}
void parse_json(char *argv[], char* json) {
char *parsed_json;
json_error_t *error;
char *pretty_print;
json_t *json_val = json_loads(json, JSON_DECODE_ANY, error);
json_unpack(json_val, "{s:o}", parsed_json);
pretty_print = json_dumps(json_val, JSON_INDENT(2));
printf("%s\n", pretty_print);
}
int main(int argc, char *argv[]) {
curl_read_data_t json;
if (argc < 1) {
fprintf(stderr, "Usage: %s terms...", argv[0]);
return EX_USAGE;
}
for (int i = 1; i < argc; i++) {
json = search(argv, argv[i]);
parse_json(argv, json.data);
}
return EX_OK;
}