/* Hiawatha | command.c * * CommandChannel routines */ #include "config.h" #ifdef HAVE_COMMAND #include #include #include #include #include #include #include #include "global.h" #include "libstr.h" #include "libmd5.h" #include "command.h" #include "client.h" #ifdef HAVE_CACHE #include "cache.h" #endif #define MAX_IDLE_TIME 30 #define MAX_CMD_SIZE 64 #define TIMESTAMP_SIZE 50 static t_admin *adminlist, *loop, *next; static char *prompt = "\033[01;34mhcc>\033[00m "; static pthread_mutex_t command_mutex; static char start_time[TIMESTAMP_SIZE]; extern char *version_string; static volatile unsigned long counters[COUNTER_MAX]; static volatile unsigned long long transfer[TRANSFER_MAX]; void increment_counter(int counter) { counters[counter]++; } void increment_transfer(int counter, long bytes) { transfer[counter] += bytes; } static void clear_counters(void) { int i; for (i = 0; i < COUNTER_MAX; i++) { counters[i] = 0; } for (i = 0; i < TRANSFER_MAX; i++) { transfer[i] = 0; } } /* Initialize the CommandChannel */ void init_command_module(void) { time_t t; struct tm *s; adminlist = NULL; loop = NULL; next = NULL; pthread_mutex_init(&command_mutex, NULL); time(&t); s = localtime(&t); start_time[TIMESTAMP_SIZE - 1] = '\0'; strftime(start_time, TIMESTAMP_SIZE - 1, "%a %d %b %Y %T %z", s); clear_counters(); } /* An administrator has connected to the CommandChannel. */ int add_admin(int sock) { t_admin *new; if ((new = (t_admin*)malloc(sizeof(t_admin))) != NULL) { if ((new->fp = fdopen(sock, "r+")) != NULL) { fprintf(new->fp, "\n\033[02;31mHiawatha v"VERSION" CommandChannel\033[00m\n"); fprintf(new->fp, "Password: \0337\033[00;30;40m"); /* Save cursor position and change color to black */ fflush(new->fp); new->next = adminlist; new->socket = sock; new->authenticated = false; new->timer = MAX_IDLE_TIME; adminlist = new; return 0; } else { return -1; } } else { return -1; } } /* An administrator has left the CommandChannel */ void remove_admin(int sock) { t_admin *deadone = NULL, *check; if (adminlist != NULL) { if (adminlist->socket == sock) { deadone = adminlist; adminlist = adminlist->next; } else { check = adminlist; while (check->next != NULL) { if (check->next->socket == sock) { deadone = check->next; check->next = deadone->next; break; } check = check->next; } } } if (deadone != NULL) { fclose(deadone->fp); free(deadone); } } /* Disconnect al the administrators. */ void disconnect_admins(void) { t_admin *admin; while (adminlist != NULL) { admin = adminlist; adminlist = adminlist->next; close(admin->socket); free(admin); } } /* Return the first admin record. */ t_admin *first_admin(void) { if ((loop = adminlist) != NULL) { next = loop->next; return loop; } else { next = NULL; } return NULL; } /* Return the next admin record. */ t_admin *next_admin(void) { if ((loop = next) != NULL) { next = loop->next; return loop; } return NULL; } /* Check administratos (only auto-logout timers for now). */ void check_admin_list(void) { t_admin *admin, *prev_admin = NULL, *next_admin; admin = adminlist; while (admin != NULL) { next_admin = admin->next; if (admin->timer == 0) { fprintf(admin->fp, "\033[00m(auto-logout)\n"); fflush(admin->fp); close(admin->socket); if (prev_admin == NULL) { adminlist = next_admin; } else { prev_admin->next = next_admin; } free(admin); } else { admin->timer--; prev_admin = admin; } admin = next_admin; } } /* Show help info. */ static void show_help(FILE *fp) { fprintf(fp, " ban [,