#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 - outputs explanation of erroneous condition code          */
/****************************************************************************/

const char whilel[]  = "while loading command";
const char whilee[]  = "while executing command";
const char whiles[]  = "while setting up for execution";

void explain_ccode( 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 );
    }

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

void execcmd( char *cmd )
    {
    /* remove white space from beginning of command */
    
    while ( *cmd <= ' ' )
        ++cmd;

    /* convert to iRMX HI string format */
        
    udistr( cmd, cmd );
    
    /* remove white space from end of command */
    
    while ( ( cmd[0] != 0 ) && ( cmd[cmd[0]] <= ' ' ) )
        --cmd[0];

    /* skip submission to iRMX HI if now null command */
    
    if ( cmd[0] == 0 )
        return;
        
    /* otherwise, submit command for execution and process its return code */
    
    RQCSENDCOMMAND( cmd_tkn, cmd, &cmd_status, &status );

    if ( ( status != E_OK ) && ( status != E_CONTINUED ) )
        {
        explain_ccode( status, whilel );
        exit( status );
        }

    if ( cmd_status != E_OK )
        explain_ccode( cmd_status, whilee );
    }
                    
/****************************************************************************/
/* execcmds - executes command(s)                                           */
/****************************************************************************/

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

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

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

int main( int argc, char *argv[] )
    {
    if ( argc < 3 )
        {
        puts( "DAILY: Daily command execution facility\n" );
        puts( "USE: \"daily 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( status, whiles );
        exit( status );
        }

    strcpy( command, argv[2] );

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

    end = ((U32)hour * 3600L) + ((U32)minute * 60L) + (U32)second;
    start = RQGETTIME( &status ) % 86400L;

    if ( start > end )
        timeout = 86400L + end - start;
    else
        timeout = end - start;

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

            RQSLEEP( rmx_timeout, &status );
            }

        start = RQGETTIME( &status ) % 86400L;
        execcmds( command );
        end = RQGETTIME( &status ) % 86400L;
        timeout = 86400L + end - start;
        }
    }
