/* system.c */

#include "ml.h"

#include <pwd.h>
#include <signal.h>
#include <sys/wait.h>

int kid_is_dead;

/*
 *  Signal handlers. You might have to fix these to get it to compile... 
 *  seems it's a different declaration on every system...
 */


#ifdef __STDC__
void dead_kid(int sig)
#else
void dead_kid(sig)
     int sig;
#endif
{
  kid_is_dead = 1;
  return;
}


/* Returns the local hostname, qualified, and lowercased */

#ifdef __STDC__
char *get_qualified_local_host_name(void)
#else
char *get_qualified_local_host_name()
#endif
{
  char host_buffer[MAXHOSTNAMELEN + 1];
  struct hostent *hent;
  char *output = NULL;
  
  host_buffer[0] = NUL_TERM;

  if((gethostname(host_buffer,MAXHOSTNAMELEN + 1)) != SYSCALL_SUCCESS)
      return((char *) NULL);

  if((hent = gethostbyname(host_buffer)) == (struct hostent *) NULL)
    output = cpystr(host_buffer);
  else
    output = cpystr((char *)hent->h_name);

  (void) lcase(output);
  return((char *) output);
}

#ifdef __STDC__
char *get_qualified_host_name(char *host)
#else
char *get_qualified_host_name(host)
     char *host;
#endif
{
  struct hostent *hent;
  char *ret = NULL;

  if(host == NULL)
    return(ret);
  if(*host == NUL_TERM)
    return(cpystr(host));

  if((hent = gethostbyname(host)) == NULL)
    ret = cpystr(host);
  else
    ret = cpystr((char *)hent->h_name);

  (void) lcase(ret);
  return((char *) ret);
}

/*
 * Fill in the local_auth global structure.
 */

#ifdef __STDC__
int get_user(void)
#else
int get_user()
#endif
{
  char *ptr;
  struct passwd *pw = getpwuid(getuid());
  if(pw == NULL)
    return(SYSCALL_FAILURE);

  if((local_auth.hostname = get_qualified_local_host_name()) == NULL)
    local_auth.hostname = cpystr(EMPTYSTR);
  local_auth.username = cpystr((pw->pw_name) ? pw->pw_name : EMPTYSTR);
  local_auth.homedir  = cpystr((pw->pw_dir) ? pw->pw_dir : EMPTYSTR);
  local_auth.shell    = cpystr((pw->pw_shell) ? pw->pw_shell : EMPTYSTR);
  local_auth.fullname = cpystr((pw->pw_gecos) ? pw->pw_gecos : EMPTYSTR);

  /* strip off office and phone info */

  if((ptr = strchr(local_auth.fullname,',')) != NULL)
    *ptr = NUL_TERM;

  return(SYSCALL_SUCCESS);
}


#ifdef __STDC__
int write_to_pipe(char * command, char *intro, char *str, 
	       unsigned long length)
#else
int write_to_pipe(command, intro, str, length)
     char *command;
     char *intro;
     char *str;
     unsigned long length;
#endif
{
  FILE *pp = NULL;
  FILE *tmpfp = NULL;
  char logbuff[FILEBUFFLEN];
  Boolean to_stdout = TRUE;
  char *tmp_filename = NULL;
  char *tmp_command = NULL;

  unsigned long bytes_written = 0L;
  int errors = 0;
  int pid;

  kid_is_dead = 0;


  /* Nothing to do. Not an error. */

  if(! command)
    return(SYSCALL_SUCCESS);

  (void) signal(SIGCHLD, dead_kid);

  if((ML_Strstr(command,"%s")) == NULL) {
    to_stdout = TRUE ;
  }
  else {
    to_stdout = FALSE;
    tmp_filename = tmpnam(NULL);
  }

  if(to_stdout) {
    tmp_command = (char *) fs_get(strlen(command) + 32);
    strcpy(tmp_command,command);

    if(! silent_pipe) {
      sprintf(logbuff,MLGetLocalized(XtNmsgExecuting,MsgExecuting)
	      ,tmp_command);
      mm_log(logbuff,NIL);
    }

    pid = fork();

    if(pid == (-1)) {
      mm_log(MLGetLocalized(XtNmsgSubProcessFailure,MsgSubProcessFailure),
	     WARN);
      return(SYSCALL_FAILURE);
    }

    
    if(pid == 0) {
      
      pp = popen(tmp_command,"w");
      if(pp) {
	if(intro) {
	  if((fwrite(intro,strlen(intro),1,pp)) != 1) 
	    errors ++;
	  if((fputs(LFSTR,pp)) == EOF) 
	    errors ++;
	}
	if(str) 
	  bytes_written = fwrite(str,1,length,pp);
	if(pclose(pp))
	  errors ++;
      }
      else
	errors ++;
      
      if((str) && (bytes_written != length)) 
	errors ++;
      exit(0);
    }

    if(pid != 0) {

      modal_main_loop(&kid_is_dead);
      waitpid(pid,NULL,0);
      (void) signal(SIGCHLD, SIG_DFL);
      
      fs_give((void **) &tmp_command);
      return((errors) ? SYSCALL_FAILURE : SYSCALL_SUCCESS);
    }
  }

  /*
   * If we've gotten to here, we're writing to a temp file
   */

  if((tmpfp = fopen(tmp_filename,"w")) != NULL) {
    (void) chmod(tmp_filename,S_IRWXU);  /* for privacy, ignore failure */
    if(intro) {
      if((fwrite(intro,strlen(intro),1,tmpfp)) != 1)
	errors ++;
      if((fputs(LFSTR,tmpfp)) == EOF)
	errors ++;
    }
    
    if(str)
      bytes_written = fwrite(str,1,length,tmpfp);
    if(fclose(tmpfp))
      errors ++;
    if((str) && (bytes_written != length))
      errors ++;
  }
  else
    errors ++;
  
  if(! errors) {
    tmp_command = 
      (char *) fs_get(strlen(command) + strlen(tmp_filename) + 32); 
    /* 
     *  Caller beware! Only one %s format arg used, and most 
     *  likely the user supplied this command string!
     */

      sprintf(tmp_command,command,tmp_filename);

    if(! silent_pipe) {
      sprintf(logbuff,MLGetLocalized(XtNmsgExecuting,MsgExecuting),
	      tmp_command);
      mm_log(logbuff,NIL);
    }
    
    pid = fork();
    
    if(pid == (-1)) {
      mm_log(MLGetLocalized(XtNmsgSubProcessFailure,MsgSubProcessFailure),
	     WARN);
      return(SYSCALL_FAILURE);
    }
    
    if(pid == 0) {
      
      pp = popen(tmp_command,"w");
      if(pp != NULL) {
	if(pclose(pp))
	  errors ++;
      }
      else
	errors ++;
      exit(0);
    }
      
    if(pid) {
      
      modal_main_loop(&kid_is_dead);
      waitpid(pid,NULL,0);
      (void) signal(SIGCHLD, SIG_DFL);
      
      if(tmp_filename) 
	unlink(tmp_filename);
      
      if(tmp_command)
	fs_give((void **) &tmp_command);
      
      return((errors) ? SYSCALL_FAILURE : SYSCALL_SUCCESS);
    }
  }
  return((errors) ? SYSCALL_FAILURE : SYSCALL_SUCCESS);
}

#ifdef __STDC__
Binary_Buffer *read_from_pipe(char *command)
#else
Binary_Buffer *read_from_pipe(command)
     char *command;
#endif
{

  Binary_Buffer *binary_buffer = NULL;

  FILE *pp = NULL;
  char logbuff[FILEBUFFLEN];
  Boolean from_stdin = TRUE;
  char *tmp_filename = NULL;
  char *tmp_command = NULL;
  int pid;
  int errors = 0;
  kid_is_dead = 0;

  if(! command)
    return(NULL);

  (void) signal(SIGCHLD, dead_kid);


  if((ML_Strstr(command,"%s")) == NULL) {
    from_stdin = TRUE ;
  }
  else {
    from_stdin = FALSE;
    tmp_filename = tmpnam(NULL);
  }

  if(! from_stdin) {

    tmp_command  = 
      (char *) fs_get(strlen(command) + strlen(tmp_filename) + 32);

    sprintf(tmp_command,command,tmp_filename);

    if(! silent_pipe) {
      sprintf(logbuff,MLGetLocalized(XtNmsgExecuting,MsgExecuting),
	      tmp_command);
      mm_log(logbuff,NIL);
    }

    pid = fork();
    
    if(pid == (-1)) {
      mm_log(MLGetLocalized(XtNmsgSubProcessFailure,MsgSubProcessFailure),
	     WARN);
      return(NULL);
    }
    
    if(pid == 0) {
      
      if((pp = popen(tmp_command,"r")) != NULL) {
	(void) chmod(tmp_filename,S_IRWXU);  /* for privacy, ignore failure */
	if(pclose(pp))
	  errors ++;
      }
      else
	errors ++;
      exit(0);

    }

    if(pid) {
      
      modal_main_loop(&kid_is_dead);
      waitpid(pid,NULL,0);
      (void) signal(SIGCHLD, SIG_DFL);
      
      if(! errors) 
	binary_buffer = load_binary_file(tmp_filename);
  
      if(tmp_filename) 
	unlink(tmp_filename);

      if(tmp_command)
	fs_give((void **) &tmp_command);

    }
  }
  
  return(binary_buffer);
}



syntax highlighted by Code2HTML, v. 0.9.1