loginhistory/
-----------------------------------------------------------------------
Login History v1.0 by Xerves (November 29 2001)
Xerves is the admin/owner of Rafermand (mud.rafermand.net port 3002)
Website: http://www.rafermand.net
Contact: xerves@rafermand.net
-----------------------------------------------------------------------

Was always curious why there was no history list of people who have logged
in easily available from the mud to view.  It is nice to see how logged in
and at what time (so I thought atleast).  So here is some code that you
can add to the last command to make this work nice

TIPS:  Make sure you can read/write/delete in your /system directory because it will
       try to do so to a file or two in there.  There is all a defined number in
       mud.h for file size  (#Define LAST_FILE_SIZE 500).  This defines the maximum
       amount of entries that can be in the file.  If you wish to make this larger just
       increase this number, or decrease it to make it smaller.  It is a good idea to
       limit the size because the file is read directly from the HD each time it is looked
       at and put into memory, then removed from memory.  It can cause a bit of system
       performance degrade if you have people looking at thousands and thousands of lines.

Suggested help file addition....
       
Syntax: last <# of entries OR \'-1\' for all entries OR \'today\' for all of today's entries>

Can be used to see the most recent people who have logged in.  This feature has 3 arguments.
 - Can supply the maximum amount to show (last 20)
 - Can type -1 to show all connections in the file (last -1)
 - Can type today to show all of today's connections (last today)
 




--------------------------------------------------------------
Files beind modified:

mud.h
tables.c
save.c
comm.c
--------------------------------------------------------------

1.  mud.h

Find #define MAX_INBUF_SIZE		 1024

     Below it Place this

#define LAST_FILE_SIZE       500  //maximum entries in the last file

Find /* tables.c */
     
     Below it Place this
     
void read_last_file args((CHAR_DATA *ch, int count));
void write_last_file args((char *entry));

Find
 
   #define IMM_HOST_FILE   SYSTEM_DIR "immortal.host" /* For stoping hackers */

Below it add the following lines

   #define LAST_LIST       SYSTEM_DIR "last.lst" //last list
   #define LAST_TEMP_LIST  SYSTEM_DIR "ltemp.lst" //temp file for the last list so the data can be copyover over


2.  tables.c

At the top, add the following include if you do not have it.

   #include <ctype.h>  

Anywhere in the file place these 3 functions.

void copy_files_contents(FILE *fsource, FILE *fdestination)
{
   int ch;
   int cnt = 1;
   
   for (;;)
   {
      ch = fgetc( fsource );
      if (!feof(fsource))
      {
          fputc( ch, fdestination);
          if (ch == '\n')
          {
             cnt++;
             if (cnt >= LAST_FILE_SIZE) //limit size of this file please :-)
                break;
          }
      }
      else
          break;
   }
}

void write_last_file(char *entry)
{
   FILE *fpout;
   FILE *fptemp;
   char filename[MAX_INPUT_LENGTH];
   char tempname[MAX_INPUT_LENGTH];
   
   sprintf(filename, "%s", LAST_LIST);
   sprintf(tempname, "%s", LAST_TEMP_LIST);
   if ((fptemp = fopen(tempname, "w")) == NULL)
   {
      bug("Cannot open: %s for writing", tempname);
      return;
   }
   fprintf(fptemp, "%s\n", entry); //adds new entry to top of the file
   if ((fpout = fopen(filename, "r")) != NULL)
   {
      copy_files_contents(fpout, fptemp); //copy the rest to the file
      fclose(fpout); //close the files since writing is done
   }
   fclose(fptemp);
   
   if (remove(filename) != 0 && fopen(filename, "r") != NULL)
   {
      bug("Do not have permission to delete the %s file", filename);
      return;
   }
   if (rename(tempname, filename) != 0)
   {
      bug("Do not have permission to rename the %s file", tempname);
      return;
   }
   return;
}

void read_last_file(CHAR_DATA *ch, int count, char *name)
{
   FILE *fpout;
   char filename[MAX_INPUT_LENGTH];
   char charname[100];
   int cnt = 0;
   int letter = 0;
   char *ln;
   char *c;
   char d, e;
   struct tm *tme;
   time_t now;
   char day[MAX_INPUT_LENGTH];
   char sday[5];
   int fnd = 0;
   
   sprintf(filename, "%s", LAST_LIST);
   if ((fpout = fopen(filename, "r")) == NULL)
   {
      send_to_char("There is no last file to look at.\n\r", ch);
      return;
   }
   
   for (;;)
   {
      if (feof(fpout))
      {
         fclose(fpout);
         ch_printf(ch, "---------------------------------------------------------------------------\n\r%d Entries Listed.\n\r", cnt);
         return;
      }
      else
      {
         if (count == -2 || ++cnt <= count || count == -1)
         {
            ln = fread_line(fpout);
            strcpy(charname, "");
            if (name) //looking for a certain name
            {
               c = ln; 
               for (;;)
               {
                  if (isalpha(*c) && !isspace(*c))
                  {
                     charname[letter] = *c;   
                     letter++;
                     c++;
                  }
                  else
                  {
                     charname[letter] = '\0';
                     if (!str_cmp(charname, name))
                     {
                        ch_printf(ch, "%s", ln);
                        letter = 0;
                        strcpy(charname, "");
                        break;  
                     }
                     else
                     {
                        if (!feof(fpout))
                        {
                           fread_line(fpout);    
                           c = ln;
                           letter = 0;
                           strcpy(charname, "");
                           continue;
                        }
                        else
                        {
                           cnt--;
                           break;
                        }
                     }
                  }
               }
            }
            else if (count == -2) //only today's entries
            {
               c = ln;
               now = time(0);
               tme = localtime(&now);
               strftime(day, 10, "%d", tme);
               for (;;)
               {
                  if (!isdigit(*c))
                  {
                     c++;
                  }
                  else
                  {
                     d = *c;
                     c++;
                     e = *c;
                     sprintf(sday, "%c%c", d, e);
                     if (!str_cmp(sday, day))
                     {
                         fnd = 1;
                         cnt++;
                         ch_printf(ch, "%s", ln);
                         break;
                     }
                     else
                     {
                        if (fnd == 1)
                        {
                           fclose(fpout);
                           ch_printf(ch, "---------------------------------------------------------------------------\n\r%d Entries Listed.\n\r", cnt);
                           return;
                        }
                        else
                           break;
                     }
                  }
               }
            }
            else                  
            {  
               ch_printf(ch, "%s", ln);
            }
               
         }
         else
         {
            fclose(fpout);
            ch_printf(ch, "--------------------------------------------------------------------------\n\r%d Entries Listed.\n\r", count);
            return;
         }
      }
   }
}





3.  Save.c

Replace do_last with the following

void do_last(CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   char arg[MAX_INPUT_LENGTH];
   char name[MAX_INPUT_LENGTH];
   struct stat fst;

   argument = one_argument(argument, arg);
   if (arg[0] == '\0')
   {
      send_to_char("Usage: last <playername>\n\r", ch);
      send_to_char("Usage: last <# of entries OR \'-1\' for all entries OR \'today\' for all of today's entries>\n\r", ch);
      send_to_char("Usage: last <playername> <count>\n\r", ch);
      return;
   }
   if (get_trust(ch) < LEVEL_ASCENDANT)
   {
      set_char_color(AT_IMMORT, ch);
      send_to_char("Their godly glow prevents you from getting a good look.\n\r", ch);
      return;
   }
   if (isdigit(arg[0]) || atoi(arg) == -1 || !str_cmp(arg, "today")) //View list instead of players
   {
      send_to_char("&w&RName                     Time                        Host/Ip\n\r&c&w---------------------------------------------------------------------------\n\r", ch);
      if (!str_cmp(arg, "today"))
         read_last_file(ch, -2, NULL);
      else
         read_last_file(ch, atoi(arg), NULL);
      return;
   }  
   strcpy(name, capitalize(arg));
   if (argument[0] != '\0')
   {
      send_to_char("&w&RName                     Time                        Host/Ip\n\r&c&w---------------------------------------------------------------------------\n\r", ch);
      read_last_file(ch, atoi(argument), name);
      return;
   }
   sprintf(buf, "%s%c/%s", PLAYER_DIR, tolower(arg[0]), name);
   
   if (stat(buf, &fst) != -1)
      sprintf(buf, "%s was last on: %s\r", name, ctime(&fst.st_mtime));
   else
      sprintf(buf, "%s was not found.\n\r", name);
   send_to_char(buf, ch);
}
   
   
   
   
4.  Comm.c

   
In CASE CON_GET_OLD_PASSWORD find these lines of code

         sprintf(log_buf, "%s@%s(%s) has connected.", ch->pcdata->filename, d->host, d->user);
         if (ch->level < LEVEL_IMM)
         {
            /*to_channel( log_buf, CHANNEL_MONITOR, "Monitor", ch->level ); */
            log_string_plus(log_buf, LOG_COMM, sysdata.log_level);
         }
         else
            log_string_plus(log_buf, LOG_COMM, ch->level);
            
Directly after that add these lines

        {
           struct tm *tme;
           time_t now;
           char day[50];
           now = time(0);
           tme = localtime(&now);
           strftime(day, 50, "%a %b %d %H:%M:%S %Y", tme);
           sprintf(log_buf, "%-20s     %-24s    %s", ch->pcdata->filename, day, d->host);
           write_last_file(log_buf); 	
        }
         
         
------------------------------------------------------------------------------------------------------------------------------
 
Well that is it, after you get done you need to make clean and recompile the code.  Once you do that, you can restart the mud
and it will start logging all the new people who login.  The file will be /system/last.lst.  The file will keep itself to 500
lines unless you change the variable in mud.h (see the TIPS section above).  Once that is in play, you are good to go, and I
hope it helps out.  If you have any ideas on things to add or you add something to this snippet, please contact me so perhaps
it can be appended to this snippet :-)

--------Xerves - Onwer/Coder of Rafermand (Code Base FeaR 2.0)