#pragma     extend

#define     RMXRET  int
#define     RMXOBJ  int
#define     FALSE   0
#define     TRUE    ~FALSE

#include    <rmx.h>
#include    <stdio.h>
#include    <string.h>
#include    <stdlib.h>
#include    <stddef.h>
#include    <time.h>

char        command[256], excp_info[5], buff[50], *this, *next;
int         ci_tkn, co_tkn, cmd_tkn, status, cmd_status, index;
U16         hour, minute, second, rmx_timeout;
U32         start, end, timeout;

/****************************************************************************/
/* explain_ccode_and_die - outputs explanation of erroneous condition code  */
/* and aborts execution                                                     */
/****************************************************************************/

const char whilel[]  = "while loading command";
const char whilee[]  = "while executing command";

void explain_ccode_and_die( int ccode, const char *msg )
    {
    buff[0] = 0;
    RQCFORMATEXCEPTION( buff, 50, ccode, 1, &status );

    if ( status != E_OK )
        sprintf( buff, "%04X: E$UNKNOWN$EXCEPTION", ccode );
    else
        (void)cstr( buff, buff );

    printf( "\n%s, %s\n", buff, msg );
    exit( ccode );
    }

/****************************************************************************/
/* execcmd - execute a single command                                       */
/****************************************************************************/

void execcmd( char *cmd )
    {
    udistr( cmd, cmd );    
    RQCSENDCOMMAND( cmd_tkn, cmd, &cmd_status, &status );

    if ( ( status != E_OK ) && ( status != E_CONTINUED ) )
        explain_ccode_and_die( status, whilel );
    
    if ( cmd_status != E_OK )
        explain_ccode_and_die( cmd_status, whilee );
    }
                    
/****************************************************************************/
/* execcmds - executes command(s)                                           */
/****************************************************************************/

void execcmds( char *cmd )
    {
    this = cmd;

    while ( ( next = strchr( this, '!' ) ) != NULL )
        {
        *next++ = '\0';
        execcmd( this );
        this = next;
        }
    
    execcmd( this );
    }

/****************************************************************************/
/* main                                                                     */
/****************************************************************************/

int main( int argc, char *argv[] )
    {
    if ( argc < 3 )
        {
        puts( "AFTER : Delayed command execution facility\n" );
        puts( "USE: \"after hh:mm:ss command [! command]*\"\n" );
        exit( E_PARAM );
        }
    
    hour = minute = second = 0;
    index = sscanf( argv[1], "%u:%u:%u", &hour, &minute, &second );

    if ( ( index < 1 ) || ( index > 3 ) || ( hour > 23 ) || ( minute > 59 ) || ( second > 59 ) )
        {
        puts( "Invalid time specification\n" );
        exit ( E_PARAM );
        }

    excp_info[4] = NO_EXCEPTIONS;
    RQSETEXCEPTIONHANDLER( excp_info, &status );
    
    ci_tkn = RQCGETINPUTCONNECTION( CONSOLE_INPUT_DEVICE, &status );

    if ( status == E_OK )
        co_tkn = RQCGETOUTPUTCONNECTION( CONSOLE_OUTPUT_DEVICE, OVER_PREPOSITION, &status );
    
    if ( status == E_OK )
        cmd_tkn = RQCCREATECOMMANDCONNECTION( ci_tkn, co_tkn, 0, &status );
    
    if ( status != E_OK )
        explain_ccode_and_die( status, whilee );

    timeout = ((U32)hour * 3600L) + ((U32)minute * 60L) + (U32)second;

    while ( timeout )
        {
        if ( timeout >= 655 )
            {
            rmx_timeout = 65500;
            timeout -= 655;
            }
        else
            {
            rmx_timeout = timeout * 100;
            timeout = 0;
            }

        RQSLEEP( rmx_timeout, &status );
        }

    strcpy( command, argv[2] );

    for ( index = 3; index < argc; index++ )
        {
        strcat( command, " " );
        strcat( command, argv[index] );
        }

    execcmds( command );
    exit( 0 );
    }
