
static char rcsid[]="$Id: test_drvr.c,v 2.0 1997/06/16 04:37:37 jzbiciak Exp $";

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>

#undef TEST
#define TEST 1

#include "wrapper.h"

#define BIG_NUMBER (65535)/* Use this many chars in a super long string */
#define MAX_ENV_CNT (32)  /* Max number of environment vars to create   */
#define MAX_ARG_CNT ARG_MAXCNT+2 


FILE * test_log;  /* All test results, plus stdout/stderr go here.      */
int  t_log; 
char * test_path; /* Prog to exec. */
char buf[BIG_NUMBER+1];
char *test_envp[MAX_ENV_CNT];
char *test_argv[MAX_ARG_CNT];

void disp_retcode(int status);


/* DO_EXECVE -- Displays the execve() being performed, and performs it  */
/*              in a child process.  Returns the exit code of child.    */

int do_execve(char * path, char *argv[], char *envp[])
{
    pid_t child;
    pid_t waited;
    int status;

    if (strlen(argv[0])>32)
        fprintf(test_log,"execve(%s, argv[0]=%.32s...)\n", path, argv[0]);
    else
        fprintf(test_log,"execve(%s, argv[0]=%s)\n", path, argv[0]);

    fflush(test_log);    

    if ((child=fork())!=0)
    {
        while ((waited=wait(&status))!=child)
            sleep(1);

        if (WIFSTOPPED(status))
        {
            fprintf(test_log,"Child has unexpectedly stopped! Aborting!\n");
            kill(child,SIGKILL);
            exit(1);
        }
        
        return status;
    } else
    {
	dup2(t_log,1);  /* replace stdout */
	dup2(t_log,2);  /* replace stderr */
        execve(path, argv, envp);
        perror("execve()");
        exit(69);
    }

    /* NOT REACHED */
    return 0;
}

/* DISP_RETCODE -- Interprets and display's a child's return code.      */
void disp_retcode(int status)
{
    if (WIFEXITED(status))
    {
	if (WEXITSTATUS(status))
    	    fprintf(test_log,"Child exited with status %d\n",WEXITSTATUS(status));
	else
            fprintf(test_log,"Child exited normally.\n");
        return;
    }

    if (WIFSIGNALED(status))
    {
        fprintf(test_log,"Child exited on signal %d\n",WTERMSIG(status));
        return;
    }

    if (WIFSTOPPED(status))
    {
        fprintf(test_log,"Child has stopped on signal %d\n",WSTOPSIG(status));
        return;
    }

    fprintf(test_log,"Child exited abnormally.\n");

    return;
}

/* TEST_ARG0 -- Tests properties of argv[0] checking in the wrapper.    */
int test_arg0(void)
{
    int i,j,r;
    int len[4]={
            0,
                ARG0_MAXLEN-ARG0_BASELEN,
                ARG0_MAXLEN,
                BIG_NUMBER-ARG0_BASELEN-1,
           };

    for (j=0;j<4;j++)
    {

        fprintf(test_log,
		len[j]==0?"Testing valid arg0 basenames without preceding paths\n"
                         :"Testing valid arg0 basenames with %d char preceding paths\n",
                len[j]);

        if (len[j])
        {
            buf[0]='.';
            for (i=1;i<len[j];i++) 
                buf[i]='/';
        }

        for (i=0;wrap_profile[i].base_name;i++)
        {
	    strcpy(buf+len[j],wrap_profile[i].base_name);
            test_argv[0]=buf;
            test_argv[1]=NULL;
            test_envp[0]=NULL;
            fprintf(test_log,"---Basename='%s'  Tot arg0 len=%d\n",
			wrap_profile[i].base_name,
			len[j]+strlen(wrap_profile[i].base_name));
            r=do_execve(test_path,test_argv,test_envp);
            disp_retcode(r);
            fprintf(test_log,"---\n\n");
        }
    }

    for (j=0;j<4;j++)
    {

        fprintf(test_log,
		"Testing %d char, invalid arg0 basenames without preceding paths\n",
                len[j]);

        for (i=0;i<len[j];i++) 
            buf[i]='%';

	buf[len[j]]=0;

        test_argv[0]=buf;
        test_argv[1]=NULL;
        test_envp[0]=NULL;
        fprintf(test_log,"---Tot arg0 len=%d\n",len[j]);
        r=do_execve(test_path,test_argv,test_envp);
        disp_retcode(r);
        fprintf(test_log,"---\n\n");
    } 

    for (j=1;j<4;j+=2)
    {
	fprintf(test_log,
		"Testing %d char basenames with %d remapped chars, no prec. paths\n",
		ARG0_BASELEN-1, j);

	for (i=0;i<ARG0_BASELEN-1;i++)
	    buf[i]='%';
	for (i=0;i<j;i++)
	    buf[i]=1;

	buf[ARG0_BASELEN-1]=0;

        test_argv[0]=buf;
        test_argv[1]=NULL;
        test_envp[0]=NULL;
        fprintf(test_log,"---Tot arg0 len=%d\n",len[j]);
        r=do_execve(test_path,test_argv,test_envp);
        disp_retcode(r);
        fprintf(test_log,"---\n\n");
    }

    return 0;
}



int main(int argc, char *argv[])
{
    int err;

    if (argc!=2 && argc!=3)
    {
	fprintf(stderr,"Usage: test_drvr program_to_invoke [logfile_to_append_to]\n");
	exit(1);
    }

    if (argc==3)
    {
	t_log=open(argv[2],O_CREAT|O_APPEND|O_WRONLY,0600);

	if (!t_log)
	{
	    perror("Unable to open logfile -- open()");
	    exit(1);
	}

	test_log=fdopen(t_log,"a");

	if (!test_log)
	{
	    perror("Unable to open logfile -- fdopen()");
	    exit(1);
	}
    } else
    {
	t_log=1;
	test_log=stdout;
    }

    test_path=argv[1];


    if ((err=test_arg0())!=0)
	fprintf(stderr,"Error %d running arg0 test.\n",err);


    return 0;
}
