wileymud-1.187b/
wileymud-1.187b/attic/
wileymud-1.187b/attic/bin/
wileymud-1.187b/attic/lib/
wileymud-1.187b/attic/lib/adm/
wileymud-1.187b/attic/lib/man/
wileymud-1.187b/attic/lib/new-wld/
wileymud-1.187b/attic/lib/new-wld/default/
wileymud-1.187b/attic/lib/old/
wileymud-1.187b/attic/lib/wld/
wileymud-1.187b/attic/public_html/
wileymud-1.187b/attic/public_html/gfx/
wileymud-1.187b/attic/src/bin/
wileymud-1.187b/attic/src/etc/
wileymud-1.187b/attic/src/libauth-4.0-p5/
wileymud-1.187b/attic/src/sedna/
wileymud-1.187b/backups/
wileymud-1.187b/bin/
wileymud-1.187b/docs/
wileymud-1.187b/etc/
wileymud-1.187b/lib/
wileymud-1.187b/lib/adm/
wileymud-1.187b/lib/boards/
wileymud-1.187b/lib/log/
wileymud-1.187b/lib/man/
wileymud-1.187b/lib/ply/
wileymud-1.187b/lib/ply/a/
wileymud-1.187b/lib/ply/b/
wileymud-1.187b/lib/ply/c/
wileymud-1.187b/lib/ply/d/
wileymud-1.187b/lib/ply/g/
wileymud-1.187b/lib/ply/k/
wileymud-1.187b/lib/ply/m/
wileymud-1.187b/lib/ply/s/
wileymud-1.187b/lib/ply/t/
wileymud-1.187b/public_html/gfx/
wileymud-1.187b/src/bin/
wileymud-1.187b/src/convert/attic/
wileymud-1.187b/src/convert/obj/
wileymud-1.187b/src/convert/perl/
wileymud-1.187b/src/convert/perl/MudConvert/
wileymud-1.187b/src/convert/perl/MudConvert/DUMP/
wileymud-1.187b/src/convert/perl/MudConvert/Report/
wileymud-1.187b/src/convert/perl/MudConvert/WileyMUD/
wileymud-1.187b/src/convert/perl/output/
wileymud-1.187b/src/convert/perl/output/DUMP/
wileymud-1.187b/src/convert/perl/output/Report/
wileymud-1.187b/src/convert/perl/output/WileyMUD/
wileymud-1.187b/src/etc/
wileymud-1.187b/src/etc/init.d/
wileymud-1.187b/src/etc/rc.d/
wileymud-1.187b/src/etc/rc.d/init.d/
wileymud-1.187b/src/lib/
wileymud-1.187b/src/lib/adm/
wileymud-1.187b/src/lib/boards/
wileymud-1.187b/src/lib/log/
wileymud-1.187b/src/lib/man/
wileymud-1.187b/src/lib/ply/
wileymud-1.187b/src/lib/ply/a/
wileymud-1.187b/src/lib/ply/b/
wileymud-1.187b/src/lib/ply/c/
wileymud-1.187b/src/lib/ply/d/
wileymud-1.187b/src/lib/ply/e/
wileymud-1.187b/src/lib/ply/f/
wileymud-1.187b/src/lib/ply/g/
wileymud-1.187b/src/lib/ply/h/
wileymud-1.187b/src/lib/ply/i/
wileymud-1.187b/src/lib/ply/j/
wileymud-1.187b/src/lib/ply/k/
wileymud-1.187b/src/lib/ply/l/
wileymud-1.187b/src/lib/ply/m/
wileymud-1.187b/src/lib/ply/n/
wileymud-1.187b/src/lib/ply/o/
wileymud-1.187b/src/lib/ply/p/
wileymud-1.187b/src/lib/ply/q/
wileymud-1.187b/src/lib/ply/r/
wileymud-1.187b/src/lib/ply/s/
wileymud-1.187b/src/lib/ply/t/
wileymud-1.187b/src/lib/ply/u/
wileymud-1.187b/src/lib/ply/v/
wileymud-1.187b/src/lib/ply/w/
wileymud-1.187b/src/lib/ply/x/
wileymud-1.187b/src/lib/ply/y/
wileymud-1.187b/src/lib/ply/z/
wileymud-1.187b/src/obj/
wileymud-1.187b/src/utils/
wileymud-1.187b/src/utils/mobmaker/
/*
 * Opens a port (the port # above the port # the game itself is
 * being run). On this port people can connect to see who's on.
 * The player wont have to enter the game to see if it's worth
 * playing at the time, thus saving money.
 *
 * Change the following #define-statements to adjust the
 * WHOD to your server.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>

#include "version.h"
#include "global.h"
#include "bug.h"
#include "db.h"
#include "comm.h"
#include "utils.h"
#include "interpreter.h"
#include "multiclass.h"
#define _WHOD_C
#include "whod.h"

/*
 * In function run_the_game(int port):
 *   ...
 *   init_whod(port);
 *   log_boot("Entering game loop.");
 *   game_loop(s);
 *   close_sockets(s);
 *   close_whod();
 *   ...
 *
 *   In function game_loop ():
 *   ...
 *   sigsetmask(mask);
 *   whod_loop();
 *   if (select(maxdesc + 1, &input_set, &output_set, &exc_set, &null_time) < 0)
 *   ...
 */

static long                             disconnect_time = 0L;
static int                              s = 0;
int                                     whod_mode = DEFAULT_MODE;
static int                              state = 0;
static int                              whod_port = 0;

/*
 * Function   : do_whod
 * Parameters : doer, argument string, number of WHOD command (not used)
 * Returns    : --
 * Description: MUD command to set the mode of the WHOD-connection according
 *              to the command string.                                  
 */

void do_whod(struct char_data *ch, const char *arg, int cmd)
{
    char                                    buf[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    char                                    tmp[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    int                                     bit = 0;

    const char                             *modes[] = {
	"on",
	"off",
	"idle",
	"level",
	"name",
	"title",
	"room",
	"site",
	"room_ingame",
	"\n"
    };

    if (DEBUG)
	log_info("called %s with %s, %s, %d", __PRETTY_FUNCTION__, SAFE_NAME(ch), VNULL(arg),
		 cmd);

    half_chop(arg, buf, tmp);
    if (!*buf) {
	cprintf(ch, "Current WHOD mode:\r\n------------------\r\n");
	sprintbit((long)whod_mode, (const char **)modes, buf);
	cprintf(ch, "%s\r\n", buf);
	return;
    }
    if ((bit = old_search_block(buf, 0, strlen(buf), modes, FALSE)) == -1) {
	cprintf(ch, "That mode does not exist.\r\nAvailable modes are:\r\n");
	*buf = '\0';
	for (bit = 0; *modes[bit] != '\n'; bit++) {
	    strcat(buf, modes[bit]);
	    strcat(buf, " ");
	}
	cprintf(ch, "%s\r\n", buf);
	return;
    }
    bit--;						       /* Is bit no + 1 */
    if (SHOW_ON == 1 << bit) {
	if (IS_SET(whod_mode, SHOW_ON))
	    cprintf(ch, "WHOD already turned on.\r\n");
	else {
	    if (IS_SET(whod_mode, SHOW_OFF)) {
		REMOVE_BIT(whod_mode, SHOW_OFF);
		SET_BIT(whod_mode, SHOW_ON);
		cprintf(ch, "WHOD turned on.\r\n");
		log_info("WHOD turned on by %s.", GET_NAME(ch));
	    }
	}
    } else {
	if (SHOW_OFF == 1 << bit) {
	    if (IS_SET(whod_mode, SHOW_OFF))
		cprintf(ch, "WHOD already turned off.\r\n");
	    else {
		if (IS_SET(whod_mode, SHOW_ON)) {
		    REMOVE_BIT(whod_mode, SHOW_ON);
		    SET_BIT(whod_mode, SHOW_OFF);
		    cprintf(ch, "WHOD turned off.\r\n");
		    log_info("WHOD turned off by %s.", GET_NAME(ch));
		}
	    }
	} else {
	    if (IS_SET(whod_mode, 1 << bit)) {
		cprintf(ch, "%c%s will not be shown on WHOD.\r\n",
			toupper(modes[bit][0]), &modes[bit][1]);
		log_info("%c%s removed from WHOD by %s.",
			 toupper(modes[bit][0]), &modes[bit][1], GET_NAME(ch));
		REMOVE_BIT(whod_mode, 1 << bit);
		return;
	    } else {
		cprintf(ch, "%c%s will now be shown on WHOD.\r\n",
			toupper(modes[bit][0]), &modes[bit][1]);
		log_info("%c%s added to WHOD by %s.", toupper(modes[bit][0]), &modes[bit][1],
			 GET_NAME(ch));
		SET_BIT(whod_mode, 1 << bit);
		return;
	    }
	}
    }

    return;
}

/*
 * ------ WHO Daemon staring here ------          
 */

/*
 * Function   : init_whod
 * Parameters : Port #-1 the daemon should be run at
 * Returns    : --
 * Description: Opens the WHOD port and sets the state of WHO-daemon to OPEN
 */

void init_whod(int port)
{
    if (DEBUG > 2)
	log_info("called %s with %d", __PRETTY_FUNCTION__, port);

    whod_port = port + 1;
    log_boot("WHOD port opened.");
    s = init_socket(whod_port);
    state = WHOD_OPEN;
}

/*
 * Function   : close_whod
 * Parameters : --
 * Returns    : --
 * Description: Closes the WHOD port and sets the state of WHO-daemon to
 *              CLOSED.                                                 
 */

void close_whod(void)
{
    if (DEBUG > 2)
	log_info("called %s with no arguments", __PRETTY_FUNCTION__);

    if (state != WHOD_CLOSED) {
	state = WHOD_CLOSED;
	close(s);
	log_boot("WHOD port closed.");
    }
}

/*
 * Function   : whod_text
 * Parameters : --
 * Returns    : a static string
 * Description: Generates plain-text output for telnet.
 */
char                                   *whod_text(void)
{
    /*
     * This is 32K, in case we have 250 players, yeah right! 
     */
    static char                             buf[32768] = "\0\0\0\0\0\0\0";
    int                                     players = 0;
    int                                     gods = 0;
    int                                     char_index = 0;
    struct char_data                       *ch = NULL;
    long                                    ttime = 0L;
    long                                    thour = 0L;
    long                                    tmin = 0L;
    long                                    tsec = 0L;
    time_t                                  now;
    char                                    uptimebuf[100];
    char                                    nowtimebuf[100];

    now = time((time_t *) 0);
    strftime(nowtimebuf, sizeof(nowtimebuf), RFC1123FMT, localtime(&now));
    strftime(uptimebuf, sizeof(uptimebuf), RFC1123FMT, localtime((time_t *) & Uptime));

    sprintf(buf, VERSION_STR);
    strcat(buf, "\r\n");

    players = 0;
    gods = 0;
    char_index = 0;

    for (ch = character_list; ch; ch = ch->next) {
	if (IS_PC(ch)) {
	    if ((INVIS_LEVEL(ch) < 2) && (GetMaxLevel(ch) <= WIZ_MAX_LEVEL) &&
		!IS_AFFECTED(ch, AFF_HIDE) && !IS_AFFECTED(ch, AFF_INVISIBLE)) {
		if (GetMaxLevel(ch) >= WIZ_MIN_LEVEL)
		    gods++;
		else
		    players++;

		char_index++;

		if (IS_SET(SHOW_IDLE, whod_mode)) {
		    if (!(ch->desc)) {
			strcat(buf, "linkdead ");
		    } else {
			ttime = GET_IDLE_TIME(ch);
			thour = ttime / 3600;
			ttime -= thour * 3600;
			tmin = ttime / 60;
			ttime -= tmin * 60;
			tsec = ttime;
			if (!thour && !tmin && (tsec <= 15))
			    strcat(buf, " playing ");
			else
			    sprintf(buf + strlen(buf), "%02ld:%02ld:%02ld ", thour, tmin, tsec);
		    }
		}

		if (IS_SET(SHOW_LEVEL, whod_mode)) {
		    if (GetMaxLevel(ch) >= WIZ_MAX_LEVEL)
			sprintf(buf + strlen(buf), "[ God ] ");
		    else if (GetMaxLevel(ch) == WIZ_MAX_LEVEL - 1)
			sprintf(buf + strlen(buf), "[Power] ");
		    else if (GetMaxLevel(ch) >= WIZ_MIN_LEVEL)
			sprintf(buf + strlen(buf), "[Whizz] ");
		    else
			sprintf(buf + strlen(buf), "[ %3d ] ", GetMaxLevel(ch));
		}

		if (IS_SET(SHOW_TITLE, whod_mode))
		    if (GET_PRETITLE(ch))
			sprintf(buf + strlen(buf), "%s ", GET_PRETITLE(ch));

		if (IS_SET(SHOW_NAME, whod_mode))
		    sprintf(buf + strlen(buf), "%s ", GET_NAME(ch));

		if (IS_SET(SHOW_TITLE, whod_mode))
		    sprintf(buf + strlen(buf), "%s ", GET_TITLE(ch));

		/*
		 * This is bad for the external whod... it pinpoints people too easily.
		 * Make them enter the game to see where people are.
		 */
		if (IS_SET(SHOW_ROOM, whod_mode)) {
		    sprintf(buf + strlen(buf), "- %s ", real_roomp(ch->in_room)->name);
		}

		if (IS_SET(SHOW_SITE, whod_mode)) {
		    if (ch->desc->host != NULL)
			sprintf(buf + strlen(buf), "(%s)", ch->desc->host);
		    else if (ch->desc->ip != NULL)
			sprintf(buf + strlen(buf), "(%s)", ch->desc->ip);
		}
		strcat(buf, "\r\n");
		/*
		 * WRITE(newdesc, buf); 
		 */
		/*
		 *buf = '\0'; */
	    }
	}
    }
    sprintf(buf + strlen(buf), "\r\nVisible Players: %d\tVisible Gods: %d\r\n", players, gods);
    sprintf(buf + strlen(buf), "Wiley start time was: %s\r\n", uptimebuf);
    sprintf(buf + strlen(buf), "Quixadhal's time is:  %s\r\n", nowtimebuf);

    return buf;
}

/*
 * Function   : whod_html
 * Parameters : --
 * Returns    : a static string
 * Description: Generates HTML output for the web.
 */
char                                   *whod_html(void)
{
    /*
     * This is 32K, in case we have 250 players, yeah right! 
     */
    char                                    buf[32768] = "\0\0\0\0\0\0\0";
    int                                     players = 0;
    int                                     gods = 0;
    int                                     char_index = 0;
    struct char_data                       *ch = NULL;
    long                                    ttime = 0L;
    long                                    thour = 0L;
    long                                    tmin = 0L;
    long                                    tsec = 0L;
    time_t                                  now;
    char                                    timebuf[100];
    char                                    uptimebuf[100];
    char                                    nowtimebuf[100];
    static char                             headers[40960];
    int                                     table_width = 0;
    struct timeval                          now_bits;
    struct timeval                          later_bits;

    now = time((time_t *) 0);
    gettimeofday(&now_bits, NULL);
    strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));
    strftime(nowtimebuf, sizeof(nowtimebuf), RFC1123FMT, localtime(&now));
    strftime(uptimebuf, sizeof(uptimebuf), RFC1123FMT, localtime((time_t *) & Uptime));

    sprintf(headers, "HTTP/1.1 200 OK\r\n");
    sprintf(headers + strlen(headers), "Server: %s\r\n", MUDNAME);
    sprintf(headers + strlen(headers), "Date: %s\r\n", timebuf);
    sprintf(headers + strlen(headers), "Content-Type: %s\r\n", "text/html; charset=iso-8859-1");

    sprintf(buf, "<html>\r\n");
    sprintf(buf + strlen(buf), "<head><title>Welcome to %s!</title></head>\r\n", MUDNAME);
    sprintf(buf + strlen(buf), "<body>\r\n");
    sprintf(buf + strlen(buf),
	    "<div align=\"center\"><h3><a href=\"telnet://wiley.shadowlord.org:3000/\">%s</a></h3></div>\r\n",
	    VERSION_STR);

    players = 0;
    gods = 0;
    char_index = 0;

    if (IS_SET(SHOW_IDLE, whod_mode))
	table_width += 100;
    if (IS_SET(SHOW_LEVEL, whod_mode))
	table_width += 100;
    table_width += 400;
    if (IS_SET(SHOW_ROOM, whod_mode))
	table_width += 100;
    if (IS_SET(SHOW_SITE, whod_mode))
	table_width += 200;

    sprintf(buf + strlen(buf), "<div align=\"center\">\r\n");
    sprintf(buf + strlen(buf),
	    "<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\" width=\"%d\">\r\n",
	    table_width);
    sprintf(buf + strlen(buf), "<tr bgcolor=\"#E7E7E7\">\r\n");
    if (IS_SET(SHOW_IDLE, whod_mode))
	sprintf(buf + strlen(buf), "<th align=\"center\" width=\"100\">%s</th>\r\n", "Idle");

    if (IS_SET(SHOW_LEVEL, whod_mode))
	sprintf(buf + strlen(buf), "<th align=\"center\" width=\"100\">%s</th>\r\n", "Level");

    sprintf(buf + strlen(buf), "<th align=\"left\" width=\"400\">%s</th>\r\n", "Name");

    if (IS_SET(SHOW_ROOM, whod_mode))
	sprintf(buf + strlen(buf), "<th align=\"center\" width=\"100\">%s</th>\r\n", "Room");

    if (IS_SET(SHOW_SITE, whod_mode))
	sprintf(buf + strlen(buf), "<th align=\"left\" width=\"200\">%s</th>\r\n", "Site");
    sprintf(buf + strlen(buf), "</tr>\r\n");

    for (ch = character_list; ch; ch = ch->next) {
	if (IS_PC(ch)) {
	    if ((INVIS_LEVEL(ch) < 2) && (GetMaxLevel(ch) <= WIZ_MAX_LEVEL) &&
		!IS_AFFECTED(ch, AFF_HIDE) && !IS_AFFECTED(ch, AFF_INVISIBLE)) {
		if (GetMaxLevel(ch) >= WIZ_MIN_LEVEL)
		    gods++;
		else
		    players++;

		char_index++;

		sprintf(buf + strlen(buf), "<tr bgcolor=\"%s\">\r\n",
			char_index % 2 ? "#E7FFE7" : "#FFFFE7");
		if (IS_SET(SHOW_IDLE, whod_mode)) {
		    if (!(ch->desc)) {
			sprintf(buf + strlen(buf), "<td align=\"center\">%s</td>\r\n",
				"linkdead");
		    } else {
			ttime = GET_IDLE_TIME(ch);
			thour = ttime / 3600;
			ttime -= thour * 3600;
			tmin = ttime / 60;
			ttime -= tmin * 60;
			tsec = ttime;
			if (!thour && !tmin && (tsec <= 15))
			    sprintf(buf + strlen(buf), "<td align=\"center\">%s</td>\r\n",
				    "playing");
			else
			    sprintf(buf + strlen(buf),
				    "<td align=\"center\">%02ld:%02ld:%02ld</td>\r\n", thour,
				    tmin, tsec);
		    }
		}

		if (IS_SET(SHOW_LEVEL, whod_mode)) {
		    if (GetMaxLevel(ch) >= WIZ_MAX_LEVEL)
			sprintf(buf + strlen(buf), "<td align=\"center\">%s</td>\r\n", "God");
		    else if (GetMaxLevel(ch) == WIZ_MAX_LEVEL - 1)
			sprintf(buf + strlen(buf), "<td align=\"center\">%s</td>\r\n", "Power");
		    else if (GetMaxLevel(ch) >= WIZ_MIN_LEVEL)
			sprintf(buf + strlen(buf), "<td align=\"center\">%s</td>\r\n", "Whizz");
		    else
			sprintf(buf + strlen(buf), "<td align=\"center\">%3d</td>\r\n",
				GetMaxLevel(ch));
		}

		sprintf(buf + strlen(buf), "<td align=\"left\">");
		if (IS_SET(SHOW_TITLE, whod_mode))
		    if (GET_PRETITLE(ch))
			sprintf(buf + strlen(buf), "%s ", GET_PRETITLE(ch));

		if (IS_SET(SHOW_NAME, whod_mode))
		    sprintf(buf + strlen(buf), "%s", GET_NAME(ch));

		if (IS_SET(SHOW_TITLE, whod_mode))
		    sprintf(buf + strlen(buf), " %s", GET_TITLE(ch));
		sprintf(buf + strlen(buf), "</td>\r\n");

		/*
		 * This is bad for the external whod... it pinpoints people too easily.
		 * Make them enter the game to see where people are.
		 */
		if (IS_SET(SHOW_ROOM, whod_mode)) {
		    sprintf(buf + strlen(buf), "<td align=\"center\">%s</td>\r\n",
			    real_roomp(ch->in_room)->name);
		}

		if (IS_SET(SHOW_SITE, whod_mode)) {
		    if (ch->desc->host != NULL)
			sprintf(buf + strlen(buf), "<td align=\"left\">%s</td>\r\n",
				ch->desc->host);
		    else if (ch->desc->ip != NULL)
			sprintf(buf + strlen(buf), "<td align=\"left\">%s</td>\r\n",
				ch->desc->ip);
		}
		sprintf(buf + strlen(buf), "</tr>\r\n");
	    }
	}
    }
    sprintf(buf + strlen(buf), "</table>\r\n");

    sprintf(buf + strlen(buf), "<br />\r\n");
    sprintf(buf + strlen(buf),
	    "<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\" width=\"%d\">\r\n",
	    table_width);
    sprintf(buf + strlen(buf), "<tr>\r\n");
    sprintf(buf + strlen(buf), "<td align=\"right\" width=\"%d\">%s</td>\r\n", table_width / 2,
	    "Visible&nbsp;Players:&nbsp;");
    sprintf(buf + strlen(buf), "<td align=\"left\" width=\"%d\">%d</td>\r\n", table_width / 2,
	    players);
    sprintf(buf + strlen(buf), "</tr>\r\n");
    sprintf(buf + strlen(buf), "<tr>\r\n");
    sprintf(buf + strlen(buf), "<td align=\"right\" width=\"%d\">%s</td>\r\n", table_width / 2,
	    "Visible&nbsp;Gods:&nbsp;");
    sprintf(buf + strlen(buf), "<td align=\"left\" width=\"%d\">%d</td>\r\n", table_width / 2,
	    gods);
    sprintf(buf + strlen(buf), "</tr>\r\n");
    sprintf(buf + strlen(buf), "<tr>\r\n");
    sprintf(buf + strlen(buf), "<td align=\"right\" width=\"%d\">%s</td>\r\n", table_width / 2,
	    "Wiley&nbsp;start&nbsp;time&nbsp;was:&nbsp;");
    sprintf(buf + strlen(buf), "<td align=\"left\" width=\"%d\">%s</td>\r\n", table_width / 2,
	    uptimebuf);
    sprintf(buf + strlen(buf), "</tr>\r\n");
    sprintf(buf + strlen(buf), "<tr>\r\n");
    sprintf(buf + strlen(buf), "<td align=\"right\" width=\"%d\">%s</td>\r\n", table_width / 2,
	    "Quixadhal's&nbsp;time&nbsp;is:&nbsp;");
    sprintf(buf + strlen(buf), "<td align=\"left\" width=\"%d\">%s</td>\r\n", table_width / 2,
	    nowtimebuf);
    sprintf(buf + strlen(buf), "</tr>\r\n");
    sprintf(buf + strlen(buf), "</table>\r\n");

    sprintf(buf + strlen(buf), "</div>\r\n");

    gettimeofday(&later_bits, NULL);
    sprintf(buf + strlen(buf),
	    "<div align=\"right\"><font size=\"-1\" color=\"#DDDDDD\">Page took %01d.%06d seconds to render.</font></div>\r\n",
	    (int)(later_bits.tv_sec - now_bits.tv_sec),
	    (int)(later_bits.tv_usec - now_bits.tv_usec));

    sprintf(buf + strlen(buf), "</body>\r\n");
    sprintf(buf + strlen(buf), "</html>\r\n");

    sprintf(headers + strlen(headers), "Content-Length: %d\r\n", (int)strlen(buf));
    sprintf(headers + strlen(headers), "Connection: %s\r\n", "close");
    sprintf(headers + strlen(headers), "\r\n");
    strcat(headers, buf);

    return headers;
}

/*
 * Function   : whod_loop
 * Parameters : --
 * Returns    : --
 * Description: Serves incoming WHO calls.                             
 */

void whod_loop(void)
{
    unsigned int                            size = 0;
    fd_set                                  in;
    unsigned long                           hostlong = 0L;
    struct timeval                          timeout;
    struct sockaddr_in                      newaddr;
    struct hostent                         *hent = NULL;

    /*
     * extern long Uptime; 
     */

    static int                              newdesc = 0;

    if (DEBUG > 2)
	log_info("called %s with no arguments", __PRETTY_FUNCTION__);

    switch (state) {
/****************************************************************/
	case WHOD_OPENING:
	    s = init_socket(whod_port);
	    log_boot("WHOD port opened.");
	    state = WHOD_OPEN;
	    break;

/****************************************************************/
	case WHOD_OPEN:

	    timeout.tv_sec = 0;
	    timeout.tv_usec = 100;

	    FD_ZERO(&in);
	    FD_SET(s, &in);

	    select(s + 1, &in, (fd_set *) 0, (fd_set *) 0, &timeout);

	    if (FD_ISSET(s, &in)) {
		size = sizeof(newaddr);
		getsockname(s, (struct sockaddr *)&newaddr, &size);

		if ((newdesc = accept(s, (struct sockaddr *)&newaddr, &size)) < 0) {
		    log_error("WHOD - Accept");
		    return;
		}
		if ((hent =
		     gethostbyaddr((char *)&newaddr.sin_addr, sizeof(newaddr.sin_addr),
				   AF_INET)))
		    log_info("WHO request from %s served.", hent->h_name);
		else {
		    hostlong = htonl(newaddr.sin_addr.s_addr);
		    log_info("WHO request from %lu.%lu.%lu.%lu served.",
			     (hostlong & 0xff000000) >> 24,
			     (hostlong & 0x00ff0000) >> 16,
			     (hostlong & 0x0000ff00) >> 8, (hostlong & 0x000000ff) >> 0);
		}

		/*
		 * Do we really need to sink input here before sending output? 
		 */
/*        if (fcntl(s, F_SETFL, O_NDELAY) != -1) {
          char junk[MAX_INPUT_LENGTH];
          while(read(newdesc, junk, MAX_INPUT_LENGTH) > 0);
        }
*/
		WRITE(newdesc, whod_html());

		disconnect_time = time(NULL) + WHOD_DELAY_TIME;
		state = WHOD_DELAY;
	    } else if (IS_SET(SHOW_OFF, whod_mode)) {
		state = WHOD_CLOSING;
	    }
	    break;

/*************************************************************************/
	case WHOD_DELAY:
	    if (time(NULL) >= disconnect_time)
		state = WHOD_END;
	    break;

/****************************************************************/
	case WHOD_END:
	    close(newdesc);
	    if (IS_SET(whod_mode, SHOW_OFF))
		state = WHOD_CLOSING;
	    else
		state = WHOD_OPEN;
	    break;

/****************************************************************/
	case WHOD_CLOSING:
	    close_whod();
	    state = WHOD_CLOSED;
	    break;

/****************************************************************/
	case WHOD_CLOSED:
	    if (IS_SET(whod_mode, SHOW_ON))
		state = WHOD_OPENING;
	    break;

    }
    return;
}

/**** You might want to use this in your help_file.                 ****/
/**** It should be placed in the end of the file, so help on WHO is ****/
/**** availeble too.                                                ****/

/*
 * WHOD
 * 
 * The who daemon is run a seperate port. The following commands exists:
 * 
 * name    : Toggles peoples name on/off the list (useless)
 * title   : Toggles peoples title on/off the list
 * site    : Toggles peoples site names on/off the list
 * on      : Turns the whod on, and thereby opens the port
 * off     : Turns the whod off, and thereby closes the port
 * 
 * NOTE:     The on/off feature is only made to use, if someone starts polling
 * a few times a second or the like, and thereby abusing the net. You
 * might then want to shut down the daemon for 15 minutes or so.
 * #
 */