home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / tinymush.zip / TinyMush / os2src / player.c < prev   
Text File  |  1999-08-28  |  15KB  |  612 lines

  1. /* player.c */
  2.  
  3. #include "autoconf.h"
  4. #include "copyright.h"
  5. #ifndef    lint
  6. static char *RCSid = "$Id: player.c,v 1.8 1995/03/21 00:01:00 ambar Exp $";
  7. USE(RCSid);
  8. #endif
  9.  
  10. #include "interface.h"
  11. #include "attrs.h"
  12.  
  13. #define    NUM_GOOD    4    /* # of successful logins to save data for */
  14. #define NUM_BAD        3    /* # of failed logins to save data for */
  15.  
  16. typedef struct hostdtm HOSTDTM;
  17.   struct hostdtm {
  18.       char *host;
  19.       char *dtm;
  20.   };
  21.  
  22. typedef struct logindata LDATA;
  23.   struct logindata {
  24.       HOSTDTM good[NUM_GOOD];
  25.       HOSTDTM bad[NUM_BAD];
  26.       int tot_good;
  27.       int tot_bad;
  28.       int new_bad;
  29.   };
  30.  
  31. #ifdef VMS
  32. #define VMSOS2
  33. #endif /* VMS */
  34.  
  35. #ifdef OS2
  36. #define VMSOS2
  37. #endif /* OS2 */
  38.  
  39. #ifndef VMSOS2
  40. extern char *FDECL(crypt, (const char *, const char *));
  41. #else
  42. char *
  43. crypt(const char *inptr, const char *inkey)
  44. {
  45.     return (char *) inptr;
  46. }
  47. #endif /* VMSOS2 */
  48.  
  49. extern time_t FDECL(time, (time_t *));
  50.  
  51. /* ---------------------------------------------------------------------------
  52.  * decrypt_logindata, encrypt_logindata: Decode and encode login info.
  53.  */
  54.  
  55. static void 
  56. decrypt_logindata(atrbuf, info)
  57.     char *atrbuf;
  58.     LDATA *info;
  59. {
  60.     int i;
  61.  
  62.     info->tot_good = 0;
  63.     info->tot_bad = 0;
  64.     info->new_bad = 0;
  65.     for (i = 0; i < NUM_GOOD; i++) {
  66.     info->good[i].host = NULL;
  67.     info->good[i].dtm = NULL;
  68.     }
  69.     for (i = 0; i < NUM_BAD; i++) {
  70.     info->bad[i].host = NULL;
  71.     info->bad[i].dtm = NULL;
  72.     }
  73.  
  74.     if (*atrbuf == '#') {
  75.     atrbuf++;
  76.     info->tot_good = atoi(grabto(&atrbuf, ';'));
  77.     for (i = 0; i < NUM_GOOD; i++) {
  78.         info->good[i].host = grabto(&atrbuf, ';');
  79.         info->good[i].dtm = grabto(&atrbuf, ';');
  80.     }
  81.     info->new_bad = atoi(grabto(&atrbuf, ';'));
  82.     info->tot_bad = atoi(grabto(&atrbuf, ';'));
  83.     for (i = 0; i < NUM_BAD; i++) {
  84.         info->bad[i].host = grabto(&atrbuf, ';');
  85.         info->bad[i].dtm = grabto(&atrbuf, ';');
  86.     }
  87.     }
  88. }
  89.  
  90. static void 
  91. encrypt_logindata(atrbuf, info)
  92.     char *atrbuf;
  93.     LDATA *info;
  94. {
  95.     char *bp, nullc;
  96.     int i;
  97.  
  98.     /* Make sure the SPRINTF call tracks NUM_GOOD and NUM_BAD for the
  99.      * number of host/dtm pairs of each type.
  100.      */
  101.  
  102.     nullc = '\0';
  103.     for (i = 0; i < NUM_GOOD; i++) {
  104.     if (!info->good[i].host)
  105.         info->good[i].host = &nullc;
  106.     if (!info->good[i].dtm)
  107.         info->good[i].dtm = &nullc;
  108.     }
  109.     for (i = 0; i < NUM_BAD; i++) {
  110.     if (!info->bad[i].host)
  111.         info->bad[i].host = &nullc;
  112.     if (!info->bad[i].dtm)
  113.         info->bad[i].dtm = &nullc;
  114.     }
  115.     bp = alloc_lbuf("encrypt_logindata");
  116.     sprintf(bp, "#%d;%s;%s;%s;%s;%s;%s;%s;%s;%d;%d;%s;%s;%s;%s;%s;%s;",
  117.         info->tot_good,
  118.         info->good[0].host, info->good[0].dtm,
  119.         info->good[1].host, info->good[1].dtm,
  120.         info->good[2].host, info->good[2].dtm,
  121.         info->good[3].host, info->good[3].dtm,
  122.         info->new_bad, info->tot_bad,
  123.         info->bad[0].host, info->bad[0].dtm,
  124.         info->bad[1].host, info->bad[1].dtm,
  125.         info->bad[2].host, info->bad[2].dtm);
  126.     strcpy(atrbuf, bp);
  127.     free_lbuf(bp);
  128. }
  129.  
  130. /* ---------------------------------------------------------------------------
  131.  * record_login: Record successful or failed login attempt.
  132.  * If successful, report last successful login and number of failures since
  133.  * last successful login.
  134.  */
  135.  
  136. void 
  137. record_login(player, isgood, ldate, lhost)
  138.     dbref player;
  139.     int isgood;
  140.     char *ldate, *lhost;
  141. {
  142.     LDATA login_info;
  143.     char *atrbuf;
  144.     dbref aowner;
  145.     int aflags, i;
  146.  
  147.     atrbuf = atr_get(player, A_LOGINDATA, &aowner, &aflags);
  148.     decrypt_logindata(atrbuf, &login_info);
  149.     if (isgood) {
  150.     if (login_info.new_bad > 0) {
  151.         notify(player, "");
  152.         notify(player,
  153.            tprintf("**** %d failed connect%s since your last successful connect. ****",
  154.                login_info.new_bad,
  155.                (login_info.new_bad == 1 ? "" : "s")));
  156.         notify(player,
  157.            tprintf("Most recent attempt was from %s on %s.",
  158.                login_info.bad[0].host,
  159.                login_info.bad[0].dtm));
  160.         notify(player, "");
  161.         login_info.new_bad = 0;
  162.     }
  163.     if (login_info.good[0].host && *login_info.good[0].host &&
  164.         login_info.good[0].dtm && *login_info.good[0].dtm) {
  165.         notify(player,
  166.            tprintf("Last connect was from %s on %s.",
  167.                login_info.good[0].host,
  168.                login_info.good[0].dtm));
  169.     }
  170.     for (i = NUM_GOOD - 1; i > 0; i--) {
  171.         login_info.good[i].dtm = login_info.good[i - 1].dtm;
  172.         login_info.good[i].host = login_info.good[i - 1].host;
  173.     }
  174.     login_info.good[0].dtm = ldate;
  175.     login_info.good[0].host = lhost;
  176.     login_info.tot_good++;
  177.     atr_add_raw(player, A_LASTSITE, lhost);
  178.     } else {
  179.     for (i = NUM_BAD - 1; i > 0; i--) {
  180.         login_info.bad[i].dtm = login_info.bad[i - 1].dtm;
  181.         login_info.bad[i].host = login_info.bad[i - 1].host;
  182.     }
  183.     login_info.bad[0].dtm = ldate;
  184.     login_info.bad[0].host = lhost;
  185.     login_info.tot_bad++;
  186.     login_info.new_bad++;
  187.     }
  188.     encrypt_logindata(atrbuf, &login_info);
  189.     atr_add_raw(player, A_LOGINDATA, atrbuf);
  190.     free_lbuf(atrbuf);
  191. }
  192.  
  193. /* ---------------------------------------------------------------------------
  194.  * check_pass: Test a password to see if it is correct.
  195.  */
  196.  
  197. int 
  198. check_pass(player, password)
  199.     dbref player;
  200.     const char *password;
  201. {
  202.     dbref aowner;
  203.     int aflags;
  204.     char *target;
  205.  
  206.     target = atr_get(player, A_PASS, &aowner, &aflags);
  207.     if (*target && strcmp(target, password) &&
  208.     strcmp(crypt(password, "XX"), target)) {
  209.     free_lbuf(target);
  210.     return 0;
  211.     }
  212.     free_lbuf(target);
  213.  
  214.     /* This is needed to prevent entering the raw encrypted password from
  215.      * working.  Do it better if you like, but it's needed. */
  216.  
  217.     if ((strlen(password) == 13) &&
  218.     (password[0] == 'X') && (password[1] == 'X'))
  219.     return 0;
  220.  
  221.     return 1;
  222. }
  223.  
  224. /* ---------------------------------------------------------------------------
  225.  * connect_player: Try to connect to an existing player.
  226.  */
  227.  
  228. dbref 
  229. connect_player(name, password, host)
  230.     char *name, *password, *host;
  231. {
  232.     dbref player, aowner;
  233.     int aflags;
  234.     time_t tt;
  235.     char *time_str, *player_last, *allowance;
  236.  
  237.     time(&tt);
  238.     time_str = ctime(&tt);
  239.     time_str[strlen(time_str) - 1] = '\0';
  240.  
  241.     if ((player = lookup_player(NOTHING, name, 0)) == NOTHING)
  242.     return NOTHING;
  243.     if (!check_pass(player, password)) {
  244.     record_login(player, 0, time_str, host);
  245.     return NOTHING;
  246.     }
  247.     time(&tt);
  248.     time_str = ctime(&tt);
  249.     time_str[strlen(time_str) - 1] = '\0';
  250.  
  251.     /* compare to last connect see if player gets salary */
  252.     player_last = atr_get(player, A_LAST, &aowner, &aflags);
  253.     if (strncmp(player_last, time_str, 10) != 0) {
  254.     if (Pennies(player) < mudconf.paylimit) {
  255.         /* Don't heap coins on players who already have lots of money. */
  256.         allowance = atr_pget(player, A_ALLOWANCE, &aowner, &aflags);
  257.         if (*allowance == '\0')
  258.         giveto(player, mudconf.paycheck);
  259.         else
  260.         giveto(player, atoi(allowance));
  261.         free_lbuf(allowance);
  262.     }
  263.     }
  264.     atr_add_raw(player, A_LAST, time_str);
  265.     free_lbuf(player_last);
  266.     return player;
  267. }
  268.  
  269. /* ---------------------------------------------------------------------------
  270.  * create_player: Create a new player.
  271.  */
  272.  
  273. dbref 
  274. create_player(name, password, creator, isrobot)
  275.     char *name, *password;
  276.     dbref creator;
  277.     int isrobot;
  278. {
  279.     dbref player;
  280.     char *pbuf;
  281.  
  282.     /* Make sure the password is OK.  Name is checked in create_obj */
  283.  
  284.     pbuf = trim_spaces(password);
  285.     if (!ok_password(pbuf, creator)) {
  286.     free_lbuf(pbuf);
  287.     return NOTHING;
  288.     }
  289.     /* If so, go create him */
  290.  
  291.     player = create_obj(creator, TYPE_PLAYER, name, isrobot);
  292.     if (player == NOTHING) {
  293.     free_lbuf(pbuf);
  294.     return NOTHING;
  295.     }
  296.     /* initialize everything */
  297.  
  298.     s_Pass(player, crypt(pbuf, "XX"));
  299.     s_Home(player, start_home());
  300.     free_lbuf(pbuf);
  301.     return player;
  302. }
  303.  
  304. /* ---------------------------------------------------------------------------
  305.  * do_password: Change the password for a player
  306.  */
  307.  
  308. void 
  309. do_password(player, cause, key, oldpass, newpass)
  310.     dbref player, cause;
  311.     int key;
  312.     char *oldpass, *newpass;
  313. {
  314.     dbref aowner;
  315.     int aflags;
  316.     char *target;
  317.  
  318.     target = atr_get(player, A_PASS, &aowner, &aflags);
  319.     if (!*target || !check_pass(player, oldpass)) {
  320.     notify(player, "Sorry.");
  321.     } else if (!ok_password(newpass, player)) {
  322.     /* Do nothing, notification is handled by ok_password() */
  323.     } else {
  324.     atr_add_raw(player, A_PASS, crypt(newpass, "XX"));
  325.     notify(player, "Password changed.");
  326.     }
  327.     free_lbuf(target);
  328. }
  329.  
  330. /* ---------------------------------------------------------------------------
  331.  * do_last Display login history data.
  332.  */
  333.  
  334. static void 
  335. disp_from_on(player, dtm_str, host_str)
  336.     dbref player;
  337.     char *dtm_str, *host_str;
  338. {
  339.     if (dtm_str && *dtm_str && host_str && *host_str) {
  340.     notify(player,
  341.            tprintf("     From: %s   On: %s", dtm_str, host_str));
  342.     }
  343. }
  344.  
  345. void 
  346. do_last(player, cause, key, who)
  347.     dbref player, cause;
  348.     int key;
  349.     char *who;
  350. {
  351.     dbref target, aowner;
  352.     LDATA login_info;
  353.     char *atrbuf;
  354.     int i, aflags;
  355.  
  356.     if (!who || !*who) {
  357.     target = Owner(player);
  358.     } else if (!(string_compare(who, "me"))) {
  359.     target = Owner(player);
  360.     } else {
  361.     target = lookup_player(player, who, 1);
  362.     }
  363.  
  364.     if (target == NOTHING) {
  365.     notify(player, "I couldn't find that player.");
  366.     } else if (!Controls(player, target)) {
  367.     notify(player, "Permission denied.");
  368.     } else {
  369.     atrbuf = atr_get(target, A_LOGINDATA, &aowner, &aflags);
  370.     decrypt_logindata(atrbuf, &login_info);
  371.  
  372.     notify(player, tprintf("Total successful connects: %d",
  373.                    login_info.tot_good));
  374.     for (i = 0; i < NUM_GOOD; i++) {
  375.         disp_from_on(player,
  376.              login_info.good[i].host,
  377.              login_info.good[i].dtm);
  378.     }
  379.     notify(player, tprintf("Total failed connects: %d",
  380.                    login_info.tot_bad));
  381.     for (i = 0; i < NUM_BAD; i++) {
  382.         disp_from_on(player,
  383.              login_info.bad[i].host,
  384.              login_info.bad[i].dtm);
  385.     }
  386.     free_lbuf(atrbuf);
  387.     }
  388. }
  389.  
  390. /* ---------------------------------------------------------------------------
  391.  * add_player_name, delete_player_name, lookup_player:
  392.  * Manage playername->dbref mapping
  393.  */
  394.  
  395. int 
  396. add_player_name(player, name)
  397.     dbref player;
  398.     char *name;
  399. {
  400.     int stat;
  401.     dbref p;
  402.     char *temp, *tp;
  403.  
  404.     /* Convert to all lowercase */
  405.  
  406.     tp = temp = alloc_lbuf("add_player_name");
  407.     safe_str(name, temp, &tp);
  408.     for (tp = temp; *tp; tp++)
  409.     *tp = ToLower(*tp);
  410.  
  411.     p = (int) hashfind(temp, &mudstate.player_htab);
  412.     if (p) {
  413.  
  414.     /* Entry found in the hashtable.  If a player, succeed if the
  415.      * numbers match (already correctly in the hash table), fail
  416.      * if they don't.  Fail if the name is a disallowed name
  417.      * (value AMBIGUOUS).
  418.      */
  419.  
  420.     if (p == AMBIGUOUS) {
  421.         free_lbuf(temp);
  422.         return 0;
  423.     }
  424.     if (Good_obj(p) && (isPlayer(p))) {
  425.         free_lbuf(temp);
  426.         if (p == player) {
  427.         return 1;
  428.         } else {
  429.         return 0;
  430.         }
  431.     }
  432.     /* It's an alias (or an incorrect entry).  Clobber it */
  433.  
  434.     stat = hashrepl(temp, (int *) player, &mudstate.player_htab);
  435.     } else {
  436.     stat = hashadd(temp, (int *) player, &mudstate.player_htab);
  437.     }
  438.     free_lbuf(temp);
  439.     return ((stat < 0) ? 0 : 1);
  440. }
  441.  
  442. int 
  443. delete_player_name(player, name)
  444.     dbref player;
  445.     char *name;
  446. {
  447.     dbref p;
  448.     char *temp, *tp;
  449.  
  450.     tp = temp = alloc_lbuf("delete_player_name");
  451.     safe_str(name, temp, &tp);
  452.     for (tp = temp; *tp; tp++)
  453.     *tp = ToLower(*tp);
  454.     p = (int) hashfind(temp, &mudstate.player_htab);
  455.     if (!p || (p == NOTHING) || ((player != NOTHING) && (p != player))) {
  456.     free_lbuf(temp);
  457.     return 0;
  458.     }
  459.     hashdelete(temp, &mudstate.player_htab);
  460.     free_lbuf(temp);
  461.     return 1;
  462. }
  463.  
  464. dbref 
  465. lookup_player(doer, name, check_who)
  466.     dbref doer;
  467.     char *name;
  468.     int check_who;
  469. {
  470.     dbref p;
  471.     char *temp, *tp;
  472.  
  473.     if (!string_compare(name, "me"))
  474.     return doer;
  475.  
  476.     if (*name == NUMBER_TOKEN) {
  477.     name++;
  478.     if (!is_number(name))
  479.         return NOTHING;
  480.     p = atoi(name);
  481.     if (!Good_obj(p))
  482.         return NOTHING;
  483.     if (!(isPlayer(p) || God(doer)))
  484.         p = NOTHING;
  485.     return p;
  486.     }
  487.     tp = temp = alloc_lbuf("lookup_player");
  488.     safe_str(name, temp, &tp);
  489.     for (tp = temp; *tp; tp++)
  490.     *tp = ToLower(*tp);
  491.     p = (int) hashfind(temp, &mudstate.player_htab);
  492.     free_lbuf(temp);
  493.     if (!p) {
  494.     if (check_who)
  495.         p = find_connected_name(doer, name);
  496.     else
  497.         p = NOTHING;
  498.     } else if (!Good_obj(p)) {
  499.     p = NOTHING;
  500.     }
  501.     return p;
  502. }
  503.  
  504. void 
  505. NDECL(load_player_names)
  506. {
  507.     dbref i, j = 0, aowner;
  508.     int aflags;
  509.     char *alias;
  510.  
  511.     DO_WHOLE_DB(i) {
  512.     if (isPlayer(i))
  513.         add_player_name(i, Name(i));
  514.     if (i % 20 == 0)
  515.         cache_reset();
  516.     }
  517.     alias = alloc_lbuf("load_player_names");
  518.  
  519.     DO_WHOLE_DB(i) {
  520.     if (isPlayer(i)) {
  521.         alias = atr_pget_str(alias, i, A_ALIAS, &aowner, &aflags);
  522.         if (*alias)
  523.         add_player_name(i, alias);
  524.         if (++j > 20) {
  525.         cache_reset(0);
  526.         j = 0;
  527.         }
  528.     }
  529.     }
  530.     free_lbuf(alias);
  531. }
  532.  
  533. /* ---------------------------------------------------------------------------
  534.  * badname_add, badname_check, badname_list: Add/look for/display bad names.
  535.  */
  536.  
  537. void 
  538. badname_add(bad_name)
  539.     char *bad_name;
  540. {
  541.     BADNAME *bp;
  542.  
  543.     /* Make a new node and link it in at the top */
  544.  
  545.     bp = (BADNAME *) XMALLOC(sizeof(BADNAME), "badname.struc");
  546.     bp->name = strsave(bad_name);
  547.     bp->next = mudstate.badname_head;
  548.     mudstate.badname_head = bp;
  549. }
  550.  
  551. void 
  552. badname_remove(bad_name)
  553.     char *bad_name;
  554. {
  555.     BADNAME *bp, *backp;
  556.  
  557.     /* Look for an exact match on the bad name and remove if found */
  558.  
  559.     backp = NULL;
  560.     for (bp = mudstate.badname_head; bp; backp = bp, bp = bp->next) {
  561.     if (!string_compare(bad_name, bp->name)) {
  562.         if (backp)
  563.         backp->next = bp->next;
  564.         else
  565.         mudstate.badname_head = bp->next;
  566.         XFREE(bp->name, "badname.name");
  567.         XFREE(bp, "badname.struc");
  568.         return;
  569.     }
  570.     }
  571. }
  572.  
  573. int 
  574. badname_check(bad_name)
  575.     char *bad_name;
  576. {
  577.     BADNAME *bp;
  578.  
  579.     /* Walk the badname list, doing wildcard matching.  If we get a hit
  580.      * then return false.  If no matches in the list, return true.
  581.      */
  582.  
  583.     for (bp = mudstate.badname_head; bp; bp = bp->next) {
  584.     if (quick_wild(bp->name, bad_name))
  585.         return 0;
  586.     }
  587.     return 1;
  588. }
  589.  
  590. void 
  591. badname_list(player, prefix)
  592.     dbref player;
  593.     const char *prefix;
  594. {
  595.     BADNAME *bp;
  596.     char *buff, *bufp;
  597.  
  598.     /* Construct an lbuf with all the names separated by spaces */
  599.  
  600.     buff = bufp = alloc_lbuf("badname_list");
  601.     safe_str((char *) prefix, buff, &bufp);
  602.     for (bp = mudstate.badname_head; bp; bp = bp->next) {
  603.     safe_chr(' ', buff, &bufp);
  604.     safe_str(bp->name, buff, &bufp);
  605.     }
  606.  
  607.     /* Now display it */
  608.  
  609.     notify(player, buff);
  610.     free_lbuf(buff);
  611. }
  612.