📄 alias.c
字号:
/* Copyright (c) 2000 Kevin Sullivan <nite@gis.net> * * Please refer to the COPYRIGHT file for more information. */#include <string.h>#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <ncurses.h>#include <sys/time.h>#include "colors.h"#include "defines.h"#include "scmds.h"#include "scheck.h"#include "vfuncs.h"#include "alias.h"#include "lists.h"#include "nap.h"#include "sscr.h"#include "winio.h"#ifdef MEMWATCH #include "memwatch.h"#endif/* the procedures in this file operate on two data structures: a * linked list of aliases and a linked list of "sets". Here a "set" is * something that is set by the command "set", i.e., a variable. * * alias_t provides for a simple key-value structure, where the key is * a string called "nm" and the value is a string called "args" (the * replacement for alias "nm"). * * sets_t provides a similar key-value structure: the key is again a * string called "nm", and the value is a pair of a string "d" and an * integer "t". Apparently the intention is that t==0 if d represents * a number, t==1 otherwise. * * There is also the array vars, which is defined in vfuncs.c, and * maps certain names to functions. * */extern vars_t vars[];extern info_t info;alias_t *alhead;sets_t *setl;/* ---------------------------------------------------------------------- *//* the first part of this file deals with "sets", or variables that can be "/set" */hardwired_t hw[] = { { "user", 1, &info.user, 0, "# your napster username" }, { "pass", 2, &info.pass, 0, "# your napster password - optional" }, { "email", 1, &info.email, 0, "# your napster email address" }, { "upload", 1, &info.up, 0, "# list of upload directories, separated by semicolons" }, { "download", 1, &info.down, 0, "# your download directory" }, { "incomplete", 1, &info.incomplete, 0, "# your directory for incomplete files" }, { "connection", 0, 0, 0, "# your connection speed, according to the following chart:\n" "#\n" "# Connection | Number\n" "# -------------------\n" "# Unknown | 0\n" "# 14.4 | 1\n" "# 28.8 | 2\n" "# 33.6 | 3\n" "# 56.7 | 4\n" "# 64K ISDN | 5\n" "# 128K ISDN | 6\n" "# Cable | 7\n" "# DSL | 8\n" "# T1 | 9\n" "# T3 or > | 10" }, { "maxuploads", 0, 0, 0, "# maximal number of simultaneous uploads allowed" }, { "maxupuser", 0, 0, 0, "# maximum number of simultaneous uploads per user" }, { "maxdownloads", 0, 0, 0, "# maximum number of simultaneous downloads allowed" }, { "maxdownuser", 0, 0, 0, "# maximum number of simultaneous downloads per user" }, { "servers", 1, &info.serverlist, 0, "# list of servers, separated by semicolons (note: this is now ignored\n" "# and overwritten unless nometa is set)" }, { "dataport", 1, &info.dataport, 0, "# port or range of ports to use for client-client connections.\n# Set this to 0 if you are behind a firewall" }, { "logfile", 1, &info.logfile, 0, "# log file for transfer logs" }, { "logallfile", 1, &info.logallfile, 0, "# log file for logging everything" }, { "bandwidthdown", 0, 0, &info.bandwidthdown, "# global bandwidth limit for downloads (in kB/s)" }, { "bandwidthdown1", 0, 0, &info.bandwidthdownconn, "# download bandwidth limit per connection (in kB/s)" }, { "bandwidthup", 0, 0, &info.bandwidthup, "# global bandwidth limit for uploads (in kB/s)" }, { "bandwidthup1", 0, 0, &info.bandwidthupconn, "# upload bandwidth limit per connection (in kB/s)" }, { "announcepongs", 0, 0, 0, "# should receipt of PONG packets be announced?" }, { "autopurge", 0, 0, 0, "# time to delete stopped items from up- and download lists" }, { "autopurgeup", 0, 0, 0, "# time to delete stopped items from upload list" }, { "autopurgedown", 0, 0, 0, "# time to delete stopped items from download list" }, { "autoreply", 0, 0, 0, "# a string to send as an automatic reply to incoming user messages" }, { "autorestart", 0, 0, &info.autorestart, "# automatically reconnect when connection to server lost?" }, { "connecttimeout", 0, 0, 0, "# timeout after this many seconds while connecting to server" }, { "cursorfollowsscreen", 0, 0, 0, "# should PgUp and PgDn move the screen, rather than the cursor, on the\n# search result screen?" }, { "debug", 0, 0, 0, "# debug level" }, { "hash", 0, 0, 0, "# shall we calculate MD5 hashes? Note that most servers don't use them." }, { "identity", 0,0, 0, "# fake client id for fooling servers that refuse connections from nap client" }, { "incompletesuffix", 0, 0, 0, "# suffix to use for incomplete files" }, { "libraryfile", 1, &info.shared_filename, 0, "# location of your library file" }, { "metaserver", 0, 0, 0, "# URL of a napigator-style metaserver" }, { "metatimeout", 0, 0, 0, "# timeout for connecting to metaserver" }, { "napping", 0, 0, 0, "# relative or absolute filename of the napping program to use" }, { "newstimeout", 0, 0, 0, "# timeout for retrieving news" }, { "noechosets", 0, 0, 0, "# should the /set command be quiet?" }, { "nomasq", 0, 0, 0, "# should filename masquerading be disabled?" }, { "nometa", 0, 0, 0, "# skip connecting to metaserver on startup?" }, { "nonews", 0, 0, 0, "# do you want to skip news about new releases on startup?" }, { "noping", 0, 0, 0, "# do you want to disable pings?" }, { "noresultscreen", 0, 0, 0, "# should search results be displayed on the main screen?" }, { "noscroll", 0, 0, 0, "# should main screen not scroll to bottom automatically on output?" }, { "proxy", 0, 0, 0, "# URL of http proxy, if needed to access www through firewall" }, { "savechannels", 0, 0, 0, "# should your open channels to be saved between sessions?" }, { "savepass", 0, 0, 0, "# should password be saved in config file?" }, { "scrollsize", 0, 0, 0, "# limit on the number of lines in main screen, or 0 for no limit" }, { "sdefaults", 0, 0, 0, "# default keystrokes for search result screen appearance" }, { "sharetypes", 0, 0, 0, "# semicolon-separated list of file extensions to share in addition to mp3 files\n" "# Case insensitive. Use '*' for 'all files'." }, { "showtoomanyuploads", 0, 0, 0, "# display a message when upload limit is reached?" }, { "turdsize", 0, 0, 0, "# size of the largest incomplete file which will be auto-removed" }};int hwsize = sizeof(hw)/sizeof(hardwired_t);/* Append sets from file. If overwrite!=0, overwrite any old * values. If overwrite==0, only write values that were previously * unset (this is used for reading the initial config file, so as to * not overwrite anything that was set explicitly on the command * line). Return -1 on i/o error (with errno set), 0 on success, and 1 * if there were ill-formed lines. Log progress info to win if verbose * is set. In any case, log warnings to win. */int loadsets(const char *fn, WINDOW *win, int overwrite, int verbose){ FILE *f; char *buf1, *nm, *val; int len; int warn = 0; f = fopen(fn, "r"); if (!f) return(-1); while (1) { buf1 = nap_getline(f); if (buf1 == NULL) { break; } nm = buf1; if (*nm == '#' || *nm == 0) { /* if comment or empty, skip line */ free(buf1); continue; } val = strchr(nm, '='); if (!val) goto badline; *val=0; val = strip(val+1); nm = strip(nm); /* at this point, nm is the name and val is the value */ if (overwrite || !getval(nm)) { chset(nm,val); if (verbose) { wp(win, "%s%s=%s%s\n", BRIGHT(BLUE), nm, val, WHITE); drw(win); } } free(buf1); continue; /* we go here is we found an ill-formed line */ badline: warn = 1; /* remember that there was a warning */ wp(win, "Warning: ill-formed line in config file (ignoring):\n"); len = strlen(buf1); if (len>0 && buf1[len-1]=='\n') buf1[len-1]=0; wp(win, "%s\n", buf1); drw(win); free(buf1); continue; } /* while (1) */ fclose(f); return warn ? 1 : 0;}/* save sets to file (in format readable by loadsets, with human-readable comments). Return 0 on success, -1 on i/o failure (with errno set). */int savesets(const char *fn){ FILE *f; sets_t *cur; int i; char *v; f = fopen(fn, "w"); if (!f) return(-1); fprintf(f, "# nap config file. Note: for boolean options, 1=true, 0=false\n\n"); /* first deal with hardwired variables */ for (i=0; i<hwsize; i++) { if (hw[i].comment) fprintf(f, "%s\n", hw[i].comment); v = getrealval(hw[i].nm); if (v) { if (hw[i].type==2 && nvar_default("savepass", 0) == 0) { fprintf(f, "%s=%s\n", hw[i].nm, "?"); } else { fprintf(f, "%s=%s\n", hw[i].nm, v); } } else { fprintf(f, "#%s=\n", hw[i].nm); } if (hw[i].comment) fprintf(f, "\n"); } fprintf(f, "# other user variables:\n"); /* now print all the remaining variables */ for (cur=setl;cur;cur=cur->next) { for (i=0; i<hwsize; i++) { if (!strcasecmp(hw[i].nm, cur->nm)) goto next; } fprintf(f, "%s=%s\n", cur->nm, cur->d); next: ; } fclose(f); return(0);}/* print a list of current variable assignments */void printsets(WINDOW *win) { sets_t *elt; int count = 0; int i; char *v; /* first print hardwired sets */ for (i=0; i<hwsize; i++) { v = getval(hw[i].nm); if (v) { wp(win, ""BRIGHT(BLUE)"%s = "WHITE"%s\n", hw[i].nm, v); count++; } } /* then print remaining sets */ list_forall(elt, setl) { for (i=0; i<hwsize; i++) { if (!strcasecmp(hw[i].nm, elt->nm)) goto next; } wp(win, ""BRIGHT(BLUE)"%s = "WHITE"%s\n", elt->nm, elt->d); count++; next: ; } if (!count) wp(win, "No variables are set\n"); drw(win);} /* look up set by name, or NULL if not found. Internal use only. */sets_t *findset(const char *nm){ sets_t *cur; for (cur=setl; cur && strcasecmp(cur->nm, nm); cur=cur->next); return(cur);}/* add a set to the list. Note: we do not check for duplicates, thus this is for internal use only. External functions should call chset. */void addset(const char *nm, const char *val){ sets_t *elt; char *endptr; int i; /* check if this is a hardwired set */ for (i=0; i<hwsize; i++) { if (!strcasecmp(nm, hw[i].nm)) break; } if (i<hwsize && hw[i].type) { free(*hw[i].strp); *hw[i].strp = strdup(val); if (hw[i].intp) { *hw[i].intp = strtol(val, &endptr, 10); if (!endptr || *endptr!='\0') { /* string was invalid number */ *hw[i].intp = 0; } } return; } /* make new assignment */ elt = (sets_t *)malloc(sizeof(sets_t)); elt->nm = strdup(nm); elt->d = strdup(val); elt->intval = strtol(val, &endptr, 10); elt->t = 0; if (!endptr || *endptr!='\0') { /* string was invalid number */ elt->intval = 0; elt->t = 1; } if (i<hwsize && hw[i].intp) { *hw[i].intp = elt->intval; } /* now append it to the list */ list_append(sets_t, setl, elt);}/* add a set to the list, but remove duplicate first. Set t=0 if this might be a number. If d is NULL, just delete the set. */void chset(const char *nm, const char *d){ delset(nm); if (d) addset(nm, d);}/* get the string value of a set, or "?" for a hidden value */char *getval(const char *nm) { return getval_t_r(nm, NULL, 0);}/* get the string value of a set, even for a hidden value */char *getrealval(const char *nm) { return getval_t_r(nm, NULL, 1);}/* get both string and integer values of a named set. Set *t to be the integer value (unless t=NULL). Let d=NULL if not found. */char *getval_t(const char *nm, int *t) { return getval_t_r(nm, t, 0);}/* get both string and integer values of a named set. Set *t to be the integer value (unless t=NULL). Let d=NULL if not found. If real==0 get "?" for a hidden value, else the actual value. */char *getval_t_r(const char *nm, int *t, int real){ sets_t *cur; int i; if (t) *t = 1; /* check for hardwired sets first */ for (i=0; i<hwsize; i++) { if (!strcasecmp(nm, hw[i].nm) && hw[i].type != 0) { if (*hw[i].strp) { if (real==1 || hw[i].type == 1) return *hw[i].strp; else return "?"; } else return NULL; } } cur = findset(nm); if (!cur) return NULL; if (t) *t = cur->t; return(cur->d);}/* remove one named set from list */void delset(const char *nm){ sets_t *cur, *cur1=NULL; int i; /* check for hardwired sets first */ for (i=0; i<hwsize; i++) { if (!strcasecmp(nm, hw[i].nm)) break; } if (i<hwsize && hw[i].type != 0) { free(*hw[i].strp); *hw[i].strp = NULL; if (hw[i].intp) { *hw[i].intp = 0; } return; } for (cur=setl;cur&&strcasecmp(cur->nm, nm);cur=cur->next) cur1 = cur; if (!cur) return; if (cur1) cur1->next = cur->next; else if (cur->next) setl = cur->next; else setl = NULL; free(cur->d); free(cur->nm); free(cur); if (i<hwsize && hw[i].intp) { *hw[i].intp = 0; }}/* lookup set's value as a number, or -1 if not set or a non-number. */long nvar(const char *nm) { return nvar_default(nm, -1);}/* lookup set's value as a number, or default if not set or a non-number. */long nvar_default(const char *nm, long deflt){ sets_t *cur; int i; /* check for hardwired sets first */ for (i=0; i<hwsize; i++) { if (!strcasecmp(nm, hw[i].nm) && hw[i].type != 0) { return *hw[i].strp ? strtol(*hw[i].strp, NULL, 10) : deflt; } } cur = findset(nm); if (!cur) return(deflt); if (cur->t) return(deflt); return(cur->intval);}/* ---------------------------------------------------------------------- *//* return a copy of m with characters bp..ep-1 replaced by n. n may be longer or shorter than ep-bp; in fact even ep<bp is permitted. The only requirement is that ep,bp <= strlen(m). */char *ins(char *m, char *n, int bp, int ep){ char *st;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -