/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                              R U N P R O G . C                               *
*                                                                              *
*                 Copyright (c) Joerg-R. Hill, October 2003                    *
*                                                                              *
********************************************************************************
*
* $Id: runprog.c,v 1.6 2003/11/07 11:15:10 jrh Exp $
* $Log: runprog.c,v $
* Revision 1.6  2003/11/07 11:15:10  jrh
* Release 2.4
*
* Revision 1.5  2000/12/10 15:16:14  jrh
* Release 2.3
*
* Revision 1.4  1999/05/24 01:27:33  jrh
* Release 2.2.1
*
* Revision 1.3  1999/02/07 21:56:33  jrh
* Release 2.2
*
* Revision 1.2  1998/01/26 00:49:27  jrh
* Release 2.1
*
* Revision 1.1  1996/12/10  18:43:53  jrh
* Initial revision
*
*/
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/errno.h>
#include<sys/param.h>
#include<sys/signal.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/utsname.h>
#include<sys/wait.h>

#ifdef _HPUX_SOURCE
#define PATH_MAX MAXPATHLEN
#endif

#define TRUE  1
#define FALSE 0

/* Prototypes */
int runProg(char *, int, char *, char *, char *, pid_t *);

extern void *getmem(size_t, size_t);
extern void fremem(void **);

int runProg(char *command, int wait_for_child, char *input, char *output,
            char *error, pid_t *pid)
{
  int status;
  char *argv[10];
  register int i=0;

  if ((*pid=fork()) < 0)
  {
    fprintf(stderr, "ERROR: Unable to fork: ");
    perror(NULL);
    return(-1);
  }
  else if (*pid == 0)
  {
    if (input != NULL)  freopen(input, "r", stdin);
    if (output != NULL) freopen(output, "w", stdout);
    if (error != NULL)  freopen(error, "w", stderr);
    argv[i++]=strtok(command, " \t");
    while ((argv[i++]=strtok(NULL, " \t")) != NULL);
    argv[i]=NULL;
    if (*command == '\0') exit(-1);
    if (execvp(command, argv))
    {
      fprintf(stderr, "ERROR: Unable to execute %s:", argv[0]);
      perror(NULL);
      exit(-1);
    }
  }
  else
  {
    if (wait_for_child)
    {
      while((wait(&status)) != *pid);
      if (WIFEXITED(status) != 0) return(WEXITSTATUS(status));
    }
    else
      return(0);
  }
  return(-1);
}

int checkFile(char **filename)
{
  static char name1[PATH_MAX], name2[PATH_MAX];
  char *c, *d, *env, *path, *opt;

  strcpy(name1, *filename);
  while ((c=strchr(name1, '$')) != NULL)
  {
    if (*(c+1) == '{')
    {
      d=strchr(c+1, '}');
      *d='\0';
      env=getenv(c+2);
    }
    else
    {
      d=strchr(c+1, '/');
      *d='\0';
      env=getenv(c+1);
    }
    *c='\0';
    strcpy(name2, name1);
    if (env != NULL) strcat(name2, env);
    if (*(c+1) != '{') strcat(name2, "/");
    strcat(name2, d+1);
    strcpy(name1, name2);
  }
  if ((opt=strchr(name1, ' ')) != NULL) *opt='\0';
  if (access(name1, F_OK))
  {
    env=getenv("PATH");
    if (env == NULL)
    {
      *filename=NULL;
      return(FALSE);
    }
    path=(char *)getmem((size_t)strlen(env)+1, sizeof(char));
    strcpy(path, env);
    c=strtok(path, ":");
    strcpy(name2, c);
    strcat(name2, "/");
    strcat(name2, name1);
    if (!access(name2, F_OK))
    {
      *filename=name2;
      if (opt != NULL)
      {
        *opt=' ';
        strcat(name2, opt);
      }
      fremem((void **)&path);
      return(TRUE);
    }
    while ((c=strtok(NULL, ":")) != NULL)
    {
      strcpy(name2, c);
      strcat(name2, "/");
      strcat(name2, name1);
      if (!access(name2, F_OK))
      {
          *filename=name2;
        if (opt != NULL)
        {
          *opt=' ';
          strcat(name2, opt);
        }
        fremem((void **)&path);
          return(TRUE);
      }
    }
    *filename=NULL;
    fremem((void **)&path);
    return(FALSE);
  }
  else
  {
    *filename=name1;
    if (opt != NULL) *opt=' ';
    return(TRUE);
  }
}
