X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilc%2Fsilc.c;fp=apps%2Fsilc%2Fsilc.c;h=0000000000000000000000000000000000000000;hb=72c2de619079457f7a68100eb13385275a424a23;hp=e449af1d89883c03da6294b2bcbcd146017e7f21;hpb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;p=runtime.git diff --git a/apps/silc/silc.c b/apps/silc/silc.c deleted file mode 100644 index e449af1d..00000000 --- a/apps/silc/silc.c +++ /dev/null @@ -1,699 +0,0 @@ -/* - - silc.c - - Author: Pekka Riikonen - - Copyright (C) 1997 - 2000 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 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 General Public License for more details. - -*/ -/* $Id$ */ - -#include "clientincludes.h" -#include "version.h" - -/* Static function prototypes */ -static int silc_client_bad_keys(unsigned char key); -static void silc_client_clear_input(SilcClientInternal app); -static void silc_client_process_message(SilcClientInternal app); -static char *silc_client_parse_command(unsigned char *buffer); - -void silc_client_create_main_window(SilcClientInternal app); - -/* Static task callback prototypes */ -SILC_TASK_CALLBACK(silc_client_update_clock); -SILC_TASK_CALLBACK(silc_client_run_commands); -SILC_TASK_CALLBACK(silc_client_process_key_press); - -/* Long command line options */ -static struct option long_opts[] = -{ - /* Generic options */ - { "server", 1, NULL, 's' }, - { "port", 1, NULL, 'p' }, - { "nickname", 1, NULL, 'n' }, - { "channel", 1, NULL, 'c' }, - { "cipher", 1, NULL, 'r' }, - { "public-key", 1, NULL, 'b' }, - { "private-key", 1, NULL, 'k' }, - { "config-file", 1, NULL, 'f' }, - { "no-silcrc", 0, NULL, 'q' }, - { "debug", 0, NULL, 'd' }, - { "help", 0, NULL, 'h' }, - { "version", 0, NULL, 'V' }, - { "list-ciphers", 0, NULL, 1 }, - { "list-hash-funcs", 0, NULL, 2 }, - { "list-pkcs", 0, NULL, 3 }, - - /* Key management options */ - { "create-key-pair", 0, NULL, 'C' }, - { "pkcs", 1, NULL, 10 }, - { "bits", 1, NULL, 11 }, - { "show-key", 1, NULL, 'S' }, - - { NULL, 0, NULL, 0 } -}; - -/* Command line option variables */ -static char *opt_server = NULL; -static int opt_port = 0; -static char *opt_nickname = NULL; -static char *opt_channel = NULL; -static char *opt_cipher = NULL; -static char *opt_public_key = NULL; -static char *opt_private_key = NULL; -static char *opt_config_file = NULL; -static bool opt_no_silcrc = FALSE; - -static bool opt_create_keypair = FALSE; -static bool opt_show_key = FALSE; -static char *opt_pkcs = NULL; -static char *opt_keyfile = NULL; -static int opt_bits = 0; - -/* SILC Client operations */ -extern SilcClientOperations ops; - -/* Prints out the usage of silc client */ - -void usage() -{ - printf("\ -Usage: silc [options]\n\ -\n\ - Generic Options:\n\ - -s, --server=HOST Open connection to server HOST\n\ - -p, --port=PORT Set PORT as default port to connect\n\ - -n, --nickname=STRING Set default nickname on startup\n\ - -c, --channel=STRING Join channel on startup\n\ - -r, --cipher=CIPHER Use CIPHER as default cipher in SILC\n\ - -b, --public-key=FILE Public key used in SILC\n\ - -k, --private-key=FILE Private key used in SILC\n\ - -f, --config-file=FILE Alternate configuration file\n\ - -q, --no-silcrc Don't load ~/.silcrc on startup\n\ - -d, --debug Enable debugging\n\ - -h, --help Display this help message\n\ - -V, --version Display version\n\ - --list-ciphers List supported ciphers\n\ - --list-hash-funcs List supported hash functions\n\ - --list-pkcs List supported PKCS's\n\ -\n\ - Key Management Options:\n\ - -C, --create-key-pair Create new public key pair\n\ - --pkcs=PKCS Set the PKCS of the public key pair\n\ - --bits=VALUE Set length of the public key pair\n\ - -S, --show-key=FILE Show the contents of the public key\n\ -\n"); -} - -int main(int argc, char **argv) -{ - int opt, option_index = 1; - int ret; - SilcClient silc = NULL; - SilcClientInternal app = NULL; - - silc_debug = FALSE; - - if (argc > 1) - { - while ((opt = - getopt_long(argc, argv, - "s:p:n:c:b:k:f:qdhVCS:", - long_opts, &option_index)) != EOF) - { - switch(opt) - { - /* - * Generic options - */ - case 's': - if (optarg) - opt_server = strdup(optarg); - break; - case 'p': - if (optarg) - opt_port = atoi(optarg); - break; - case 'n': - if (optarg) - opt_nickname = strdup(optarg); - break; - case 'c': - if (optarg) - opt_channel = strdup(optarg); - break; - case 'r': - if (optarg) - opt_cipher = strdup(optarg); - break; - case 'b': - if (optarg) - opt_public_key = strdup(optarg); - break; - case 'k': - if (optarg) - opt_private_key = strdup(optarg); - break; - case 'f': - if (optarg) - opt_config_file = strdup(optarg); - break; - case 'q': - opt_no_silcrc = TRUE; - break; - case 'd': - silc_debug = TRUE; - break; - case 'h': - usage(); - exit(0); - break; - case 'V': - printf("\ -SILC Secure Internet Live Conferencing, version %s\n", - silc_version); - printf("\ -(c) 1997 - 2000 Pekka Riikonen \n"); - exit(0); - break; - case 1: - silc_client_list_ciphers(); - exit(0); - break; - case 2: - silc_client_list_hash_funcs(); - exit(0); - break; - case 3: - silc_client_list_pkcs(); - exit(0); - break; - - /* - * Key management options - */ - case 'C': - opt_create_keypair = TRUE; - break; - case 10: - if (optarg) - opt_pkcs = strdup(optarg); - break; - case 11: - if (optarg) - opt_bits = atoi(optarg); - break; - case 'S': - opt_show_key = TRUE; - if (optarg) - opt_keyfile = strdup(optarg); - break; - - default: - exit(0); - break; - } - } - } - - /* Init signals */ - signal(SIGHUP, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGPIPE, SIG_IGN); - signal(SIGCHLD, SIG_DFL); - signal(SIGALRM, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGSEGV, SIG_DFL); - signal(SIGBUS, SIG_DFL); - signal(SIGFPE, SIG_DFL); - // signal(SIGINT, SIG_IGN); - -#ifdef SOCKS - /* Init SOCKS */ - SOCKSinit(argv[0]); -#endif - - if (opt_create_keypair == TRUE) { - /* Create new key pair and exit */ - silc_cipher_register_default(); - silc_pkcs_register_default(); - silc_hash_register_default(); - silc_hmac_register_default(); - silc_client_create_key_pair(opt_pkcs, opt_bits, - NULL, NULL, NULL, NULL, NULL); - silc_free(opt_pkcs); - exit(0); - } - - if (opt_show_key == TRUE) { - /* Dump the key */ - silc_cipher_register_default(); - silc_pkcs_register_default(); - silc_hash_register_default(); - silc_hmac_register_default(); - silc_client_show_key(opt_keyfile); - silc_free(opt_keyfile); - exit(0); - } - - /* Default configuration file */ - if (!opt_config_file) - opt_config_file = strdup(SILC_CLIENT_CONFIG_FILE); - - /* Allocate internal application context */ - app = silc_calloc(1, sizeof(*app)); - - /* Allocate new client */ - app->client = silc = silc_client_alloc(&ops, app, silc_version_string); - if (!silc) - goto fail; - - /* Read global configuration file. */ - app->config = silc_client_config_alloc(opt_config_file); - - /* XXX Read local configuration file */ - - /* Get user information */ - silc->username = silc_get_username(); - silc->hostname = silc_net_localhost(); - silc->realname = silc_get_real_name(); - - /* Register all configured ciphers, PKCS and hash functions. */ - if (app->config) { - app->config->client = (void *)app; - if (!silc_client_config_register_ciphers(app->config)) - silc_cipher_register_default(); - if (!silc_client_config_register_pkcs(app->config)) - silc_pkcs_register_default(); - if (!silc_client_config_register_hashfuncs(app->config)) - silc_hash_register_default(); - if (!silc_client_config_register_hmacs(app->config)) - silc_hmac_register_default(); - } else { - /* Register default ciphers, pkcs, hash funtions and hmacs. */ - silc_cipher_register_default(); - silc_pkcs_register_default(); - silc_hash_register_default(); - silc_hmac_register_default(); - } - - /* Check ~/.silc directory and public and private keys */ - if (silc_client_check_silc_dir() == FALSE) - goto fail; - - /* Load public and private key */ - if (silc_client_load_keys(silc) == FALSE) - goto fail; - - /* Initialize the client. This initializes the client library and - sets everything ready for silc_client_run. */ - ret = silc_client_init(silc); - if (ret == FALSE) - goto fail; - - /* Register the main task that is used in client. This receives - the key pressings. */ - silc_task_register(silc->io_queue, fileno(stdin), - silc_client_process_key_press, - (void *)silc, 0, 0, - SILC_TASK_FD, - SILC_TASK_PRI_NORMAL); - - /* Register timeout task that updates clock every minute. */ - silc_task_register(silc->timeout_queue, 0, - silc_client_update_clock, - (void *)silc, - silc_client_time_til_next_min(), 0, - SILC_TASK_TIMEOUT, - SILC_TASK_PRI_LOW); - - if (app->config && app->config->commands) { - /* Run user configured commands with timeout */ - silc_task_register(silc->timeout_queue, 0, - silc_client_run_commands, - (void *)silc, 0, 1, - SILC_TASK_TIMEOUT, - SILC_TASK_PRI_LOW); - } - - /* Allocate the input buffer used to save typed characters */ - app->input_buffer = silc_buffer_alloc(SILC_SCREEN_INPUT_WIN_SIZE); - silc_buffer_pull_tail(app->input_buffer, - SILC_BUFFER_END(app->input_buffer)); - - /* Initialize the screen */ - silc_client_create_main_window(app); - silc_screen_print_coordinates(app->screen, 0); - - /* Run the client. When this returns the application will be - terminated. */ - silc_client_run(silc); - - /* Stop the client. This probably has been done already but it - doesn't hurt to do it here again. */ - silc_client_stop(silc); - silc_client_free(silc); - - exit(0); - - fail: - if (opt_config_file) - silc_free(opt_config_file); - if (app->config) - silc_client_config_free(app->config); - if (silc) - silc_client_free(silc); - exit(1); -} - -/* Creates the main window used in SILC client. This is called always - at the initialization of the client. If user wants to create more - than one windows a new windows are always created by calling - silc_client_add_window. */ - -void silc_client_create_main_window(SilcClientInternal app) -{ - void *screen; - - SILC_LOG_DEBUG(("Creating main window")); - - app->screen = silc_screen_init(); - app->screen->input_buffer = app->input_buffer->data; - app->screen->u_stat_line.program_name = silc_name; - app->screen->u_stat_line.program_version = silc_version; - - /* Create the actual screen */ - screen = (void *)silc_screen_create_output_window(app->screen); - silc_screen_create_input_window(app->screen); - silc_screen_init_upper_status_line(app->screen); - silc_screen_init_output_status_line(app->screen); - - app->screen->bottom_line->nickname = silc_get_username(); - silc_screen_print_bottom_line(app->screen, 0); -} - -/* The main task on SILC client. This processes the key pressings user - has made. */ - -SILC_TASK_CALLBACK(silc_client_process_key_press) -{ - SilcClient client = (SilcClient)context; - SilcClientInternal app = (SilcClientInternal)client->application; - int c; - - /* There is data pending in stdin, this gets it directly */ - c = wgetch(app->screen->input_win); - if (silc_client_bad_keys(c)) - return; - - SILC_LOG_DEBUG(("Pressed key: %d", c)); - - switch(c) { - /* - * Special character handling - */ - case KEY_UP: - case KEY_DOWN: - break; - case KEY_RIGHT: - /* Right arrow */ - SILC_LOG_DEBUG(("RIGHT")); - silc_screen_input_cursor_right(app->screen); - break; - case KEY_LEFT: - /* Left arrow */ - SILC_LOG_DEBUG(("LEFT")); - silc_screen_input_cursor_left(app->screen); - break; - case KEY_BACKSPACE: - case KEY_DC: - case '\177': - case '\b': - /* Backspace */ - silc_screen_input_backspace(app->screen); - break; - case '\011': - /* Tabulator */ - break; - case KEY_IC: - /* Insert switch. Turns on/off insert on input window */ - silc_screen_input_insert(app->screen); - break; - case CTRL('j'): - case '\r': - /* Enter, Return. User pressed enter we are ready to - process the message. */ - silc_client_process_message(app); - break; - case CTRL('l'): - /* Refresh screen, Ctrl^l */ - silc_screen_refresh_all(app->screen); - break; - case CTRL('a'): - case KEY_HOME: -#ifdef KEY_BEG - case KEY_BEG: -#endif - /* Beginning, Home */ - silc_screen_input_cursor_home(app->screen); - break; - case CTRL('e'): -#ifdef KEY_END - case KEY_END: -#endif - case KEY_LL: - /* End */ - silc_screen_input_cursor_end(app->screen); - break; - case CTRL('g'): - /* Bell, Ctrl^g */ - beep(); - break; - case KEY_DL: - case CTRL('u'): - /* Delete line */ - silc_client_clear_input(app); - break; - default: - /* - * Other characters - */ - if (c < 32) { - /* Control codes are printed as reversed */ - c = (c & 127) | 64; - wattron(app->screen->input_win, A_REVERSE); - silc_screen_input_print(app->screen, c); - wattroff(app->screen->input_win, A_REVERSE); - } else { - /* Normal character */ - silc_screen_input_print(app->screen, c); - } - } - - silc_screen_print_coordinates(app->screen, 0); - silc_screen_refresh_win(app->screen->input_win); -} - -static int silc_client_bad_keys(unsigned char key) -{ - /* these are explained in curses.h */ - switch(key) { - case KEY_SF: - case KEY_SR: - case KEY_NPAGE: - case KEY_PPAGE: - case KEY_PRINT: - case KEY_A1: - case KEY_A3: - case KEY_B2: - case KEY_C1: - case KEY_C3: -#ifdef KEY_UNDO - case KEY_UNDO: -#endif -#ifdef KEY_EXIT - case KEY_EXIT: -#endif - case '\v': /* VT */ - case '\E': /* we ignore ESC */ - return TRUE; - default: - return FALSE; - } -} - -/* Clears input buffer */ - -static void silc_client_clear_input(SilcClientInternal app) -{ - silc_buffer_clear(app->input_buffer); - silc_buffer_pull_tail(app->input_buffer, - SILC_BUFFER_END(app->input_buffer)); - silc_screen_input_reset(app->screen); -} - -/* Processes messages user has typed on the screen. This either sends - a packet out to network or if command were written executes it. */ - -static void silc_client_process_message(SilcClientInternal app) -{ - unsigned char *data; - SilcUInt32 len; - - SILC_LOG_DEBUG(("Start")); - - data = app->input_buffer->data; - len = strlen(data); - - if (data[0] == '/' && data[1] != ' ') { - /* Command */ - SilcUInt32 argc = 0; - unsigned char **argv, *tmpcmd; - SilcUInt32 *argv_lens, *argv_types; - SilcClientCommand *cmd; - SilcClientCommandContext ctx; - - /* Get the command */ - tmpcmd = silc_client_parse_command(data); - cmd = silc_client_local_command_find(tmpcmd); - if (!cmd && (cmd = silc_client_command_find(tmpcmd)) == NULL) { - silc_say(app->client, app->current_win, "Invalid command: %s", tmpcmd); - silc_free(tmpcmd); - goto out; - } - - /* Now parse all arguments */ - silc_parse_command_line(data + 1, &argv, &argv_lens, - &argv_types, &argc, cmd->max_args); - silc_free(tmpcmd); - - SILC_LOG_DEBUG(("Executing command: %s", cmd->name)); - - /* Allocate command context. This and its internals must be free'd - by the command routine receiving it. */ - ctx = silc_client_command_alloc(); - ctx->client = app->client; - ctx->conn = app->conn; - ctx->command = cmd; - ctx->argc = argc; - ctx->argv = argv; - ctx->argv_lens = argv_lens; - ctx->argv_types = argv_types; - - /* Execute command */ - (*cmd->cb)(ctx); - - } else { - /* Normal message to a channel */ - if (len && app->conn && app->conn->current_channel && - app->conn->current_channel->on_channel == TRUE) { - silc_print(app->client, "> %s", data); - silc_client_send_channel_message(app->client, - app->conn, - app->conn->current_channel, NULL, - 0, data, strlen(data), TRUE); - } - } - - out: - /* Clear the input buffer */ - silc_client_clear_input(app); -} - -/* Returns the command fetched from user typed command line */ - -static char *silc_client_parse_command(unsigned char *buffer) -{ - char *ret; - const char *cp = buffer; - int len; - - len = strcspn(cp, " "); - ret = silc_to_upper((char *)++cp); - ret[len - 1] = 0; - - return ret; -} - -/* Updates clock on the screen every minute. */ - -SILC_TASK_CALLBACK(silc_client_update_clock) -{ - SilcClient client = (SilcClient)context; - SilcClientInternal app = (SilcClientInternal)client->application; - - /* Update the clock on the screen */ - silc_screen_print_clock(app->screen); - - /* Re-register this same task */ - silc_task_register(qptr, 0, silc_client_update_clock, context, - silc_client_time_til_next_min(), 0, - SILC_TASK_TIMEOUT, - SILC_TASK_PRI_LOW); - - silc_screen_refresh_win(app->screen->input_win); -} - -/* Runs commands user configured in configuration file. This is - called when initializing client. */ - -SILC_TASK_CALLBACK(silc_client_run_commands) -{ - SilcClient client = (SilcClient)context; - SilcClientInternal app = (SilcClientInternal)client->application; - SilcClientConfigSectionCommand *cs; - - SILC_LOG_DEBUG(("Start")); - - cs = app->config->commands; - while(cs) { - SilcUInt32 argc = 0; - unsigned char **argv, *tmpcmd; - SilcUInt32 *argv_lens, *argv_types; - SilcClientCommand *cmd; - SilcClientCommandContext ctx; - - /* Get the command */ - tmpcmd = silc_client_parse_command(cs->command); - cmd = silc_client_local_command_find(tmpcmd); - if (!cmd && (cmd = silc_client_command_find(tmpcmd)) == NULL) { - silc_say(client, app->conn, "Invalid command: %s", tmpcmd); - silc_free(tmpcmd); - continue; - } - - /* Now parse all arguments */ - silc_parse_command_line(cs->command + 1, &argv, &argv_lens, - &argv_types, &argc, cmd->max_args); - silc_free(tmpcmd); - - SILC_LOG_DEBUG(("Executing command: %s", cmd->name)); - - /* Allocate command context. This and its internals must be free'd - by the command routine receiving it. */ - ctx = silc_client_command_alloc(); - ctx->client = client; - ctx->conn = app->conn; - ctx->command = cmd; - ctx->argc = argc; - ctx->argv = argv; - ctx->argv_lens = argv_lens; - ctx->argv_types = argv_types; - - /* Execute command */ - (*cmd->cb)(ctx); - - cs = cs->next; - } -}