diff options
author | Steve Slaven <bpk@hoopajoo.net> | 2019-11-05 06:26:14 (GMT) |
---|---|---|
committer | Steve Slaven <bpk@hoopajoo.net> | 2019-11-05 06:26:14 (GMT) |
commit | 9c4c0a1e366b9d932e4ab2ce03a0e80126d93d9b (patch) | |
tree | 928e4c6f49ac50f7e69777b00073df37d7d11e3f /cmd.c | |
parent | eb9898c7fcc017a35c240c1bd83c8a8ff451431a (diff) | |
download | powwow-9c4c0a1e366b9d932e4ab2ce03a0e80126d93d9b.zip powwow-9c4c0a1e366b9d932e4ab2ce03a0e80126d93d9b.tar.gz powwow-9c4c0a1e366b9d932e4ab2ce03a0e80126d93d9b.tar.bz2 |
reorganizing files
Diffstat (limited to 'cmd.c')
-rw-r--r-- | cmd.c | 2713 |
1 files changed, 0 insertions, 2713 deletions
@@ -1,2713 +0,0 @@ -/* - * cmd.c -- functions for powwow's built-in #commands - * - * (created: Finn Arne Gangstad (Ilie), Dec 25th, 1993) - * - * Copyright (C) 1998 by Massimiliano Ghilardi - * - * 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. - * - */ - -#include <limits.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <signal.h> -#include <ctype.h> -#include <time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> - -#ifdef HAVE_LIBDL -#include <dlfcn.h> -#endif - -#include "defines.h" -#include "main.h" -#include "utils.h" -#include "beam.h" -#include "cmd.h" -#include "cmd2.h" -#include "edit.h" -#include "list.h" -#include "map.h" -#include "tcp.h" -#include "tty.h" -#include "eval.h" -#include "log.h" - -/* local function declarations */ -#define F(name) cmd_ ## name(char *arg) - -static void F(help), F(shell), F(action), F(add), - F(addstatic), F(alias), F(at), F(beep), F(bind), - F(cancel), F(capture), F(clear), F(connect), F(cpu), - F(do), F(delim), F(edit), F(emulate), F(exe), - F(file), F(for), F(hilite), F(history), F(host), - F(identify), F(if), F(in), F(init), F(isprompt), - F(key), F(keyedit), - F(load), F(map), F(mark), F(movie), - F(net), F(nice), F(option), - F(prefix), F(print), F(prompt), F(put), - F(qui), F(quit), F(quote), - F(rawsend), F(rawprint), F(rebind), F(rebindall), F(rebindALL), - F(record), F(request), F(reset), F(retrace), - F(save), F(send), F(setvar), F(snoop), F(spawn), F(stop), - F(time), F(var), F(ver), F(while), F(write), - F(eval), F(zap), F(module), F(group), F(speedwalk), F(groupdelim); - -#ifdef BUG_TELNET -static void F(color); -#endif - -#undef F - -/* This must be init'd now at runtime */ -cmdstruct *commands = NULL; - -#define C(name, func, help) { NULL, name, help, func, NULL } - -/* The builtin commands */ -cmdstruct default_commands[] = -{ - C("help", cmd_help, - "[keys|math|command]\tthis text, or help on specified topic"), - C("17", (function_str)0, - "command\t\t\trepeat \"command\" 17 times"), -#ifndef NO_SHELL - C("!", cmd_shell, - "shell-command\t\texecute a shell command using /bin/sh"), -#endif - C("action", cmd_action, - "[[<|=|>|%][+|-]name] [{pattern|(expression)} [=[command]]]\n" - "\t\t\t\tdelete/list/define actions"), - C("add", cmd_add, - "{string|(expr)}\t\tadd the string to word completion list"), - C("addstatic", cmd_addstatic, - "{string|(expr)}\t\tadd the string to the static word completion list"), - C("alias", cmd_alias, - "[name[=[text]]]\t\tdelete/list/define aliases"), - C("at", cmd_at, - "[name [(time-string) [command]]\n\t\t\t\tset time of delayed label"), - C("beep", cmd_beep, - "\t\t\t\tmake your terminal beep (like #print (*7))"), - C("bind", cmd_bind, - "[edit|name [seq][=[command]]]\n" - "\t\t\t\tdelete/list/define key bindings"), - C("cancel", cmd_cancel, - "[number]\t\tcancel editing session"), - C("capture", cmd_capture, - "[filename]\t\tbegin/end of capture to file"), - C("clear", cmd_clear, - "\t\t\tclear input line (use from spawned programs)"), -#ifdef BUG_TELNET - C("color", cmd_color, - "attr\t\t\tset default colors/attributes"), -#endif - C("connect", cmd_connect, - "[connect-id [initstr] [address port]\n" - "\t\t\t\topen a new connection"), - C("cpu", cmd_cpu, - "\t\t\t\tshow CPU time used by powwow"), - C("delim", cmd_delim, - "[normal|program|{custom [chars]}]\n" - "\t\t\t\tset word completion delimeters"), - C("do", cmd_do, - "(expr) command\t\trepeat \"command\" (expr) times"), - C("edit", cmd_edit, - "\t\t\t\tlist editing sessions"), - C("emulate", cmd_emulate, - "[<|!]{text|(expr)}\tprocess result as if received from host"), - C("exe", cmd_exe, - "[<|!]{text|(string-expr)}\texecute result as if typed from keyboard"), - C("file", cmd_file, - "[=[filename]]\t\tset/show powwow definition file"), - C("for", cmd_for, - "([init];check;[loop]) command\n" - "\t\t\t\twhile \"check\" is true exec \"command\""), - C("group", cmd_group, - "[name] [on|off|list]\tgroup alias/action manipulation"), - C("groupdelim", cmd_groupdelim, - "[delimiter]\tchange delimiter for action/alias groups"), - C("hilite", cmd_hilite, - "[attr]\t\t\thighlight your input line"), - C("history", cmd_history, - "[{number|(expr)}]\tlist/execute commands in history"), - C("host", cmd_host, - "[hostname port]]\tset/show address of default host"), - C("identify", cmd_identify, - "[startact [endact]]\tsend MUME client identification"), - C("if", cmd_if, - "(expr) instr1 [; #else instr2]\n" - "\t\t\t\tif \"expr\" is true execute \"instr1\",\n" - "\t\t\t\totherwise execute \"instr2\""), - C("in", cmd_in, - "[label [(delay) [command]]]\tdelete/list/define delayed labels"), - C("init", cmd_init, - "[=[command]]\t\tdefine command to execute on connect to host"), - C("isprompt", cmd_isprompt, - "\t\t\trecognize a prompt as such"), - C("key", cmd_key, - "name\t\t\texecute the \"name\" key binding"), - C("keyedit", cmd_keyedit, - "editing-name\t\trun a line-editing function"), - C("load", cmd_load, - "[filename]\t\tload powwow settings from file"), - C("map", cmd_map, - "[-[number]|walksequence]\tshow/clear/edit (auto)map"), - C("mark", cmd_mark, - "[string[=[attr]]]\t\tdelete/list/define markers"), -#ifdef HAVE_LIBDL - C("module", cmd_module, - "[name]\t\t\tload shared library extension"), -#endif - C("movie", cmd_movie, - "[filename]\t\tbegin/end of movie record to file"), - C("net", cmd_net, - "\t\t\t\tprint amount of data received from/sent to host"), - C("nice", cmd_nice, - "[{number|(expr)}[command]]\n" - "\t\t\t\tset/show priority of new actions/marks"), - C("option", cmd_option, - "[[+|-|=]name]|list\tlist or view various options"), - C("prefix", cmd_prefix, - "string\t\t\tprefix all lines with string"), - C("", cmd_eval, - "(expr)\t\t\tevaluate expression, trashing result"), - C("print", cmd_print, - "[<|!][text|(expr)]\tprint text/result on screen, appending a \\n\n" - "\t\t\t\tif no argument, prints value of variable $0"), - C("prompt", cmd_prompt, - "[[<|=|>|%][+|-]name] [{pattern|(expression)} [=[prompt-command]]]\n" - "\t\t\t\tdelete/list/define actions on prompts"), - C("put", cmd_put, - "{text|(expr)}\t\tput text/result of expression in history"), - C("qui", cmd_qui, - "\t\t\t\tdo nothing"), - C("quit", cmd_quit, - "\t\t\t\tquit powwow"), - C("quote", cmd_quote, - "[on|off]\t\t\ttoggle verbatim-flag on/off"), - C("rawsend", cmd_rawsend, - "{string|(expr)}\tsend raw data to the MUD"), - C("rawprint", cmd_rawprint, - "{string|(expr)}\tsend raw data to the screen"), - C("rebind", cmd_rebind, - "name [seq]\t\tchange sequence of a key binding"), - C("rebindall", cmd_rebindall, - "\t\t\trebind all key bindings"), - C("rebindALL", cmd_rebindALL, - "\t\t\trebind ALL key bindings, even trivial ones"), - C("record", cmd_record, - "[filename]\t\tbegin/end of record to file"), - C("request", cmd_request, - "[editor][prompt][all]\tsend various identification strings"), - C("reset", cmd_reset, - "<list-name>\t\tclear the whole defined list and reload default"), - C("retrace", cmd_retrace, - "[number]\t\tretrace the last number steps"), - C("save", cmd_save, - "[filename]\t\tsave powwow settings to file"), - C("send", cmd_send, - "[<|!]{text|(expr)}\teval expression, sending result to the MUD"), - C("setvar", cmd_setvar, - "name[=text|(expr)]\tset/show internal limits and variables"), - C("snoop", cmd_snoop, - "connect-id\t\ttoggle output display for connections"), - C("spawn", cmd_spawn, - "connect-id command\ttalk with a shell command"), - C("speedwalk", cmd_speedwalk, - "[speedwalk sequence]\texecute a speedwalk sequence explicitly"), - C("stop", cmd_stop, - "\t\t\t\tremove all delayed commands from active list"), - C("time", cmd_time, - "\t\t\t\tprint current time and date"), - C("var", cmd_var, - "variable [= [<|!]{string|(expr)} ]\n" - "\t\t\t\twrite result into the variable"), - C("ver", cmd_ver, - "\t\t\t\tshow powwow version"), - C("while", cmd_while, - "(expr) instr\t\twhile \"expr\" is true execute \"instr\""), - C("write", cmd_write, - "[>|!](expr;name)\t\twrite result of expr to \"name\" file"), - C("zap", cmd_zap, - "connect-id\t\t\tclose a connection"), - { NULL } -}; - -char *_cmd_sort_name( cmdstruct *cmd ) { - if( cmd -> sortname == NULL ) - return( cmd -> name ); - else - return( cmd -> sortname ); -} - -/* Adds a cmd to commands (inserts the ptr in the list, DO NOT FREE IT) */ -void cmd_add_command( cmdstruct *cmd ) { - /* do insert/sort */ - cmdstruct *c = commands; - - /* - * make sure it doesn't override another commmand - * this is important not just because it'd be irritating, - * but if a module defined the command in the global static - * space, it would create an infinite loop because the -> next - * ptr would point at itself - * - * doing it up front because based on the sortname, we may never see - * the dup item if we do it at sort time - */ - for( c = commands; c != NULL; c = c -> next ) { - if( strcmp( cmd -> name, c -> name ) == 0 ) { - PRINTF( "#error %s is already defined\n", c -> name ); - return; - } - } - - - /* catch insertion to head of list */ - if( commands == NULL ) { - /* no commands yet */ - commands = cmd; - cmd -> next = NULL; - return; - } - - if( strcmp( _cmd_sort_name( commands ), _cmd_sort_name( cmd ) ) > 0 ) { - /* this is lower in sort than every item, so - * make it the head of the list */ - cmd -> next = commands; - commands = cmd; - return; - } - - for( c = commands; c != NULL; c = c -> next ) { - if( strcmp( _cmd_sort_name( cmd ), _cmd_sort_name( c ) ) >= 0 ) { - /* Need second check to handle empty string case */ - if( c -> next == NULL || strcmp( _cmd_sort_name( cmd ), _cmd_sort_name( c -> next ) ) <= 0 ) { - /*PRINTF( "Inserting %s after %s\n", cmd -> name, c -> name ); */ - - /* insert after this one, it is greater than this - * entry but less than the next */ - cmd -> next = c -> next; - c -> next = cmd; - return; - } - } - } - - PRINTF( "ERROR INSERTING COMMAND\n" ); -} - -/* Init the command listing, called from main */ -void initialize_cmd(void) { - int i; - - /* Now add the default command list */ - for( i = 0; default_commands[ i ].name; i++ ) - cmd_add_command( &default_commands[ i ] ); -} - -#ifdef HAVE_LIBDL -static void cmd_module(char *arg) { - char libname[1024]; - void *lib; - void (*func)(); - - int pindex; - struct stat junk; - char *prefixes[] = { - PLUGIN_DIR, - ".", - "/lib/powwow", - "/usr/lib/powwow", - "/usr/local/lib/powwow", - "$HOME/.powwow/lib" /* this doesn't work, but is here to remind me :p */ - }; - - arg = skipspace(arg); - - /* I changed it to work this way so that you can have libs in multiple places and - * also eventually to allow it to use .dll instead of .so under the cygwin environment */ - for( pindex = 0; pindex < 5; pindex++ ) { - memset( libname, 0, sizeof libname ); - - /* don't look for name without .so, it breaks if you have a file - * with the same name in the current dir and making it .so for sure - * will skip these files since they are probably not libs to load - snprintf( libname, 1024, "%s/%s", prefixes[ pindex ], arg ); - if( stat( libname, &junk ) == 0 ) { - break; - } - */ - - snprintf( libname, 1024, "%s/%s.so", prefixes[ pindex ], arg ); - if( stat( libname, &junk ) == 0 ) { - break; - } - } - - /* open lib */ - lib = dlopen( libname, RTLD_GLOBAL | RTLD_LAZY ); - if( ! lib ) { - PRINTF( "#module error: %s\n", dlerror() ); - return; - }else{ - PRINTF( "#module loaded %s\n", libname ); - } - - func = dlsym( lib, "powwow_init" ); - if( func ) { - (*func)(); - }else{ - PRINTF( "#module error: %s\n", dlerror() ); - } -} -#endif - -static void cmd_group(char *arg) { - char *group; - int active; - aliasnode *p; - actionnode *a; - - arg = skipspace(arg); - - if( *arg ) { - arg = first_regular( group = arg, ' '); - *arg = '\0'; - arg = skipspace( arg + 1 ); - - if( strcmp( arg, "on" ) == 0 ) { - active = 1; - }else if( strcmp( arg, "off" ) == 0 ) { - active = 0; - }else if( strcmp( arg, "list" ) == 0 ) { - PRINTF( "#not implemented\n" ); - return; - }else{ - PRINTF( "#unknown group command, use off/on/list\n" ); - return; - } - - /* Now loop over all aliases/actions by groupname and toggle */ - for( p = sortedaliases; p; p = p -> snext ) { - if( p -> group && strcmp( p -> group, group ) == 0 ) { - p -> active = active; - } - } - - /* Same for actions */ - for( a = actions; a; a = a -> next ) { - if( a -> group && strcmp( a -> group, group ) == 0 ) { - a -> active = active; - } - } - }else{ - PRINTF( "#group name required\n" ); - } -} - -static void cmd_groupdelim(char *arg) { - if( *arg != 0 ) { - free( group_delim ); - group_delim = my_strdup( arg ); - PRINTF( "#group delimiter is now '%s'\n", group_delim ); - } -} - -static void cmd_help(char *arg) -{ - int i, size; - char *text, *tmp; - FILE *f; - char line[BUFSIZE]; - int len; - cmdstruct *c; - - arg = skipspace(arg); - if (*arg == '#') arg++; - if (!*arg) { - size = 25; - for( c = commands; c != NULL; c = c -> next ) - size += strlen(c -> name) + strlen(c -> help) + 5; - - text = tmp = (char *)malloc(size); - if (!text) { - errmsg("malloc"); - return; - } - - /* do not use sprintf() return value, almost every OS returns a different thing. */ - sprintf(tmp, "#help\n#commands available:\n"); - tmp += strlen(tmp); - - for( c = commands; c != NULL; c = c -> next ) { - sprintf(tmp, "#%s %s\n", c -> name, c -> help); - tmp += strlen(tmp); - } - - message_edit(text, strlen(text), 1, 1); - return; - } - - if (!strncmp(arg, "copyright", strlen(arg))) { - int fd, left, got = 0; - struct stat stbuf; - - if (stat(copyfile, &stbuf) < 0) { - errmsg("stat(copyright file)"); - return; - } - - if (!(text = (char *)malloc(left = stbuf.st_size))) { - errmsg("malloc"); - return; - } - if ((fd = open(copyfile, O_RDONLY)) < 0) { - errmsg("open(copyright file)"); - free(text); - return; - } - while (left > 0) { - while ((i = read(fd, text + got, left)) < 0 && errno == EINTR) - ; - if (i < 0 && errno == EINTR) { - errmsg("read (copyright file)"); - free(text); - close(fd); - return; - } - if (i == 0) - break; - left -= i, got += i; - } - close(fd); - message_edit(text, strlen(text), 1, 1); - return; - } - - /* !copyright */ - - f = fopen(helpfile, "r"); - if (!f) { - PRINTF("#cannot open help file \"%s\": %s\n", - helpfile, strerror(errno)); - return; - } - - while ((tmp = fgets(line, BUFSIZE, f)) && - (line[0] != '@' || strncmp(line + 1, arg, strlen(arg)))) - ; - - if (!tmp) { - PRINTF("#no entry for \"%s\" in the help file.\n", arg); - fclose(f); - return; - } - - if (!(text = (char *)malloc(size = BUFSIZE))) { - errmsg("malloc"); - fclose(f); - return; - } - - /* the first line becomes $TITLE */ - tmp = strchr(line, '\n'); - if (tmp) *tmp = '\0'; - i = sprintf(text, "Help on '%s'\n", line + 1); - - /* allow multiple commands to share the same help */ - while (fgets(line, BUFSIZE, f) && line[0] == '@') ; - - do { - if ((len = strlen(line)) >= size - i) { - /* Not enough space in current buffer */ - - if (!(tmp = (char *)malloc(size += BUFSIZE))) { - errmsg("malloc"); - free(text); - fclose(f); - return; - } else { - memcpy(tmp, text, i); - free(text); - text = tmp; - } - } - memcpy(text + i, line, len); - i += len; - } while (fgets(line, BUFSIZE, f) && line[0] != '@'); - - fclose(f); - text[i] = '\0'; /* safe, there is space */ - message_edit(text, strlen(text), 1, 1); -} - -static void cmd_clear(char *arg) -{ - if (line_status == 0) { - clear_input_line(opt_compact); - if (!opt_compact) { - tty_putc('\n'); - col0 = 0; - } - status(1); - } -} - -#ifndef NO_SHELL -static void cmd_shell(char *arg) -{ - if (!*arg) { - if (opt_info) { - PRINTF("#that's easy.\n"); - } - } else { - tty_quit(); - - if (system(arg) == -1) { - perror("system()"); - } - - tty_start(); - tty_gotoxy(col0 = 0, line0 = lines -1); - tty_puts(tty_clreoln); - } -} -#endif - -static void cmd_alias(char *arg) -{ - arg = skipspace(arg); - if (!*arg) - show_aliases(); - else - parse_alias(arg); -} - -static void cmd_action(char *arg) -{ - arg = skipspace(arg); - if (!*arg) - show_actions(); - else - parse_action(arg, 0); -} - -static void cmd_prompt(char *arg) -{ - arg = skipspace(arg); - if (!*arg) - show_prompts(); - else - parse_action(arg, 1); -} - -static void cmd_beep(char *arg) -{ - tty_putc('\007'); -} - -/* - * create/list/edit/delete bindings - */ -static void cmd_bind(char *arg) -{ - arg = skipspace(arg); - if (!*arg) - show_binds(0); - else if (!strcmp(arg, "edit")) - show_binds(1); - else - parse_bind(arg); -} - -static void cmd_delim(char *arg) -{ - char buf[BUFSIZE]; - int n; - - arg = skipspace(arg); - if (!*arg) { - PRINTF("#delim: \"%s\" (%s)\n", delim_name[delim_mode], DELIM); - return; - } - - arg = split_first_word(buf, BUFSIZE, arg); - n = 0; - while (n < DELIM_MODES && strncmp(delim_name[n], buf, strlen(buf)) != 0) - n++; - - if (n >= DELIM_MODES) { - PRINTF("#delim [normal|program|{custom <chars>}\n"); - return; - } - - if (n == DELIM_CUSTOM) { - if (!strchr(arg, ' ')) { - my_strncpy(buf+1, arg, BUFSIZE-2); - *buf = ' '; /* force ' ' in the delims */ - arg = buf; - } - unescape(arg); - set_custom_delimeters(arg); - } else - delim_mode = n; -} - -static void cmd_do(char *arg) -{ - int type; - long result; - - arg = skipspace(arg); - if (*arg != '(') { - PRINTF("#do: "); - print_error(error=MISMATCH_PAREN_ERROR); - return; - } - arg++; - - type = evall(&result, &arg); - if (REAL_ERROR) return; - - if (type != TYPE_NUM) { - PRINTF("#do: "); - print_error(error=NO_NUM_VALUE_ERROR); - return; - } - - if (*arg == ')') { /* skip the ')' */ - if (*++arg == ' ') - arg++; - } - else { - PRINTF("#do: "); - print_error(error=MISSING_PAREN_ERROR); - return; - } - - if (result >= 0) - while (!error && result--) - (void)parse_instruction(arg, 1, 0, 1); - else { - PRINTF("#do: bogus repeat count \"%ld\"\n", result); - } -} - -static void cmd_hilite(char *arg) -{ - int attr; - - arg = skipspace(arg); - attr = parse_attributes(arg); - if (attr == -1) { - PRINTF("#attribute syntax error.\n"); - if (opt_info) - show_attr_syntax(); - } else { - attr_string(attr, edattrbeg, edattrend); - - edattrbg = ATTR(attr) & ATTR_INVERSE ? 1 - : BACKGROUND(attr) != NO_COLOR || ATTR(attr) & ATTR_BLINK; - - if (opt_info) { - PRINTF("#input highlighting is now %so%s%s.\n", - edattrbeg, (attr == NOATTRCODE) ? "ff" : "n", - edattrend); - } - } -} - -static void cmd_history(char *arg) -{ - int num = 0; - long buf; - - arg = skipspace(arg); - - if (history_done >= MAX_HIST) { - print_error(error=HISTORY_RECURSION_ERROR); - return; - } - history_done++; - - if (*arg == '(') { - arg++; - num = evall(&buf, &arg); - if (!REAL_ERROR && num != TYPE_NUM) - error=NO_NUM_VALUE_ERROR; - if (REAL_ERROR) { - PRINTF("#history: "); - print_error(error=NO_NUM_VALUE_ERROR); - return; - } - num = (int)buf; - } else - num = atoi(arg); - - if (num > 0) - exe_history(num); - else - show_history(-num); -} - -static void cmd_host(char *arg) -{ - char newhost[BUFSIZE]; - - arg = skipspace(arg); - if (*arg) { - arg = split_first_word(newhost, BUFSIZE, arg); - if (*arg) { - my_strncpy(hostname, newhost, BUFSIZE-1); - portnumber = atoi(arg); - if (opt_info) { - PRINTF("#host set to: %s %d\n", hostname, portnumber); - } - } else { - PRINTF("#host: missing portnumber.\n"); - } - } else if (*hostname) - sprintf(inserted_next, "#host %.*s %d", BUFSIZE-INTLEN-8, - hostname, portnumber); - else { - PRINTF("#syntax: #host hostname port\n"); - } -} - -static void cmd_request(char *arg) -{ - char *idprompt = "~$#EP2\nG\n"; - char *ideditor = "~$#EI\n"; - char buf[256]; - int all, len; - - if (tcp_fd == -1) { - PRINTF("#not connected to a MUD!\n"); - return; - } - while (*(arg = skipspace(arg))) { - arg = split_first_word(buf, 256, arg); - if (*buf) { - all = !strcmp(buf, "all"); - len = strlen(buf); - if ((all || !strncmp(buf, "editor", len))) { - tcp_raw_write(tcp_fd, ideditor, strlen(ideditor)); - CONN_LIST(tcp_fd).flags |= IDEDITOR; - if (opt_info) { - PRINTF("#request editor: %s done!\n", ideditor); - } - } - if ((all || !strncmp(buf, "prompt", len))) { - tcp_raw_write(tcp_fd, idprompt, strlen(idprompt)); - CONN_LIST(tcp_fd).flags |= IDPROMPT; - if (opt_info) { - PRINTF("#request prompt: %s done!\n", idprompt); - } - } - } - } - -} - -static void cmd_identify(char *arg) -{ - edit_start[0] = edit_end[0] = '\0'; - if (*arg) { - char *p = strchr(arg, ' '); - if (p) { - *(p++) = '\0'; - my_strncpy(edit_end, p, BUFSIZE-1); - } - my_strncpy(edit_start, arg, BUFSIZE-1); - } - cmd_request("editor"); -} - -static void cmd_in(char *arg) -{ - char *name; - long millisec, buf; - int type; - delaynode **p; - - arg = skipspace(arg); - if (!*arg) { - show_delays(); - return; - } - - arg = first_regular(name = arg, ' '); - if (*arg) - *arg++ = 0; - - unescape(name); - - p = lookup_delay(name, 0); - if (!*p) p = lookup_delay(name, 1); - - if (!*arg && !*p) { - PRINTF("#unknown delay label, cannot show: \"%s\"\n", name); - return; - } - if (!*arg) { - show_delaynode(*p, 1); - return; - } - if (*arg != '(') { - PRINTF("#in: "); - print_error(error=MISMATCH_PAREN_ERROR); - return; - } - arg++; /* skip the '(' */ - - type = evall(&buf, &arg); - if (!REAL_ERROR) { - if (type!=TYPE_NUM) - error=NO_NUM_VALUE_ERROR; - else if (*arg != ')') - error=MISSING_PAREN_ERROR; - } - if (REAL_ERROR) { - PRINTF("#in: "); - print_error(error); - return; - } - - arg = skipspace(arg+1); - millisec = buf; - if (*p && millisec) - change_delaynode(p, arg, millisec); - else if (!*p && millisec) { - if (*arg) - new_delaynode(name, arg, millisec); - else { - PRINTF("#cannot create delay label without a command.\n"); - } - } else if (*p && !millisec) { - if (opt_info) { - PRINTF("#deleting delay label: %s %s\n", name, (*p)->command); - } - delete_delaynode(p); - } else { - PRINTF("#unknown delay label, cannot delete: \"%s\"\n", name); - } -} - -static void cmd_at(char *arg) -{ - char *name, *buf = NULL; - char dayflag=0; - struct tm *twhen; - int num, hour = -1, minute = -1, second = -1; - delaynode **p; - long millisec; - ptr pbuf = (ptr)0; - - arg = skipspace(arg); - if (!*arg) { - show_delays(); - return; - } - - arg = first_regular(name = arg, ' '); - if (*arg) - *arg++ = 0; - - unescape(name); - - p = lookup_delay(name, 0); - if (!*p) p = lookup_delay(name, 1); - - if (!*arg && !*p) { - PRINTF("#unknown delay label, cannot show: \"%s\"\n", name); - return; - } - if (!*arg) { - show_delaynode(*p, 2); - return; - } - if (*arg != '(') { - PRINTF("#in: "); - print_error(error=MISMATCH_PAREN_ERROR); - return; - } - arg++; /* skip the '(' */ - - (void)evalp(&pbuf, &arg); - if (REAL_ERROR) { - print_error(error); - ptrdel(pbuf); - return; - } - if (pbuf) { - /* convert time-string into hour, minute, second */ - buf = skipspace(ptrdata(pbuf)); - if (!*buf || !isdigit(*buf)) { - PRINTF("#at: "); - print_error(error=NO_NUM_VALUE_ERROR); - ptrdel(pbuf); - return; - } - num = atoi(buf); - second = num % 100; - minute = (num /= 100) % 100; - hour = num / 100; - } - if (hour < 0 || hour>23 || minute < 0 || minute>59 - || second < 0 || second>59) { - - PRINTF("#at: #error: invalid time \"%s\"\n", - pbuf && buf ? buf : (char *)""); - error=OUT_RANGE_ERROR; - ptrdel(pbuf); - return; - } - ptrdel(pbuf); - - if (*arg == ')') { /* skip the ')' */ - if (*++arg == ' ') - arg++; - } - else { - PRINTF("#at: "); - print_error(error=MISSING_PAREN_ERROR); - return; - } - - arg = skipspace(arg); - update_now(); - twhen = localtime((time_t *)&now.tv_sec); - /* put current year, month, day in calendar struct */ - - if (hour < twhen->tm_hour || - (hour == twhen->tm_hour && - (minute < twhen->tm_min || - (minute == twhen->tm_min && - second <= twhen->tm_sec)))) { - dayflag = 1; - /* it is NOT possible to define an #at refering to the past */ - } - - /* if you use a time smaller than the current, it refers to tomorrow */ - - millisec = (hour - twhen->tm_hour) * 3600 + (minute - twhen->tm_min) * 60 + - second - twhen->tm_sec + (dayflag ? 24*60*60 : 0); - millisec *= mSEC_PER_SEC; /* Comparing time with current calendar, - we finally got the delay */ - millisec -= now.tv_usec / uSEC_PER_mSEC; - - if (*p) - change_delaynode(p, arg, millisec); - else - if (*arg) - new_delaynode(name, arg, millisec); - else { - PRINTF("#cannot create delay label without a command.\n"); - } -} - -static void cmd_init(char *arg) -{ - arg = skipspace(arg); - - if (*arg == '=') { - if (*++arg) { - my_strncpy(initstr, arg, BUFSIZE-1); - if (opt_info) { - PRINTF("#init: %s\n", initstr); - } - } else { - *initstr = '\0'; - if (opt_info) { - PRINTF("#init cleared.\n"); - } - } - } else - sprintf(inserted_next, "#init =%.*s", BUFSIZE-8, initstr); -} - -static void cmd_isprompt(char *arg) -{ - if (tcp_fd == tcp_main_fd) { - int i; - long l; - arg = skipspace(arg); - if (*arg == '(') { - arg++; - i = evall(&l, &arg); - if (!REAL_ERROR) { - if (i!=TYPE_NUM) - error=NO_NUM_VALUE_ERROR; - else if (*arg != ')') - error=MISSING_PAREN_ERROR; - } - if (REAL_ERROR) { - PRINTF("#isprompt: "); - print_error(error); - return; - } - i = (int)l; - } else - i = atoi(arg); - - if (i == 0) - surely_isprompt = -1; - else if (i < 0) { - if (i > -NUMPARAM && *VAR[-i].str) - ptrtrunc(prompt->str, surely_isprompt = ptrlen(*VAR[-i].str)); - } else - ptrtrunc(prompt->str, surely_isprompt = i); - } -} - -static void cmd_key(char *arg) -{ - keynode *q=NULL; - - arg = skipspace(arg); - if (!*arg) - return; - - if ((q = *lookup_key(arg))) - q->funct(q->call_data); - else { - PRINTF("#no such key: \"%s\"\n", arg); - } -} - -static void cmd_keyedit(char *arg) -{ - int function; - char *param; - - arg = skipspace(arg); - if (!*arg) - return; - - if ((function = lookup_edit_name(arg, ¶m))) - internal_functions[function].funct(param); - else { - PRINTF("#no such editing function: \"%s\"\n", arg); - } -} - -static void cmd_map(char *arg) -{ - arg = skipspace(arg); - if (!*arg) /* show map */ - map_show(); - else if (*arg == '-') /* retrace steps without walking */ - map_retrace(atoi(arg + 1), 0); - else - map_walk(arg, 1, 1); -} - -static void cmd_retrace(char *arg) -{ - map_retrace(atoi(arg), 1); -} - -static void cmd_mark(char *arg) -{ - if (!*arg) - show_marks(); - else - parse_mark(arg); -} - -static void cmd_nice(char *arg) -{ - int nnice = a_nice; - arg = skipspace(arg); - if (!*arg) { - PRINTF("#nice: %d\n", a_nice); - return; - } - if (isdigit(*arg)) { - a_nice = 0; - while (isdigit(*arg)) { - a_nice *= 10; - a_nice += *arg++ - '0'; - } - } - else if (*arg++=='(') { - long buf; - int type; - - type = evall(&buf, &arg); - if (!REAL_ERROR && type!=TYPE_NUM) - error=NO_NUM_VALUE_ERROR; - else if (!REAL_ERROR && *arg++ != ')') - error=MISSING_PAREN_ERROR; - if (REAL_ERROR) { - PRINTF("#nice: "); - print_error(error); - return; - } - a_nice = (int)buf; - if (a_nice<0) - a_nice = 0; - } - arg = skipspace(arg); - if (*arg) { - parse_instruction(arg, 0, 0, 1); - a_nice = nnice; - } -} - -static void cmd_prefix(char *arg) -{ - strcpy(prefixstr, arg); - if (opt_info) { - PRINTF("#prefix %s.\n", *arg ? "set" : "cleared"); - } -} - -static void cmd_quote(char *arg) -{ - arg = skipspace(arg); - if (!*arg) - verbatim ^= 1; - else if (!strcmp(arg, "on")) - verbatim = 1; - else if (!strcmp(arg, "off")) - verbatim = 0; - if (opt_info) { - PRINTF("#%s mode.\n", verbatim ? "verbatim" : "normal"); - } -} - -/* - * change the escape sequence of an existing binding - */ -static void cmd_rebind(char *arg) -{ - parse_rebind(arg); -} - -static void cmd_rebindall(char *arg) -{ - keynode *kp; - char *seq; - - for (kp = keydefs; kp; kp = kp->next) { - seq = kp->sequence; - if (kp->seqlen == 1 && seq[0] < ' ') - ; - else if (kp->seqlen == 2 && seq[0] == '\033' && isalnum(seq[1])) - ; - else { - parse_rebind(kp->name); - if (error) - break; - } - } -} - -static void cmd_rebindALL(char *arg) -{ - keynode *kp; - - for (kp = keydefs; kp; kp = kp->next) { - parse_rebind(kp->name); - if (error) - break; - } -} - -static void cmd_reset(char *arg) -{ - char all = 0; - arg = skipspace(arg); - if (!*arg) { - PRINTF("#reset: must specify one of:\n"); - tty_puts(" alias, action, bind, in (or at), mark, prompt, var, all.\n"); - return; - } - all = !strcmp(arg, "all"); - if (all || !strcmp(arg, "alias")) { - int n; - for (n = 0; n < MAX_HASH; n++) { - while (aliases[n]) - delete_aliasnode(&aliases[n]); - } - if (!all) - return; - } - if (all || !strcmp(arg, "action")) { - while (actions) - delete_actionnode(&actions); - if (!all) - return; - } - if (all || !strcmp(arg, "bind")) { - while (keydefs) - delete_keynode(&keydefs); - tty_add_initial_binds(); - tty_add_walk_binds(); - if (!all) - return; - } - if (all || !strcmp(arg, "in") || !strcmp(arg, "at")) { - while (delays) - delete_delaynode(&delays); - while (dead_delays) - delete_delaynode(&dead_delays); - if (!all) - return; - } - if (all || !strcmp(arg, "mark")) { - while (markers) - delete_marknode(&markers); - if (!all) - return; - } - if (all || !strcmp(arg, "prompt")) { - while (prompts) - delete_promptnode(&prompts); - if (!all) - return; - } - if (all || !strcmp(arg, "var")) { - int n; - varnode **first; - - for (n = 0; n < MAX_HASH; n++) { - while (named_vars[0][n]) - delete_varnode(&named_vars[0][n], 0); - first = &named_vars[1][n]; - while (*first) { - if (is_permanent_variable(*first)) - first = &(*first)->next; - else - delete_varnode(first, 1); - } - } - - for (n = 0; n < NUMVAR; n++) { - *var[n].num = 0; - ptrdel(*var[n].str); - *var[n].str = NULL; - } - if (!all) - return; - } -} - -static void cmd_snoop(char *arg) -{ - if (!*arg) { - PRINTF("#snoop: which connection?\n"); - } else - tcp_togglesnoop(arg); -} - -static void cmd_stop(char *arg) -{ - delaynode *dying; - - if (delays) - update_now(); - - while (delays) { - dying = delays; - delays = dying->next; - dying->when.tv_sec = now.tv_sec; - dying->when.tv_usec = now.tv_usec; - dying->next = dead_delays; - dead_delays = dying; - } - if (opt_info) { - PRINTF("#all delayed labels are now disabled.\n"); - } -} - -static void cmd_time(char *arg) -{ - struct tm *s; - char buf[BUFSIZE]; - - update_now(); - s = localtime((time_t *)&now.tv_sec); - (void)strftime(buf, BUFSIZE - 1, "%a, %d %b %Y %H:%M:%S", s); - PRINTF("#current time is %s\n", buf); -} - -static void cmd_ver(char *arg) -{ - printver(); -} - -static void cmd_emulate(char *arg) -{ - char kind; - FILE *fp; - long start, end, i = 1; - int len; - ptr pbuf = (ptr)0; - - arg = redirect(arg, &pbuf, &kind, "emulate", 0, &start, &end); - if (REAL_ERROR || !arg) - return; - - if (kind) { - char buf[BUFSIZE]; - - fp = (kind == '!') ? popen(arg, "r") : fopen(arg, "r"); - if (!fp) { - PRINTF("#emulate: #error opening \"%s\"\n", arg); - print_error(error=SYNTAX_ERROR); - ptrdel(pbuf); - return; - } - status(-1); /* we're pretending we got something from the MUD */ - while (!error && (!start || i<=end) && fgets(buf, BUFSIZE, fp)) - if (!start || i++>=start) - process_remote_input(buf, strlen(buf)); - - if (kind == '!') pclose(fp); else fclose(fp); - } else { - status(-1); /* idem */ - /* WARNING: no guarantee there is space! */ - arg[len = strlen(arg)] = '\n'; - arg[++len] = '\0'; - process_remote_input(arg, len); - } - ptrdel(pbuf); -} - -static void cmd_eval(char *arg) -{ - arg = skipspace(arg); - if (*arg=='(') { - arg++; - (void)evaln(&arg); - if (*arg != ')') { - PRINTF("#(): "); - print_error(error=MISSING_PAREN_ERROR); - } - } - else { - PRINTF("#(): "); - print_error(error=MISMATCH_PAREN_ERROR); - } -} - -static void cmd_exe(char *arg) -{ - char kind; - char *clear; - long offset, start, end, i = 1; - FILE *fp; - ptr pbuf = (ptr)0; - - arg = redirect(arg, &pbuf, &kind, "exe", 0, &start, &end); - if (REAL_ERROR || !arg) - return; - - if (kind) { - char buf[BUFSIZE]; - - fp = (kind == '!') ? popen(arg, "r") : fopen(arg, "r"); - if (!fp) { - PRINTF("#exe: #error opening \"%s\"\n", arg); - error = SYNTAX_ERROR; - ptrdel(pbuf); - return; - } - offset = 0; - /* We may go in to a loop if a single function is more than 4k, but if that's - * the case then maybe you should break it down a little bit :p */ - while (!error && (!start || i<=end) && fgets(buf + offset, BUFSIZE - offset, fp)) - /* If it ends with \\\n then it's a line continuation, so clear - * the \\\n and do another fgets */ - if (buf[offset + strlen(buf + offset) - 2] == '\\') { - /* Clear \n prefixed with a literal backslash '\\' */ - if ((clear = strstr(buf + offset, "\\\n"))) - *clear = '\0'; - offset += strlen(buf + offset); - } else { - if (!start || i++ >= start) { - buf[strlen(buf)-1] = '\0'; - parse_user_input(buf, 0); - offset = 0; - } - } - - if (kind == '!') pclose(fp); else fclose(fp); - } else - parse_user_input(arg, 0); - ptrdel(pbuf); -} - -static void cmd_print(char *arg) -{ - char kind; - long start, end, i = 1; - FILE *fp; - ptr pbuf = (ptr)0; - - clear_input_line(opt_compact); - - if (!*arg) { - smart_print(*VAR[0].str ? ptrdata(*VAR[0].str) : (char *)"", 1); - return; - } - - arg = redirect(arg, &pbuf, &kind, "print", 1, &start, &end); - if (REAL_ERROR || !arg) - return; - - if (kind) { - char buf[BUFSIZE]; - fp = (kind == '!') ? popen(arg, "r") : fopen(arg, "r"); - if (!fp) { - PRINTF("#print: #error opening \"%s\"\n", arg); - error=SYNTAX_ERROR; - ptrdel(pbuf); - return; - } - while (!error && (!start || i <= end) && fgets(buf, BUFSIZE, fp)) - if (!start || i++>=start) - tty_puts(buf); - tty_putc('\n'); - - if (kind == '!') pclose(fp); else fclose(fp); - } else - smart_print(arg, 1); - ptrdel(pbuf); -} - -static void cmd_send(char *arg) -{ - char *newline, kind; - long start, end, i = 1; - FILE *fp; - ptr pbuf = (ptr)0; - - arg = redirect(arg, &pbuf, &kind, "send", 0, &start, &end); - if (REAL_ERROR ||!arg) - return; - - if (kind) { - char buf[BUFSIZE]; - fp = (kind == '!') ? popen(arg, "r") : fopen(arg, "r"); - if (!fp) { - PRINTF("#send: #error opening \"%s\"\n", arg); - error = SYNTAX_ERROR; - ptrdel(pbuf); - return; - } - while (!error && (!start || i<=end) && fgets(buf, BUFSIZE, fp)) { - if ((newline = strchr(buf, '\n'))) - *newline = '\0'; - - if (!start || i++>=start) { - if (opt_echo) { - PRINTF("[%s]\n", buf); - } - tcp_write(tcp_fd, buf); - } - } - if (kind == '!') pclose(fp); else fclose(fp); - } else { - if (opt_echo) { - PRINTF("[%s]\n", arg); - } - tcp_write(tcp_fd, arg); - } - ptrdel(pbuf); -} - -static void cmd_rawsend(char *arg) -{ - char *tmp = skipspace(arg); - - if (*tmp=='(') { - ptr pbuf = (ptr)0; - arg = tmp + 1; - (void)evalp(&pbuf, &arg); - if (REAL_ERROR) { - print_error(error); - ptrdel(pbuf); - } else if (pbuf) - tcp_raw_write(tcp_fd, ptrdata(pbuf), ptrlen(pbuf)); - } else { - int len; - if ((len = memunescape(arg, strlen(arg)))) - tcp_raw_write(tcp_fd, arg, len); - } -} - -static void cmd_rawprint(char *arg) -{ - char *tmp = skipspace(arg); - - if (*tmp=='(') { - ptr pbuf = (ptr)0; - arg = tmp + 1; - (void)evalp(&pbuf, &arg); - if (REAL_ERROR) { - print_error(error); - ptrdel(pbuf); - } else if (pbuf) - tty_raw_write(ptrdata(pbuf), ptrlen(pbuf)); - } else { - int len; - if ((len = memunescape(arg, strlen(arg)))) - tty_raw_write(arg, len); - } -} - - -static void cmd_write(char *arg) -{ - ptr p1 = (ptr)0, p2 = (ptr)0; - char *tmp = skipspace(arg), kind; - FILE *fp; - - kind = *tmp; - if (kind == '!' || kind == '>') - arg = ++tmp; - else - kind = 0; - - if (*tmp=='(') { - arg = tmp + 1; - (void)evalp(&p1, &arg); - if (REAL_ERROR) - goto write_cleanup; - - if (*arg == CMDSEP) { - arg++; - (void)evalp(&p2, &arg); - if (!REAL_ERROR && !p2) - error = NO_STRING_ERROR; - if (REAL_ERROR) - goto write_cleanup; - } else { - PRINTF("#write: "); - error=SYNTAX_ERROR; - goto write_cleanup; - } - if (*arg != ')') { - PRINTF("#write: "); - error=MISSING_PAREN_ERROR; - goto write_cleanup; - } - arg = ptrdata(p2); - - fp = (kind == '!') ? popen(arg, "w") : fopen(arg, kind ? "w" : "a"); - if (!fp) { - PRINTF("#write: #error opening \"%s\"\n", arg); - error=SYNTAX_ERROR; - goto write_cleanup2; - } - fprintf(fp, "%s\n", p1 ? ptrdata(p1) : (char *)""); - fflush(fp); - if (kind == '!') pclose(fp); else fclose(fp); - } else { - PRINTF("#write: "); - error=MISMATCH_PAREN_ERROR; - } - -write_cleanup: - if (REAL_ERROR) - print_error(error); -write_cleanup2: - ptrdel(p1); - ptrdel(p2); -} - -static void cmd_var(char *arg) -{ - char *buf, *expr, *tmp, kind, type, right = 0, deleting = 0; - varnode **p_named_var = NULL, *named_var = NULL; - FILE *fp; - long start, end, i = 1; - int len, idx; - ptr pbuf = (ptr)0; - - arg = skipspace(arg); - expr = first_regular(arg, '='); - - if (*expr) { - *expr++ = '\0'; /* skip the = */ - if (!*expr) - deleting = 1; - else { - right = 1; - if (*expr == ' ') - expr++; - } - } - - if (*arg == '$') - type = TYPE_TXT_VAR; - else if (*arg == '@') - type = TYPE_NUM_VAR; - else if (*arg) { - print_error(error=INVALID_NAME_ERROR); - return; - } else { - show_vars(); - return; - } - - kind = *++arg; - if (isalpha(kind) || kind == '_') { - /* found a named variable */ - tmp = arg; - while (*tmp && (isalnum(*tmp) || *tmp == '_')) - tmp++; - if (*tmp) { - print_error(error=INVALID_NAME_ERROR); - return; - } - kind = type==TYPE_TXT_VAR ? 1 : 0; - p_named_var = lookup_varnode(arg, kind); - if (!*p_named_var) { - /* it doesn't (yet) exist */ - if (!deleting) { - /* so create it */ - named_var = add_varnode(arg, kind); - if (REAL_ERROR) - return; - if (opt_info) { - PRINTF("#new variable: \"%s\"\n", arg - 1); - } - } else { - print_error(error=UNDEFINED_VARIABLE_ERROR); - return; - } - } else - /* it exists, hold on */ - named_var = *p_named_var; - - idx = named_var->index; - } else { - /* not a named variable, may be - * an unnamed variable or an expression */ - kind = type==TYPE_TXT_VAR ? 1 : 0; - tmp = skipspace(arg); - if (*tmp == '(') { - /* an expression */ - arg = tmp+1; - idx = evalp(&pbuf, &arg); - if (!REAL_ERROR && idx != TYPE_TXT) - error=NO_STRING_ERROR; - if (REAL_ERROR) { - PRINTF("#var: "); - print_error(error); - ptrdel(pbuf); - return; - } - if (pbuf) - buf = ptrdata(pbuf); - else { - print_error(error=INVALID_NAME_ERROR); - return; - } - char err_det; - if (isdigit(*buf) || *buf=='-' || *buf=='+') { - if (sscanf(buf, "%d%c", &idx, &err_det)==1) { - if (idx < -NUMVAR || idx >= NUMPARAM) { - print_error(error=OUT_RANGE_ERROR); - ptrdel(pbuf); - return; - } - } else { - print_error(error=INVALID_NAME_ERROR); - return; - } - } else { - if (!isalpha(*buf) && *buf!='_') { - print_error(error=INVALID_NAME_ERROR); - return; - } - tmp = buf + 1; - while (*tmp && (isalnum(*tmp) || *tmp=='_')) - tmp++; - if (*tmp) { - print_error(error=INVALID_NAME_ERROR); - return; - } - if (!(named_var = *(p_named_var = lookup_varnode(buf, kind)))) { - if (!deleting) { - named_var = add_varnode(buf, kind); - if (REAL_ERROR) { - print_error(error); - ptrdel(pbuf); - return; - } - if (opt_info) { - PRINTF("#new variable: %c%s\n", kind - ? '$' : '@', buf); - } - } else { - print_error(error=UNDEFINED_VARIABLE_ERROR); - ptrdel(pbuf); - return; - } - } - idx = named_var->index; - } - } else { - /* an unnamed var */ - long buf2; - - idx = evall(&buf2, &arg); - if (!REAL_ERROR && idx != TYPE_NUM) - error=NO_STRING_ERROR; - if (REAL_ERROR) { - PRINTF("#var: "); - print_error(error); - return; - } - idx = (int)buf2; - if (idx < -NUMVAR || idx >= NUMPARAM) { - print_error(error=OUT_RANGE_ERROR); - return; - } - /* ok, it's an unnamed var */ - } - } - - - if (type == TYPE_TXT_VAR && right && !*VAR[idx].str) { - /* create it */ - *VAR[idx].str = ptrnew(PARAMLEN); - if (MEM_ERROR) { - print_error(error); - ptrdel(pbuf); - return; - } - } - - if (deleting) { - /* R.I.P. named variables */ - if (named_var) { - if (is_permanent_variable(named_var)) { - PRINTF("#cannot delete variable: \"%s\"\n", arg - 1); - } else { - delete_varnode(p_named_var, kind); - if (opt_info) { - PRINTF("#deleted variable: \"%s\"\n", arg - 1); - } - } - } else if ((type = TYPE_TXT_VAR)) { - /* R.I.P. unnamed variables */ - if (*VAR[idx].str) { - if (idx < 0) { - ptrdel(*VAR[idx].str); - *VAR[idx].str = 0; - } else - ptrzero(*VAR[idx].str); - } - } else - *VAR[idx].num = 0; - ptrdel(pbuf); - return; - } else if (!right) { - /* no right-hand expression, just show */ - if (named_var) { - if (type == TYPE_TXT_VAR) { - pbuf = ptrescape(pbuf, *VAR[idx].str, 0); - if (REAL_ERROR) { - print_error(error); - ptrdel(pbuf); - return; - } - sprintf(inserted_next, "#($%.*s = \"%.*s\")", - BUFSIZE - 10, named_var->name, - BUFSIZE - (int)strlen(named_var->name) - 10, - pbuf ? ptrdata(pbuf) : (char *)""); - } else { - sprintf(inserted_next, "#(@%.*s = %ld)", - BUFSIZE - 8, named_var->name, - *VAR[idx].num); - } - } else { - if (type == TYPE_TXT_VAR) { - pbuf = ptrescape(pbuf, *VAR[idx].str, 0); - sprintf(inserted_next, "#($%d = \"%.*s\")", idx, - BUFSIZE - INTLEN - 10, - pbuf ? ptrdata(pbuf) : (char *)""); - } else { - sprintf(inserted_next, "#(@%d = %ld)", idx, - *VAR[idx].num); - } - } - ptrdel(pbuf); - return; - } - - /* only case left: assign a value to a variable */ - arg = redirect(expr, &pbuf, &kind, "var", 1, &start, &end); - if (REAL_ERROR || !arg) - return; - - if (kind) { - char buf2[BUFSIZE]; - fp = (kind == '!') ? popen(arg, "r") : fopen(arg, "r"); - if (!fp) { - PRINTF("#var: #error opening \"%s\"\n", arg); - error=SYNTAX_ERROR; - ptrdel(pbuf); - return; - } - len = 0; - i = 1; - while (!error && (!start || i<=end) && fgets(buf2+len, BUFSIZE-len, fp)) - if (!start || i++>=start) - len += strlen(buf2 + len); - - if (kind == '!') pclose(fp); else fclose(fp); - if (len>PARAMLEN) - len = PARAMLEN; - buf2[len] = '\0'; - arg = buf2; - } - - if (type == TYPE_NUM_VAR) { - arg = skipspace(arg); - type = 1; - len = 0; - - if (*arg == '-') - arg++, type = -1; - else if (*arg == '+') - arg++; - - if (isdigit(kind=*arg)) while (isdigit(kind)) { - len*=10; - len+=(kind-'0'); - kind=*++arg; - } - else { - PRINTF("#var: "); - print_error(error=NO_NUM_VALUE_ERROR); - } - *VAR[idx].num = len * type; - } - else { - *VAR[idx].str = ptrmcpy(*VAR[idx].str, arg, strlen(arg)); - if (MEM_ERROR) - print_error(error); - } - ptrdel(pbuf); -} - -static void cmd_setvar(char *arg) -{ - char *name; - int i, func = 0; /* show */ - long buf; - - name = arg = skipspace(arg); - arg = first_regular(arg, '='); - if (*arg) { - *arg++ = '\0'; - if (*arg) { - func = 1; /* set */ - if (*arg == '(') { - arg++; - i = evall(&buf, &arg); - if (!REAL_ERROR && i != TYPE_NUM) - error=NO_NUM_VALUE_ERROR; - else if (!REAL_ERROR && *arg != ')') - error=MISSING_PAREN_ERROR; - } else - buf = strtol(arg, NULL, 0); - } else - buf = 0; - - if (REAL_ERROR) { - PRINTF("#setvar: "); - print_error(error); - return; - } - } - - i = strlen(name); - if (i && !strncmp(name, "timer", i)) { - vtime t; - update_now(); - if (func == 0) - sprintf(inserted_next, "#setvar timer=%ld", - diff_vtime(&now, &ref_time)); - else { - t.tv_usec = ((-buf) % mSEC_PER_SEC) * uSEC_PER_mSEC; - t.tv_sec = (-buf) / mSEC_PER_SEC; - ref_time.tv_usec = now.tv_usec; - ref_time.tv_sec = now.tv_sec; - add_vtime(&ref_time, &t); - } - } - else if (i && !strncmp(name, "lines", i)) { - if (func == 0) - sprintf(inserted_next, "#setvar lines=%d", lines); - else { - if (buf > 0) - lines = (int)buf; - if (opt_info) { - PRINTF("#setvar: lines=%d\n", lines); - } - } - } - else if (i && !strncmp(name, "mem", i)) { - if (func == 0) - sprintf(inserted_next, "#setvar mem=%d", limit_mem); - else { - if (buf == 0 || buf >= PARAMLEN) - limit_mem = buf <= INT_MAX ? (int)buf : INT_MAX; - if (opt_info) { - PRINTF("#setvar: mem=%d%s\n", limit_mem, - limit_mem ? "" : " (unlimited)"); - } - } - } - else if (i && !strncmp(name, "buffer", i)) { - if (func == 0) - sprintf(inserted_next, "#setvar buffer=%d", log_getsize()); - else - log_resize(buf); - } else { - update_now(); - PRINTF("#setvar buffer=%d\n#setvar lines=%d\n#setvar mem=%d\n#setvar timer=%ld\n", - log_getsize(), lines, limit_mem, diff_vtime(&now, &ref_time)); - } -} - -static void cmd_if(char *arg) -{ - long buf; - int type; - - arg = skipspace(arg); - if (*arg!='(') { - PRINTF("#if: "); - print_error(error=MISMATCH_PAREN_ERROR); - return; - } - arg++; /* skip the '(' */ - - type = evall(&buf, &arg); - if (!REAL_ERROR) { - if (type!=TYPE_NUM) - error=NO_NUM_VALUE_ERROR; - if (*arg != ')') - error=MISSING_PAREN_ERROR; - else { /* skip the ')' */ - if (*++arg == ' ') - arg++; - } - } - if (REAL_ERROR) { - PRINTF("#if: "); - print_error(error); - return; - } - - if (buf) - (void)parse_instruction(arg, 0, 0, 1); - else { - arg = get_next_instr(arg); - if (!strncmp(arg = skipspace(arg), "#else ", 6)) - (void)parse_instruction(arg + 6, 0, 0, 1); - } -} - -static void cmd_for(char *arg) -{ - int type = TYPE_NUM, loop=MAX_LOOP; - long buf; - char *check, *tmp, *increm = 0; - - arg = skipspace(arg); - if (*arg != '(') { - PRINTF("#for: "); - print_error(error=MISMATCH_PAREN_ERROR); - return; - } - push_params(); - if (REAL_ERROR) - return; - - arg = skipspace(arg + 1); /* skip the '(' */ - if (*arg != CMDSEP) - (void)evaln(&arg); /* execute <init> */ - - check = arg + 1; - - if (REAL_ERROR) - ; - else if (*arg != CMDSEP) { - PRINTF("#for: "); - print_error(error=MISSING_SEPARATOR_ERROR); - } - else while (!error && loop - && (increm=check, (type = evall(&buf, &increm)) == TYPE_NUM - && !error && *increm == CMDSEP && buf)) { - - tmp = first_regular(increm + 1, ')'); - if (*tmp) - (void)parse_instruction(tmp + 1, 1, 1, 1); - else { - PRINTF("#for: "); - print_error(error=MISSING_PAREN_ERROR); - } - - if (!error) { - tmp = increm + 1; - if (*tmp != ')') - (void)evaln(&tmp); - } - - loop--; - } - if (REAL_ERROR) - ; - else if (increm && *increm != CMDSEP) - error=MISSING_SEPARATOR_ERROR; - else if (!loop) - error=MAX_LOOP_ERROR; - else if (type != TYPE_NUM) - error=NO_NUM_VALUE_ERROR; - if (REAL_ERROR) { - PRINTF("#for: "); - print_error(error); - } - if (error!=DYN_STACK_UND_ERROR && error!=DYN_STACK_OV_ERROR) - pop_params(); -} - -static void cmd_while(char *arg) -{ - int type = TYPE_NUM, loop=MAX_LOOP; - long buf; - char *check, *tmp; - - arg = skipspace(arg); - if (!*arg) { - PRINTF("#while: "); - print_error(error=MISMATCH_PAREN_ERROR); - return; - } - push_params(); - - check = ++arg; /* skip the '(' */ - while (!error && loop - && (arg=check, (type = evall(&buf, &arg)) == TYPE_NUM && - !error && *arg == ')' && buf)) { - - if (*(tmp = arg + 1) == ' ') /* skip the ')' */ - tmp++; - if (*tmp) - (void)parse_instruction(tmp, 1, 1, 1); - loop--; - } - if (REAL_ERROR) - ; - else if (*arg != ')') - error=MISSING_PAREN_ERROR; - else if (!loop) - error=MAX_LOOP_ERROR; - else if (type != TYPE_NUM) - error=NO_NUM_VALUE_ERROR; - if (REAL_ERROR) { - PRINTF("#while: "); - print_error(error); - } - if (error!=DYN_STACK_UND_ERROR && error!=DYN_STACK_OV_ERROR) - pop_params(); -} - -static void cmd_capture(char *arg) -{ - arg = skipspace(arg); - - if (!*arg) { - if (capturefile) { - log_flush(); - fclose(capturefile); - capturefile = NULL; - if (opt_info) { - PRINTF("#end of capture to file.\n"); - } - } else { - PRINTF("#capture to what file?\n"); - } - } else { - if (capturefile) { - PRINTF("#capture already active.\n"); - } else { - short append = 0; - /* Append to log file, if the name starts with '>' */ - if (*arg == '>') { - arg++; - append = 1; - } - if ((capturefile = fopen(arg, (append) ? "a" : "w")) == NULL) { - PRINTF("#error writing file \"%s\"\n", arg); - } else if (opt_info) { - PRINTF("#capture to \"%s\" active, \"#capture\" ends.\n", arg); - } - } - } -} - -static void cmd_movie(char *arg) -{ - arg = skipspace(arg); - - if (!*arg) { - if (moviefile) { - log_flush(); - fclose(moviefile); - moviefile = NULL; - if (opt_info) { - PRINTF("#end of movie to file.\n"); - } - } else { - PRINTF("#movie to what file?\n"); - } - } else { - if (moviefile) { - PRINTF("#movie already active.\n"); - } else { - if ((moviefile = fopen(arg, "w")) == NULL) { - PRINTF("#error writing file \"%s\"\n", arg); - } else { - if (opt_info) { - PRINTF("#movie to \"%s\" active, \"#movie\" ends.\n", arg); - } - update_now(); - movie_last = now; - log_clearsleep(); - } - } - } -} - -static void cmd_record(char *arg) -{ - arg = skipspace(arg); - - if (!*arg) { - if (recordfile) { - fclose(recordfile); - recordfile = NULL; - if (opt_info) { - PRINTF("#end of record to file.\n"); - } - } else { - PRINTF("#record to what file?\n"); - } - } else { - if (recordfile) { - PRINTF("#record already active.\n"); - } else { - if ((recordfile = fopen(arg, "w")) == NULL) { - PRINTF("#error writing file \"%s\"\n", arg); - } else if (opt_info) { - PRINTF("#record to \"%s\" active, \"#record\" ends.\n", arg); - } - } - } -} - -static void cmd_edit(char *arg) -{ - editsess *sp; - - if (edit_sess) { - for (sp = edit_sess; sp; sp = sp->next) { - PRINTF("# %s (%u)\n", sp->descr, sp->key); - } - } else { - PRINTF("#no active editors.\n"); - } -} - -static void cmd_cancel(char *arg) -{ - editsess *sp; - - if (!edit_sess) { - PRINTF("#no editing sessions to cancel.\n"); - } else { - if (*arg) { - for (sp = edit_sess; sp; sp = sp->next) - if (strtoul(arg, NULL, 10) == sp->key) { - cancel_edit(sp); - break; - } - if (!sp) { - PRINTF("#unknown editing session %d\n", atoi(arg)); - } - } else { - if (edit_sess->next) { - PRINTF("#several editing sessions active, use #cancel <number>\n"); - } else - cancel_edit(edit_sess); - } - } -} - -static void cmd_net(char *arg) -{ - PRINTF("#received from host: %ld chars, sent to host: %ld chars.\n", - received, sent); -} - - -#ifndef CLOCKS_PER_SEC -# define CLOCKS_PER_SEC uSEC_PER_SEC -#endif -/* hope it works.... */ - -static void cmd_cpu(char *arg) -{ - float f, l; - update_now(); - f = (float)((cpu_clock = clock()) - start_clock) / (float)CLOCKS_PER_SEC; - l = (float)(diff_vtime(&now, &start_time)) / (float)mSEC_PER_SEC; - PRINTF("#CPU time used: %.3f sec. (%.2f%%)\n", f, - (l > 0 && l > f) ? f * 100.0 / l : 100.0); -} - -void show_stat(void) -{ - cmd_net(NULL); - cmd_cpu(NULL); -} - -#ifdef BUG_TELNET -static void cmd_color(char *arg) -{ - int attrcode; - - arg = skipspace(arg); - if (!*arg) { - strcpy(tty_modenorm, tty_modenormbackup); - tty_puts(tty_modenorm); - if (opt_info) { - PRINTF("#standard color cleared.\n"); - } - return; - } - - attrcode = parse_attributes(arg); - if (attrcode == -1) { - PRINTF("#invalid attribute syntax.\n"); - if (opt_info) - show_attr_syntax(); - } else { - int bg = BACKGROUND(attrcode), fg = FOREGROUND(attrcode); - if (fg >= COLORS || bg >= COLORS) { - PRINTF("#please specify foreground and background colors.\n"); - } else { - sprintf(tty_modenorm, "\033[;%c%d;%s%dm", - fg<LOWCOLORS ? '3' : '9', fg % LOWCOLORS, - bg<LOWCOLORS ? "4" :"10", bg % LOWCOLORS); - tty_puts(tty_modenorm); - if (opt_info) { - PRINTF("#standard colour set.\n"); - } - } - } -} -#endif - -static void cmd_connect(char *arg) -{ -#ifdef TERM - PRINTF("#connect: multiple connections not supported in term version.\n"); -#else - char *s1, *s2, *s3 = NULL, *s4 = NULL; - int argc = 1; - - if (!*skipspace(arg)) { - tcp_show(); - return; - } - else { - s1 = strtok(arg, " "); - s2 = strtok(NULL, " "); - if (s2 && *s2) { - argc++; - s3 = strtok(NULL, " "); - if (s3 && *s3) { - argc++; - s4 = strtok(NULL, " "); - if (s4 && *s4) - argc++; - } - } - } - - if (argc <= 2) { - if (*hostname) - tcp_open(s1, s2, hostname, portnumber); - else { - PRINTF("#connect: no host defined!\n#syntax: #connect session-id [[init-str] [hostname] [port]]\n"); - } - } else if (argc == 3) { - if (!*hostname) { - my_strncpy(hostname, s2, BUFSIZE-1); - portnumber = atoi(s3); - } - tcp_open(s1, NULL, s2, atoi(s3)); - } else { - if (!*hostname) { - my_strncpy(hostname, s3, BUFSIZE-1); - portnumber = atoi(s4); - } - tcp_open(s1, s2, s3, atoi(s4)); - } -#endif /* TERM */ -} - - -static void cmd_spawn(char *arg) -{ - char s[BUFSIZE]; - if (*(arg = skipspace(arg))) { - arg = split_first_word(s, BUFSIZE, arg); - if (*arg && *s) { - tcp_spawn(s, arg); - return; - } - } - PRINTF("#syntax: #spawn connect-id command\n"); -} - -/* If you have speedwalk off but still want to use a speedwalk sequence, - * you can manually trigger a speedwalk this way */ -static void cmd_speedwalk(char *arg) -{ - char save_speedwalk = opt_speedwalk; - PRINTF( "Executing speedwalk '%s'\n", arg ); - opt_speedwalk = 1; - if( ! map_walk( skipspace(arg), 0, 0 ) ) { - PRINTF( "Error executing speedwalk\n" ); - } - opt_speedwalk = save_speedwalk; -} - -static void cmd_zap(char *arg) -{ - if (!*arg) { - PRINTF("#zap: no connection name.\n"); - } else - tcp_close(arg); -} - -static void cmd_qui(char *arg) -{ - PRINTF("#you have to write '#quit' - no less, to quit!\n"); -} - -static void cmd_quit(char *arg) -{ - if (*arg) { /* no skipspace() here! */ - PRINTF("#quit: spurious argument?\n"); - } else - exit_powwow(); -} - -static const struct { - const char *name; - char *option; - const char *doc; -} options[] = { - { "autoclear", &opt_autoclear, - "clear input line before executing commands" }, - { "autoprint", &opt_autoprint, - "#print lines matched by actions" }, - { "compact", &opt_compact, - "remove prompt when receiving new messages from mud" }, - { "debug", &opt_debug, - "print commands before executing" }, - { "echo", &opt_echo, - "print command action commands when executed" }, - { "exit", &opt_exit, - "automatically exit powwow when mud connection closes" }, - { "history", &opt_history, - "also save command history" }, - { "info", &opt_info, - "print information about command effects" }, - { "keyecho", &opt_keyecho, - "print command bound to key when executed" }, - { "reprint", &opt_reprint, - "reprint sent commands when getting new prompt" }, - { "sendsize", &opt_sendsize, - "send terminal size when opening connection" }, - { "speedwalk", &opt_speedwalk, - "enable speed walking (ness3ew...)" }, - { "words", &opt_words, - "also save word history" }, - { "wrap", &opt_wrap, - "enable word wrapping" }, - { NULL } -}; - -/* print all options to 'file', or tty if file is NULL; return -1 on - * error, 1 on success */ -int print_all_options(FILE *file) -{ - const char *prefix = "#option"; - int width = (file ? 80 : cols) - 16; - int len = 0, i; - for (i = 0; options[i].name; ++i) { - int res; - if (file) - res = fprintf(file, "%s %c%s", prefix, - *options[i].option ? '+' : '-', - options[i].name); - else - res = tty_printf("%s %c%s", prefix, - *options[i].option ? '+' : '-', - options[i].name); - if (res < 0) - return -1; - /* don't rely on printf() return value */ - len += strlen(prefix) + strlen(options[i].name) + 2; - if (len >= width) { - prefix = "\n#option"; - len = -1; - } else { - prefix = ""; - } - } - if (file) { - fputc('\n', file); - } else { - tty_putc('\n'); - status(1); - } - return 1; -} - -static void cmd_option(char *arg) -{ - char buf[BUFSIZE]; - int count = 0; - - arg = skipspace(arg); - if (!*arg) { - print_all_options(NULL); - return; - } - - while ((arg = skipspace(split_first_word(buf, BUFSIZE, arg))), *buf) { - enum { MODE_ON, MODE_OFF, MODE_TOGGLE, MODE_REP } mode; - char *varp = NULL; - char *p = buf; - char c = *p; - int len = strlen(p); - int i; - - switch (c) { - case '=': mode = MODE_REP; p++; break; - case '+': mode = MODE_ON; p++; break; - case '-': mode = MODE_OFF; p++; break; - default: mode = MODE_TOGGLE; break; - } - count++; - for (i = 0; options[i].name; i++) { - if (strncmp(options[i].name, p, len) == 0) { - varp = options[i].option; - break; - } - } - if (varp == NULL) { - if (strncmp("list", p, len) == 0) { - tty_puts("#list of options:\n"); - for (i = 0; options[i].name; ++i) { - tty_printf("#option %c%-12s %s\n", - *options[i].option ? '+' : '-', - options[i].name, - options[i].doc); - } - } else { - tty_puts("#syntax: #option [[+|-|=]<name>] | list\n"); - } - status(1); - return; - } - - switch (mode) { - case MODE_REP: - sprintf(inserted_next, "#option %c%s", *varp ? '+' : '-', - p); - break; - case MODE_ON: *varp = 1; break; - case MODE_OFF: *varp = 0; break; - case MODE_TOGGLE: *varp ^= 1; break; - } - /* - * reset the reprint buffer if changing its status - */ - if (varp == &opt_reprint) - reprint_clear(); - - /* as above, but always print status if - * "#option info" alone was typed */ - if (mode != MODE_REP && !*arg && count==1 && - (opt_info || (mode == MODE_TOGGLE && varp==&opt_info))) { - PRINTF("#option %s is now o%s.\n", - options[i].name, - *varp ? "n" : "ff"); - } - } -} - -static void cmd_file(char *arg) -{ - arg = skipspace(arg); - if (*arg == '=') { - set_deffile(++arg); - if (opt_info) { - if (*arg) { - PRINTF("#save-file set to \"%s\"\n", deffile); - } else { - PRINTF("#save-file is now undefined.\n"); - } - } - } else if (*deffile) { - sprintf(inserted_next, "#file =%.*s", BUFSIZE-8, deffile); - } else { - PRINTF("#save-file not defined.\n"); - } -} - -static void cmd_save(char *arg) -{ - arg = skipspace(arg); - if (*arg) { - set_deffile(arg); - if (opt_info) { - PRINTF("#save-file set to \"%s\"\n", deffile); - } - } else if (!*deffile) { - PRINTF("#save-file not defined.\n"); - return; - } - - if (*deffile && save_settings() > 0 && opt_info) { - PRINTF("#settings saved to file.\n"); - } -} - -static void cmd_load(char *arg) -{ - int res; - - arg = skipspace(arg); - if (*arg) { - set_deffile(arg); - if (opt_info) { - PRINTF("#save-file set to \"%s\"\n", deffile); - } - } - else if (!*deffile) { - PRINTF("#save-file not defined.\n"); - return; - } - - res = read_settings(); - - if (res > 0) { - /* success */ - if (opt_info) { - PRINTF("#settings loaded from file.\n"); - } - } else if (res < 0) { - /* critical error */ - while (keydefs) - delete_keynode(&keydefs); - tty_add_initial_binds(); - tty_add_walk_binds(); - limit_mem = 1048576; - PRINTF("#emergency loaded default settings.\n"); - } -} - -static char *trivial_eval(ptr *pbuf, char *arg, char *name) -{ - char *tmp = skipspace(arg); - - if (!pbuf) - return NULL; - - if (*tmp=='(') { - arg = tmp + 1; - (void)evalp(pbuf, &arg); - if (!REAL_ERROR && *arg != ')') - error=MISSING_PAREN_ERROR; - if (REAL_ERROR) { - PRINTF("#%s: ", name); - print_error(error); - return NULL; - } - if (*pbuf) - arg = ptrdata(*pbuf); - else - arg = ""; - } - else - unescape(arg); - - return arg; -} - -static void do_cmd_add(char *arg, int is_static) -{ - ptr pbuf = (ptr)0; - char buf[BUFSIZE]; - - arg = trivial_eval(&pbuf, arg, "add"); - if (!REAL_ERROR) - while (*arg) { - arg = split_first_word(buf, BUFSIZE, arg); - if (strlen(buf) >= MIN_WORDLEN) - (is_static ? put_static_word : put_word)(buf); - } - ptrdel(pbuf); -} - -static void cmd_add(char *arg) -{ - do_cmd_add(arg, 0); -} - -static void cmd_addstatic(char *arg) -{ - do_cmd_add(arg, 1); -} - -static void cmd_put(char *arg) -{ - ptr pbuf = (ptr)0; - arg = trivial_eval(&pbuf, arg, "put"); - if (!REAL_ERROR && *arg) - put_history(arg); - ptrdel(pbuf); -} - - |