2 Copyright (c) 1993 Richard V. Nash.
3 Copyright (c) 2000 Dan Papasian
4 Copyright (C) Andrew Tridgell 2002
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * adminproc.c - All administrative commands and related functions
33 check that a player has sufficient rights for an operation
35 int check_admin(int p, unsigned level)
37 struct player *pp = &player_globals.parray[p];
38 /* gods and head admins always get what they want */
39 if (pp->adminLevel >= ADMIN_GOD ||
43 return pp->adminLevel >= level;
47 check that player p1 can do an admin operation on player p2
49 static int check_admin2(int p1, int p2)
51 return check_admin(p1, player_globals.parray[p2].adminLevel+1);
57 * Usage: adjudicate white_player black_player result
59 * Adjudicates a saved (stored) game between white_player and black_player.
60 * The result is one of: abort, draw, white, black. "Abort" cancels the game
61 * (no win, loss or draw), "white" gives white_player the win, "black" gives
62 * black_player the win, and "draw" gives a draw.
64 int com_adjudicate(int p, param_list param)
66 int wp, wconnected, bp, bconnected, g, inprogress, confused = 0;
68 if (!FindPlayer(p, param[0].val.word, &wp, &wconnected))
70 if (!FindPlayer(p, param[1].val.word, &bp, &bconnected)) {
76 inprogress = ((player_globals.parray[wp].game >=0) &&(player_globals.parray[wp].opponent == bp));
79 g = player_globals.parray[wp].game;
82 if (game_read(g, wp, bp) < 0) {
84 pprintf(p, "There is no stored game %s vs. %s\n", player_globals.parray[wp].name, player_globals.parray[bp].name);
86 game_globals.garray[g].white = wp;
87 game_globals.garray[g].black = bp;
91 if (strstr("abort", param[2].val.word) != NULL) {
92 game_ended(g, WHITE, END_ADJABORT);
94 pcommand(p, "message %s Your game \"%s vs. %s\" has been aborted.",
95 player_globals.parray[wp].name, player_globals.parray[wp].name, player_globals.parray[bp].name);
97 pcommand(p, "message %s Your game \"%s vs. %s\" has been aborted.",
98 player_globals.parray[bp].name, player_globals.parray[wp].name, player_globals.parray[bp].name);
99 } else if (strstr("draw", param[2].val.word) != NULL) {
100 game_ended(g, WHITE, END_ADJDRAW);
102 pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated "
103 "as a draw", player_globals.parray[wp].name, player_globals.parray[wp].name, player_globals.parray[bp].name);
105 pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated "
106 "as a draw", player_globals.parray[bp].name, player_globals.parray[wp].name, player_globals.parray[bp].name);
107 } else if (strstr("white", param[2].val.word) != NULL) {
108 game_ended(g, WHITE, END_ADJWIN);
110 pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated "
111 "as a win", player_globals.parray[wp].name, player_globals.parray[wp].name, player_globals.parray[bp].name);
113 pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated "
114 "as a loss", player_globals.parray[bp].name, player_globals.parray[wp].name, player_globals.parray[bp].name);
115 } else if (strstr("black", param[2].val.word) != NULL) {
116 game_ended(g, BLACK, END_ADJWIN);
117 pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated "
118 "as a loss", player_globals.parray[wp].name, player_globals.parray[wp].name, player_globals.parray[bp].name);
120 pcommand(p, "message %s Your game \"%s vs. %s\" has been adjudicated "
121 "as a win", player_globals.parray[bp].name, player_globals.parray[wp].name, player_globals.parray[bp].name);
124 pprintf(p, "Result must be one of: abort draw white black\n");
128 pprintf(p, "Game adjudicated.\n");
147 * Usage: remplayer name
149 * Removes an account. A copy of its files are saved under .rem.* which can
150 * be found in the appropriate directory (useful in case of an accident).
152 * The account's details, messages, games and logons are all saved as
153 * 'zombie' files. These zombie accounts are not listed in handles or
156 int com_remplayer(int p, param_list param)
158 char *player = param[0].val.word;
159 char playerlower[MAX_LOGIN_NAME];
162 strcpy(playerlower, player);
163 stolower(playerlower);
165 lookup = player_read(p1, playerlower);
167 if (!check_admin2(p, p1)) {
168 pprintf(p, "You can't remove an admin with a level higher than or equal to yourself.\n");
175 pprintf(p, "No player by the name %s is registered.\n", player);
178 if (player_find_bylogin(playerlower) >= 0) {
179 pprintf(p, "A player by that name is logged in.\n");
182 if (!player_kill(playerlower)) {
183 pprintf(p, "Player %s removed.\n", player);
184 UpdateRank(TYPE_BLITZ, NULL, NULL, player);
185 UpdateRank(TYPE_STAND, NULL, NULL, player);
186 UpdateRank(TYPE_WILD, NULL, NULL, player);
188 pprintf(p, "Remplayer failed.\n");
196 * Usage: raisedead oldname [newname]
198 * Restores an account that has been previously removed using "remplayer".
199 * The zombie files from which it came are removed. Under most
200 * circumstances, you restore the account to the same handle it had
201 * before (oldname). However, in some circumstances you may need to
202 * restore the account to a different handle, in which case you include
203 * "newname" as the new handle. After "raisedead", you may need to use the
204 * "asetpasswd" command to get the player started again as a registered
205 * user, especially if the account had been locked
206 * by setting the password to *.
208 int com_raisedead(int p, param_list param)
210 char *player = param[0].val.word;
211 char *newplayer = (param[1].type == TYPE_NULL ? player : param[1].val.word);
212 char playerlower[MAX_LOGIN_NAME], newplayerlower[MAX_LOGIN_NAME];
213 char plrFile[MAX_FILENAME_SIZE];
217 strcpy(playerlower, player);
218 stolower(playerlower);
219 strcpy(newplayerlower, newplayer);
220 stolower(newplayerlower);
222 /* First make sure we have a player to raise. */
223 sprintf (plrFile, "%s/%c/.rem.%s", PLAYER_DIR, playerlower[0], playerlower);
224 if (!file_exists (plrFile)) {
225 pprintf(p, "No deleted player %s.\n", player);
229 /* Now check for registered player. */
230 sprintf (plrFile, "%s/%c/%s", PLAYER_DIR, newplayerlower[0], newplayerlower);
231 if (file_exists (plrFile)) {
232 pprintf(p, "A player named %s is already registered.\n", newplayerlower);
233 pprintf(p, "Obtain a new handle for the dead person.\n");
234 pprintf(p, "Then use raisedead [oldname] [newname].\n");
238 /* Don't raise over a logged in user. */
239 if (player_find_bylogin(newplayerlower) >= 0) {
240 pprintf(p, "A player named %s is logged in.\n", newplayerlower);
241 pprintf(p, "Can't raise until that person leaves.\n");
245 /* OK, ready to go. */
246 if (!player_reincarn(playerlower, newplayerlower)) {
247 if (param[1].type == TYPE_WORD)
248 pprintf(p, "Player %s reincarnated to %s.\n", player, newplayer);
250 pprintf(p, "Player %s raised.\n", player);
252 if (!(lookup = player_read(p2, newplayerlower))) {
253 if (param[1].type == TYPE_WORD) {
254 free(player_globals.parray[p2].name);
255 player_globals.parray[p2].name = strdup(newplayer);
258 if (player_globals.parray[p2].s_stats.rating > 0)
259 UpdateRank(TYPE_STAND, newplayer, &player_globals.parray[p2].s_stats, newplayer);
260 if (player_globals.parray[p2].b_stats.rating > 0)
261 UpdateRank(TYPE_BLITZ, newplayer, &player_globals.parray[p2].b_stats, newplayer);
262 if (player_globals.parray[p2].w_stats.rating > 0)
263 UpdateRank(TYPE_WILD, newplayer, &player_globals.parray[p2].w_stats, newplayer);
267 pprintf(p, "Raisedead failed.\n");
271 if (param[1].type == TYPE_NULL) {
272 if (!player_raise(playerlower)) {
273 pprintf(p, "Player %s raised from dead.\n", player);
276 if (!(lookup = player_read(p1, playerlower))) {
277 if (player_globals.parray[p1].s_stats.rating > 0)
278 UpdateRank(TYPE_STAND, player, &player_globals.parray[p1].s_stats, player);
279 if (player_globals.parray[p1].b_stats.rating > 0)
280 UpdateRank(TYPE_BLITZ, player, &player_globals.parray[p1].b_stats, player);
281 if (player_globals.parray[p1].w_stats.rating > 0)
282 UpdateRank(TYPE_WILD, player, &player_globals.parray[p1].w_stats, player);
286 pprintf(p, "Raisedead failed.\n");
290 if (player_find_bylogin(newplayerlower) >= 0) {
291 pprintf(p, "A player by the requested name is logged in.\n");
292 pprintf(p, "Can't reincarnate until they leave.\n");
296 lookup = player_read(p2, newplayerlower);
299 pprintf(p, "A player by the name %s is already registered.\n", player);
300 pprintf(p, "Obtain another new handle for the dead person.\n");
303 if (!player_reincarn(playerlower, newplayerlower)) {
304 pprintf(p, "Player %s reincarnated to %s.\n", player, newplayer);
306 if (!(lookup = player_read(p2, newplayerlower))) {
307 free(player_globals.parray[p2].name);
308 player_globals.parray[p2].name = strdup(newplayer);
310 if (player_globals.parray[p2].s_stats.rating > 0)
311 UpdateRank(TYPE_STAND, newplayer, &player_globals.parray[p2].s_stats, newplayer);
312 if (player_globals.parray[p2].b_stats.rating > 0)
313 UpdateRank(TYPE_BLITZ, newplayer, &player_globals.parray[p2].b_stats, newplayer);
314 if (player_globals.parray[p2].w_stats.rating > 0)
315 UpdateRank(TYPE_WILD, newplayer, &player_globals.parray[p2].w_stats, newplayer);
319 pprintf(p, "Raisedead failed.\n");
329 * Usage: addplayer playername emailaddress realname
331 * Adds a local player to the server with the handle of "playername". For
334 * addplayer Hawk u940456@daimi.aau.dk Henrik Gram
336 int com_addplayer(int p, param_list param)
339 char *newplayer = param[0].val.word;
340 char *newname = param[2].val.string;
341 char *newemail = param[1].val.word;
342 char password[PASSLEN + 1];
343 char newplayerlower[MAX_LOGIN_NAME];
348 if (strlen(newplayer) >= MAX_LOGIN_NAME) {
349 pprintf(p, "Player name is too long\n");
352 if (strlen(newplayer) < 3) {
353 pprintf(p, "Player name is too short\n");
356 if (!alphastring(newplayer)) {
357 pprintf(p, "Illegal characters in player name. Only A-Za-z allowed.\n");
360 strcpy(newplayerlower, newplayer);
361 stolower(newplayerlower);
363 lookup = player_read(p1, newplayerlower);
365 pprintf(p, "A player by the name %s is already registered.\n", newplayerlower);
369 player_globals.parray[p1].name = strdup(newplayer);
370 player_globals.parray[p1].login = strdup(newplayerlower);
371 player_globals.parray[p1].fullName = strdup(newname);
372 player_globals.parray[p1].emailAddress = strdup(newemail);
373 if (strcmp(newemail, "none")) {
374 for (i = 0; i < PASSLEN; i++) {
375 password[i] = 'a' + random() % 26;
378 salt[0] = 'a' + random() % 26;
379 salt[1] = 'a' + random() % 26;
381 player_globals.parray[p1].passwd = strdup(chessd_crypt(password, salt));
384 player_globals.parray[p1].passwd = strdup(password);
386 PFlagON(p1, PFLAG_REG);
387 /* player_globals.parray[p1].network_player = 0; */
388 PFlagON(p1, PFLAG_RATED);
389 player_add_comment(p, p1, "Player added by addplayer.");
392 pprintf(p, "Added: >%s< >%s< >%s< >%s<\n", newplayer, newname, newemail, password);
393 if (strcmp(newemail, "none")) {
395 sprintf(text, "\nYou have been added as a local player.\n\nLogin Name: "
396 "%s\nFull Name: %s\nEmail Address: %s\nInitial Password: "
397 "%s\n\nIf any of this information is incorrect, please "
398 "contact the administrator\nto get it corrected.\n\n"
399 "Please write down your password.\n\nRegards,\n\nThe FICS admins\n",
400 newplayer, newname, newemail, password);
403 sprintf(text, "\nYour player account has been created.\n\n"
404 "Login Name: %s\nFull Name: %s\nEmail Address: %s\nInitial Password: %s\n\n"
405 "If any of this information is incorrect, please contact the administrator\n"
406 "to get it corrected.\n\n"
407 "You may change your password with the password command on the the server.\n"
408 "\nPlease be advised that if this is an unauthorized duplicate account for\n"
409 "you, by using it you take the risk of being banned from accessing this\n"
411 "Regards,\n\nThe FICS admins\n",
412 newplayer, newname, newemail, password);
414 mail_string_to_address(newemail, "FICS Account Created", text);
415 if ((p1 = player_find_part_login(newplayer)) >= 0) {
416 pprintf_prompt(p1, "\n\nYou are now registered! Confirmation together with\npassword is sent to your email address.\n\n");
417 player_read(p1, newplayer);
422 if ((p1 = player_find_part_login(newplayer)) >= 0) {
423 pprintf_prompt(p1, "\n\nYou are now registered! Your have NO password!\n\n");
424 player_read(p1, newplayer);
431 int com_pose(int p, param_list param)
435 if ((p1 = player_find_part_login(param[0].val.word)) < 0) {
436 pprintf(p, "%s is not logged in.\n", param[0].val.word);
439 if (!check_admin2(p, p1)) {
440 pprintf(p, "You can only pose as players below your adminlevel.\n");
443 pprintf(p, "Command issued as %s\n", player_globals.parray[p1].name);
444 pcommand(p1, "%s\n", param[1].val.string);
451 * Usage: asetv user instructions
453 * This command executes "set" instructions as if they had been made by the
454 * user indicated. For example, "asetv DAV shout 0" would set DAV's shout
457 int com_asetv(int p, param_list param)
461 if ((p1 = player_find_part_login(param[0].val.word)) < 0) {
462 pprintf(p, "%s is not logged in.\n", param[0].val.word);
465 if (!check_admin2(p, p1)) {
466 pprintf(p, "You can only aset players below your adminlevel.\n");
469 pprintf(p, "Command issued as %s\n", player_globals.parray[p1].name);
470 pcommand(p1, "set %s\n", param[1].val.string);
477 * Usage: announce message
479 * Broadcasts your message to all logged on users. Announcements reach all
480 * users and cannot be censored in any way (such as by "set shout 0").
482 int com_announce(int p, param_list param)
484 struct player *pp = &player_globals.parray[p];
488 if (!printablestring(param[0].val.string)) {
489 pprintf(p, "Your message contains some unprintable character(s).\n");
492 for (p1 = 0; p1 < player_globals.p_num; p1++) {
495 if (player_globals.parray[p1].status != PLAYER_PROMPT)
498 pprintf_prompt(p1, "\n\n **ANNOUNCEMENT** from %s: %s\n\n", pp->name, param[0].val.string);
500 pprintf(p, "\n(%d) **ANNOUNCEMENT** from %s: %s\n\n", count, pp->name, param[0].val.string);
507 * Usage: annunreg message
509 * Broadcasts your message to all logged on unregistered users, and admins,
510 * too. Announcements reach all unregistered users and admins and cannot be
511 * censored in any way (such as by "set shout 0").
513 int com_annunreg(int p, param_list param)
515 struct player *pp = &player_globals.parray[p];
519 if (!printablestring(param[0].val.string)) {
520 pprintf(p, "Your message contains some unprintable character(s).\n");
523 for (p1 = 0; p1 < player_globals.p_num; p1++) {
524 if (p1 == p) continue;
525 if (player_globals.parray[p1].status != PLAYER_PROMPT) continue;
526 if (CheckPFlag(p1, PFLAG_REG)
527 && !check_admin(p1, ADMIN_ADMIN))
530 pprintf_prompt(p1, "\n\n **UNREG ANNOUNCEMENT** from %s: %s\n\n",
531 pp->name, param[0].val.string);
533 pprintf(p, "\n(%d) **UNREG ANNOUNCEMENT** from %s: %s\n\n",
534 count, pp->name, param[0].val.string);
541 * Usage: asetpasswd player {password,*}
543 * This command sets the password of the player to the password given.
544 * If '*' is specified then the player's account is locked, and no password
545 * will work until a new one is set by asetpasswd.
547 * If the player is connected, he is told of the new password and the name
548 * of the admin who changed it, or likewise of his account status. An
549 * email message is mailed to the player's email address as well.
551 int com_asetpasswd(int p, param_list param)
553 struct player *pp = &player_globals.parray[p];
555 char subject[400], text[10100];
558 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
561 if (!check_admin2(p, p1)) {
562 pprintf(p, "You can only set password for players below your adminlevel.\n");
567 if (!CheckPFlag(p1, PFLAG_REG)) {
568 pprintf(p, "You cannot set the password of an unregistered player!\n");
571 if (player_globals.parray[p1].passwd)
572 free(player_globals.parray[p1].passwd);
573 if (param[1].val.word[0] == '*') {
574 player_globals.parray[p1].passwd = strdup(param[1].val.word);
575 pprintf(p, "Account %s locked!\n", player_globals.parray[p1].name);
576 sprintf(text, "Password of %s is now useless. Your account at our"
577 " FICS has been locked.\n", player_globals.parray[p1].name);
578 pprintf(p, "Please leave a comment to explain why %s's account"
579 " was locked.\n", player_globals.parray[p1].name);
580 pcommand(p, "addcomment %s Account locked.\n", player_globals.parray[p1].name);
582 salt[0] = 'a' + random() % 26;
583 salt[1] = 'a' + random() % 26;
585 player_globals.parray[p1].passwd = strdup(chessd_crypt(param[1].val.word, salt));
586 sprintf(text, "Password of %s changed to \"%s\".\n", player_globals.parray[p1].name, param[1].val.word);
587 pprintf(p, "%s", text);
589 if (param[1].val.word[0] == '*') {
590 sprintf(subject, "CHESSD: %s has locked your account.", pp->name);
592 pprintf_prompt(p1, "\n%s\n", subject);
594 sprintf(subject, "CHESSD: %s has changed your password.", pp->name);
596 pprintf_prompt(p1, "\n%s\n", subject);
598 mail_string_to_address(player_globals.parray[p1].emailAddress, subject, text);
608 * Usage: asetemail player [address]
610 * Sets the email address of the player to the address given. If the
611 * address is omited, then the player's email address is cleared. The
612 * person's email address is revealed to them when they use the "finger"
613 * command, but no other users -- except admins -- will have another
614 * player's email address displayed.
616 int com_asetemail(int p, param_list param)
618 struct player *pp = &player_globals.parray[p];
622 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
625 if (!check_admin2(p, p1)) {
626 pprintf(p, "You can only set email addr for players below your adminlevel.\n");
631 if (player_globals.parray[p1].emailAddress) {
632 oldemail = strdup(player_globals.parray[p1].emailAddress);
633 free(player_globals.parray[p1].emailAddress);
635 oldemail = strdup("");
638 if (param[1].type == TYPE_NULL) {
639 player_globals.parray[p1].emailAddress = NULL;
640 pprintf(p, "Email address for %s removed\n", player_globals.parray[p1].name);
641 pcommand(p, "addcomment %s Email address removed.\n", player_globals.parray[p1].name);
644 player_globals.parray[p1].emailAddress = strdup(param[1].val.word);
645 pprintf(p, "Email address of %s changed to \"%s\".\n", player_globals.parray[p1].name, param[1].val.word);
646 pcommand(p, "addcomment %s Email address changed from %s to %s.\n", player_globals.parray[p1].name, oldemail, player_globals.parray[p1].emailAddress);
651 if (param[1].type == TYPE_NULL) {
652 pprintf_prompt(p1, "\n\n%s has removed your email address.\n\n", pp->name);
654 pprintf_prompt(p1, "\n\n%s has changed your email address.\n\n", pp->name);
665 * Usage: asetrealname user newname
667 * This command sets the user's real name (as displayed to admins on finger
668 * notes) to "newname".
670 int com_asetrealname(int p, param_list param)
672 struct player *pp = &player_globals.parray[p];
675 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
678 if (!check_admin2(p, p1)) {
679 pprintf(p, "You can only set real names for players below your adminlevel.\n");
684 if (player_globals.parray[p1].fullName)
685 free(player_globals.parray[p1].fullName);
686 if (param[1].type == TYPE_NULL) {
687 player_globals.parray[p1].fullName = NULL;
688 pprintf(p, "Real name for %s removed\n", player_globals.parray[p1].name);
690 player_globals.parray[p1].fullName = strdup(param[1].val.word);
691 pprintf(p, "Real name of %s changed to \"%s\".\n", player_globals.parray[p1].name, param[1].val.word);
695 if (param[1].type == TYPE_NULL) {
696 pprintf_prompt(p1, "\n\n%s has removed your real name.\n\n", pp->name);
698 pprintf_prompt(p1, "\n\n%s has changed your real name.\n\n", pp->name);
709 * Usage: asethandle oldname newname
711 * This command changes the handle of the player from oldname to
712 * newname. The various player information, messages, logins, comments
713 * and games should be automatically transferred to the new account.
715 int com_asethandle(int p, param_list param)
717 char *player = param[0].val.word;
718 char *newplayer = param[1].val.word;
719 char playerlower[MAX_LOGIN_NAME], newplayerlower[MAX_LOGIN_NAME];
722 strcpy(playerlower, player);
723 stolower(playerlower);
724 strcpy(newplayerlower, newplayer);
725 stolower(newplayerlower);
726 if (player_find_bylogin(playerlower) >= 0) {
727 pprintf(p, "A player by that name is logged in.\n");
730 if (player_find_bylogin(newplayerlower) >= 0) {
731 pprintf(p, "A player by that new name is logged in.\n");
735 if (player_read(p1, playerlower)) {
736 pprintf(p, "No player by the name %s is registered.\n", player);
740 if (!check_admin2(p, p1)) {
741 pprintf(p, "You can't set handles for an admin with a level higher than or equal to yourself.\n");
749 if ((!player_read(p1, newplayerlower)) && (strcmp(playerlower, newplayerlower))) {
750 pprintf(p, "Sorry that handle is already taken.\n");
756 if ((!player_rename(playerlower, newplayerlower)) && (!player_read(p1, newplayerlower))) {
757 pprintf(p, "Player %s renamed to %s.\n", player, newplayer);
758 free(player_globals.parray[p1].name);
759 player_globals.parray[p1].name = strdup(newplayer);
761 if (player_globals.parray[p1].s_stats.rating > 0)
762 UpdateRank(TYPE_STAND, newplayer, &player_globals.parray[p1].s_stats, player);
763 if (player_globals.parray[p1].b_stats.rating > 0)
764 UpdateRank(TYPE_BLITZ, newplayer, &player_globals.parray[p1].b_stats, player);
765 if (player_globals.parray[p1].w_stats.rating > 0)
766 UpdateRank(TYPE_WILD, newplayer, &player_globals.parray[p1].w_stats, player);
768 pprintf(p, "Asethandle failed.\n");
777 * Usage: asetadmin player AdminLevel
779 * Sets the admin level of the player with the following restrictions.
780 * 1. You can only set the admin level of players lower than yourself.
781 * 2. You can only set the admin level to a level that is lower than
784 int com_asetadmin(int p, param_list param)
786 struct player *pp = &player_globals.parray[p];
787 int p1, connected, oldlevel;
789 if (!FindPlayer(p, param[0].val.word,&p1, &connected))
792 if (!check_admin2(p, p1)) {
793 pprintf(p, "You can only set adminlevel for players below your adminlevel.\n");
798 if (!strcmp(player_globals.parray[p1].login, pp->login)) {
799 pprintf(p, "You can't change your own adminlevel.\n");
802 if (!check_admin(p, param[1].val.integer+1)) {
803 pprintf(p, "You can't promote someone to or above your adminlevel.\n");
808 oldlevel = player_globals.parray[p1].adminLevel;
809 player_globals.parray[p1].adminLevel = param[1].val.integer;
810 pprintf(p, "Admin level of %s set to %d.\n", player_globals.parray[p1].name, player_globals.parray[p1].adminLevel);
813 pprintf_prompt(p1, "\n\n%s has set your admin level to %d.\n\n", pp->name, player_globals.parray[p1].adminLevel);
820 static void SetRating(int p1, param_list param, struct statistics *s)
822 s->rating = param[1].val.integer;
826 if (param[2].type == TYPE_INT) {
827 s->win = param[2].val.integer;
828 if (param[3].type == TYPE_INT) {
829 s->los = param[3].val.integer;
830 if (param[4].type == TYPE_INT) {
831 s->dra = param[4].val.integer;
832 if (param[5].type == TYPE_INT) {
833 s->sterr = (double) param[5].val.integer;
838 s->num = s->win + s->los + s->dra;
853 * Usage: asetblitz handle rating won lost drew RD
855 * This command allows admins to set a user's statistics for Blitz games.
856 * The parameters are self-explanatory: rating, # of wins, # of losses,
857 * # of draws, and ratings deviation.
859 int com_asetblitz(int p, param_list param)
863 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
866 if (CheckPFlag(p1, PFLAG_REG)) {
867 SetRating(p1, param, &player_globals.parray[p1].b_stats);
869 UpdateRank(TYPE_BLITZ, player_globals.parray[p1].name, &player_globals.parray[p1].b_stats,
870 player_globals.parray[p1].name);
872 pprintf(p, "%s is unregistered. Can't modify rating.\n", player_globals.parray[p1].name);
882 * Usage: asetwild handle rating won lost drew RD
884 * This command allows admins to set a user's statistics for Wild games.
885 * The parameters are self-explanatory: rating, # of wins, # of losses,
886 * # of draws, and ratings deviation.
888 int com_asetwild(int p, param_list param)
892 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
895 if (CheckPFlag(p1, PFLAG_REG)) {
896 SetRating(p1, param, &player_globals.parray[p1].w_stats);
898 UpdateRank(TYPE_WILD, player_globals.parray[p1].name, &player_globals.parray[p1].w_stats,
899 player_globals.parray[p1].name);
900 pprintf(p, "Wild rating for %s modified.\n", player_globals.parray[p1].name);
902 pprintf(p, "%s is unregistered. Can't modify rating.\n", player_globals.parray[p1].name);
912 * Usage: asetstd handle rating won lost drew RD
914 * This command allows admins to set a user's statistics for Standard games.
915 * The parameters are self-explanatory: rating, # of wins, # of losses, # of
916 * draws, and ratings deviation.
918 int com_asetstd(int p, param_list param)
922 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
925 if (CheckPFlag(p1, PFLAG_REG)) {
926 SetRating(p1, param, &player_globals.parray[p1].s_stats);
928 UpdateRank(TYPE_STAND, player_globals.parray[p1].name, &player_globals.parray[p1].s_stats,
929 player_globals.parray[p1].name);
930 pprintf(p, "Standard rating for %s modified.\n", player_globals.parray[p1].name);
932 pprintf(p, "%s is unregistered. Can't modify rating.\n", player_globals.parray[p1].name);
942 * Usage: asetlight handle rating won lost drew RD
944 * This command allows admins to set a user's statistics for Lightning games.
945 * The parameters are self-explanatory: rating, # of wins, # of losses, # of
946 * draws, and ratings deviation.
948 int com_asetlight(int p, param_list param)
952 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
955 if (CheckPFlag(p1, PFLAG_REG)) {
956 SetRating(p1, param, &player_globals.parray[p1].l_stats);
958 pprintf(p, "Lightning rating for %s modified.\n", player_globals.parray[p1].name);
960 pprintf(p, "%s is unregistered. Can't modify rating.\n", player_globals.parray[p1].name);
970 * Usage: asetbug handle rating won lost drew RD
972 * This command allows admins to set a user's statistics for Bughouse
973 * games. The parameters are self-explanatory: rating, # of wins,
974 * # of losses, # of draws, and ratings deviation.
976 int com_asetbug(int p, param_list param)
980 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
983 if (CheckPFlag(p1, PFLAG_REG)) {
984 SetRating(p1, param, &player_globals.parray[p1].bug_stats);
986 pprintf(p, "Bughouse rating for %s modified.\n", player_globals.parray[p1].name);
988 pprintf(p, "%s is unregistered. Can't modify rating.\n", player_globals.parray[p1].name);
999 * This command forwards all further conversation between an admin and a
1000 * user to all those listening in channel 0.
1001 * It is unset as soon as the user logs off or ftell is typed without a
1005 int com_ftell(int p, param_list param)
1007 struct player *pp = &player_globals.parray[p];
1011 if (param[0].type == TYPE_WORD) {
1013 if ((p1 = player_find_part_login(param[0].val.word)) < 0) {
1014 pprintf(p, "%s isn't logged in.\n", param[0].val.word);
1019 pprintf (p, "Nobody wants to listen to you talking to yourself! :-)\n");
1023 if (pp->ftell != -1) {
1024 sprintf (command, "tell 0 I will no longer be forwarding the conversation between *%s* and myself.", player_globals.parray[pp->ftell].name);
1025 pcommand (p,command);
1028 sprintf (command, "tell 0 I will be forwarding the conversation between *%s* and myself to channel 0.", player_globals.parray[p1].name);
1029 pcommand (p,command);
1032 return COM_OK_NOPROMPT;
1036 if (pp->ftell != -1) {
1038 pprintf (p,"Stopping the forwarding of the conservation with %s.\n",
1039 player_globals.parray[pp->ftell].name);
1040 pcommand (p,"tell 0 I will no longer be forwarding the conversation between *%s* and myself.",
1041 player_globals.parray[pp->ftell].name);
1044 return COM_OK_NOPROMPT;
1046 pprintf (p,"You were not forwarding a conversation.\n");
1057 * This command disconnects the user from the server. The user is informed
1058 * that she/he has been nuked by the admin named and a comment is
1059 * automatically placed in the user's files (if she/he is a registered
1062 int com_nuke(int p, param_list param)
1064 struct player *pp = &player_globals.parray[p];
1067 if ((p1 = player_find_part_login(param[0].val.word)) < 0) {
1068 pprintf(p, "%s isn't logged in.\n", param[0].val.word);
1072 if (!check_admin2(p, p1)) {
1073 pprintf(p, "You need a higher adminlevel to nuke %s!\n", param[0].val.word);
1077 pprintf(p, "Nuking: %s\n", param[0].val.word);
1078 pprintf(p, "Please leave a comment explaining why %s was nuked.\n", player_globals.parray[p1].name);
1079 pprintf(p1, "\n\n**** You have been kicked out by %s! ****\n\n", pp->name);
1080 pcommand(p, "addcomment %s Nuked\n", player_globals.parray[p1].name);
1081 fd = player_globals.parray[p1].socket;
1082 process_disconnection(fd);
1083 net_close_connection(fd);
1090 * Usage: summon player
1092 * This command gives a beep and a message to the player indicating that you
1093 * want to talk with him/her. The command is useful for waking someone up,
1094 * for example a sleepy admin or an ignorant player.
1096 int com_summon(int p, param_list param)
1098 struct player *pp = &player_globals.parray[p];
1101 if ((p1 = player_find_part_login(param[0].val.word)) < 0) {
1102 pprintf(p, "%s isn't logged in.\n", param[0].val.word);
1106 pprintf(p1, "\a\n");
1107 pprintf_highlight(p1, "%s", pp->name);
1108 pprintf_prompt(p1, " needs to talk with you. Use tell %s <message> to reply.\a\n", pp->name);
1109 pprintf(p, "Summoning sent to %s.\n", player_globals.parray[p1].name);
1116 * Usage: addcomment user comment
1118 * Places "comment" in the user's comments. If a user has comments, the
1119 * number of comments is indicated to admins using the "finger" command.
1120 * The comments themselves are displayed by the "showcomments" command.
1122 int com_addcomment(int p, param_list param)
1126 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
1129 if (player_add_comment(p, p1, param[1].val.string)) {
1130 pprintf(p, "Error adding comment!\n");
1132 pprintf(p, "Comment added for %s.\n", player_globals.parray[p1].name);
1143 * Usage: showcomment user
1145 * This command will display all of the comments added to the user's account.
1147 int com_showcomment(int p, param_list param)
1151 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
1153 player_show_comments(p, p1);
1164 * This command toggles your admin symbol (*) on/off. This symbol appears
1167 int com_admin(int p, param_list param)
1169 TogglePFlag(p, PFLAG_ADMINLIGHT);
1170 if (CheckPFlag(p, PFLAG_ADMINLIGHT)) {
1171 pprintf(p, "Admin mode (*) is now shown.\n");
1173 pprintf(p, "Admin mode (*) is now not shown.\n");
1178 int com_hideinfo(int p, param_list param)
1180 TogglePFlag(p, PFLAG_HIDEINFO);
1182 if (CheckPFlag(p, PFLAG_HIDEINFO))
1183 pprintf(p, "Private user information now not shown.\n");
1185 pprintf(p, "Private user information now shown.\n");
1195 * The command sets the number of seconds (n) for the shout quota, which
1196 * affects only those persons on the shout quota list. If no parameter
1197 * (n) is given, the current setting is displayed.
1199 int com_quota(int p, param_list param)
1201 if (param[0].type == TYPE_NULL) {
1202 pprintf(p, "The current shout quota is 2 shouts per %d seconds.\n", seek_globals.quota_time);
1205 seek_globals.quota_time = param[0].val.integer;
1206 pprintf(p, "The shout quota is now 2 shouts per %d seconds.\n", seek_globals.quota_time);
1212 force a server reload
1214 int com_areload(int p, param_list param)
1216 extern unsigned chessd_reload_flag;
1218 chessd_reload_flag = 1;
1220 pprintf(p, "Server reload started\n");