Shell Command Processor
-----------------------

New core command processor written by Thoric <thoric@game.org>
Old core command processor written by Ferris <ferris@FootPrints.net>

Copier and compiler commands written by Samson of Alsherok.
Grep interface by Noplex of Crimson Blade.

Prerequisite Requirements
-------------------------

Only one - but it's a BIG one: That you ***NOT*** be using the 
EmberMUD shell code I'm distributing. The 2 versions will conflict
with each other and cause you unpredictable results at best, and at
worst.... well..... yeah. Just don't do it.

Terms of Use
------------

You may use this snippet provided the following conditions are met:

1. Any included comment headers in the code are left intact. You may
   add your own, but do not take mine out.

2. This snippet may not be posted for redistribution on any site
without obtaining prior written consent from the Alsherok team.

If you can't agree to these terms, don't use this code, and don't expect
me to help if something breaks while installing it. Harsh? Hardly. I'm
tired of people who come crawling to whine and complain when they haven't
bothered to comply with the terms first.

NOTE: Special condition for this code: Support of any kind will not be given
due to the extremely sensitive nature of what this does. If you can't fix it
on your own, don't ask me for help. This is being done to limit my liability
in the event it is somehow then used to damage your mud. You can thank our
litigious society for that. Besides, suing me won't help. I'm broke.

What this code does
-------------------

First off:

I am NOT responsible for any damage this code may cause your mud.
Use this at your own risk!!! I also take no responsibility for any
damage caused as a result of following someone elses instructions for
fixing the deliberate errors.

With that aside, this code provides several nice useful features.
Although you will still need to upload whatever files your working on,
once you upload them, you can then spread them around to your other
ports in a fraction of the time it would take to upload them yourself.
Read each of the helpfiles, they pretty well explain how it all works.
The compiler option arose merely out of my own laziness, and the fact
that having too many windows open saps poor Windows of resources.
Well ok, now that I have XP this is moot. I'm lazy.

This code as is will run perfectly on a mud with 3 ports. If you only
have 2 ports, well, that's your new project then. It can be done.
I know, we used to only have 2 ports :)

If you only have one port to work with, the copy commands won't be of
any use to you, but the compiler option might.

Before proceeding with this installation, you should know
that this code can represent a serious security risk if it's misused.
The two core functions that drive these command processors give whoever
uses them direct access to the mud's shell account. For that reason, 
this code has been deliberately handicapped so as to prevent 
inexperienced coders from opening their muds up to too much risk.
Don't expect me to tell you how to fix the problem if you don't understand
what your compiler is trying to tell you. If you don't know how to fix
the errors being reported, you really don't have any business trying to
install this code anyway. Do NOT contact the original authors of
any of this stuff either, they are not providing support for this.

Known bugs:

1. On muds with the MCCP client compression protocol installed, immortals
who log on with that ability enabled and have access to the shell command
will be presented with a screenful of garbage if using a client that supports
MCCP. To correct this temporarily, I've added 2 lines in both shell routines
to turn off the user's MCCP. It will generally need to be restarted manually.

2. The "globbing" support which enables wildcards to be used in commands
does not appear to work on all systems. It didn't used to work for me
either at first, but now for some reason it does and the code hasn't been
altered. If you run into this, turn it off. You'll know when it breaks
because your child processes will segfault.

Installation Instructions
-------------------------

1. To install this code, place shell.c and shell.h in your source
   directory. Make the appropriate additions to your Makefile for
   shell.c and shell.o.

2. In mud.h, below the following line:

   #define LEVEL_AVATAR		   (MAX_LEVEL - 15)

   Add: #include "shell.h"

   Find the section with the connected states ( search for CON_PLAYING )

   After the last one in the array, add: CON_FORKED and CON_IAFORKED

   A bit further down, in the descriptor_data structure
   add the following to the end:

   pid_t process; /* Samson 4-16-98 - For new command shell code */

3. In file comm.c,

   In the includes section, add: #include <sys/wait.h>

   Locate function game_loop.

   Directly above the function, add the following:

static void SigChld( int signum )
{
   int pid, status;
   CHAR_DATA *ch;
   DESCRIPTOR_DATA *d;

   while( 1 )
   {
      pid = waitpid( WAIT_ANY, &status, WNOHANG );
      if( pid < 0 )
         break;

      if( pid == 0 )
         break;

      for( d = first_descriptor; d; d = d->next )
      {
         if( d->connected == CON_FORKED && d->process == pid )
         {
            if( compilelock )
            {
               echo_to_all( AT_GREEN, "Compiler operation completed. Reboot and shutdown commands unlocked.", ECHOTAR_IMM );
               compilelock = FALSE;
            }
            d->process = 0;
            d->connected = CON_PLAYING;
            ch = d->original ? d->original : d->character;
            if( ch )
               ch_printf( ch, "Process exited with status code %d.\r\n", status );
         }
      }
   }
}

   Then find the following:

#ifndef WIN32
   signal( SIGPIPE, SIG_IGN );
   signal( SIGALRM, caught_alarm );
#endif

   Directly below that, add:

   signal( SIGCHLD, SigChld );

   Find the following lines of code:

	for ( d = first_descriptor; d; d = d_next )
	{
	    if ( d == d->next )
	    {
	      bug( "descriptor_loop: loop found & fixed" );
	      d->next = NULL;
	    }
 	    d_next = d->next;

    Directly below that, add the following:

         /*
          * Shell code - checks for forked descriptors 
          */
         if( d->connected == CON_FORKED )
         {
            int status;
            if( !d->process )
               d->connected = CON_PLAYING;

            if( ( waitpid( d->process, &status, WNOHANG ) ) == -1 )
            {
               d->connected = CON_PLAYING;
               d->process = 0;
            }
            else if( status > 0 )
            {
               CHAR_DATA *ch;
               d->connected = CON_PLAYING;
               d->process = 0;
               ch = d->original ? d->original : d->character;
               if( ch )
                  ch_printf( ch, "Process exited with status code %d.\r\n", status );
            }
            if( d->connected == CON_FORKED )
               continue;
         }

   Locate function new_descriptor, and find the following lines:

    CREATE( dnew, DESCRIPTOR_DATA, 1 );
    dnew->next		= NULL;
    dnew->descriptor	= desc;
    dnew->connected	= CON_GET_NAME;
    dnew->outsize	= 2000;
    dnew->idle		= 0;
    dnew->lines		= 0;
    dnew->scrlen	= 24;
    dnew->port		= ntohs( sock.sin_port );
    dnew->user 		= STRALLOC("(unknown)");
    dnew->newstate	= 0;
    dnew->prevcolor	= 0x08;

   Insert this line below dnew->next = NULL :

   dnew->process = 0; /* Samson 4-16-98 - For new command shell */

4. In file act_wiz.c,

   Locate function do_reboot.

   And add the following immediately below the final declaration:

   if( compilelock )
   {
      set_char_color( AT_RED, ch );
      send_to_char( "Sorry, the mud cannot be rebooted during a compiler operation.\r\nPlease wait for the compiler to finish.\r\n", ch );
      return;
   }

   Locate function do_shutdown.

   And add the following immediately below the final declaration:

   if( compilelock )
   {
      set_char_color( AT_RED, ch );
      send_to_char( "Sorry, the mud cannot be shutdown during a compiler operation.\r\nPlease wait for the compiler to finish.\r\n", ch );
      return;
   }

5. Add the appropriate entries in tables.c for the following:
   do_copy, do_compile, do_copyclass, do_copycode, do_copydeity,
   do_copyrace, do_copysocial, and do_copyzone.

   For reasons of security, I'll leave out the last 2 since they are
   the ones that allow access to the shell via the mud. I suspect if
   you are paying attention, you already realize which 2 they are and
   can figure out which table entries to make.

6. Add the text included in Shell.help to your help.are file. Adjust the
   levels to suite your situation.

7. Make clean, and recompile. Remember, expect errors if you haven't fixed
   the handicapping.

8. Once rebooted, add the following commands:
   copy, compile, copyclass, copycode, copydeity, copyrace, copysocial
   copyzone, and grep. If you have overland installed, add a copymap command.
   These commands should be restricted to higher level
   immortals. The 2 other commands that act as the core to all of this
   should either be restricted to implementors only, or not entered at
   all. The shell code will still operate just fine without them.

This code has been installed and tested on Smaug 1.6 FUSS, which is a bugfixed
and cleaned up version of the base Smaug 1.4a code. The Smaug FUSS Project is
maintained on servers which run the Redhat and Fedora family of Linux. Limited
testing has also been done on the Cygwin package under WindowsXP SP1 and SP2.
Users of BSD, MSVC, MSVC++, or Macintosh platforms are on their own as The
Smaug FUSS Project does not have access to these development environments for testing.
The Smaug FUSS Project can be found at: http://www.smaugfuss.org

No guarantees are made that this code will be compatible with your codebase and any
modifications you may have made to it. No warranty of any kind is expressed or implied
by the use of this code, and we are not responsible for any damages which may result
from the application of this snippet to your codebase.

Adventure beckons in the lands of mystique....
Samson, Implementor of Alsherok
http://www.alsherok.net
telnet://alsherok.net:5500

IMC2 contact: Samson@Alsherok