#include <stdio.h> #include <ctype.h> #include <string.h> #include "externs.h" #include "db.h" char *swlm; #define W_EMAIL 0x1 #define W_DOING 0x2 #define W_HOST 0x4 #define W_PORT 0x8 #define W_DESCRIPTOR 0x10 #define W_THROUGHPUT 0x20 #define W_IDLE 0x40 #define W_ONFOR 0x80 #define W_CLASS 0x100 #define W_FLAGS 0x200 #define W_ALIAS 0x400 #define W_NAME 0x800 #define W_LASTBIT 0x800 #define NAME_LEN 9 #define ALIAS_LEN 5 #define CLASS_LEN 5 #define IDLE_LEN 4 #define ONFOR_LEN 7 #define DOING_LEN 30 #define FLAGS_LEN 5 #define DESCRIPTOR_LEN 10 #define THROUGHPUT_LEN 10 #define HOST_LEN 19 #define PORT_LEN 4 #define EMAIL_LEN 14 static unsigned long DEF_WHO_FLAGS = W_NAME|W_ALIAS|W_FLAGS|W_IDLE|W_ONFOR|W_DOING; static unsigned long parse_flags(OBJ *player, char *list) { char *l; unsigned long flags = 0; for(l = list;*l;l++) { switch(tolower(*l)) { case 'n': flags |= W_NAME; break; case 'a': flags |= W_ALIAS; break; case 'c': flags |= W_CLASS; break; case 'i': flags |= W_IDLE; break; case 'o': flags |= W_ONFOR; break; case 'd': flags |= W_DOING; break; case 'f': flags |= W_FLAGS; break; case 'h': flags |= W_HOST; break; case 'x': flags |= W_DESCRIPTOR; break; case 't': flags |= W_THROUGHPUT; break; case 'p': flags |= W_PORT; break; case 'e': flags |= W_EMAIL; break; default: notify(player, tprintf("Unknown who flag: %c", *l)); return(0); } } return(flags); } static char *get_field(OBJ *player, DDATA *d, unsigned long bit, int header) { char buf[4096]; *buf = '\0'; switch(bit) { case W_NAME: if(header) strcpy(buf, my_ljust("NAME", NAME_LEN)); else strcpy(buf, my_ljust(name(d->player), NAME_LEN)); break; case W_ALIAS: if(header) strcpy(buf, my_ljust("ALIAS", ALIAS_LEN)); else strcpy(buf, my_ljust(atr_get(d->player, "ALIAS"), ALIAS_LEN)); break; case W_CLASS: if(header) strcpy(buf, my_ljust("CLASS", CLASS_LEN)); else strcpy(buf, my_ljust(short_class_to_name(get_class(d->player)), CLASS_LEN)); break; case W_FLAGS: if(header) strcpy(buf, my_ljust("FLAGS", FLAGS_LEN)); else { /* Make sure FLAGS_LEN is at least as big as the amount of flags */ strcpy(buf, my_string(" ", FLAGS_LEN)); /* Init buf */ if(get_class(d->player) > CLASS_CITIZEN) buf[0] = 'W'; if(now-d->last_time > 300) buf[1] = 'i'; if(*atr_get(d->player, "LHIDE")) buf[2] = 'h'; if(d->player->flags & PLAYER_NEWBIE) buf[3] = 'n'; if(d->player->flags & PLAYER_NO_WALLS) buf[4] = 'N'; } break; case W_IDLE: if(header) strcpy(buf, my_rjust("IDLE", IDLE_LEN)); else strcpy(buf, my_rjust(time_format(now-d->last_time, 1), IDLE_LEN)); break; case W_ONFOR: if(header) strcpy(buf, my_rjust("ONFOR", ONFOR_LEN)); else strcpy(buf, my_rjust(time_format(now-d->connected_at, 2), ONFOR_LEN)); break; case W_DOING: if(header) strcpy(buf, my_ljust("DOING", DOING_LEN)); else strcpy(buf, my_ljust(atr_get(d->player, "DOING"), DOING_LEN)); break; case W_HOST: if(header) strcpy(buf, my_ljust("HOST", HOST_LEN)); else { if(!controls(player, d->player, POW_HOST)) strcpy(buf, "???"); else strcpy(buf, my_ljust(tprintf("%s@%s", d->user, d->addr), HOST_LEN)); } break; case W_DESCRIPTOR: if(header) strcpy(buf, my_ljust("DESCRIPTOR", DESCRIPTOR_LEN)); else strcpy(buf, my_ljust(tprintf("%d", d->descriptor), DESCRIPTOR_LEN)); break; case W_THROUGHPUT: if(header) strcpy(buf, my_ljust("THROUGHPUT", THROUGHPUT_LEN)); else strcpy(buf, my_rjust(tprintf("%.1f", get_input(d)+get_output(d)), THROUGHPUT_LEN)); break; case W_PORT: if(header) strcpy(buf, my_ljust("PORT", PORT_LEN)); else strcpy(buf, my_ljust(tprintf("%d", ntohs(d->address.sin_port)), PORT_LEN)); break; case W_EMAIL: if(header) strcpy(buf, my_ljust("EMAIL", EMAIL_LEN)); else strcpy(buf, my_ljust(atr_get(d->player, "EMAIL"), EMAIL_LEN)); break; } return(stack_string_alloc(buf, 0)); } static char *cur_time() { char buf[4096]; struct tm *tim = localtime(&now); char *suffix; int hour; suffix = (tim->tm_hour/12)?"pm":"am"; hour = (tim->tm_hour%12)?tim->tm_hour%12:12; sprintf(buf, "%d:%02d:%02d%s", hour, tim->tm_min, tim->tm_sec, suffix); return(stack_string_alloc(buf, 0)); } static int get_plist(DDATA ***plist, OBJ *player, char *arg) { DDATA *d; OBJ *victim; int ctr = 0, done = 0; char *p, *q; for(d = descriptor_list;d;d = d->next) ctr++; *plist = (DDATA **)stack_alloc(sizeof(DDATA *)*ctr, 0, 0); ctr = 0; if(!*arg) { for(d = descriptor_list;d;d = d->next) (*plist)[ctr++] = d; return(ctr); } for(p = arg;p && *p;) { if((q = strchr(p, ' '))) *q = '\0'; else done = 1; if(!(victim = match_player(NULL, p))) { notify(player, no_match(p)); p = q; if(!done) p++; continue; } for(d = descriptor_list;d;d = d->next) if(d->player == victim) if(controls(player, victim, POW_WHO) || could_doit(player, victim, "LHIDE")) { (*plist)[ctr++] = d; } p = q; if(!done) p++; } return(ctr); } void do_who(OBJ *player, char *arg1, char *arg2) { unsigned long flags; DDATA *d; char buf[4096], output[4096]; unsigned long bit; int total_users = 0, total_hidden = 0, total_active = 0; double average_onfor = 0, average_idle = 0; char *header_color; unsigned int num_shown = 0; DDATA **plist; int i, num_in_list; if(!*(header_color = atr_get(player, "WHOCOLOR"))) header_color = "n"; if(!*arg1) flags = DEF_WHO_FLAGS; else flags = parse_flags(player, arg1); if(!flags) return; if(!(num_in_list = get_plist(&plist, player, arg2))) { notify(player, "Nothing to show."); return; } *output = '\0'; notify(player, tprintf("|+W|%s", my_string("-", 78))); do_swlm(player, ""); notify(player, tprintf("|+W|%s", my_string("-", 78))); for(bit = W_LASTBIT;bit > 0;bit >>= 1) { if(!(flags & bit)) continue; sprintf(output+strlen(output), "%s ", get_field(player, NULL, bit, 1)); } notify(player, tprintf("|%s|%s", header_color, output)); for(i = 0, d = plist[0];i < num_in_list;d = plist[++i]) { if(!check_state(d, STATE_CONNECTED)) continue; total_users++; if(!could_doit(player, d->player, "LHIDE")) { total_hidden++; if(!controls(player, d->player, POW_WHO)) continue; } num_shown++; if(now-d->last_time < 300) total_active++; average_onfor += (double)(now-d->connected_at); average_idle += (double)(now-d->last_time); *output = '\0'; for(bit = W_LASTBIT;bit > 0;bit >>= 1) { if(!(flags & bit)) continue; strcpy(buf, get_field(player, d, bit, 0)); strcat(buf, " "); strcat(output, buf); } notify(player, output); } notify(player, tprintf("|+W|%s", my_string("-", 78))); sprintf(buf, "|%s|Total Users: |+W|%d", header_color, total_users); sprintf(buf+strlen(buf), "|%s| Hidden Users: |+W|%d", header_color, total_hidden); sprintf(buf+strlen(buf), "|%s| Active Users: |+W|%d", header_color, total_active); notify(player, buf); if(num_shown) { average_onfor /= num_shown; average_idle /= num_shown; } sprintf(buf, "|%s|Average Onfor: |+W|%s", header_color, time_format(average_onfor, 3)); sprintf(buf+strlen(buf), "|%s| Average Idle: |+W|%s", header_color, time_format(average_idle, 2)); sprintf(buf+strlen(buf), "|%s| Current Time: |+W|%s", header_color, cur_time()); notify(player, buf); notify(player, tprintf("|+W|%s", my_string("-", 78))); } void do_whocolor(OBJ *player, char *arg) { char clr[1024]; char *c = atr_get(player, "WHOCOLOR"); if(!my_is_color(c)) sprintf(clr, "|n|n"); else sprintf(clr, "|%s|%s", c, c); if(!*arg) { notify(player, tprintf("Who list header color: %s", clr)); return; } if(!my_is_color(arg)) { notify(player, tprintf("%s is not a valid color.", arg)); return; } atr_add(player, "WHOCOLOR", arg); notify(player, tprintf("Who list color set to |%s|%s.", arg, arg)); } void do_swlm(OBJ *player, char *arg) { const char *default_msg = "|C|This is the Stupid Who List Message. To change me type '+swlm <msg>'."; char buf[4096]; char *clr; if(!*(clr = atr_get(player, "WHOCOLOR"))) clr = "n"; if(!*arg) { notify(player, tprintf("|%s|SWLM|+W|: |n|%s", clr, swlm)); return; } if(!strcmp(arg, "default")) { strcpy(buf, default_msg); log_important(tprintf("%s set the SWLM to the default message", unparse_object(player, player))); } else { if(strlen(arg) > 800) *(arg+800) = '\0'; sprintf(buf, "|C|%s |+W|--%s", arg, name(player)); log_important(tprintf("%s changed the SWLM to: %s", unparse_object(player, player), arg)); } if(!swlm) swlm = stack_string_alloc(buf, 1); else swlm = stack_string_realloc(swlm, buf); notify(player, "SWLM set."); }