Skip to content

Instantly share code, notes, and snippets.

@mattn
Created March 11, 2009 04:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattn/77313 to your computer and use it in GitHub Desktop.
Save mattn/77313 to your computer and use it in GitHub Desktop.
dan the shell
// for MSVC: cl -I.. /Tp dansh.cpp curl.lib readline.lib ..\Release\json.lib
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
namespace json {
#include "json.h"
}
#define READLINE_STATIC
#include <readline/readline.h>
#include <readline/history.h>
#include <curl/curl.h>
#define API_URL "http://api.dan.co.jp/lleval.cgi?c=callback&s="
typedef struct {
char* data; // response data from server
size_t size; // response size of data
} MEMFILE;
MEMFILE*
memfopen() {
MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE));
mf->data = NULL;
mf->size = 0;
return mf;
}
void
memfclose(MEMFILE* mf) {
if (mf->data) free(mf->data);
free(mf);
}
size_t
memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) {
MEMFILE* mf = (MEMFILE*) stream;
int block = size * nmemb;
if (!mf->data)
mf->data = (char*) malloc(block);
else
mf->data = (char*) realloc(mf->data, mf->size + block);
if (mf->data) {
memcpy(mf->data + mf->size, ptr, block);
mf->size += block;
}
return block;
}
char*
memfstrdup(MEMFILE* mf) {
char* buf = (char*) malloc(mf->size + 1);
memcpy(buf, mf->data, mf->size);
buf[mf->size] = 0;
return buf;
}
char*
url_encode_alloc(const char* str, int force_encode) {
const char* hex = "0123456789abcdef";
char* buf = NULL;
unsigned char* pbuf = NULL;
int len = 0;
if (!str) return NULL;
len = strlen(str)*3;
buf = (char*) malloc(len+1);
memset(buf, 0, len+1);
pbuf = (unsigned char*)buf;
while(*str) {
unsigned char c = (unsigned char)*str;
if (c == ' ')
*pbuf++ = '+';
else if (c & 0x80 || force_encode) {
*pbuf++ = '%';
*pbuf++ = hex[c >> 4];
*pbuf++ = hex[c & 0x0f];
} else
*pbuf++ = c;
str++;
}
return buf;
}
void do_dan(const char* line, const char* lang) {
char* url;
if (line != NULL) {
char* source = url_encode_alloc(line, TRUE);
url = (char*) malloc(strlen(API_URL) + strlen(source) + 10);
strcpy(url, API_URL);
strcat(url, source);
if (lang) {
strcat(url, "&l=");
strcat(url, lang);
}
} else {
url = strdup("http://api.dan.co.jp/lleval.cgi?q=1");
}
MEMFILE* mf = memfopen();
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf);
CURLcode res = curl_easy_perform(curl);
free(url);
if (res == CURLE_OK) {
char* data = memfstrdup(mf);
memfclose(mf);
// remove callback function
char* ptr;
ptr = strrchr(data, ')');
if (ptr) *ptr = 0;
ptr = strchr(data, '(');
if (ptr) *ptr++ = 0;
else ptr = data;
json::json_object *obj = json::json_tokener_parse(ptr);
if (!is_error(obj)) {
if (line == NULL) {
char *key;
struct json::json_object *val;
struct json::lh_entry *entry;
for(entry = json_object_get_object(obj)->head; (entry ? (key = (char*)entry->k, val = (struct json::json_object*)entry->v, entry) : 0); entry = entry->next) {
printf("%s:%s\n", key, json::json_object_get_string(val));
}
} else {
json::json_object *result = json::json_object_object_get(obj, "stdout");
if (!is_error(result)) {
printf("%s\n", json::json_object_get_string(result));
json_object_put(result);
}
}
}
free(data);
}
curl_easy_cleanup(curl);
}
int main(int argc, char **argv)
{
char* line = NULL;
//json::mc_set_debug(1);
if (argc == 2) {
FILE* fp = fopen(argv[1], "rb");
if (!fp) {
perror("can't open file");
exit(-1);
}
char buf[BUFSIZ];
while (fgets(buf, sizeof(buf), fp)) {
if (!line) {
if (strncmp(buf, "#!", 2))
line = strdup(buf);
} else {
line = (char*) realloc(line, strlen(line) + strlen(buf) + 1);
strcat(line, buf);
}
}
fclose(fp);
do_dan(line, NULL);
free(line);
}
if (!isatty(fileno(stdin))) {
char buf[BUFSIZ];
while (fgets(buf, sizeof(buf), stdin)) {
if (!line) {
if (strncmp(buf, "#!", 2))
line = strdup(buf);
} else {
line = (char*) realloc(line, strlen(line) + strlen(buf) + 1);
strcat(line, buf);
}
}
do_dan(line, NULL);
free(line);
} else {
int history_count = 0;
while (line = readline("dan> ")) {
add_history(line);
if (++history_count > 200) {
free(remove_history(0));
}
if (!strcmp(line, "#!?")) {
do_dan(NULL, NULL);
} else
if (line[0] == '#' && line[1] == '!') {
char* ptr = strchr(line, ' ');
if (ptr) {
*ptr++ = 0;
do_dan(ptr, line + 2);
}
} else
do_dan(line, "pl"); // default: perl
free(line);
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment