Starting DoT as a daemon

Posted by Viruz on Fri 08 Feb 2002 07:45 AM — 8 posts, 36,849 views.

#0
I know I am a pain in the arse, but I am so excited about this code that I come up with new questions all the time.

OpenBSD 3.0
Want to start dot at boot.
Problem:
Dot does not want to be run as root(understandable)

I need a solution to have dot start as username "mud" using the bootmud script from the dot site. or whatever you can recommend.

Australia Forum Administrator #1
I think you can do that with "su". Set up the user "mud" and then use su to start dawn as that user.

BTW - in case you haven't noticed, dawn has a "pipe" command that lets you execute arbitrary OS commands. Thus running it as root would be a very bad idea.

Because of that I have set up a "chroot jail" for running Dawn under OpenBSD. Whether it is totally secure I am not sure, but I think it is more secure than doing nothing.

If anyone is interested I can post the technique. Basically it involves setting up a pseudo-root directory, with only enough files to run dawn. Thus, even if someone somehow gets admin access (eg. by guessing a password) and then running a "pipe" command, the damage they can do is limited to the command you put in the "jail" environment (eg. only things like ls).
#2
Nick I don't think that's what I meant

What I would like to do is add a reference to bootmud to rc.local to have it start at boot time.

automagically.. rc.local won't seem to boot the mud so what's next?
Australia Forum Administrator #3
Hmmm - you haven't said in what way it didn't work, but here is stuff I got going (I think) for junkbuster, I imagine you can use similar stuff for DoT ...

This is in rc.local, and I set up a special user called "junkbuster" for this purpose:

 
# Junkbuster proxy server

if [ -x /usr/sbin/junkbuster ]; then
  echo 'starting junkbuster ...'
  su junkbstr -c 'nohup /usr/sbin/junkbuster /etc/junkbuster/config > /dev/null &'
fi


Modify that slightly to change the user to "mud" and add the appropriate path to the mud server, and it should work. Something like this, although I haven't tested it ...

 
# Start Dawn Of Time

if [ -x /home/nick/dot/dawn ]; then
  echo 'starting DoT ...'
  su mud -c 'nohup /home/nick/dot/dawn > /dev/null &'
fi


USA #4
Ok, I used the same script that you said for junkbuster, but I changed it a bit to go into a logfile, the problem is, it still directs the output to the screen. I know this probably sounds like a typical newbie problem, but I've just changed it from '/dev/null' to '/muds/logfiles/logfile.log' and it doesn't seem to work well. Any help would be appreciated.
Australia Forum Administrator #5
This is what I have under OpenBSD ...

In rc.local (I am running it under user nick):



#
# Dawn Of Time - (need bash for the stderr redirection)
#

echo 'Starting DoT ...'
sudo -u nick /usr/local/bin/bash -c '/mudroot/dot/chroot_jail/startdawn'



The file /mudroot/dot/chroot_jail/startdawn:



# cannot run from chroot area - switch to my home directory
cd ~nick

# now run it
./runchroot &> dawn.log &



The program runchroot:



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <paths.h>
#include <unistd.h>
#include <err.h>

/*

runchroot - Program to run a MUD from a chroot jail

Author: Nick Gammon 
Date: 16 Apr 2002

To compile: gcc runchroot.c -o runchroot

Then, as root: chown root runchroot
               chmod u+s runchroot

*/

#define NEWROOT "/mudroot"   // new root directory
#define STARTDIR "/dot"      // where MUD is within new root
char * args [] = { "./dawn", NULL };  // program to run, null argument list

int
main(int argc, char **argv)
{
// Change to new root directory, and chroot to it
if (chdir(NEWROOT) || chroot("."))
        err(1, "%s", argv[0]);

// switch to actual user id (not root)
setuid (getuid ());

// change to required directory in new root
if (chdir(STARTDIR))
        err(1, "%s", argv[0]);

// execute the requested program
execvp(args[0], &args[0]);

// shouldn't return, error if we do
err(1, "%s", args[0]);
}
Amended on Wed 24 Sep 2003 01:23 AM by Nick Gammon
Australia Forum Administrator #6
However the simple solution might be to just modify your script to redirect &> rather than >.
United Kingdom #7
I normally just use a crontab job setup under the mud account you want to use.

Say you have an account called dawn to run the mud under.

Login as dawn.


mkdir bin    (to create ~/bin)
cd bin       (change into the bin dir)


create a bootmud.pl file based on the one shown below in the bin dir.


crontab -e   (to edit your crontab)
*/5 * * * * ~/bin/bootmud.pl   (add this line in the editor then exit)


That above line in your crontab, will run the bootmud.pl script every 5 minutes... if the mud is down it will automatically be rebooted.

Below is the bootmud.pl script, you will need to change the port number and directories.

- Kalahn
Developer of the Dawn of Time Codebase.
http://www.dawnoftime.org/


cat ~/bin/bootmud.pl
#!/usr/bin/perl
#########################################################################
# bootdawn.pl                       Version 1.1                         #
# Created: Jun 28, 1997             Kalahn@dawnoftime                   #
# Last Modified: 18 March 2001      http://www.dawnoftime.org/          #
#########################################################################
# README
#
# This is a pretty simple script that checks to see if a mud is running #
# properly.  Be sure to change the 'important vars' section.  The best  #
# idea is to run this script from cron every couple of minutes... That  #
# way you can be sure that it stays running. 
#
# You probably should stop using startup as a script and delete it.
# Here's how to do it...
#
# 1) Make sure to edit the bootdawn.pl file and insert your values at 
#    the top.
#
# 2) Edit your crontab file, type crontab -e, it's a vi editor.
# 
# 3) Put the following line as your crontab script:
# 
#    */8 * * * * /home/dawn/bin/bootdawn.pl
# 
# 4) Make sure to change the directory in the above line as needed.
# 
#########################################################################
# CHANGES AND HISTORY                                                   #
#                                                                       #
# v 1.0, Jun 28, 1997   Written by Jared Proudfoot                      #
#                           <jproudfo@footprints.net>                   #
# v 1.1, Mar 18, 2001   Customised for Dawn of time - Kalahn            #
#########################################################################
#########################################################################
# Define the important vars                                             #
#                                                                       #
# Define the host and port number where the mud resides.                #

$server     =   "localhost";
$port       =   "1111";

# $string is the string of characters we will look for upon connecting. #
# If we connect, but don't see this string, we will assume the mud      #
# isn't responding (locked up?) and we'll restart it.  The string       #
# *must* be on the first line after connect.    

# You may enter this as a regexp if you wish.                           #

$replyString        =   ".+";

# How long do we wait before we connect timeout (in seconds)?           #

$timeOut    =   "60";

# What to execute if we need to restart the mud.  Please include the    #
# FULL path.                                                            #

$exec       =   "ulimit -c unlimited ; /home/mf/dot/dawn";

# Path where you want the mud logs to be kept.

$logdir     =   "/home/mf/dot/logs/game";

# Path where we should start the mud from.                              #
$startPath  =   "/home/mf/dot";

# That's it.  You shouldn't need to change anything after this line.    #
#########################################################################

# What do we need to use?
use Socket;
require 5.003;

#########################################################################
# Main                                                                  #
#########################################################################

if (&connect_server == 0) {
    # If we couldn't connect, try and restart.  #
    print ("Connection to $server on port $port failed or timed out after $timeOut seconds!\n");
    $time = (scalar localtime);
    print ("Attempting to restart the mud on $time...\n");
    # Restart the mud                           #
    &restart_mud;
}
else {
    # We connected, but is it working properly?         #
        $readline = (&gl);
        if ($readline =~ /$replyString/) {
            # We found what we were looking for, so exit    #
            # properly.                 #
            &disconnect_server;
            exit 1;
        }
    # After all those searches, we didn't find anything.  The mud   #
    # must be locked up.  Lets kill and restart it.         #
    &disconnect_server;
    print ("The connection was sucessful, but it doesn't seem to be responding\n");
    $time = (scalar localtime);
    print ("Attempting to restart the mud on $time...\n");
    system("killall $exec");
    &restart_mud;
}
    
    


#########################################################################
# Subroutines                               #
#########################################################################


sub connect_server {
    # Connect to the server                     #
    my ($iaddr, $paddr, $proto);
    $iaddr = inet_aton ($server)
        or die ("ERROR: No host: $server!\n");
    $paddr = sockaddr_in ($port, $iaddr);
    $proto = getprotobyname('tcp');
    socket (SOCK, PF_INET, SOCK_STREAM, $proto)
        or die ("ERROR: Socket error $!\n");
    alarm ($timeOut);
    if (connect (SOCK, $paddr)) {;
        alarm (0);
        return 1;
    }
    else {
        return 0;
    }
}

sub disconnect_server {
    # Disconnect from the server                    #
    close (SOCK);
    return;
}

sub sl {
    # Send a line                           #
    my ($line)=@_;
    print SOCK ("$line")
        or die ("ERROR: Error writing to server: $!\n");
    select SOCK;
    $|=1;
    select STDOUT;
    $|=1;
    return;
}
    
sub gl {
    # Get a line                            #
    my ($buffer, @reply);
    $buffer=(<SOCK>);
#   (@reply) = split (/\s/, $buffer);
#   return (@reply);
    return ($buffer);
}

sub restart_mud {
        # Restart the mud                   #
        $timet = time();
        chdir $startPath;
        system ("$exec $port > $logdir/$timet.log 2>&1 &");
        return;
}