/*
Calisto (c) 1998-2000 Peter Howkins, Matthew Howkins, Simon Howkins
$Id: commands.c,v 1.32 2000/03/12 00:58:01 peter Exp $
*/
static char rcsid[] = "$Id: commands.c,v 1.32 2000/03/12 00:58:01 peter Exp $";
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "unistd.h"
#include "config.h"
#include "colours.h"
#include "commands.h"
#include "globals.h"
#include "help.h"
#include "library.h"
#include "log.h"
#include "msnprintf.h"
#include "playerdb.h"
#include "privs.h"
#include "structs.h"
#include "strplus.h"
typedef struct {
const char *name;
const char *shortcut;
void (*function)(character *, char *);
const char *privname;
} command;
void command_bug(character *, char *);
void command_cls(character *, char *);
void command_commands(character *, char *);
void command_dc(character *, char *);
void command_emote(character *, char *);
void command_finger(character *, char *);
void command_grant(character *, char *);
void command_group(character *, char *);
void command_idea(character *, char *);
void command_lsd(character *, char *);
void command_motd(character *, char *);
void command_ping(character *, char *);
void command_prompt(character *, char *);
void command_quit(character *, char *);
void command_recap(character *, char *);
void command_reload(character *, char *);
void command_remote(character *, char *);
void command_remove(character *, char *);
void command_save(character *, char *);
void command_say(character *, char *);
void command_set(character *, char *);
void command_shout(character *, char *);
void command_shutdown(character *, char *);
void command_stat(character *, char *);
void command_sumotd(character *, char *);
void command_tell(character *, char *);
void command_time(character *, char *);
void command_typo(character *, char *);
void command_users(character *, char *);
void command_version(character *, char *);
void command_who(character *, char *);
void command_whoami(character *, char *);
const command commands[] = {
{ "bug", "", command_bug, "n_base" },
{ "bump", "", command_dc, "s_bump" },
{ "clear", "", command_cls, "n_base" },
{ "cls", "", command_cls, "n_base" },
{ "commands","", command_commands, "n_base" },
{ "dc", "", command_dc, "s_bump" },
{ "emote", ";:",command_emote, "n_talk" },
{ "exit", "", command_quit, "n_base" },
{ "finger", "", command_finger, "n_base" },
{ "grant", "", command_grant, "a_grant" },
{ "group", "", command_group, "n_base" },
{ "help", "", command_help, "n_base" }, /* Found in help.c */
{ "idea", "", command_idea, "n_base" },
{ "lsd", "", command_lsd, "s_trace" },
{ "motd", "", command_motd, "n_base" },
{ "ping", "", command_ping, "n_base" },
{ "prompt", "", command_prompt, "n_base" },
{ "quit", "", command_quit, "n_base" },
{ "recap", "", command_recap, "n_base" },
{ "reload", "", command_reload, "a_base" },
{ "remote", ",", command_remote, "n_talk" },
{ "remove", "", command_remove, "a_grant" },
{ "save", "", command_save, "n_save" },
{ "say", "'", command_say, "n_talk" },
{ "set", "", command_set, "a_base" },
{ "shout", "", command_shout, "n_talk" },
{ "shutdown","", command_shutdown, "a_shutdown" },
{ "stat", "", command_stat, "a_base" },
{ "sumotd", "", command_sumotd, "s_base" },
{ "tell", ".", command_tell, "n_talk" },
{ "time", "", command_time, "n_base" },
{ "typo", "", command_typo, "n_base" },
{ "users", "", command_users, "n_base" },
{ "version", "", command_version, "n_base" },
{ "who", "", command_who, "n_base" },
{ "whoami", "", command_whoami, "n_base" },
{ "x", "", command_finger, "n_base" }
};
const unsigned commandn = sizeof commands / sizeof(command);
void command_version(character *c, char *r)
{
descriptor *des = getdes(c);
bar2(des, "Version", NULL, NULL);
send_to_char(c, "^PCalisto^n %u.%02u (c) 1998-2000 ^YFlibble^n, ^YThe_Pope^n and ^YWilfred^n\n", version/100, version%100);
send_to_char(c, " ^G+^n Colour Code ^G-^n ^YEkto^n (ekto@ekto.org)\n");
send_to_char(c, " ^G+^n snprintf ^G-^n based on code by ^YAlain Magloire^n (alainm@rcsm.ee.mcgill.ca)\n");
bar2(des, NULL, NULL, NULL);
}
void command_set(character *c, char *r)
{
char *variable;
char *value;
bool quoted = FALSE;
if (STREQ(r, "")) {
send_to_char(c, "use_net_lookups: %d\n", use_net_lookups);
send_to_char(c, "idle_boot_time: %u minutes\n", idle_boot_time);
send_to_char(c, "max_connections: %u\n", max_connections);
return;
}
/* Break input into variable and value */
strmunch(r, &variable, &r);
if (*r == '\"') {
quoted = TRUE;
r++;
}
value = r;
if (quoted) {
while (*r && *r != '\"')
r++;
} else {
while (*r && !isspace(*r))
r++;
}
*r = '\0';
/* send_to_char(c, "variable = \'%s\'\n", variable);
send_to_char(c, "value = \'%s\'\n", value);*/
/* Check if value specified OK */
if (STREQ(value, "")) {
help_usage(c, "set");
return;
}
/* Handle known variables, and complain about unknown ones */
if (STRIEQ(variable, "use_net_lookups")) {
use_net_lookups = atoi(value);
if (use_net_lookups)
use_net_lookups = TRUE;
} else if (STRIEQ(variable, "idle_boot_time")) {
idle_boot_time = (unsigned) atoi(value);
} else if (STRIEQ(variable, "max_connections")) {
max_connections = (unsigned) atoi(value);
} else {
send_to_char(c, "Unknown variable '%s'\n"
"Use the set command without parameters to list variables.\n",
variable);
}
}
void command_recap(character *c, char *r)
{
if(STREQ(r, "")) {
help_usage(c, "recap");
return;
}
if(STRIEQ(r, c->name)) {
STRNCOPY(c->name, r, sizeof(c->name));
send_to_char(c, "Name recapitalised\n");
} else {
send_to_char(c, "Input must be the same as your name\n");
}
}
void command_save(character *c, char *r)
{
int error = save_player(c, c->name);
if(error) {
send_to_char(c, "Error saving your character\n");
} else {
send_to_char(c, "Successfully saved your character\n");
}
}
void command_sumotd(character *c, char *r)
{
descriptor *des = getdes(c);
bar2(des, "Super-user Message Of The Day", NULL, NULL);
send_file_to_descriptor("lib/etc/sumotd", des);
bar2(des, NULL, NULL, NULL);
}
void command_cls(character *c, char *r)
{
descriptor *des = getdes(c);
int i;
for (i = 0; i < des->term_height; i++) {
send_to_char(c, "\n");
}
/* send_to_char(c, "\x1b[0;0H"); */
send_to_char(c, "\x1b[%dA", des->term_height);
}
void command_reload(character *c, char *r)
{
if (STRIEQ(r, "help")) {
help_reload(c);
} else if (STRIEQ(r, "all")) {
help_reload(c);
} else {
send_to_char(c, "Unrecognised reload option %s\n", r);
}
}
#define COMMAND_STAT_OPTIONS "net mem"
static void command_stat_usage(character *c)
{
send_to_char(c, "Usage: stat <option> [<option>...]\n");
send_to_char(c, "where <option> is one of `%s all`\n",
COMMAND_STAT_OPTIONS);
}
void command_stat(character *c, char *r)
{
if (*r) {
while (*r) {
char *sub;
strmunch(r, &sub, &r);
if (STRIEQ(sub, "mem")) {
pool_stat_t ps = pool_stat(descriptor_pool);
send_to_char(c, "^H[Memory - Descriptors]^n\n");
send_to_char(c, " Block Size : %u\n", ps.block_size);
send_to_char(c, " Usage : %u\n", ps.usage);
send_to_char(c, " Capacity : %u (%.1fk)\n", ps.capacity,
(double) (ps.block_size * ps.capacity) / 1024.0);
send_to_char(c, " Free : %u\n", ps.capacity - ps.usage);
send_to_char(c, " Connections : %u/%u\n", ps.usage,
max_connections);
} else if (STRIEQ(sub, "net")) {
FILE *f;
const char *hostname = getenv("HOSTNAME");
const char *machtype = getenv("MACHTYPE");
send_to_char(c, "^H[Network and Machine]^n\n");
send_to_char(c, " PID : %u\n", (unsigned) getpid());
send_to_char(c, " PPID : %u\n", (unsigned) getppid());
send_to_char(c, " HOST : %s\n", hostname ? hostname : "** Unknown **");
send_to_char(c, " TYPE : %s\n", machtype ? machtype : "** Unknown **");
/* Display load average of server, if available */
f = fopen("/proc/loadavg", "r");
if (f) {
char buffer[256];
float load1, load5, load15;
if (fgets(buffer, sizeof(buffer), f)) {
if (sscanf(buffer, "%f %f %f", &load1, &load5, &load15) == 3) {
send_to_char(c, "LoadAvg : %.2f %.2f %.2f\n",
load1, load5, load15);
}
}
fclose(f);
}
} else if (STRIEQ(sub, "all")) {
char all[] = COMMAND_STAT_OPTIONS;
command_stat(c, all);
} else {
send_to_char(c, "Unknown stat option `%s`\n", sub);
command_stat_usage(c);
}
}
} else {
command_stat_usage(c);
}
#undef COMMAND_STAT_OPTIONS
}
void command_finger(character *c, char *r)
{
/* formats
finger - does a finger on the character that called func
finger bob - does a finger on bob
check for
r = ""
r logged in
r not logged in and exists
r not logged in and doesn't exist
*/
time_t now;
descriptor *des = getdes(c);
descriptor *victdes;
character *victim;
character target;
char buffer[OUTPUT_BUFFER];
bool loggedin = FALSE;
if(STREQ(r, "")) {
victim = c;
loggedin = TRUE;
} else {
if((victim = character_from_name(r)) != NULL) {
/* victim is logged on and found */
loggedin = TRUE;
} else {
/* check to see is r is in the players directory, if so load
else return */
int failed;
failed = load_player(&target, r);
if (failed) {
send_to_char(c, "Player %s, not found\n", r);
return;
} else {
victim = ⌖
loggedin = FALSE;
}
}
}
now = time(NULL);
victdes = getdes(victim);
if (loggedin) {
seconds_to_string(victim->prevtime + difftime(now, victim->logintime),
buffer, sizeof(buffer));
} else {
seconds_to_string(victim->prevtime, buffer, sizeof(buffer));
}
bar2(des, "Finger", NULL, NULL);
send_to_char(c, " Name: %s\n", victim->name);
send_to_char(c, "Total Time: %s\n", buffer);
/* Display privileges */
if (victim == c || haspriv(c, "s_base")) {
send_to_char(c, " Privs:");
privs_list_player(c, victim);
send_to_char(c, "^n\n");
}
if (loggedin) {
send_to_char(c, " Group: %s\n", victim->group);
send_to_char(c, " Termtype: %s (%ux%u)\n", victdes->termtype,
victdes->term_width, victdes->term_height);
if (haspriv(c, "s_trace")) {
send_to_char(c, " Host: %s\n", victdes->hostname);
}
}
bar2(des, NULL, NULL, NULL);
}
void command_group(character *c, char *r)
{
char groupname[MAX_GROUP_NAME_LENGTH+1];
stripCodes(groupname, r);
if(STREQ(r, "")) {
STRNCOPY(groupname, "Public", sizeof(groupname));
}
if (strlen(r) > MAX_GROUP_NAME_LENGTH) {
send_to_char(c, "Group name too long (max %d)\n", MAX_GROUP_NAME_LENGTH);
return;
}
strlower(groupname);
groupname[0] = toupper(groupname[0]);
if (!STREQ(groupname, c->group)) {
/* Announce departure of character from old group */
send_to_room_except(c->group, c, "\n+++ %s joins group %s\n",
c->name, groupname);
STRNCOPY(c->group, groupname, sizeof(c->group));
/* annouce arrival in new group */
send_to_char(c, "+++ You have joined group ^y%s^n\n", c->group);
send_to_room_except(c->group, c, "\n+++ %s joins this group\n", c->name);
} else {
send_to_char(c, "You are already in group ^y%s^n\n", c->group);
}
}
void command_dc(character *c, char *r)
{
descriptor *des = NULL;
character *ch;
if (STREQ(r, "")) {
help_usage(c, "bump/dc");
return;
}
ch = character_from_name(r);
if (ch) {
/* found character, drop em */
des = getdes(ch);
} else {
/* char name not found - assume a number */
if (!strisdigit(r)) {
/* Not a number - report bad character name */
send_to_char(c, "Character %s not known\n", r);
return;
} else {
int sfd = atoi(r);
listnode *dNode = AllConns.head.next;
while (LIST_NODE_IS_REAL(dNode)) {
descriptor *des2 = LIST_GET_DATA(dNode, descriptor *, descriptorlink);
if (sfd == des2->sfd) {
des = des2;
break;
}
dNode = dNode->next;
}
if (!des) {
send_to_char(c, "SFD %d not found\n", sfd);
return;
}
}
}
/* Before we drop, check we are not dropping ourselves */
if (des == getdes(c)) {
send_to_char(c, "Haven't you heard of the quit command?\n");
return;
}
des->state = STATE_CLOSING;
if (des->player.loggedin) {
send_to_all_except(&des->player, "\n+++ ^r%s^n has logged out\n",
des->player.name);
}
}
void command_time(character *c, char *r)
{
time_t now;
struct tm nowtm;
char buff[OUTPUT_BUFFER];
unsigned long howlong;
now = time(NULL);
nowtm = *localtime(&now);
strftime(buff, sizeof(buff), "%a %b %d %H:%M:%S %Y", &nowtm);
send_to_char(c, "^WCurrent : %s\n^n", buff);
nowtm = *localtime(&starttime);
strftime(buff, sizeof(buff), "%a %b %d %H:%M:%S %Y", &nowtm);
send_to_char(c, "Up Since : %s\n", buff);
howlong = (unsigned long) difftime(now, starttime);
seconds_to_string(howlong, buff, sizeof(buff));
send_to_char(c, "Up Time : %s\n", buff);
}
void command_ping(character *c, char *r)
{
character *target;
if (STREQ(r, "")) {
help_usage(c, "ping");
} else {
target = character_from_name(r);
if (target == NULL) {
send_to_char(c, "%s not found\n", r);
} else {
send_to_char(target, "\a^YPING\n^n%s is trying to contact you\n",
c->name);
}
}
}
void command_remove(character *c, char *r)
{
if (STREQ(r, "")) {
help_usage(c, "remove");
return;
}
{
character *target;
char *privname = r;
strmunch(r, &r, &privname);
/* r should now be player name, privname should be the priv */
/* try to find player, if not found bail out of function */
target = character_from_name(r);
if (!target) {
send_to_char(c, "Player %s not found\n", r);
help_usage(c, "remove");
return;
}
/* check if removing privs from oneself */
if (c == target) {
send_to_char(c, "You may not remove your own privs\n");
return;
}
/* if privname is blank print out usage and bail out */
if (STREQ(privname, "")) {
send_to_char(c, "Unknown priv\n");
help_usage(c, "remove");
return;
}
/* search through the priv list and try to find the priv */
if (privname_exists(privname)) {
send_to_char(c, "You have removed from %s the %s priv.\n",
target->name, privname);
send_to_char(target, "You have lost the %s priv\n",
privname);
clearpriv(target, privname);
} else {
send_to_char(c, "Priv %s not found\n", privname);
help_usage(c, "remove");
}
}
}
static void command_grant_usage(character *c)
{
help_usage(c, "grant");
send_to_char(c, "Available privs:\n");
privs_list_all(c);
send_to_char(c, "\n");
}
void command_grant(character *c, char *r)
{
if (STREQ(r, "")) {
command_grant_usage(c);
return;
}
{
character *target;
char *privname = r;
strmunch(r, &r, &privname);
/* r should now be player name, privname should be the priv */
/* if privname is blank print out usage and bail out */
if (STREQ(privname, "")) {
command_grant_usage(c);
return;
}
/* try to find player, if not found bail out of function */
target = character_from_name(r);
if (!target) {
send_to_char(c, "Player %s not found\n", r);
command_grant_usage(c);
return;
}
/* search through the priv list and try to find the priv */
if (privname_exists(privname)) {
send_to_char(c, "You have granted %s the %s priv.\n",
target->name, privname);
send_to_char(target, "You have been granted the %s priv\n",
privname);
setpriv(target, privname);
} else {
send_to_char(c, "Priv %s not found\n", privname);
command_grant_usage(c);
}
}
}
void command_lsd(character *c, char *r)
{
listnode *dNode = AllConns.head.next;
descriptor *des2;
unsigned long howlong;
time_t now;
des2 = getdes(c);
bar2(des2, "Sockets connected and states", NULL, NULL);
send_to_char(c, "^YSFD State (name) (login) Idle Host^n\n\n");
while (LIST_NODE_IS_REAL(dNode)) {
descriptor *des = LIST_GET_DATA(dNode, descriptor *, descriptorlink);
character *c2 = &des->player;
char *state = "";
send_to_char(c, "%.3d ", des->sfd);
switch (des->state) {
case STATE_LOGIN: state = "LOGIN"; break;
case STATE_NEW1: state = "NEW1"; break;
case STATE_NEW2: state = "NEW2"; break;
case STATE_NEW3: state = "NEW3"; break;
case STATE_PASSWORD: state = "PASSWORD"; break;
case STATE_PLAY: state = "PLAY"; break;
case STATE_CLOSING: state = "CLOSING"; break;
}
send_to_char(c, "%-9s", state);
now = time(NULL);
if (des->state == STATE_PLAY) {
send_to_char(c, "%-13s", c2->name);
/* login Time */
howlong = (unsigned long) difftime(now, c2->logintime);
send_to_char(c, " %02lu:", howlong / 3600);
howlong %= 3600;
send_to_char(c, "%02lu:", howlong / 60);
howlong %= 60;
send_to_char(c, "%02lu", howlong);
} else {
send_to_char(c, " ");
}
/* Idle Time */
howlong = (unsigned long) difftime(now, des->idletime);
send_to_char(c, " %02lu:", howlong / 60);
howlong %= 60;
send_to_char(c, "%02lu %s\n", howlong, des->hostname);
dNode = dNode->next;
}
bar2(des2, NULL, NULL, NULL);
}
void command_bug(character *c, char *r)
{
if (STREQ(r, "")) {
help_usage(c, "bug");
} else {
log(bug, "%s - %s", c->name, r);
send_to_char(c, "Thank you, the bug has been recorded\n");
}
}
void command_idea(character *c, char *r)
{
if (STREQ(r, "")) {
help_usage(c, "idea");
} else {
log(idea, "%s - %s", c->name, r);
send_to_char(c, "Thank you, your idea has been recorded\n");
}
}
void command_typo(character *c, char *r)
{
if (STREQ(r, "")) {
help_usage(c, "typo");
} else {
log(typo, "%s - %s", c->name, r);
send_to_char(c, "Thank you, the typo has been recorded\n");
}
}
void command_shutdown(character *c, char *r)
{
sdown = TRUE;
}
void command_motd(character *c, char *r)
{
descriptor *des = getdes(c);
bar2(des, "Message Of The Day", NULL, NULL);
send_file_to_descriptor("lib/etc/motd", des);
bar2(des, NULL, NULL, NULL);
}
void command_prompt(character *c, char *r)
{
if(strlen(r) > MAX_PROMPT_LENGTH-2) {
send_to_char(c, "Prompt too long (max %d)\n", MAX_PROMPT_LENGTH-2);
} else {
STRNCOPY(c->prompt, r, sizeof(c->prompt));
}
}
void command_commands(character *c, char *r)
{
descriptor *des = getdes(c);
int i;
bar2(des, "List of commands", NULL, NULL);
for(i = 0;i < commandn;i++) {
if(haspriv(c, commands[i].privname))
send_to_char(c, "%s%s^n ", privcol(commands[i].privname),
commands[i].name);
}
send_to_char(c, "\n");
bar2(des, NULL, NULL, NULL);
}
void command_users(character *c, char *r)
{
listnode *pNode = AllPlayers.head.next;
while (LIST_NODE_IS_REAL(pNode)) {
character *pChar = LIST_GET_DATA(pNode,character *, characterlink);
send_to_char(c, "%s ", pChar->name);
pNode = pNode->next;
}
send_to_char(c, "\n");
}
void command_who(character *c, char *r)
{
descriptor *des = getdes(c);
listnode *pNode = AllPlayers.head.next;
int howmany = 0;
time_t now;
unsigned long howlong;
now = time(NULL);
bar2(des, "Who is logged on?", NULL, NULL);
send_to_char(c, "^Y%-*s Login Idle %-*s ",
MAX_NAME_LENGTH, "Name", MAX_GROUP_NAME_LENGTH, "Group");
if(haspriv(c, "s_trace")) {
send_to_char(c, "Host");
}
send_to_char(c, "^n\n");
while (LIST_NODE_IS_REAL(pNode)) {
character *pChar = LIST_GET_DATA(pNode, character *, characterlink);
descriptor *des = LIST_GET_DATA(pChar, descriptor *, player);
/* Display name */
send_to_char(c, "%-*s", MAX_NAME_LENGTH, pChar->name);
/* Calculate how long they have been logged in */
howlong = (unsigned long) difftime(now, pChar->logintime);
send_to_char(c, " %02lu:", howlong / 3600);
howlong %= 3600;
send_to_char(c, "%02lu:", howlong / 60);
howlong %= 60;
send_to_char(c, "%02lu", howlong);
/* Calculate how long they have been idle for */
howlong = (unsigned long) difftime(now, des->idletime);
send_to_char(c, " %02lu:", howlong / 60);
howlong %= 60;
send_to_char(c, "%02lu ", howlong);
send_to_char(c, "%-*s ", MAX_GROUP_NAME_LENGTH, pChar->group);
if(haspriv(c, "s_trace")) {
send_to_char(c, "%s", des->hostname);
}
send_to_char(c, "\n");
pNode = pNode->next;
howmany++;
}
send_to_char(c, "Total: %d user%s\n", howmany, howmany != 1 ? "s" : "");
bar2(des, NULL, NULL, NULL);
}
void command_tell(character *c, char *sRemainder)
{
char *sMessage = sRemainder;
char *sTerm;
while (*sMessage && !isspace(*sMessage))
sMessage++;
sTerm = sMessage;
while (*sMessage && isspace(*sMessage))
sMessage++;
*sTerm = 0;
{
character *pDest = character_from_name(sRemainder);
if (!pDest) {
send_to_char(c, "Character '%s' could not be found or is ambiguous.\n", sRemainder);
return;
}
if (pDest == c) {
send_to_char(c, "Talking to yourself again?\n");
return;
}
if(STREQ(sMessage, "")) {
send_to_char(c, "Tell %s, what ?\n", pDest->name);
return;
}
send_to_char(pDest, "^W> %s tells you '%s^W'^n\n", c->name, sMessage);
send_to_char(c, "You tell %s '%s^n'\n", pDest->name, sMessage);
}
}
void command_remote(character *c, char *sRemainder)
{
char *sMessage = sRemainder;
char *sTerm;
while (*sMessage && !isspace(*sMessage))
sMessage++;
sTerm = sMessage;
while (*sMessage && isspace(*sMessage))
sMessage++;
*sTerm = 0;
{
character *pDest = character_from_name(sRemainder);
if (!pDest) {
send_to_char(c, "Character '%s' could not be found or is ambiguous.\n", sRemainder);
return;
}
if (pDest == c) {
send_to_char(c, "Thats you, you fool\n");
return;
}
if(STREQ(sMessage, "")) {
send_to_char(c, "Emote to %s, what ?\n", pDest->name);
return;
}
send_to_char(pDest, "^W> %s %s^W, at you^n\n", c->name, sMessage);
send_to_char(c, "You emote '%s %s^n' to %s^n\n", c->name, sMessage,
pDest->name);
}
}
void command_say(character *c, char *r)
{
if (STREQ(r, "")) {
help_usage(c, "say");
return;
}
send_to_room_except(c->group, c, "%s says \'%s^n\'\n", c->name, r);
send_to_char(c, "You say \'%s^n\'\n", r);
}
void command_emote(character *c, char *r)
{
if (STREQ(r, "")) {
help_usage(c, "emote");
return;
}
send_to_room_except(c->group, c, "%s %s\n", c->name, r);
send_to_char(c, "You emote \'%s %s\'\n", c->name, r);
}
void command_shout(character *c, char *r)
{
if (STREQ(r, "")) {
help_usage(c, "shout");
return;
}
send_to_all_except(c, "%s shouts \'%s^n\'\n", c->name, r);
send_to_char(c, "You shout \'%s^n\'\n", r);
}
void command_quit(character *c, char *r)
{
descriptor *des = getdes(c);
des->state = STATE_CLOSING;
send_to_all_except(c, "\n+++ ^r%s^n has logged out\n", c->name);
send_to_char(c, "\n+++ You have logged out\n");
if (send_file_to_descriptor("lib/etc/logout", des) !=0)
send_to_descriptor(des, "Goodbye!\n");
des->safe = FALSE;
}
void command_whoami(character *c, char *r)
{
send_to_char(c, "You are ^r%s^n\n", c->name);
}
bool command_shortcut_run(descriptor *des, char *s)
{
character *p = &des->player;
int c;
s = strip_leading_white_space(s);
if (strlen(s) != 0) {
for (c = 0; c < commandn; c++) {
if (strchr(commands[c].shortcut, s[0]) &&
haspriv(p, commands[c].privname))
{
void (*function)(character *, char *);
function = commands[c].function;
s++; /* to get past the shortcut character */
s = strip_leading_white_space(s);
function(p, s);
return TRUE;
}
}
}
return FALSE;
}
void command_parse_n_run(descriptor *des, const char *first,
char *remainder)
{
unsigned int count = 0;
unsigned int index = 0;
unsigned int c;
character *p = &des->player;
if (STREQ(first, ""))
return;
for (c = 0; c < commandn; c++) {
if (STREQ(first, commands[c].name) &&
haspriv(p, commands[c].privname))
{
/* Matches exactly */
void (*function)(character *, char *);
function = commands[c].function;
function(p, remainder);
return;
} else if (STRNEQ(first, commands[c].name, strlen(first))
&& haspriv(p, commands[c].privname)) {
/* Part matches */
index = c;
count ++;
}
}
switch (count) {
case 0:
send_to_char(p, "Command \'%s\' not known, try help\n", first);
break;
case 1:
/* Matches one command without ambiguity */
{
void (*function)(character *, char *);
function = commands[index].function;
function(p, remainder);
return;
break;
}
default:
/* Part matches more than one command */
send_to_char(p, "Command \'%s\' ambiguous, try help\n", first);
break;
}
}
void command_do(descriptor *des, const char *buffer)
{
char line[MAX_RAW_INPUT_BUFFER];
char *first, *remainder;
char *temp;
bool carryon = TRUE;
STRNCOPY(line, buffer, sizeof(line));
first = line;
while (carryon == TRUE) {
/* strip leading white space in command */
first = strip_leading_white_space(first);
/* search for a ; in the input */
temp = strchr(first+1, ';');
if (temp != NULL) {
/* found a ; */
*temp = '\0';
temp++;
if (*temp == '\0') {
/* is temp a 0 length string ? */
carryon = FALSE;
} else {
carryon = TRUE;
}
} else {
carryon = FALSE;
}
strip_trailing_white_space(first);
if (command_shortcut_run(des, first) == FALSE) {
strmunch(first, &first, &remainder);
strlower(first);
command_parse_n_run(des, first, remainder);
}
if (carryon == TRUE) {
first = temp;
}
}
/* Do a prompt */
send_to_char(&des->player, "%s^n", &des->player.prompt);
}
descriptor* getdes(character *c) {
return LIST_GET_DATA(c, descriptor *, player);
}
void seconds_to_string(unsigned long seconds, char *buffer, size_t size)
{
unsigned long t;
int len;
t = seconds / (60 * 60 * 24);
if (t > 0) {
len = msnprintf(buffer, size, "%lu day%s, ", t, t != 1 ? "s" : "");
buffer += len;
size -= len;
}
seconds %= (60 * 60 * 24);
t = seconds / (60 * 60);
if (t > 0) {
len = msnprintf(buffer, size, "%lu hr%s, ", t, t != 1 ? "s" : "");
buffer += len;
size -= len;
}
seconds %= (60 * 60);
t = seconds / 60;
if (t > 0) {
len = msnprintf(buffer, size, "%lu min%s, ", t, t != 1 ? "s" : "");
buffer += len;
size -= len;
}
seconds %= 60;
msnprintf(buffer, size, "%lu sec%s", seconds, seconds != 1 ? "s": "");
}