/* utils.c */ #include "copyright.h" #include "config.h" #include <stdio.h> #ifdef STRING_H #include <string.h> #else #include <strings.h> #endif /* STRING_H */ #include <ctype.h> #include <sys/time.h> #ifdef STDDEF_H #include <stddef.h> #else /* STDDEF_H */ #define size_t unsigned #endif /* STDDEF_H */ #ifdef MALLOC_H #include <malloc.h> #endif /* MALLOC_H */ #if defined(ALLOCA_H) && !defined(NO_ALLOCA) #include <alloca.h> #endif #include "teeny.h" #include "rwho.h" void announce_connect(); void announce_disconnect(); int malloc_calls = 0, malloc_total = 0, malloc_free = 0; /* * Some generic utility functions for TeenyMUD */ /* * Write a timestamp on an object. In minutes since Jan 1 1970 */ void stamp(obj) { struct timeval foo; (void) gettimeofday(&foo, (struct timezone *) 0); if (set_int_elt(obj, TIMESTAMP, (int) foo.tv_sec) == -1) { warning("timestamp", "failed write to object"); } } /* * Manufactures a new player and returns the object number, one doesn't exist * already. * */ int create_player(p, code) char *p; int code; { char *name, *pwd; int player; int list, flags; if (parse_name_pwd(p, &name, &pwd) == -1) return (-1); if (!ok_player_name(name)) return (-1); if (!pwd || !*pwd) return (-1); /* Create a player in object number 0 */ player = create_obj(TYP_PLAYER); if (set_str_elt(player, NAME, name) == -1) goto createboom; if (set_str_elt(player, PASSWORD, crypt(pwd, CRYPT_KEY)) == -1) goto createboom; if (code == -1) { if (get_int_elt(STARTING_LOC, CONTENTS, &list) == -1) goto createboom; if (set_int_elt(player, LOC, STARTING_LOC) == -1) goto createboom; if (set_int_elt(STARTING_LOC, CONTENTS, player) == -1) goto createboom; #ifdef AUTO_GUEST if (get_int_elt(player, FLAGS, &flags) == -1) goto createboom; if (set_int_elt(player, FLAGS, flags | GUEST) == -1) goto createboom; #endif } else { if (get_int_elt(code, CONTENTS, &list) == -1) goto createboom; if (set_int_elt(player, LOC, code) == -1) goto createboom; if (set_int_elt(code, CONTENTS, player) == -1) goto createboom; } if (set_int_elt(player, NEXT, list) == -1) goto createboom; if (set_int_elt(player, HOME, STARTING_LOC) == -1) goto createboom; if (set_int_elt(player, OWNER, player) == -1) goto createboom; #ifdef AUTO_BUILDER if (get_int_elt(player, FLAGS, &flags) == -1) goto createboom; if (set_int_elt(player, FLAGS, flags | BUILDER) == -1) goto createboom; #endif if (set_int_elt(player, QUOTA, STARTING_QUOTA) == -1) goto createboom; if (code == -1) { int loc; if (get_int_elt(player, LOC, &loc) == -1) goto createboom; if (!isdark(player) && !isdark(loc)) do_pose(player, "has connected."); announce_connect(player); } return (player); createboom: destroy_obj(player); return (-1); } /* * Connects a player, if it exists and the password matches. Returns -1 if no * dice. * */ int connect_player(p) char *p; { char *name, *pwd; char *realpwd; int player; if (parse_name_pwd(p, &name, &pwd) == -1) return (-1); player = match_player(name); if (player == -1) { return (-1); } /* Check the password */ if (get_str_elt(player, PASSWORD, &realpwd) == -1) { warning("connect_player", "could not reference pword"); return (-1); } if (((!realpwd || !*realpwd) && !pwd) || (pwd && *pwd && (strcmp(realpwd, crypt(pwd, CRYPT_KEY)) == 0))) { return (player); } return (-1); } void connect_player2(player) int player; { int loc; if (get_int_elt(player, LOC, &loc) != -1) { if (!isdark(player) && !isdark(loc)) do_pose(player, "has connected."); } announce_connect(player); } void disconnect_player(player) int player; { int loc; if (get_int_elt(player, LOC, &loc) == -1) { warning("disconnect_player", "could not ref player loc"); return; } if (!isdark(player) && !isdark(loc)) do_pose(player, "has disconnected."); announce_disconnect(player); if (isguest(player)) { /* send "GUEST" players to their home */ send_home(player, loc); if (isroom(loc)) flush_room(loc); } #ifdef SUPPORT_RWHO if (rwho_enabled) rwho_logout(player); #endif } /* * Hack name/pwd pair up. Hopefully modified to support multi-word names. */ int parse_name_pwd(p, name, pwd) char *p; char **name, **pwd; { register char *q; char ch; while (isspace(*p) && *p) p++; if (*p == '\0') return (-1); if (*p != '\"') { /* the name isn't quoted, fuck */ /* assume the first word is name, all other is pword */ *name = p; while (!isspace(*p) && *p) p++; if (*p == '\0') return (-1); *p++ = '\0'; while (isspace(*p) && *p) p++; if (*p == '\0') *pwd = (char *) 0; else *pwd = p; /* Assume no trailing whitespace. */ return (0); } else { /* quoted name! YAY! */ while (*p && *p == '\"') p++; while (*p && isspace(*p)) p++; if (*p == 0) return (-1); for (*name = p; *p && *p != '\"'; p++); if (*p == 0) return (-1); /* found the other quote! */ *p++ = 0; /* terminate the name */ while (*p && isspace(*p)) p++; if (*p == 0) *pwd = (char *) 0; else *pwd = p; return (0); } } /* * Reliable memory allocation. */ char * ty_malloc(n, util) int n; char *util; /* Identifies the calling routine */ { char *p; extern char *malloc(); if ((p = (char *) malloc((size_t) n)) == NULL) { fatal(util, "memory allocation failed"); } malloc_calls++; malloc_total += n; return (p); } /* * Reliable free(), which does NULL OK. */ void ty_free(p) char *p; { if (p == NULL) { return; /* Ok */ } malloc_free++; free(p); } void parse_type(str, ret) char *str; int *ret; { if (stringprefix(str, "player")) { *ret = TYP_PLAYER; } else if (stringprefix(str, "room")) { *ret = TYP_ROOM; } else if (stringprefix(str, "thing") || stringprefix(str, "object")) { *ret = TYP_THING; } else if (stringprefix(str, "exit")) { *ret = TYP_EXIT; } /* else leave ret alone */ } /* an idea from TinyMUD that has been a long time in coming.. */ int ok_name(name) char *name; { return (name && *name && *name != '*' && *name != '#' && *name != '!' && !index(name, '=') && !index(name, '&') && !index(name, '|') #ifdef ILLEGAL_NAMES && strcasecmp(name, "A") && strcasecmp(name, "An") && strcasecmp(name, "The") && strcasecmp(name, "You") && strcasecmp(name, "Your") && strcasecmp(name, "Going") && strcasecmp(name, "Huh?") && strcasecmp(name, "[") #endif /* ILLEGAL_NAMES */ && strcasecmp(name, "me") && strcasecmp(name, "home") && strcasecmp(name, "here")); } int ok_player_name(name) char *name; { if (!ok_name(name) || (strlen(name) > 16) || (match_player(name) != -1) /* || index(name, '=') || index(name, '&') || index(name, '|') */ || isspace(name[0]) || isspace(name[strlen(name) - 1])) return (0); else return (1); } int ok_exit_name(name) char *name; { char *p, *q, *buf; if (!ok_name(name)) return (0); #ifdef NO_ALLOCA buf = (char *) ty_malloc(strlen(name) + 1, "ok_exit_name"); #else buf = (char *) alloca(strlen(name) + 1); #endif (void) strcpy(buf, name); /* we have to check each sub string... */ q = buf; while (q && *q) { for (p = q; *p && *p != ';'; p++); if (*p) *p++ = 0; if (!ok_name(q)) { #ifdef NO_ALLOCA ty_free((char *) buf); #endif return (0); } q = p; } #ifdef NO_ALLOCA ty_free((char *) buf); #endif return (1); } void fix_newline(buff) char *buff; { register int i; i = strlen(buff); if (buff[i - 1] == '\n') { buff[i - 1] = '\r'; buff[i] = '\n'; buff[i + 1] = '\0'; } } int domaincmp(x, y, i) char *x; char *y; int i; { register char *p; while (i) { for (p = x; *p && *p != '.'; p++); p++; i--; } return (strcasecmp(p, y)); } void announce_connect(player) int player; { char *name; char buf[80]; if (get_str_elt(player, NAME, &name) != -1) { (void) sprintf(buf, "* %s has connected. *\r\n", name); notify_wizz(buf); } } void announce_disconnect(player) int player; { char *name; char buf[80]; if (get_str_elt(player, NAME, &name) != -1) { (void) sprintf(buf, "* %s has disconnected. *\r\n", name); notify_wizz(buf); } } void check_last(player) int player; { char *host, *time; int last; extern char *ctime(); extern char cmdwork[]; if (get_int_elt(player, TIMESTAMP, &last) == -1 || get_str_elt(player, SITE, &host) == -1) return; if (last == 0) return; time = ctime(&((long) last)); time[strlen(time) - 1] = 0; (void) sprintf(cmdwork, "Last connection: %s from %s\r\n", time, (host == NULL) ? "???" : host); notify_player(player, cmdwork); } char *getname(obj) int obj; { char *nm; if (!exists_object(obj)) return (char *) NULL; if (get_str_elt(obj, NAME, &nm) == -1) return (char *) NULL; return nm; }