Changeset - 7b322e60270c
[Not reviewed]
default
0 2 0
Nathan Brink (binki) - 17 years ago 2009-03-16 23:11:35
ohnobinki@ohnopublishing.net
a few polishes to execio

maybe we're ready to start working on:
common configfile setup
and then remoteio, which uses the configfile
2 files changed with 33 insertions and 5 deletions:
0 comments (0 inline, 0 general)
src/common/execio.c
Show inline comments
 
@@ -5,48 +5,49 @@
 

	
 
  DistRen is free software: you can redistribute it and/or modify
 
  it under the terms of the GNU Affero General Public License as published by
 
  the Free Software Foundation, either version 3 of the License, or
 
  (at your option) any later version.
 

	
 
  DistRen is distributed in the hope that it will be useful,
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  GNU Affero General Public License for more details.
 

	
 
  You should have received a copy of the GNU Affero General Public License
 
  along with DistRen.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#include "execio.h"
 

	
 
#include <unistd.h>
 
#include <sys/types.h>
 
#include <sys/wait.h>
 
#include <signal.h>
 
#include <malloc.h>
 
#include <fcntl.h>
 
#include <stdio.h>
 
#include <errno.h>
 

	
 
int execio_open(struct execio **rem, const char *progname, char *const argv[])
 
{
 
  /* pipe used to write to child */
 
  int pipe_write[2];
 
  /* pipe used to read from child */
 
  int pipe_read[2];
 

	
 
  pid_t child;
 

	
 
  /* for wait(2) if needed */
 
  int childstatus;
 
  
 
  int counter;
 
  int counter2;
 
  int maxfds;
 

	
 
  /* create two pipes to facilitate communication with child */
 
  if(pipe(pipe_write))
 
    return 1;
 
  if(pipe(pipe_read))
 
    {
 
      close(pipe_write[0]);
 
      close(pipe_write[1]);
 
@@ -161,56 +162,78 @@ int _execio_checkpid(struct execio *eio)
 

	
 

	
 
int execio_read(struct execio *eio, void *buf, size_t len, size_t *bytesread)
 
{
 
  /*
 
    TODO: detect NULL eio? 
 
    TODO: errno?
 
    update status of eio for execio_status/to be able to cleanup subproc??
 

	
 
    whenever read() returns 0, it means EOF
 
   */
 
  (*bytesread) = read(eio->pipe_read, buf, len);
 
  if(!*bytesread)
 
    {
 
      /* should also be able to figure out if is bad fd and should set EXECIO_STATE_ERROR instead of _EOF */
 
      eio->state = EXECIO_STATE_EOF;
 
      return 1;
 
    }
 

	
 
  return 0;
 
}
 

	
 
int execio_write(struct execio *eio, void *buf, size_t len, size_t *bytesread)
 
{
 
  /*
 
    TODO: errno handling
 
   */
 
  errno = 0;
 
  (*bytesread) = write(eio->pipe_write, buf, len);
 
  if(!*bytesread)
 
    {
 
      switch(errno)
 
	{
 
	case EPIPE:
 
	  /* 
 
	     the program closed the pipe (died)
 
	  */
 
	fprintf(stderr, "execio_write: the child program closed its stdin pipe\n");
 
	eio->state = EXECIO_STATE_EOF;
 
	break;
 
	
 
	default:
 
	  fprintf(stderr, "execio_write: unhandled error writing to an fd: \n");
 
	  perror("write");
 
    eio->state = EXECIO_STATE_ERROR;
 
	  break;
 
	  
 
	}
 
      
 
      return 1;
 
    }
 

	
 
  return 0;
 
}
 

	
 

	
 
enum execio_state execio_state(struct execio *eio)
 
{
 
  return eio->state;
 
}
 

	
 

	
 
int execio_close(struct execio *eio)
 
{
 
  int childstatus;
 

	
 
  close(eio->pipe_read);
 
  close(eio->pipe_write);
 

	
 
  /* maybe we should just kill the child */
 
  kill(eio->child, SIGTERM);
 
  /* the waitpid(2) seems to indicate that only when the child is terminated will this wait return. */
 
  /* 
 
     the waitpid(2) seems to indicate that only when the child is terminated will this wait return. 
 
     This are of code will probably need improving - the ability to seng SIGKILL after a timeout? So we'll output a debug line before running waitpid
 
  */
 
  fprintf(stderr, "execio_close: running waitpid\n");
 
  waitpid(eio->child, &childstatus, 0);
 
  
 
  return 0;
 
}
 

	
src/common/execio.h
Show inline comments
 
@@ -36,31 +36,36 @@ enum execio_state
 
struct execio
 
{
 
  int pipe_write;
 
  int pipe_read;
 

	
 
  enum execio_state state;
 

	
 
  pid_t child;
 
};
 

	
 
/*
 
  runs progname with the arguments in argv. argv must be null terminated!!!!!!!!!
 

	
 
  returns nonzero return on error
 
*/
 
int execio_open(struct execio **rem, const char *progname, char *const argv[]);
 

	
 
/*
 
   doesn't block,
 
   returns 0 on success, 1 on failure
 
*/
 
int execio_read(struct execio *eio, void *buf, size_t len, size_t *bytesread);
 
int execio_write(struct execio *eio, void *buf, size_t len, size_t *bytesread);
 

	
 
/*
 
  use this function to determine if the using program should keep trying to read/write
 
 */
 
enum execio_state execio_state(struct execio *eio);
 

	
 
/* nonzero return on error */
 
/* 
 
   nonzero return on error 
 
*/
 
int execio_close(struct execio *eio);
 

	
 
#endif
 

	
0 comments (0 inline, 0 general)