main.c++ 5.89 KB

//////////////////////////////////////////////////////////////////////
// This is a driver ViewKit program generated by RapidApp 1.1 

//
// This program instantiates a ViewKit VkApp object and creates
// any main window objects that are meant to be shown at startup.
// There should rarely be a reason to modify this file.
// Make application-specific changes in the classes created
// by the main window classes
// Some applications may wish to change this code to instantiate
// a different application class, however.
//////////////////////////////////////////////////////////////////////


#include <stdio.h>     
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <sys/procfs.h> 
#include <fcntl.h>
#include <paths.h>
#include <unistd.h>
#include <errno.h>

#include "MidiMain.h"
#include "AeN64Driver.h"
#include "AeTypes.h"
#include <sys/u64gio.h>

extern void AeMainProc (void *);

static char isAppRunning (char *);
static void parseArgs (int, char **);
static void finiDriver (void);
static void initSignals (void);
static void initSubProcesses (void);
static void mySigHandler (int signo);


int		gArgc;
char **		gArgv;
int		midiPID;
int		aePID;
int             gloadPID;
int		parentPID;
int		parentDie = 0;
char		verbose = False;

char *		bankFileName = NULL;
char *		cFileName = NULL;
AeN64Driver *	n64Driver = NULL;



void main (int argc, char **argv)
{
    struct sigaction sigAct;

    gArgc = argc;
    gArgv = argv;
    
    // Check to see if there is another copy of AudioEditor already running
    if (isAppRunning (argv[0]))
    {
        fprintf (stdout,"%s is already running, will exit\n", argv[0]);
        exit(-1);
    }

    parseArgs (argc, argv);

    initSignals ();
    initSubProcesses ();

    while (!parentDie)
	sleep (0x7FFFFFF);

    finiDriver ();
}



void
parseArgs (int argc, char ** argv)
{
    int c;

    while ((c = getopt(argc, argv, "vb:c:")) != EOF)
    {
        switch (c) 
        {
            case 'v':
                verbose = True;
                break;
            case 'c':
                cFileName = optarg;
                break;
            case 'b':
                bankFileName = optarg;
                break;
            case '?':
                fprintf(stdout,"Usage [-b <.inst file] [-c <.cnfg file>] [-v]\n");
		fprintf(stdout,"-v verbose (debugging)\n-b .inst file\n-c configuration file\n");
                exit(0);
                break;
        }
    }
}


void
finiDriver (void)
{
    if (n64Driver)
	delete n64Driver;	// to to free the n64 device
}


//
// Setup the signal handling which is needed
// to handle subprocesses.
//
static void
initSignals (void)
{
    struct sigaction sigAct;

    sigAct.sa_handler = (void(*)(...))mySigHandler;
    sigemptyset (&sigAct.sa_mask);
    sigAct.sa_flags = 0;

    if(sigaction(SIGCHLD,&sigAct,NULL) < 0)
    {
        perror("Unable to install signal handler SIGCHLD");
        exit(-1);
    }

    if(sigaction(SIGINT,&sigAct,NULL) < 0)
    {
        perror("Unable to install signal handler SIGINT");
        exit(-1);
    }

    if(sigaction(SIGTERM,&sigAct,NULL) < 0)
    {
        perror("Unable to install signal handler SIGTERM");
        exit(-1);
    }

    if(sigaction(SIGQUIT,&sigAct,NULL) < 0)
    {
        perror("Unable to install signal handler SIGQUIT");
        exit(-1);
    }
}

void runGload(void * arg)
{
    (void)execlp("gload", "gload", "-n", 0);	// never returns unless failure
}


void
initSubProcesses (void)
{
    parentPID = getpid();
    int         tmpFD;

    aePID = sproc(AeMainProc, PR_SALL, NULL);
    if(aePID < 0)
    {
	fprintf (stdout, "error: ie: unable to start main thread, will exit\n");
	exit(-1);
    }

    midiPID = sproc(midiMain, PR_SALL, NULL);
    if(midiPID < 0)
    {
	fprintf (stdout, "error: ie: unable to start midi thread, will exit\n");
	exit(-1);
    }

    tmpFD = open( DEV_U64_PRINT, O_RDWR);
    if(tmpFD == -1 && errno != EBUSY)
    {
	if(errno != ENOENT) /* ENOENT indicates that there is no dev system board */
	{
	    fprintf(stderr,"error: ie: unable to open DEV_U64_PRINT, errno = %d, will exit\n", errno);
	    exit(-1);
	}
	if(verbose)
	    fprintf(stderr,"debug: ie: no dev board found on this system\n");
    }
    else
    {
	if(tmpFD != -1)
	    close(tmpFD);
	gloadPID = sproc(runGload, PR_SALL, NULL);
	if(gloadPID < 0)
	{
	    fprintf (stdout, "error: ie: unable to start gload thread, will exit\n");
	    exit(-1);
	}
    }
}


static char
isAppRunning (char *appname)
{
    DIR             *dirp;      /* Directory pointer */
    struct direct   *dp;        /* Directory entry */
    char            pbuf[PATH_MAX]; /* Buffer for procfs file name */
    int             pfd;        /* Process file descriptor */
    prpsinfo_t      psinfo;     /* Process information */
    char            found = 0;  /* Flag indicating that we found a match */
    pid_t           mypid;      /* My Process ID */

    /* Open the process info directory */
    if ((dirp = opendir(_PATH_PROCFSPI)) == NULL)
        return True;

    mypid = getpid();

    /* Iterate through all of the files in the directory */
    while ((dp = readdir(dirp)) != NULL && !found)
    {
        /* We don't care about ourselves */
        if (mypid == atoi(dp->d_name))
            continue;

        /* Open the actual process file */
        strcpy(pbuf, _PATH_PROCFSPI);
        strcat(pbuf, dp->d_name);
        if ((pfd = open(pbuf, O_RDONLY)) < 0)
            continue;

        /* Try and retrieve the process info */
        if (ioctl(pfd, PIOCPSINFO, &psinfo) == -1)
        {
            close(pfd);
            continue;
        }

        close(pfd);

        if (strcmp(appname, psinfo.pr_fname) == 0)
            found = psinfo.pr_pid;
    }

    closedir(dirp);
    return found;
}


static void
mySigHandler (int signo)
{
    kill (midiPID, SIGKILL);
    kill (aePID, SIGKILL);
    kill (gloadPID, SIGKILL);

    parentDie = 1;
}