#include #include #include #include #include /* * mcstatus - simple cli using mcserverstat.us' API * see https://api.mcsrvstat.us/ * 29/12/2025 - this software provides no guarantees. * made by texturawasd (https://texturawasd.duckdns.org) * License: MIT * * note 06/01/2026: api has updated (V3) so player list logic was updated */ /* * use: * cc mcstatus.c -ljansson -lcurl -o mcstatus && ./mcstatus */ #define OK 0 #define NOT_OK 1 #define ERR_USAGE 64 struct memory { char *response; size_t size; }; static size_t write_callback( void *data, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct memory *mem = (struct memory *)userp; char *ptr = realloc(mem->response, mem->size + realsize + 1); if (!ptr) return 0; /* have curl abort the transfer */ mem->response = ptr; memcpy(&(mem->response[mem->size]), data, realsize); mem->size += realsize; mem->response[mem->size] = 0; return realsize; } int main(int argc, char **argv) { if (argc != 2) { printf("Usage: %s \n", argv[0]); return ERR_USAGE; } char url[256]; snprintf(url, sizeof(url), "https://api.mcsrvstat.us/3/%s", argv[1]); CURL *curl = curl_easy_init(); struct memory chunk = {.response = NULL, .size = 0}; if (!curl) return NOT_OK; curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); curl_easy_setopt(curl, CURLOPT_USERAGENT, "mcstatus-cli/1.0"); CURLcode res = curl_easy_perform(curl); curl_easy_cleanup(curl); if (res != CURLE_OK) { fprintf(stderr, "curl failed: %s\n", curl_easy_strerror(res)); free(chunk.response); return NOT_OK; } json_t *root; json_error_t error; if (!chunk.response) { // guard before loading chunk.response fprintf(stderr, "Empty response\n"); return NOT_OK; } // chunk.resonse could technically be NULL root = json_loads(chunk.response, 0, &error); free(chunk.response); if (!root) { fprintf(stderr, "JSON parse error: %s\n", error.text); return NOT_OK; } json_t *online = json_object_get(root, "online"); if (!json_is_boolean(online) || !json_boolean_value(online)) { puts("server is OFFLINE"); json_decref(root); return OK; } puts("server is ONLINE!!!!11!!!!1!!!"); /* version */ json_t *version = json_object_get(root, "version"); if (json_is_string(version)) printf("Version: %s\n", json_string_value(version)); /* players */ json_t *players = json_object_get(root, "players"); if (json_is_object(players)) { json_t *online_players = json_object_get(players, "online"); json_t *max_players = json_object_get(players, "max"); long long online_val = json_is_integer(online_players) ? json_integer_value(online_players) : 0; long long max_val = json_is_integer(max_players) ? json_integer_value(max_players) : 0; printf("Players: %lld/%lld\n", online_val, max_val); /* player list */ json_t *list = json_object_get(players, "list"); if (json_is_array(list) && json_array_size(list) > 0) { size_t index; json_t *value; printf("Player List:\n"); json_array_foreach(list, index, value) { /* 06/01/2026: In v3, list items are objects: {"name": "...", "uuid": "..."} */ if (json_is_object(value)) { json_t *pname = json_object_get(value, "name"); if (json_is_string(pname)) { printf("%s\n", json_string_value(pname)); } } } } else { printf("Player list unavailable or hidden\n"); } } json_decref(root); return OK; }