/**********************************************************************
**
** invoke.c - invokes processes on both the local and remote machines.
**		Invoke currently uses only the system utility 'rsh'
**		for remote processes.
**
**********************************************************************/

/*
 * $Log: invoke.c,v $
 * Revision 1.9  1992/01/30  19:34:14  jplevyak
 * Change cray to _ARCH_CRAY (using new arch.h file)
 *
 * Revision 1.8  1991/11/05  22:17:02  sreedhar
 * no change again
 *
 * Revision 1.7  1991/11/04  22:39:14  jefft
 * NOW invokeProcess() returns process ID.  I don't know what happened
 * to the original changes.
 *
 * Revision 1.6  1991/11/04  17:27:11  sreedhar
 * no change
 *
 * Revision 1.5  1991/11/04  17:21:51  jefft
 * invokeProcess() now returns process ID.
 *
 * Revision 1.4  91/10/30  22:47:06  sreedhar
 * setenv for convex
 * 
 * Revision 1.3  1991/10/30  22:09:45  jplevyak
 * Use dtm.h instead of dtmnserv.h as source of environment variable
 * names.
 *
 * Revision 1.2  1991/10/29  17:18:02  jplevyak
 * Added a quiet mode, modified to use remsh on the cray.... we may
 * have to add this for other machines.
 *
 * Revision 1.1  1991/10/11  23:16:03  jefft
 * Initial revision
 *
 */

#include	<stdio.h>
#include	<string.h>
#include	<pwd.h>
#include	<signal.h>
#include	<dtm.h>

#include	"agents.h"

extern	int	quietMode;

static char	serveraddr[256] = "";
static char	defaultname[16];


/* WARNING - the following routine does not find a hostname match */
/* 		when the domain name is optionally included or excluded. */
static void get_user_name(remote, name)
  char	*remote;
  char	*name;
{
  char	line[256];
  char	*cptr;

  struct passwd	*pwd_ent;
  register FILE	*fp;


  /* get passwd entry using process uid */
  setpwent();
  if ((pwd_ent = getpwuid((int)getuid())) == (struct passwd *) NULL) {
    fprintf(stderr,"error: couldn't get passwd entry\n");
    exit(1);
    }
  endpwent();

  /* get home directory of user and append rhost */
  strcpy(line,pwd_ent->pw_dir);
  strcat(line,"/.rhosts");

  /* open user's ".rhosts" file */
  if ((fp = fopen(line, "r")) == NULL) {
    fprintf(stderr, "Error: could not open %s file.\n", line);
    strcpy(name, defaultname);		/* use default name */
    return;
    }

  /* read ".rhosts" file and process it i.e. get user name and host*/
  while (fgets(line, sizeof line, fp) != NULL)

    if (strncasecmp(line, remote, strlen(remote)))
      continue;

    else  {
      strtok(line, " \t\n");
      if ((cptr = strtok(NULL, " \t\n")) != NULL)
        strcpy(name, cptr);
      else
        strcpy(name, defaultname);
      return;
      }

  strcpy(name, defaultname);
}



static int invoke_remote(refname, machine, path, args)
  char	*refname, *machine, *path, *args;
{
  int	pid;
  char	name[16];
  char	cmd[256];

  get_user_name(machine, name);

  switch(pid = fork())  {

    /* error */
    case -1:
      return -1;

    /* child process */
    case 0:
      if (args == NULL)
        sprintf(cmd, "setenv %s %s ; setenv %s %s ; %s ", DTM_NAMESERVER,
          serveraddr, DTM_REFNAME, refname, path);
      else
        sprintf(cmd, "setenv %s %s ; setenv %s %s ; %s %s", DTM_NAMESERVER,
          serveraddr, DTM_REFNAME, refname, path, args);

#if !defined(_ARCH_CRAY)
      execlp("rsh", "rsh", machine, "-l", name, cmd, (char *)0);
#else
      execlp("remsh", "remsh", machine, "-l", name, cmd, (char *)0);
#endif

    default:
      break;
    }

  return pid;
}


/* machine variable is ignored in this case */
static int invoke_local(refname, machine, path, args)
  char	*refname, *machine, *path, *args;
{
  int	pid;
  char	env1[64], env2[64];


  switch(pid = fork())  {

    /* error */
    case -1:
      return -1;

    /* child process */
    case 0:
      strcpy(env1, DTM_NAMESERVER);
      strcat(env1, "=");
      strcat(env1, serveraddr);
#if defined(_CONVEX_SOURCE)
	setenv( DTM_NAMESERVER, serveraddr, 1 );
#else
      putenv(env1);
#endif

      strcpy(env2, DTM_REFNAME);
      strcat(env2, "=");
      strcat(env2, refname);
#if defined(_CONVEX_SOURCE)
	setenv( DTM_REFNAME, refname, 1 );
#else
      putenv(env2);
#endif

      if (args == NULL)
        execlp(path, path, (char *)0);
      else  {
        char	*arglist[32];
        int	argc = 0;

        arglist[argc++] = path;
        arglist[argc++] = strtok(args, " \t\n");
        while ((arglist[argc++] = strtok(NULL, " \t\n")) != NULL);
          ;

        execvp(path, arglist);
        }

    /* parent process */
    default:
      break;
    }
  return pid;
}


int invoke(refname, path, args) 
  char	*refname, *path, *args;
{
  int	pid;
  char *colon;

  if (strlen(serveraddr) == 0)  {
    fprintf(stderr, "Error: server address has not been initialized.\n");
    return -1;
    }

  if ((colon = strchr(path, ':')) == NULL)  {
    return invoke_local(refname, NULL, path, args);
    }

  else  {
    *colon = '\0';
    pid = invoke_remote(refname, path, colon+1, args);
    *colon = ':';
    return pid;
    }
}


int invokeProcess(refname, agent)
  char	*refname, *agent;
{
  AGENT	*ptr;

  if (!quietMode)
    fprintf(stderr, "invoking agent: '%s' refname = '%s', ", agent, refname);

  if ((ptr = findAgent(agent)) == NULL)  {
    fprintf(stderr, "Error: unknown agent = '%s'\n", agent);
    return -1;
    }

  if (!quietMode)
    fprintf(stderr, "exec = '%s %s'\n", ptr->path, ptr->args);

  return invoke(refname, ptr->path, ptr->args);
}


initServerAddr(addr)
  char  *addr;
{
  struct passwd *pwd_ent;

#ifdef  NONO
  /* get passwd entry using process uid */
  setpwent();
  if ((pwd_ent = getpwuid((int)getuid())) == (struct passwd *) NULL) {
    fprintf(stderr,"error: couldn't get passwd entry\n");
    exit(1);
    }
  endpwent();
  strcpy(defaultname, pwd_ent->pw_name);
#endif

  strcpy(serveraddr, addr);
  if ( !quietMode )
    fprintf( stdout, "serveraddr is '%s'\n", serveraddr );

}
