📄 cmds.c
字号:
/* Copyright (c) 2000 Kevin Sullivan <nite@gis.net> * * Please refer to the COPYRIGHT file for more information. *//* this file defines "user commands" such as /get and /search. */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pwd.h>#include <errno.h>#include <netdb.h>#include <ncurses.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/time.h>#include <unistd.h>#include <signal.h>#include <time.h>#include <math.h>#include <ctype.h>#include "getopt.h"#include "defines.h"#include "colors.h"#include "codes.h"#include "lists.h"#include "handlers.h"#include "alias.h"#include "nap.h"#include "sscr.h"#include "event.h"#include "winio.h"#include "timer.h"#include "scheck.h"#include "irc.h"#include "cmds.h"#include "scmds.h"#include "mp3s.h"#include "dlul_screen.h"#include "missing.h"#ifdef MEMWATCH #include "memwatch.h"#endifextern info_t info;extern scroll_t *mscroll, *mscrollend;extern int lastlogflag;extern chans_t *chanl, *curchan, *recent;extern int tind, ircsock;extern int noprint, ircmode;extern int ipcs[2];extern char *mnick;extern hotlist_t *hlist;extern void *hnd;extern alias_t *alhead;extern handler_t *hndhead;extern int quit_now, quit_after_transfers, upsocks, downsocks;extern sock_t *socklist;extern cmds_t *cmdl;extern sets_t *setl;int fl, wmode = 0;unsigned char *dwi=NULL;char *tbuf = NULL;upload_t *up = NULL; /* the upload list */download_t *down = NULL; /* the download list */ssearch_t *search=NULL; /* search results */int srch=0; /* set while a search is in progress (and thus the state of the search result list is not well-defined) */int noping; /* when a search is in progress, this flag indicates whether we should collect ping results or not */int quit_after_transfers = 0; /* set by /tquit and checked by tevent() */inbrowse_t directbrowse = {COMPLETE, NULL, (time_t)0, NULL, NULL}; /* holds state for an incoming direct browse connection */out_nap_cmd_t out[] = { { "about", 1, dabout, "- Shows credits" }, { "alias", 1, dalias, "[name] [args] - Creates an alias, or lists current aliases" }, { "aliaslist", 1, daliaslist, "- Shows current list of aliases" }, { "announce", 0, dannounce, "<msg> - Broadcasts a message to all users" }, { "ban", 0, dban, "[user/IP] - Bans specified user or IP, or lists banned users" }, { "banlist", 0, dbanlist, "- Prints a list of the current bans on the server" }, { "block", 0, dblock, "[IP] [reason] - Blocks the specified IP, or lists blocked users" }, { "blocklist", 0, dblocklist, "- Gives a list of current blocked users" }, { "break", 1, dbreak, "- Breaks out of a loop" }, { "browse", 0, dbrowse, "<user> - Browses user's files" }, { "browse2", 0, dbrowse2, "<user> - Directly browse user's files" }, { "cban", 0, dcban, "[user] [reason] - Bans a user from a channel, or lists banned users" }, { "cbanlist", 0, dcbanlist, "- Returns a list of banned users in a channel" }, { "chupload", 1, dchupload, "<path> - Changes your upload path (still need to /rebuild to update your files)" }, { "clear", 1, dclear, "- Clears your screen buffer" }, { "clearalias", 1, dclearalias, "- Clears all aliases" }, { "clearhandler", 1, dclearhandler, "- Clears all handlers" }, { "clist", 0, dclist, "- Gets a list of channels" }, { "clist2", 0, dclist2, "- Gets a list of channels (includes user created)" }, { "cloak", 0, dcloak, "- Cloaks yourself" }, { "conf", 0, dsetconf, "<config-string> - Request a change in server configuration variables" }, { "cunban", 0, dcunban, "<user> [reason] - Unbans a user from a channel" }, { "ddown", 0, dddown, "<number or range> - Deletes downloads by number as returned from /pdown" }, { "dec", 1, ddec, "- Decreases the variable by one" }, { "debug", 1, ddebug, "<level> - Sets debug level" }, { "disconnect", 0, ddisconnect, "- Disconnects you from the server" }, { "dlul", 1, ddlul, "- Switches to the download/upload monitor screen" }, { "dns", 1, ddns, "<host/IP> - Attempts to resolve the specified address" }, { "done", 1, ddone, "- Ends an alias" }, { "dtimer", 1, ddtimer, "<number> - Delete the timed event with the given number" }, { "dup", 0, ddup, "<number or range> - Deletes uploads by number as returned from /pup" }, { "echo", 1, decho, "<text> - Echos text to the screen" }, { "eval", 1, deval, "<name> - Returns the value of a variable" }, { "exec", 1, dexec, "[-o] <command> - Executes a command from a shell and redirects the input to the client" }, { "fdown", 0, dfdown, "<number or range> - Gets information on the user as returned from /pdown" }, { "finger", 0, dwhois, "<user> - Gets information on the specified user" }, { "force", 0, dforce, "<number or range> - Forces download of queued items, overriding download limit" }, { "fup", 0, dfup, "<number or range> - Gets information on the user as returned from /pup" }, { "g", 0, dg, "<number or range> - Gets file by number as returned from /search" }, { "get", 0, dg, "<number or range>... - Gets file by number as returned from /search" }, { "getservers", 0, dgetservers, "- Read server list from napigator-style metaserver" }, { "gusers", 0, dgusers, "- Gets a global list of users" }, { "handler", 1, dhandler, "[code] [args] - Adds a handler, or prints current handlers" }, { "handlerlist", 1, dhandlerlist, "- Returns a list of handlers created" }, { "help", 0, dhelp, "<command> - Returns help on the specified command" }, { "hotlist", 0, dnotify, "[user] - Adds a user to your hotlist, or shows current hotlist" }, { "if", 1, dif, "(<val> <op> <val>) <cmd> - Compares two values" }, { "ignore", 0, dignore, "[user] - Ignores a user, or lists ignored users" }, { "ignoreclear", 0, dignoreclear, "- Clears your ignore list" }, { "ignorelist", 0, dignorelist, "- Lists ignored users" }, { "inc", 1, dinc, "<var> - Increases the variable by 1" }, { "irc", 0, dirc, NULL }, { "join", 0, djoin, "[chan] - Joins the specified channel, or prints a list of all channels" }, { "kick", 0, dkick, "<user> [reason] - Kicks a user from a channel" }, { "kickall", 0, dkickall, "<user> [reason] - Kicks a user from all channels you and the user are in" }, { "kill", 0, dkill, "<user> - Kills the specified user" }, { "lastlog", 1, dlastlog, "<str> - Returns all occurences of \"str\" that have been said or printed" }, { "loadalias", 1, dloadalias, "[filename] - Loads a list of aliases from a file" }, { "loadchannels", 1, dloadchannels, "[filename] - Reads channels from a filename and joins them" }, { "loadconfig", 1, dloadconfig, "[filename] - Loads a list of settings from a filename" }, { "loadhandler", 1, dloadhandler, "[filename] - Loads a list of handlers from a filename" }, { "me", 0, dme, "<string> - Does an emotion" },#ifdef MEMWATCH { "memwatch", 0, dmemwatch, " - Prints details about memory usage to a log file" },#endif { "msg", 0, dtell, "<user> <msg> - Sends the user the message specified" }, { "muzzle", 0, dmuzzle, "<user> <msg> - Muzzles the user with the specified message" }, { "names", 0, dusers, "<channel> - Gets a list of channel users" }, { "news", 1, dnews, "- Checks for any news on the client" }, { "noprint", 1, dnoprint, "- Stops the client from echoing anything until the command returns" }, { "notify", 0, dnotify, "[user] - Adds a user to your hotlist, or shows current hotlist" }, { "opsay", 0, dopsay, "<msg> - Broadcasts a message to all moderators/admins/elite" }, { "part", 0, dpart, "[chan/user] - Parts the specified or current channel or query" }, { "pchans", 1, dpchans, "- Shows which channels you are on" }, { "pdown", 1, dpdown, "[dqsf] - Gives a listing of your current downloads. Optional flags select downloading, queued, succeeded, failed items." }, { "ping", 0, dping, "<user> - Pings a user" }, { "psocks", 1, dpsocks, "- Print the socket list (for debugging purposes)" }, { "pup", 0, dpup, "- Gives a listing of your current uploads" }, { "purge", 0, dpurge, "- Removes all stopped items from upload and download lists" }, { "purgedown", 0, dpurgedown, "- Removes all stopped items from download list" }, { "purgeup", 0, dpurgeup, "- Removes all stopped items from upload list" }, { "pvars", 0, dpvars, "- Prints the values of all variables currently set" }, { "query", 0, dquery, "<user> - Queries a user" }, { "q", 0, dquit, "- Closes the program" }, { "quit", 0, dquit, "- Closes the program" }, { "rebuild", 1, drebuild, "- Rebuilds your library unconditionally. See also /update." }, { "reconnect", 0, dreconnect, "- Reconnects you to the next available server on the list" }, { "reload", 0, dreloadconf, "<config-variable> - Resets server configuration parameter to its default value" }, { "repeat", 1, drepeat, "<min:sec> <cmd> - Initiates a timed event which repeats every <min:sec> interval" }, { "results", 1, dresults, "- Switches to the search results screen" }, { "retry", 0, dretry, "<number or range> - Puts stopped downloads back in the download queue" }, { "retryall", 0, dretryall, " - Puts all stopped downloads back in the download queue" }, { "savealias", 1, dsavealias, "[filename] - Saves current aliases" }, { "savechannels", 1, dsavechannels, "[filename] - Saves current channels to a filename" }, { "saveconfig", 1, dsaveconfig, "[filename] - Saves current settings to a filename" }, { "savehandler", 1, dsavehandler, "[filename] - Saves current handlers to a filename" }, { "say", 0, dsay, "<msg> - Sends msg to the current channel" }, { "search", 0, dsearch, "[-b>bitrate] [-c>speed] [-r>freq] [-s>size] [-d>duration] [-x exclude]... [-t filetype] [-mmaxresults] [-l] [-p] [-f] <query> - Searches the napster database" }, { "serv", 0, dserver, "[IP:port] - Connects to the specificed server and port, or shows current server and port" }, { "server", 0, dserver, "[IP:port] - Connects to the specificed server and port, or shows current server and port" }, { "set", 1, dset, "[name] [value] - Sets a user variable, or prints current values" }, { "setdataport", 0, ddatap, "<user> <port> - Sets a user's data port" }, { "setlevel", 0, dsetlevel, "<channel> <level> - ?" }, { "setlinespeed", 0, dlspeed, "<user> <speed> - Changes a user's linespeed" }, { "setpassword", 0, duserpass, "<user> <password> - Sets a user's password" }, { "setuserlevel", 0, dlevel, "<user> <level> - Changes a user's userlevel" }, { "sraw", 0, dsraw, "<type> <string> - Send raw command to the server" }, { "stop", 1, dstop, "- Returns from the current command and stops all processing on it" }, { "sver", 0, dsver, "- Returns the server version" }, { "tell", 0, dtell, "<user> <msg> - Sends the user the message specified" }, { "timer", 1, dtimer, "<min:sec> <cmd> - Initiates a timer to execute in the specified time" }, { "tlist", 1, dtlist, "- Prints out a list of the current timers" }, { "topic", 0, dtopic, "<channel> <topic> - Changes a channel's topic" }, { "tquit", 0, dtquit, "- Quits when all remaining transfers have completed. Can be canceled with /unquit." }, { "unalias", 1, dunalias, "<name> - Removes an alias" }, { "unban", 0, dunban, "<IP> - Unbans the specified IP" }, { "unblock", 0, dunblock, "<IP> - Unblocks the specified IP" }, { "unhandler", 1, dunhandler, "<code> - Removes a handler" }, { "unhotlist", 0, dunnotify, "<user> - Removes a user from your hotlist" }, { "unignore", 0, dunignore, "<user> - Unignores a user" }, { "unmuzzle", 0, dunmuzzle, "<user> - Unmuzzles the user" }, { "unnotify", 0, dunnotify, "<user> - Removes a user from your hotlist" }, { "unquit", 0, dunquit, "- Cancels the effect of /tquit" }, { "unset", 1, dunset, "<name> - Unsets a variable" }, { "update", 1, dupdate, "- Rebuilds your library if necessary. See also /rebuild." }, { "while", 1, dwhile, "(<val> <op> <val>) cmd - Keeps executing cmd while the comparison is true" }, { "whois", 0, dwhois, "<user> - Gets information on the specified user" }, { "window", 1, dwindow, "- Enables/disables window mode" }, { "wstats", 1, dwstats, NULL }, { NULL, 0, NULL, NULL },};/* destructively replaces double quotes by single quotes - returns the same string. It used to be that napster servers would cut off private and channel message if they contained a double quote. With newer servers, this is no longer a problem; however, it's still needed for the /me command. */char *fixquotes(char *s) { char *p = s; while (*p) { if (*p == '\"') *p = '\''; p++; } return s;}/* free the given channel datastructure */void freechan(chans_t *c) { user_t *u; if (c) { list_forall_unlink(u, c->users) { free(u->nm); free(u->addr); free(u); } free(c->topic); free(c->nm); free(c->key); free(c); }} /* the following two functions replace the old "upchan" function *//* rotate curchan through the channel list. If curchan==NULL, go to first channel. If there are no channels, set curchan to NULL. Also set channel title indentation level to 0. */void nextchan() { tind = 0; if (curchan) { curchan = curchan->next; } if (!curchan) { curchan = chanl; }}/* delete the given channel c from the channel list. If c==curchan, also change curchan to the next valid channel in the list, or to NULL if the list is empty. Also set channel title indentation level to 0. */void delchan(chans_t *c) { tind = 0; /* modify curchan */ if (curchan == c) { curchan = c->next; if (curchan == NULL) { curchan = chanl; } if (curchan == c) { curchan = NULL; } } /* now curchan is definitely not c */ /* delete c from channel list */ list_unlink(chans_t, chanl, c); if (c) { freechan(c); }}/* reduces a list of tokens. Input is a list IN of CNT tokens. Output is a NULL-terminated list OUT of *RCNT tokens. The original list IN is deallocated. OUT is obtained from IN by replacing any consecutive tokens A B ... C by a single token, if A starts with "$" and if no initial segment of A B ... C has balanced parentheses. */char **fxv(char **in, int cnt, int *rcnt){ int i, k, j, c; char **out; out = (char **)malloc((cnt+1) * sizeof(char *)); for (i=0, k=0; in[i]; k++) { out[k] = strdup(in[i]); if (*in[i] == '$' && strchr(in[i], '(')) { c = 0; while (1) { for (j=0;in[i][j];j++) { if (c < 0) c = 0; if (in[i][j] == '(') c++; else if (in[i][j] == ')') c--; } i++; if (!c || !in[i]) break; out[k] = (char *)realloc(out[k], strlen(out[k])+2+strlen(in[i])); strcat(out[k], " "); strcat(out[k], in[i]); } } else { i++; } } /* for (i=0,k=0,*rcnt=0;in[i];) */ out[k] = NULL; *rcnt = k; for (i=0;i<cnt;i++) free(in[i]); free(in); return(out);}/* original version of fxv. Presumably they do the same thing, but fxv_old is more complicated and uses static limits on the size of tokens/token lists */char **fxv_old(char **in, int cnt, int *rcnt){ int i, k, j, n=cnt, c=0; char **ret; ret = (char **)malloc(4096); for (i=0,k=0,*rcnt=0;in[i];i++,k++) { if (*in[i] == '$' && strchr(in[i], '(')) { ret[k] = (char *)malloc(512); ret[k+1] = NULL; memset(ret[k], 0, 512); do { if (!in[i]) break; for (j=0;in[i][j];j++) { if (c < 0) c = 0; if (in[i][j] == '(') c++; else if (in[i][j] == ')') c--; } strcat(ret[k], in[i++]); strcat(ret[k], " "); } while (c); ret[k][strlen(ret[k])-1] = 0; ret[k] = (char *)realloc(ret[k], strlen(ret[k])+1); if (!in[i]) { k++; break; } else i--; } else { ret[k] = strdup(in[i]); ret[k+1] = NULL; } } if (ret[k]) k++; ret[k] = NULL; *rcnt = k; for (i=0;i<n;i++) free(in[i]); free(in); return(ret);}/* The functions parseout and parsenout, as well as the O_NAP_FUNC * functions (command handlers), use their return values to control * the control flow. The return values observe the following * convention: If the return value is * * 1: continue execution normally, * * 2: skip the remaining commands. If inside a loop, continue * with the next loop iteration. (This is like "continue" in C). * * -4: break out of the most recent loop, then continue * normally. (This is like "break" in C). * * -3: stop execution and unwind to the top level. * * Here, "top level" means the enclosing call of parseout, normally * from winio.c:input(), but sometimes from timer.c or irc.c:inap. * * 2 is returned by dstop(). * -4 is returned by dbreak(). * -3 is returned by: ddone(), dquit(), dwhile() if the loop was * interrupted by a SIGINT, and sometimes by commands which produce * a fatal error (although this is not consistently done). * * Previously, the return values 0, -1, and -2 also existed, but they * were used in buggy ways and have been removed. In particular, * dquit() now uses a global variable to signal its intent to quit * nap, rather than doing it through a return value. -PS * **//* parseout: parse and execute the (user) command in buf. If it's an alias, expand it, otherwise let parseoutn handle it (or its various subparts individually?) *//* ### warning: this function contains static string limits */int parseout(int s, char *buf, WINDOW *win){ char **tok, *st, t[2048], *b, *p, nb[2048]; alias_t *cur; int i, j=0, k, cnt, c = 0, rn, sw, js=0, x, y, f=0, bc = 0; if (*buf == '/') { b = strdup(buf+1); sw = 1; } else { b = strdup(buf); sw = 0; } while (1) { if (!b[j]) break; if (sw && !bc) { memset(t, 0, sizeof(t)); while (b[j] && b[j] == ' ') /* read past spaces */ j++; for (k=0, c=0, f=j; b[j]; j++) { if (b[j] == '{') c++; else if (b[j] == '}') c--; else if ((b[j] == '|' || b[j] == '\n' || !b[j]) && !c) break; t[k] = b[j]; k++; if (c < 0) c = 0; } } else { strcpy(t, b); j = strlen(t); } if (*t == '#') { if (b[j])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -