diff options
Diffstat (limited to 'FICS/adminproc.c')
-rw-r--r-- | FICS/adminproc.c | 1596 |
1 files changed, 1596 insertions, 0 deletions
diff --git a/FICS/adminproc.c b/FICS/adminproc.c new file mode 100644 index 0000000..ed96d4a --- /dev/null +++ b/FICS/adminproc.c @@ -0,0 +1,1596 @@ +/* + fics - An internet chess server + Copyright (c) 1993 Richard V. Nash + + 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. + + Continued development of this software is done by the GNU ICS + development team. Contact <chess@caissa.onenet.net> with questions. + + + adminproc.c - All administrative commands and related functions */ + + +#include "stdinclude.h" +#include "common.h" +#include "network.h" +#include "adminproc.h" +#include "command.h" +#include "playerdb.h" +#include "gamedb.h" +#include "gameproc.h" +#include "obsproc.h" +#include "ratings.h" +#include "utils.h" +#include "rmalloc.h" +#include "talkproc.h" +#include "comproc.h" +#include "multicol.h" +#include <sys/param.h> + +#define PASSLEN 4 + +PUBLIC int num_anews = -1; + +/* + * adjudicate + * + * Usage: adjudicate white_player black_player result + * + * Adjudicates a saved (stored) game between white_player and black_player. + * The result is one of: abort, draw, white, black. "Abort" cancels the game + * (no win, loss or draw), "white" gives white_player the win, "black" gives + * black_player the win, and "draw" gives a draw. + */ +PUBLIC int com_adjudicate(int p, param_list param) +{ + int wp, wconnected, bp, bconnected, g, inprogress, confused = 0; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (!FindPlayer(p, param[0].val.word, &wp, &wconnected)) + return COM_OK; + if (!FindPlayer(p, param[1].val.word, &bp, &bconnected)) { + if (!wconnected) + player_remove(wp); + return COM_OK; + } + + inprogress = ((parray[wp].game >=0) &&(parray[wp].opponent == bp)); + + if (inprogress) { + g = parray[wp].game; + } else { + g = game_new(); + if (game_read(g, wp, bp) < 0) { + confused = 1; + pprintf(p, "There is no stored game %s vs. %s\n", parray[wp].name, parray[bp].name); + } else { + garray[g].white = wp; + garray[g].black = bp; + } + } + if (!confused) { + if (strstr("abort", param[2].val.word) != NULL) { + game_ended(g, WHITE, END_ADJABORT); + + pcommand(p, "message %s Your game \"%s vs. %s\" has been aborted.", + parray[wp].name, parray[wp].name, parray[bp].name); + + pcommand(p, "message %s Your game \"%s vs. %s\" has been aborted.", + parray[bp].name, parray[wp].name, parray[bp].name); + } else if (strstr("draw", param[2].val.word) != NULL) { + game_ended(g, WHITE, END_ADJDRAW); + + pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated " + "as a draw", parray[wp].name, parray[wp].name, parray[bp].name); + + pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated " + "as a draw", parray[bp].name, parray[wp].name, parray[bp].name); + } else if (strstr("white", param[2].val.word) != NULL) { + game_ended(g, WHITE, END_ADJWIN); + + pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated " + "as a win", parray[wp].name, parray[wp].name, parray[bp].name); + + pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated " + "as a loss", parray[bp].name, parray[wp].name, parray[bp].name); + } else if (strstr("black", param[2].val.word) != NULL) { + game_ended(g, BLACK, END_ADJWIN); + pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated " + "as a loss", parray[wp].name, parray[wp].name, parray[bp].name); + + pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated " + "as a win", parray[bp].name, parray[wp].name, parray[bp].name); + } else { + confused = 1; + pprintf(p, "Result must be one of: abort draw white black\n"); + } + } + if (!confused) { + pprintf(p, "Game adjudicated.\n"); + if (!inprogress) { + game_delete(wp, bp); + } else { + return (COM_OK); + } + } + game_remove(g); + if (!wconnected) + player_remove(wp); + if (!bconnected) + player_remove(bp); + return COM_OK; +} + +/* + * create_news_file: Creates either a general or and admin news + * file, depending upon the admin switch. + */ +PRIVATE int create_news_file(int p, param_list param, int admin) +{ + FILE *fp; + char filename[MAX_FILENAME_SIZE]; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + + if (admin) { + if (param[0].val.integer > num_anews) + pprintf(p, "There must be an admin news index #%d before you can create the file.", param[0].val.integer); + else { + sprintf(filename, "%s/adminnews.%d", news_dir, param[0].val.integer); + fp = fopen(filename, "w"); + fprintf(fp, "%s\n", param[1].val.string); + fclose(fp); + } + } else { + if (param[0].val.integer > num_news) + pprintf(p, "There must be a news index #%d before you can create the file.", param[0].val.integer); + else { + sprintf(filename, "%s/news.%d", news_dir, param[0].val.integer); + fp = fopen(filename, "w"); + fprintf(fp, "%s\n", param[1].val.string); + fclose(fp); + } + } + + return COM_OK; +} + +PRIVATE int add_item(char *new_item, char *filename) +{ + FILE *new_fp, *old_fp; + char tmp_file[MAX_FILENAME_SIZE]; + char junk[MAX_LINE_SIZE]; + + sprintf(tmp_file, "%s/.tmp.idx", news_dir); + new_fp = fopen(tmp_file, "w"); + old_fp = fopen(filename, "r"); + + if (!new_fp || !old_fp) + return 0; + + fprintf(new_fp, "%s", new_item); + while (1) { + fgets(junk, MAX_LINE_SIZE, old_fp); + if (feof(old_fp)) + break; + fprintf(new_fp, "%s", junk); + } + fclose(new_fp); + fclose(old_fp); + remove(filename); + rename(tmp_file, filename); + + return 1; +} + +/* + * create_news_index: Adds a new item to either the general or admin news + * index file, depending upon the admin switch. + */ +PRIVATE int create_news_index(int p, param_list param, int admin) +{ + char filename[MAX_FILENAME_SIZE]; + char new_item[MAX_LINE_SIZE]; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + + if (admin) { + if (strlen(param[0].val.string) > 50) + pprintf(p, "Sorry, you must limit an index to 50 charaters! Admin news index not created.\n"); + else { + num_anews++; + sprintf(new_item, "%d %d %s\n", (int) time(0), num_anews, param[0].val.string); + sprintf(filename, "%s/newadminnews.index", news_dir); + if (add_item(new_item, filename)) { + pprintf(p, "Index for admin news item #%d created.\n", num_anews); + pprintf(p, "Please use 'canewsf' to include more info.\n"); + } else + pprintf(p, "Something went wrong creating item.\nNotify Marsalis.\n"); + } + } else { + if (strlen(param[0].val.string) > 50) + pprintf(p, "Sorry, you must limit an index to 50 charaters! News index not created.\n"); + else { + num_news++; + sprintf(filename, "%s/newnews.index", news_dir); + sprintf(new_item, "%d %d %s\n", (int) time(0), num_news, param[0].val.string); + if (add_item(new_item, filename)) { + pprintf(p, "Index for news item #%d created.\n", num_news); + pprintf(p, "Please use 'cnewsf' to include more info.\n"); + } else + pprintf(p, "Something went wrong creating item.\nNotify Marsalis.\n"); + } + } + + return COM_OK; +} + +/* cnewsi + * + * Usage: cnewsi message + * + * + * This command adds a new item to the news index. The message is limited to + * 45 characters for formating purposes. In essence, the news index works + * like a newspaper headline, giving the user enough information to know + * whether they should read the entire news file for that item. After + * creating the news item, the command reports the news item number along + * with a reminder to create a news file if necessary. + */ +PUBLIC int com_cnewsi(int p, param_list param) +{ + return create_news_index(p, param, 0); +} + +/* cnewsf + * + * Usage: cnewsf # message + * + * This command allows you to add additional information about a news item + * that had previously been created using 'cnewsi'. The '#' is the number + * of the news index and 'message' is the additional text. You can also + * modify a previous news item description and thus update the news item + * easily. + */ +PUBLIC int com_cnewsf(int p, param_list param) +{ + return create_news_file(p, param, 0); +} + +PUBLIC int com_canewsi(int p, param_list param) +{ + return create_news_index(p, param, 1); +} + +PUBLIC int com_canewsf(int p, param_list param) +{ + return create_news_file(p, param, 1); +} + +/* + * anews + * + * + * Usage: anews [#, all] + * + * This command is used to display anews (admin news) entries. The + * entries are numbered. "Anews #" displays that anews item. "Anews + * all" will display all items. + * + */ +PUBLIC int com_anews(int p, param_list param) +{ + FILE *fp; + char filename[MAX_FILENAME_SIZE]; + char junk[MAX_LINE_SIZE]; + char *junkp; + int crtime, found = 0; + char count[10]; + + sprintf(filename, "%s/newadminnews.index", news_dir); + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Cant find news index.\n"); + return COM_OK; + } + + if (param[0].type == 0) { + + /* no params - then just display index over news */ + sprintf(filename, "%s/newadminnews.index", news_dir); + pprintf(p, "Index of recent admin news items:\n"); + fgets(junk, MAX_LINE_SIZE, fp); + sscanf(junk, "%d %s", &crtime, count); + rscan_news2(fp, p, 9); + junkp = junk; + junkp = nextword(junkp); + junkp = nextword(junkp); + pprintf(p, "%3s (%s) %s", count, fix_time(strltime(&crtime)), junkp); + fclose(fp); + + } else if ((param[0].type == TYPE_WORD) && !strcmp(param[0].val.word, "all")) { + /* param all - displays all news items */ + pprintf(p, "Index of all admin news items:\n"); + fgets(junk, MAX_LINE_SIZE, fp); + sscanf(junkp, "%d %s", &crtime, count); + rscan_news(fp, p, 0); + junkp = junk; + junkp = nextword(junkp); + junkp = nextword(junkp); + pprintf(p, "%3s (%s) %s", count, fix_time(strltime(&crtime)), junkp); + fclose(fp); + + } else { + + while (!feof(fp) && !found) { + junkp = junk; + fgets(junk, MAX_LINE_SIZE, fp); + if (feof(fp)) + break; + if (strlen(junk) > 1) { + sscanf(junkp, "%d %s", &crtime, count); + if (!strcmp(count, param[0].val.word)) { + found = 1; + junkp = nextword(junkp); + junkp = nextword(junkp); + pprintf(p, "ANEWS %3s (%s) %s\n", count, fix_time(strltime(&crtime)), + junkp); + } + } + } + fclose(fp); + if (!found) { + pprintf(p, "Bad index number!\n"); + return COM_OK; + } + /* file exists - show it */ + sprintf(filename, "%s/adminnews.%s", news_dir, param[0].val.word); + fp = fopen(filename, "r"); + if (!fp) { + pprintf(p, "No more info.\n"); + return COM_OK; + } + fclose(fp); + sprintf(filename, "adminnews.%s", param[0].val.word); + if (psend_file(p, news_dir, filename) < 0) { + pprintf(p, "Internal error - couldn't send news file!\n"); + } + } + return COM_OK; +} + +PUBLIC int strcmpwild(char *mainstr, char *searchstr) +{ + int i; + + if (strlen(mainstr) < strlen(searchstr)) + return 1; + for (i = 0; i < strlen(mainstr); i++) { + if (searchstr[i] == '*') + return 0; + if (mainstr[i] != searchstr[i]) + return 1; + } + return 0; +} + +/* + * chkip + * + * Usage: chkip ip_address + * + * This command returns the names of all users currently logged on + * from a given IP address. + */ +PUBLIC int com_checkIP(int p, param_list param) +{ + char *ipstr = param[0].val.word; + int p1; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + pprintf(p, "Matches the following player(s): \n\n"); + for (p1 = 0; p1 < p_num; p1++) + if (!strcmpwild(dotQuad(parray[p1].thisHost), ipstr) && (parray[p1].status != PLAYER_EMPTY)) + pprintf(p, "%16.16s %s\n", parray[p1].name, dotQuad(parray[p1].thisHost)); + return COM_OK; +} + +PUBLIC int com_checkSOCKET(int p, param_list param) +{ + int fd = param[0].val.integer; + int p1, flag; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + flag = 0; + for (p1 = 0; p1 < p_num; p1++) { + if (parray[p1].socket == fd) { + flag = 1; + pprintf(p, "Socket %d is used by %s\n", fd, parray[p1].name); + } + } + if (!flag) + pprintf(p, "Socket %d is unused!\n", fd); + return COM_OK; +} + +/* + * chkpl + * + * Usage: chkpl handle + * + * This command displays server information about a given user. Items + * displayed are: + * + * number X in parray of size Y + * name + * login + * fullName + * emailAddress + * socket + * registered + * last_tell + * last_channel + * logon_time + * adminLevel + * thisHost + * lastHost + * num_comments + */ +PUBLIC int com_checkPLAYER(int p, param_list param) +{ + char *player = param[0].val.word; + int p1; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + p1 = player_search(p, param[0].val.word); + if (!p1) + return COM_OK; + if (p1 < 0) { + p1 = (-p1) - 1; + pprintf(p, "%s is not logged in.\n", player); + stolower(player); + pprintf(p, "name = %s\n", parray[p1].name); + pprintf(p, "login = %s\n", parray[p1].login); + pprintf(p, "fullName = %s\n", (parray[p1].fullName ? parray[p1].fullName : "(none)")); + pprintf(p, "emailAddress = %s\n", (parray[p1].emailAddress ? parray[p1].emailAddress : "(none)")); + pprintf(p, "adminLevel = %d\n", parray[p1].adminLevel); +/* pprintf(p, "network_player = %d\n", parray[p1].network_player); */ + pprintf(p, "lastHost = %s\n", dotQuad(parray[p1].lastHost)); + pprintf(p, "num_comments = %d\n", parray[p1].num_comments); + + player_remove(p1); + return COM_OK; + } else { + p1 = p1 - 1; + pprintf(p, "%s is number %d in parray of size %d\n", player, p1, p_num + 1); + pprintf(p, "name = %s\n", parray[p1].name); + pprintf(p, "login = %s\n", parray[p1].login); + pprintf(p, "fullName = %s\n", parray[p1].fullName ? parray[p1].fullName : "(none)"); + pprintf(p, "emailAddress = %s\n", parray[p1].emailAddress ? parray[p1].emailAddress : "(none)"); + pprintf(p, "socket = %d\n", parray[p1].socket); + pprintf(p, "registered = %d\n", parray[p1].registered); + pprintf(p, "last_tell = %d\n", parray[p1].last_tell); + pprintf(p, "last_channel = %d\n", parray[p1].last_channel); + pprintf(p, "logon_time = %s", ctime((time_t *) &parray[p1].logon_time)); + pprintf(p, "adminLevel = %d\n", parray[p1].adminLevel); +/* pprintf(p, "network_player = %d\n", parray[p1].network_player); */ + pprintf(p, "thisHost = %s\n", dotQuad(parray[p1].thisHost)); + pprintf(p, "lastHost = %s\n", dotQuad(parray[p1].lastHost)); + pprintf(p, "num_comments = %d\n", parray[p1].num_comments); + + } + return COM_OK; +} + +/* + * chkts + * + * Usage: chkts + * + * This command displays all current users who are using timeseal. + */ +PUBLIC int com_checkTIMESEAL(int p, param_list param) +{ + int p1, count = 0; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + pprintf(p, "The following player(s) are using timeseal:\n\n"); + +#ifdef TIMESEAL + for (p1 = 0; p1 < p_num; p1++) { + if (parray[p1].status != PLAYER_EMPTY + && con[parray[p1].socket].timeseal) { + pprintf(p, "%s\n", parray[p1].name); + count++; + } + } + pprintf(p, "\nNumber of people using timeseal: %d\n", count); +#endif + + return COM_OK; +} + +PUBLIC int com_checkGAME (int p,param_list param) +{ + int p1,g,link; + char tmp[10 + 1 + 7]; /* enough to store number 'black: ' and \0 */ + int startTime; + multicol *m; + int found = 0; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + + if (g_num == 0) { + pprintf (p,"No games are currently linked into the garray structure.\n"); + return COM_OK; + } + + if (param[0].type == TYPE_WORD) { /* a player name */ + if ((p1 = player_find_part_login(param[0].val.word)) < 0) { + pprintf(p, "%s doesn't appear to be logged in.\n", param[0].val.word); + pprintf(p,"Searching through garray to find matching game numbers.\n"); + pprintf(p,"Use chkgame <number> to view the results.\n"); + m = multicol_start(g_num*2); /* Obviously no more than that */ + for (g = 0; g < g_num; g++) { + multicol_store(m,tmp); + if (!(strcasecmp (garray[g].white_name,param[0].val.word))) { + sprintf (tmp,"White: %d",g); + multicol_store(m,tmp); + found = 1; + } + if (!(strcasecmp (garray[g].black_name,param[0].val.word))) { + sprintf (tmp,"Black: %d",g); + multicol_store(m,tmp); + found = 1; + } + } + if (found) + multicol_pprint(m,p,parray[p].d_width,2); + else + pprintf(p,"No matching games were found.\n"); + multicol_end(m); + return COM_OK; + } + + if ((g = parray[p1].game) < 0) { + pprintf(p,"%s doesn't appear to be playing a game.\n",parray[p1].name); + pprintf(p,"Searching through garray to find matching game numbers.\n"); + pprintf(p,"Use chkgame <number> to view the results.\n"); + m = multicol_start(g_num*2); /* Obviously no more than that */ + for (g = 0; g < g_num; g++) { + if ((garray[g].white) == p1) { + sprintf (tmp,"White: %d",g); + multicol_store(m,tmp); + found = 1; + } + if ((garray[g].black) == p1) { + sprintf (tmp,"Black: %d",g); + multicol_store(m,tmp); + found = 1; + } + } + if (found) + multicol_pprint(m,p,parray[p].d_width,2); + else + pprintf (p,"No matching games were found.\n"); + multicol_end(m); + return COM_OK; + } + } else { + if (((g = param[0].val.integer - 1) < 0) || (g >= g_num)) { + pprintf (p, "The current range of game numbers is 1 to %d.\n",g_num); + return COM_OK; + } + } + startTime = untenths(garray[g].timeOfStart); + pprintf (p,"Current stored info for game %d (garray[%d]):\n",g+1,g); + pprintf (p,"Initial white time: %d Initial white increment %d\n", + garray[g].wInitTime/600,garray[g].wIncrement/10); + pprintf (p,"Initial black time: %d Initial black increment %d\n", + garray[g].bInitTime/600,garray[g].bIncrement/10); + pprintf (p,"Time of starting: %s\n",strltime (&startTime)); + pprintf (p,"Game is: %s (%d) vs. %s (%d)\n",garray[g].white_name,garray[g].white_rating, + garray[g].black_name,garray[g].black_rating); + pprintf (p,"White parray entry: %d Black parray entry %d\n",garray[g].white,garray[g].black); + if ((link = garray[g].link) >= 0) { + pprintf (p,"Bughouse linked to game: %d\n",garray[g].link + 1); + pprintf (p,"Partner is playing game: %s (%d) vs. %s (%d)\n",garray[link].white_name,garray[link].white_rating, + garray[link].black_name,garray[link].black_rating); + } else + pprintf (p,"Game is not bughouse or link to partner's game not found.\n"); + pprintf (p,"Game is %s\n",(garray[g].rated) ? "rated" : "unrated"); + pprintf (p,"Game is %s\n",(garray[g].private) ? "private" : "not private"); + pprintf (p,"Games is of type %s\n", + garray[g].type == TYPE_UNTIMED ? "untimed" : + garray[g].type == TYPE_BLITZ ? "blitz" : + garray[g].type == TYPE_STAND ? "standard" : + garray[g].type == TYPE_NONSTANDARD ? "non-standard" : + garray[g].type == TYPE_WILD ? "wild" : + garray[g].type == TYPE_LIGHT ? "lightning" : + garray[g].type == TYPE_BUGHOUSE ? "bughouse" : + "Unknown - Error!"); + pprintf (p,"%d halfmove(s) have been made\n",garray[g].numHalfMoves); + if (garray[g].status == GAME_ACTIVE) + game_update_time(g); + pprintf (p,"White's time %s Black's time ", + tenth_str((garray[g].wTime > 0 ? garray[g].wTime : 0), 0)); + pprintf (p,"%s\n", + tenth_str((garray[g].bTime > 0 ? garray[g].bTime : 0), 0)); + pprintf (p,"The clock is%sticking\n", + (garray[g].clockStopped || (garray[g].status != GAME_ACTIVE)) ? " not " : " "); + pprintf (p,"Game status: %s\n", + garray[g].status == GAME_EMPTY ? "GAME_EMPTY" : + garray[g].status == GAME_NEW ? "GAME_NEW" : + garray[g].status == GAME_ACTIVE ? "GAME_ACTIVE" : + garray[g].status == GAME_EXAMINE ? "GAME_EXAMINE" : + "Unknown - Error!"); + return COM_OK; +} + +/* + * remplayer + * + * Usage: remplayer name + * + * Removes an account. A copy of its files are saved under .rem.* which can + * be found in the appropriate directory (useful in case of an accident). + * + * The account's details, messages, games and logons are all saved as + * 'zombie' files. These zombie accounts are not listed in handles or + * totals. + */ +PUBLIC int com_remplayer(int p, param_list param) +{ + char *player = param[0].val.word; + char playerlower[MAX_LOGIN_NAME]; + int p1, lookup; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + strcpy(playerlower, player); + stolower(playerlower); + p1 = player_new(); + lookup = player_read(p1, playerlower); + if (!lookup) { + if ((parray[p].adminLevel <= parray[p1].adminLevel) && !player_ishead(p)) { + pprintf(p, "You can't remove an admin with a level higher than or equal to yourself.\n"); + player_remove(p1); + return COM_OK; + } + } + player_remove(p1); + if (lookup) { + pprintf(p, "No player by the name %s is registered.\n", player); + return COM_OK; + } + if (player_find_bylogin(playerlower) >= 0) { + pprintf(p, "A player by that name is logged in.\n"); + return COM_OK; + } + if (!player_kill(playerlower)) { + pprintf(p, "Player %s removed.\n", player); + UpdateRank(TYPE_BLITZ, NULL, NULL, player); + UpdateRank(TYPE_STAND, NULL, NULL, player); + UpdateRank(TYPE_WILD, NULL, NULL, player); + } else { + pprintf(p, "Remplayer failed.\n"); + } + return COM_OK; +} + +/* + * raisedead + * + * Usage: raisedead oldname [newname] + * + * Restores an account that has been previously removed using "remplayer". + * The zombie files from which it came are removed. Under most + * circumstances, you restore the account to the same handle it had + * before (oldname). However, in some circumstances you may need to + * restore the account to a different handle, in which case you include + * "newname" as the new handle. After "raisedead", you may need to use the + * "asetpasswd" command to get the player started again as a registered + * user, especially if the account had been locked + * by setting the password to *. + */ +PUBLIC int com_raisedead(int p, param_list param) +{ + char *player = param[0].val.word; + char playerlower[MAX_LOGIN_NAME], newplayerlower[MAX_LOGIN_NAME]; + + int p1, p2, lookup; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + strcpy(playerlower, player); + stolower(playerlower); + if (player_find_bylogin(playerlower) >= 0) { + pprintf(p, "A player by that name is logged in.\n"); + pprintf(p, "Can't raise until they leave.\n"); + return COM_OK; + } + p1 = player_new(); + lookup = player_read(p1, playerlower); + player_remove(p1); + if (!lookup) { + pprintf(p, "A player by the name %s is already registered.\n", player); + pprintf(p, "Obtain a new handle for the dead person.\n"); + pprintf(p, "Then use raisedead [oldname] [newname].\n"); + return COM_OK; + } + if (param[1].type == TYPE_NULL) { + if (!player_raise(playerlower)) { + pprintf(p, "Player %s raised from dead.\n", player); + + p1 = player_new(); + if (!(lookup = player_read(p1, playerlower))) { + if (parray[p1].s_stats.rating > 0) + UpdateRank(TYPE_STAND, player, &parray[p1].s_stats, player); + if (parray[p1].b_stats.rating > 0) + UpdateRank(TYPE_BLITZ, player, &parray[p1].b_stats, player); + if (parray[p1].w_stats.rating > 0) + UpdateRank(TYPE_WILD, player, &parray[p1].w_stats, player); + } + player_remove(p1); + } else { + pprintf(p, "Raisedead failed.\n"); + } + return COM_OK; + } else { + char *newplayer = param[1].val.word; + strcpy(newplayerlower, newplayer); + stolower(newplayerlower); + if (player_find_bylogin(newplayerlower) >= 0) { + pprintf(p, "A player by the requested name is logged in.\n"); + pprintf(p, "Can't reincarnate until they leave.\n"); + return COM_OK; + } + p2 = player_new(); + lookup = player_read(p2, newplayerlower); + player_remove(p2); + if (!lookup) { + pprintf(p, "A player by the name %s is already registered.\n", player); + pprintf(p, "Obtain another new handle for the dead person.\n"); + return COM_OK; + } + if (!player_reincarn(playerlower, newplayerlower)) { + pprintf(p, "Player %s reincarnated to %s.\n", player, newplayer); + p2 = player_new(); + if (!(lookup = player_read(p2, newplayerlower))) { + strfree(parray[p2].name); + parray[p2].name = strdup(newplayer); + player_save(p2); + if (parray[p2].s_stats.rating > 0) + UpdateRank(TYPE_STAND, newplayer, &parray[p2].s_stats, newplayer); + if (parray[p2].b_stats.rating > 0) + UpdateRank(TYPE_BLITZ, newplayer, &parray[p2].b_stats, newplayer); + if (parray[p2].w_stats.rating > 0) + UpdateRank(TYPE_WILD, newplayer, &parray[p2].w_stats, newplayer); + } + player_remove(p2); + } else { + pprintf(p, "Raisedead failed.\n"); + } + } + return COM_OK; +} + +/* + * addplayer + * + * Usage: addplayer playername emailaddress realname + * + * Adds a local player to the server with the handle of "playername". For + * example: + * + * addplayer Hawk u940456@daimi.aau.dk Henrik Gram + */ +PUBLIC int com_addplayer(int p, param_list param) +{ + char text[2048]; + char *newplayer = param[0].val.word; + char *newname = param[2].val.string; + char *newemail = param[1].val.word; + char password[PASSLEN + 1]; + char newplayerlower[MAX_LOGIN_NAME]; + char salt[3]; + int p1, lookup; + int i; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (strlen(newplayer) >= MAX_LOGIN_NAME) { + pprintf(p, "Player name is too long\n"); + return COM_OK; + } + if (strlen(newplayer) < 3) { + pprintf(p, "Player name is too short\n"); + return COM_OK; + } + if (!alphastring(newplayer)) { + pprintf(p, "Illegal characters in player name. Only A-Za-z allowed.\n"); + return COM_OK; + } + strcpy(newplayerlower, newplayer); + stolower(newplayerlower); + p1 = player_new(); + lookup = player_read(p1, newplayerlower); + if (!lookup) { + pprintf(p, "A player by the name %s is already registered.\n", newplayerlower); + player_remove(p1); + return COM_OK; + } + parray[p1].name = strdup(newplayer); + parray[p1].login = strdup(newplayerlower); + parray[p1].fullName = strdup(newname); + parray[p1].emailAddress = strdup(newemail); + if (strcmp(newemail, "none")) { + for (i = 0; i < PASSLEN; i++) { + password[i] = 'a' + rand() % 26; + } + password[i] = '\0'; + salt[0] = 'a' + rand() % 26; + salt[1] = 'a' + rand() % 26; + salt[2] = '\0'; + parray[p1].passwd = strdup(crypt(password, salt)); + } else { + password[0] = '\0'; + parray[p1].passwd = strdup(password); + } + parray[p1].registered = 1; +/* parray[p1].network_player = 0; */ + parray[p1].rated = 1; + player_add_comment(p, p1, "Player added by addplayer."); + player_save(p1); + player_remove(p1); + pprintf(p, "Added: >%s< >%s< >%s< >%s<\n", newplayer, newname, newemail, password); + if (strcmp(newemail, "none")) { +/* + sprintf(text, "\nYou have been added as a local player.\n\nLogin Name: " + "%s\nFull Name: %s\nEmail Address: %s\nInitial Password: " + "%s\n\nIf any of this information is incorrect, please " + "contact the administrator\nto get it corrected.\n\n" + "Please write down your password.\n\nRegards,\n\nThe FICS admins\n", + newplayer, newname, newemail, password); +*/ + + sprintf(text, "\nYour player account has been created.\n\n" + "Login Name: %s\nFull Name: %s\nEmail Address: %s\nInitial Password: %s\n\n" + "If any of this information is incorrect, please contact the administrator\n" + "to get it corrected.\n\n" + "You may change your password with the password command on the the server.\n" + "\nPlease be advised that if this is an unauthorized duplicate account for\n" + "you, by using it you take the risk of being banned from accessing this\n" + "chess server.\n\nTo connect to the server and use this account:\n\n" + " telnet %s 5000\n\nand enter your handle name and password.\n\n" + "Regards,\n\nThe FICS admins\n", + newplayer, newname, newemail, password, fics_hostname); + + mail_string_to_address(newemail, "FICS Account Created", text); + if ((p1 = player_find_part_login(newplayer)) >= 0) { + pprintf_prompt(p1, "\n\nYou are now registered! Confirmation together with\npassword is sent to your email address.\n\n"); + return COM_OK; + } + return COM_OK; + } else { + if ((p1 = player_find_part_login(newplayer)) >= 0) { + pprintf_prompt(p1, "\n\nYou are now registered! Your have NO password!\n\n"); + return COM_OK; + } + } + return COM_OK; +} + +PUBLIC int com_pose(int p, param_list param) +{ + int p1; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if ((p1 = player_find_part_login(param[0].val.word)) < 0) { + pprintf(p, "%s is not logged in.\n", param[0].val.word); + return COM_OK; + } + if ((parray[p].adminLevel <= parray[p1].adminLevel) && !player_ishead(p)) { + pprintf(p, "You can only pose as players below your adminlevel.\n"); + return COM_OK; + } + pprintf(p, "Command issued as %s\n", parray[p1].name); + pcommand(p1, "%s\n", param[1].val.string); + return COM_OK; +} + +/* + * asetv + * + * Usage: asetv user instructions + * + * This command executes "set" instructions as if they had been made by the + * user indicated. For example, "asetv DAV shout 0" would set DAV's shout + * variable to 0. + */ +PUBLIC int com_asetv(int p, param_list param) +{ + int p1; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if ((p1 = player_find_part_login(param[0].val.word)) < 0) { + pprintf(p, "%s is not logged in.\n", param[0].val.word); + return COM_OK; + } + if ((parray[p].adminLevel <= parray[p1].adminLevel) && !player_ishead(p)) { + pprintf(p, "You can only aset players below your adminlevel.\n"); + return COM_OK; + } + pprintf(p, "Command issued as %s\n", parray[p1].name); + pcommand(p1, "set %s\n", param[1].val.string); + return COM_OK; +} + +/* + * announce + * + * Usage: announce message + * + * Broadcasts your message to all logged on users. Announcements reach all + * users and cannot be censored in any way (such as by "set shout 0"). + */ +PUBLIC int com_announce(int p, param_list param) +{ + int p1; + int count = 0; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (!printablestring(param[0].val.string)) { + pprintf(p, "Your message contains some unprintable character(s).\n"); + return COM_OK; + } + for (p1 = 0; p1 < p_num; p1++) { + if (p1 == p) + continue; + if (parray[p1].status != PLAYER_PROMPT) + continue; + count++; + pprintf_prompt(p1, "\n\n **ANNOUNCEMENT** from %s: %s\n\n", parray[p].name, param[0].val.string); + } + pprintf(p, "\n(%d) **ANNOUNCEMENT** from %s: %s\n\n", count, parray[p].name, param[0].val.string); + return COM_OK; +} + +/* + * annunreg + * + * Usage: annunreg message + * + * Broadcasts your message to all logged on unregistered users, and admins, + * too. Announcements reach all unregistered users and admins and cannot be + * censored in any way (such as by "set shout 0"). + */ +PUBLIC int com_annunreg(int p, param_list param) +{ + int p1; + int count = 0; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (!printablestring(param[0].val.string)) { + pprintf(p, "Your message contains some unprintable character(s).\n"); + return COM_OK; + } + for (p1 = 0; p1 < p_num; p1++) { + if (p1 == p) + continue; + if (parray[p1].status != PLAYER_PROMPT) + continue; + if ((parray[p1].registered) && (parray[p1].adminLevel < ADMIN_ADMIN)) + continue; + count++; + pprintf_prompt(p1, "\n\n **UNREG ANNOUNCEMENT** from %s: %s\n\n", parray[p].name, param[0].val.string); + } + pprintf(p, "\n(%d) **UNREG ANNOUNCEMENT** from %s: %s\n\n", count, parray[p].name, param[0].val.string); + return COM_OK; +} + +PUBLIC int com_muzzle(int p, param_list param) +{ + pprintf(p, "Obsolete command: Please use +muzzle and -muzzle.\n"); + return COM_OK; +} + +PUBLIC int com_cmuzzle(int p, param_list param) +{ + pprintf(p, "Obsolete command: Please use +cmuzzle and -cmuzzle.\n"); + return COM_OK; +} + +/* + * asetpasswd + * + * Usage: asetpasswd player {password,*} + * + * This command sets the password of the player to the password given. + * If '*' is specified then the player's account is locked, and no password + * will work until a new one is set by asetpasswd. + * + * If the player is connected, he is told of the new password and the name + * of the admin who changed it, or likewise of his account status. An + * email message is mailed to the player's email address as well. + */ +PUBLIC int com_asetpasswd(int p, param_list param) +{ + int p1, connected; + char subject[400], text[10100]; + char salt[3]; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + + if (!FindPlayer(p, param[0].val.word, &p1, &connected)) + return COM_OK; + + if ((parray[p].adminLevel <= parray[p1].adminLevel) && !player_ishead(p)) { + pprintf(p, "You can only set password for players below your adminlevel.\n"); + if (!connected) + player_remove(p1); + return COM_OK; + } + if (!parray[p1].registered) { + pprintf(p, "You cannot set the password of an unregistered player!\n"); + return COM_OK; + } + if (parray[p1].passwd) + rfree(parray[p1].passwd); + if (param[1].val.word[0] == '*') { + parray[p1].passwd = strdup(param[1].val.word); + pprintf(p, "Account %s locked!\n", parray[p1].name); + sprintf(text, "Password of %s is now useless. Your account at our FICS has been locked.\n", parray[p1].name); + } else { + salt[0] = 'a' + rand() % 26; + salt[1] = 'a' + rand() % 26; + salt[2] = '\0'; + parray[p1].passwd = strdup(crypt(param[1].val.word, salt)); + sprintf(text, "Password of %s changed to \"%s\".\n", parray[p1].name, param[1].val.word); + pprintf(p, "%s", text); + } + if (param[1].val.word[0] == '*') { + sprintf(subject, "FICS: %s has locked your account.", parray[p].name); + if (connected) + pprintf_prompt(p1, "\n%s\n", subject); + } else { + sprintf(subject, "FICS: %s has changed your password.", parray[p].name); + if (connected) + pprintf_prompt(p1, "\n%s\n", subject); + } + mail_string_to_address(parray[p1].emailAddress, subject, text); + player_save(p1); + if (!connected) + player_remove(p1); + return COM_OK; +} + +/* + * asetemail + * + * Usage: asetemail player [address] + * + * Sets the email address of the player to the address given. If the + * address is omited, then the player's email address is cleared. The + * person's email address is revealed to them when they use the "finger" + * command, but no other users -- except admins -- will have another + * player's email address displayed. + */ +PUBLIC int com_asetemail(int p, param_list param) +{ + int p1, connected; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + + if (!FindPlayer(p, param[0].val.word, &p1, &connected)) + return COM_OK; + + if ((parray[p].adminLevel <= parray[p1].adminLevel) && !player_ishead(p)) { + pprintf(p, "You can only set email addr for players below your adminlevel.\n"); + if (!connected) + player_remove(p1); + return COM_OK; + } + if (parray[p1].emailAddress) + rfree(parray[p1].emailAddress); + if (param[1].type == TYPE_NULL) { + parray[p1].emailAddress = NULL; + pprintf(p, "Email address for %s removed\n", parray[p1].name); + } else { + parray[p1].emailAddress = strdup(param[1].val.word); + pprintf(p, "Email address of %s changed to \"%s\".\n", parray[p1].name, param[1].val.word); + } + player_save(p1); + if (connected) { + if (param[1].type == TYPE_NULL) { + pprintf_prompt(p1, "\n\n%s has removed your email address.\n\n", parray[p].name); + } else { + pprintf_prompt(p1, "\n\n%s has changed your email address.\n\n", parray[p].name); + } + } else { + player_remove(p1); + } + return COM_OK; +} + +/* + * asetrealname + * + * Usage: asetrealname user newname + * + * This command sets the user's real name (as displayed to admins on finger + * notes) to "newname". + */ +PUBLIC int com_asetrealname(int p, param_list param) +{ + int p1, connected; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (!FindPlayer(p, param[0].val.word, &p1, &connected)) + return COM_OK; + + if ((parray[p].adminLevel <= parray[p1].adminLevel) && !player_ishead(p)) { + pprintf(p, "You can only set real names for players below your adminlevel.\n"); + if (!connected) + player_remove(p1); + return COM_OK; + } + if (parray[p1].fullName) + rfree(parray[p1].fullName); + if (param[1].type == TYPE_NULL) { + parray[p1].fullName = NULL; + pprintf(p, "Real name for %s removed\n", parray[p1].name); + } else { + parray[p1].fullName = strdup(param[1].val.word); + pprintf(p, "Real name of %s changed to \"%s\".\n", parray[p1].name, param[1].val.word); + } + player_save(p1); + if (connected) { + if (param[1].type == TYPE_NULL) { + pprintf_prompt(p1, "\n\n%s has removed your real name.\n\n", parray[p].name); + } else { + pprintf_prompt(p1, "\n\n%s has changed your real name.\n\n", parray[p].name); + } + } else { + player_remove(p1); + } + return COM_OK; +} + +/* + * asethandle + * + * Usage: asethandle oldname newname + * + * This command changes the handle of the player from oldname to + * newname. The various player information, messages, logins, comments + * and games should be automatically transferred to the new account. + */ +PUBLIC int com_asethandle(int p, param_list param) +{ + char *player = param[0].val.word; + char *newplayer = param[1].val.word; + char playerlower[MAX_LOGIN_NAME], newplayerlower[MAX_LOGIN_NAME]; + int p1; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + strcpy(playerlower, player); + stolower(playerlower); + strcpy(newplayerlower, newplayer); + stolower(newplayerlower); + if (player_find_bylogin(playerlower) >= 0) { + pprintf(p, "A player by that name is logged in.\n"); + return COM_OK; + } + if (player_find_bylogin(newplayerlower) >= 0) { + pprintf(p, "A player by that new name is logged in.\n"); + return COM_OK; + } + p1 = player_new(); + if (player_read(p1, playerlower)) { + pprintf(p, "No player by the name %s is registered.\n", player); + player_remove(p1); + return COM_OK; + } else { + if ((parray[p].adminLevel <= parray[p1].adminLevel) && !player_ishead(p)) { + pprintf(p, "You can't set handles for an admin with a level higher than or equal to yourself.\n"); + player_remove(p1); + return COM_OK; + } + } + player_remove(p1); + + p1 = player_new(); + if ((!player_read(p1, newplayerlower)) && (strcmp(playerlower, newplayerlower))) { + pprintf(p, "Sorry that handle is already taken.\n"); + player_remove(p1); + return COM_OK; + } + player_remove(p1); + + if ((!player_rename(playerlower, newplayerlower)) && (!player_read(p1, newplayerlower))) { + pprintf(p, "Player %s renamed to %s.\n", player, newplayer); + strfree(parray[p1].name); + parray[p1].name = strdup(newplayer); + player_save(p1); + if (parray[p1].s_stats.rating > 0) + UpdateRank(TYPE_STAND, newplayer, &parray[p1].s_stats, player); + if (parray[p1].b_stats.rating > 0) + UpdateRank(TYPE_BLITZ, newplayer, &parray[p1].b_stats, player); + if (parray[p1].w_stats.rating > 0) + UpdateRank(TYPE_WILD, newplayer, &parray[p1].w_stats, player); + } else { + pprintf(p, "Asethandle failed.\n"); + } + player_remove(p1); + return COM_OK; +} + +/* + * asetadmin + * + * Usage: asetadmin player AdminLevel + * + * Sets the admin level of the player with the following restrictions. + * 1. You can only set the admin level of players lower than yourself. + * 2. You can only set the admin level to a level that is lower than + * yourself. + */ +PUBLIC int com_asetadmin(int p, param_list param) +{ + int p1, connected, oldlevel; + + ASSERT(parray[p].adminLevel >= ADMIN_GOD); + if (!FindPlayer(p, param[0].val.word,&p1, &connected)) + return COM_OK; + + if ((parray[p].adminLevel <= parray[p1].adminLevel) && !player_ishead(p)) { + pprintf(p, "You can only set adminlevel for players below your adminlevel.\n"); + if (!connected) + player_remove(p1); + return COM_OK; + } + if ((parray[p1].login) == (parray[p].login)) { + pprintf(p, "You can't change your own adminlevel.\n"); + return COM_OK; + } + if ((param[1].val.integer >= parray[p].adminLevel) && !player_ishead(p)) { + pprintf(p, "You can't promote someone to or above your adminlevel.\n"); + if (!connected) + player_remove(p1); + return COM_OK; + } + oldlevel = parray[p1].adminLevel; + parray[p1].adminLevel = param[1].val.integer; + pprintf(p, "Admin level of %s set to %d.\n", parray[p1].name, parray[p1].adminLevel); + player_save(p1); + if (connected) { + pprintf_prompt(p1, "\n\n%s has set your admin level to %d.\n\n", parray[p].name, parray[p1].adminLevel); + } else { + player_remove(p1); + } + return COM_OK; +} + +PRIVATE void SetRating(int p1, param_list param, statistics *s) +{ + s->rating = param[1].val.integer; + if (s->ltime == 0L) + s->sterr = 70.0; + + if (param[2].type == TYPE_INT) { + s->win = param[2].val.integer; + if (param[3].type == TYPE_INT) { + s->los = param[3].val.integer; + if (param[4].type == TYPE_INT) { + s->dra = param[4].val.integer; + if (param[5].type == TYPE_INT) { + s->sterr = (double) param[5].val.integer; + } + } + } + } + s->num = s->win + s->los + s->dra; + if (s->num == 0) { + s->ltime = 0L; +#if 0 + s->dra = 1; + s->num = 1; +#endif + } else { + s->ltime = time(0); + } +} + +/* + * asetblitz + * + * Usage: asetblitz handle rating won lost drew RD + * + * This command allows admins to set a user's statistics for Blitz games. + * The parameters are self-explanatory: rating, # of wins, # of losses, + * # of draws, and ratings deviation. + */ +PUBLIC int com_asetblitz(int p, param_list param) +{ + int p1, connected; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (!FindPlayer(p, param[0].val.word, &p1, &connected)) + return COM_OK; + + SetRating(p1, param, &parray[p1].b_stats); + player_save(p1); + UpdateRank(TYPE_BLITZ, parray[p1].name, &parray[p1].b_stats, + parray[p1].name); + pprintf(p, "Blitz rating for %s modified.\n", parray[p1].name); + if (!connected) + player_remove(p1); + return COM_OK; +} + +/* + * asetwild + * + * Usage: asetwild handle rating won lost drew RD + * + * This command allows admins to set a user's statistics for Wild games. + * The parameters are self-explanatory: rating, # of wins, # of losses, + * # of draws, and ratings deviation. + */ +PUBLIC int com_asetwild(int p, param_list param) +{ + int p1, connected; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (!FindPlayer(p, param[0].val.word, &p1, &connected)) + return COM_OK; + + SetRating(p1, param, &parray[p1].w_stats); + player_save(p1); + UpdateRank(TYPE_WILD, parray[p1].name, &parray[p1].w_stats, + parray[p1].name); + pprintf(p, "Wild rating for %s modified.\n", parray[p1].name); + if (!connected) + player_remove(p1); + return COM_OK; +} + +/* + * asetstd + * + * Usage: asetstd handle rating won lost drew RD + * + * This command allows admins to set a user's statistics for Standard games. + * The parameters are self-explanatory: rating, # of wins, # of losses, # of + * draws, and ratings deviation. + */ +PUBLIC int com_asetstd(int p, param_list param) +{ + int p1, connected; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (!FindPlayer(p, param[0].val.word, &p1, &connected)) + return COM_OK; + + SetRating(p1, param, &parray[p1].s_stats); + player_save(p1); + UpdateRank(TYPE_STAND, parray[p1].name, &parray[p1].s_stats, + parray[p1].name); + pprintf(p, "Standard rating for %s modified.\n", parray[p1].name); + if (!connected) + player_remove(p1); + return COM_OK; +} + +/* + * asetlight + * + * Usage: asetlight handle rating won lost drew RD + * + * This command allows admins to set a user's statistics for Lightning games. + * The parameters are self-explanatory: rating, # of wins, # of losses, # of + * draws, and ratings deviation. + */ +PUBLIC int com_asetlight(int p, param_list param) +{ + int p1, connected; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (!FindPlayer(p, param[0].val.word, &p1, &connected)) + return COM_OK; + + SetRating(p1, param, &parray[p1].l_stats); + player_save(p1); + pprintf(p, "Lightning rating for %s modified.\n", parray[p1].name); + if (!connected) + player_remove(p1); + return COM_OK; +} + +/* + * nuke + * + * Usage: nuke user + * + * This command disconnects the user from the server. The user is informed + * that she/he has been nuked by the admin named and a comment is + * automatically placed in the user's files (if she/he is a registered + * user, of course). + */ +PUBLIC int com_nuke(int p, param_list param) +{ + int p1, fd; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if ((p1 = player_find_part_login(param[0].val.word)) < 0) { + pprintf(p, "%s isn't logged in.\n", param[0].val.word); + } else { + if ((parray[p].adminLevel > parray[p1].adminLevel) || player_ishead(p)) { + pprintf(p, "Nuking: %s\n", param[0].val.word); + pprintf(p, "Please leave a comment explaining why %s was nuked.\n", parray[p1].name); + pprintf(p1, "\n\n**** You have been kicked out by %s! ****\n\n", parray[p].name); + pcommand(p, "addcomment %s Nuked\n", parray[p1].name); + fd = parray[p1].socket; + process_disconnection(fd); + net_close_connection(fd); + return COM_OK; + } else { + pprintf(p, "You need a higher adminlevel to nuke %s!\n", param[0].val.word); + } + } + return COM_OK; +} + +/* + * summon + * + * Usage: summon player + * + * This command gives a beep and a message to the player indicating that you + * want to talk with him/her. The command is useful for waking someone up, + * for example a sleepy admin or an ignorant player. + */ +PUBLIC int com_summon(int p, param_list param) +{ + int p1; + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if ((p1 = player_find_part_login(param[0].val.word)) < 0) { + pprintf(p, "%s isn't logged in.\n", param[0].val.word); + return COM_OK; + } else { + pprintf(p1, "\a\n"); + pprintf_highlight(p1, "%s", parray[p].name); + pprintf_prompt(p1, " needs to talk with you. Use tell %s <message> to reply.\a\n", parray[p].name); + pprintf(p, "Summoning sent to %s.\n", parray[p1].name); + return COM_OK; + } +} + +/* + * addcomment + * + * Usage: addcomment user comment + * + * Places "comment" in the user's comments. If a user has comments, the + * number of comments is indicated to admins using the "finger" command. + * The comments themselves are displayed by the "showcomments" command. + */ +PUBLIC int com_addcomment(int p, param_list param) +{ + int p1, connected; + + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (!FindPlayer(p, param[0].val.word, &p1, &connected)) + return COM_OK; + + if (player_add_comment(p, p1, param[1].val.string)) { + pprintf(p, "Error adding comment!\n"); + } else { + pprintf(p, "Comment added for %s.\n", parray[p1].name); + player_save(p1); + } + if (!connected) + player_remove(p1); + return COM_OK; +} + +/* + * showcomment + * + * Usage: showcomment user + * + * This command will display all of the comments added to the user's account. + */ +PUBLIC int com_showcomment(int p, param_list param) +{ + int p1, connected; + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + ASSERT(param[0].type == TYPE_WORD); + + if (!FindPlayer(p, param[0].val.word, &p1, &connected)) + return COM_OK; + player_show_comments(p, p1); + if (!connected) + player_remove(p1); + return COM_OK; +} + +/* + * admin + * + * Usage: admin + * + * This command toggles your admin symbol (*) on/off. This symbol appears + * in who listings. + */ +PUBLIC int com_admin(int p, param_list param) +{ + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + parray[p].i_admin = !(parray[p].i_admin); + if (parray[p].i_admin) { + pprintf(p, "Admin mode (*) is now shown\n"); + } else { + pprintf(p, "Admin mode (*) is now not shown\n"); + } + return COM_OK; +} + +/* + * quota + * + * Usage: quota [n] + * + * The command sets the number of seconds (n) for the shout quota, which + * affects only those persons on the shout quota list. If no parameter + * (n) is given, the current setting is displayed. + */ +PUBLIC int com_quota(int p, param_list param) +{ + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (param[0].type == TYPE_NULL) { + pprintf(p, "The current shout quota is 2 shouts per %d seconds.\n", quota_time); + return COM_OK; + } + quota_time = param[0].val.integer; + pprintf(p, "The shout quota is now 2 shouts per %d seconds.\n", quota_time); + return COM_OK; +} + + +/* + * asetmaxplayer + * + * Usage: asetmaxplayer [n] + * + * The command sets the maximum number of players (n) who can connect. + */ +PUBLIC int com_asetmaxplayer(int p, param_list param) +{ + ASSERT(parray[p].adminLevel >= ADMIN_ADMIN); + if (param[0].type != TYPE_NULL) { + pprintf(p, "Previously %d total conenctions allowed...\n", max_connections); + max_connections = param[0].val.integer; + if ((max_connections > MAX_PLAYER) || (max_connections > getdtablesize()-4)) { + max_connections = MIN(MAX_PLAYER, getdtablesize()-4); + pprintf (p, "Value too high. System OS limits us to %d.\n", + max_connections); + pprintf (p, "For saftey's sake, it should not be higher than %d.\n", + max_connections-2); + } + } + pprintf(p, + "There are currently %d regular and %d admin connections available,\n", + max_connections-10, 10 ); + pprintf(p, + "with %d maximum logins before unregistered login restrictions begin.\n", + MAX(max_connections-50, 200) ); + pprintf(p, "Total allowed connections: %d.\n", max_connections ); + return COM_OK; +} |