touched up code a little
This commit is contained in:
		@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id: pio.h 243 2009-07-24 04:11:07Z hyunghwan.chung $
 | 
			
		||||
 * $Id: pio.h 244 2009-07-24 12:22:00Z hyunghwan.chung $
 | 
			
		||||
 *
 | 
			
		||||
   Copyright 2006-2009 Chung, Hyung-Hwan.
 | 
			
		||||
 | 
			
		||||
@ -24,22 +24,22 @@
 | 
			
		||||
#include <qse/cmn/tio.h>
 | 
			
		||||
 | 
			
		||||
/** @file 
 | 
			
		||||
 * This file defines a piped interface to a child process. It provides more
 | 
			
		||||
 * advanced interface than popen() and pclose().
 | 
			
		||||
 * This file defines a piped interface to a child process. You can execute
 | 
			
		||||
 * a child process, read and write to its stdin, stdout, stderr, and terminate
 | 
			
		||||
 * it. It provides more advanced interface than popen() and pclose().
 | 
			
		||||
 *
 | 
			
		||||
 * @todo 
 | 
			
		||||
 * - rename flags to option
 | 
			
		||||
 * @example pio.c
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Open flags 
 | 
			
		||||
 * The qse_pio_oflag_t defines enumerators to compose flags to qse_pio_open().
 | 
			
		||||
 */
 | 
			
		||||
enum qse_pio_open_flag_t
 | 
			
		||||
enum qse_pio_oflag_t
 | 
			
		||||
{
 | 
			
		||||
	/** enable text based IO. */
 | 
			
		||||
	/** enable text based I/O. */
 | 
			
		||||
	QSE_PIO_TEXT       = (1 << 0),
 | 
			
		||||
 | 
			
		||||
	/** invoke the command through a system shell 
 | 
			
		||||
	/** execute the command via a system shell 
 | 
			
		||||
	 * (/bin/sh on *nix, cmd.exe on windows) */
 | 
			
		||||
	QSE_PIO_SHELL      = (1 << 1),
 | 
			
		||||
 | 
			
		||||
@ -50,9 +50,9 @@ enum qse_pio_open_flag_t
 | 
			
		||||
	/** read stderr of a child process */
 | 
			
		||||
	QSE_PIO_READERR    = (1 << 10),
 | 
			
		||||
 | 
			
		||||
	/** redirect stderr to stdout(2>&1). require QSE_PIO_READOUT */
 | 
			
		||||
	/** redirect stderr to stdout (2>&1, require QSE_PIO_READOUT) */
 | 
			
		||||
	QSE_PIO_ERRTOOUT   = (1 << 11),	
 | 
			
		||||
	/** redirect stdout to stderr(1>&2). require QSE_PIO_READERR */
 | 
			
		||||
	/** redirect stdout to stderr (1>&2, require QSE_PIO_READERR) */
 | 
			
		||||
	QSE_PIO_OUTTOERR   = (1 << 12),
 | 
			
		||||
 | 
			
		||||
	/** redirect stdin to the null device (</dev/null, <NUL) */
 | 
			
		||||
@ -67,17 +67,26 @@ enum qse_pio_open_flag_t
 | 
			
		||||
	/** drop stdout */
 | 
			
		||||
	QSE_PIO_DROPOUT    = (1 << 17),
 | 
			
		||||
	/** drop stderr */
 | 
			
		||||
	QSE_PIO_DROPERR    = (1 << 18),
 | 
			
		||||
	QSE_PIO_DROPERR    = (1 << 18)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_hid_t type defines pipe IDs established to a child process.
 | 
			
		||||
 */
 | 
			
		||||
enum qse_pio_hid_t
 | 
			
		||||
{
 | 
			
		||||
	QSE_PIO_IN  = 0,
 | 
			
		||||
	QSE_PIO_OUT = 1,
 | 
			
		||||
	QSE_PIO_ERR = 2
 | 
			
		||||
	QSE_PIO_IN  = 0, /**< stdin of a child process */ 
 | 
			
		||||
	QSE_PIO_OUT = 1, /**< stdout of a child process */
 | 
			
		||||
	QSE_PIO_ERR = 2  /**< stderr of a child process */
 | 
			
		||||
};
 | 
			
		||||
typedef enum qse_pio_hid_t qse_pio_hid_t;
 | 
			
		||||
 | 
			
		||||
enum qse_pio_io_flag_t
 | 
			
		||||
/** 
 | 
			
		||||
 * The qse_pio_option_t type defines options to change the behavior of
 | 
			
		||||
 * qse_pio_xxx functions.
 | 
			
		||||
 */
 | 
			
		||||
enum qse_pio_option_t
 | 
			
		||||
{
 | 
			
		||||
	/*QSE_PIO_READ_NOBLOCK   = (1 << 0),*/
 | 
			
		||||
 | 
			
		||||
@ -89,12 +98,16 @@ enum qse_pio_io_flag_t
 | 
			
		||||
	/** do not rewrite if write has been interrupted */
 | 
			
		||||
	QSE_PIO_WRITE_NORETRY  = (1 << 3),
 | 
			
		||||
 | 
			
		||||
	/** return immediately from qse_pio_wait() if a child has not exited */
 | 
			
		||||
	QSE_PIO_WAIT_NOBLOCK   = (1 << 4),
 | 
			
		||||
 | 
			
		||||
	/** do not wait again if waitpid has been interrupted */
 | 
			
		||||
	QSE_PIO_WAIT_NORETRY   = (1 << 5)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_errnum_t type defines error numbers.
 | 
			
		||||
 */
 | 
			
		||||
enum qse_pio_errnum_t
 | 
			
		||||
{
 | 
			
		||||
	QSE_PIO_ENOERR = 0, /**< no error */
 | 
			
		||||
@ -105,21 +118,19 @@ enum qse_pio_errnum_t
 | 
			
		||||
	QSE_PIO_EPIPE,      /**< broken pipe */
 | 
			
		||||
	QSE_PIO_ESUBSYS     /**< subsystem(system call) error */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef enum qse_pio_hid_t qse_pio_hid_t;
 | 
			
		||||
typedef enum qse_pio_errnum_t qse_pio_errnum_t;
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
	/* <winnt.h> => typedef PVOID HANDLE; */
 | 
			
		||||
	typedef void* qse_pio_hnd_t;
 | 
			
		||||
	typedef void* qse_pio_pid_t;
 | 
			
		||||
	typedef void* qse_pio_hnd_t; /**< defines a pipe handle type */
 | 
			
		||||
	typedef void* qse_pio_pid_t; /**< defines a process handle type */
 | 
			
		||||
#	define  QSE_PIO_HND_NIL ((qse_pio_hnd_t)QSE_NULL)
 | 
			
		||||
#	define  QSE_PIO_PID_NIL ((qse_pio_pid_t)QSE_NULL)
 | 
			
		||||
#else
 | 
			
		||||
	typedef int qse_pio_hnd_t;
 | 
			
		||||
	typedef int qse_pio_pid_t;
 | 
			
		||||
	typedef int qse_pio_hnd_t; /**< defines a pipe handle type */
 | 
			
		||||
	typedef int qse_pio_pid_t; /**< defines a process handle type */
 | 
			
		||||
#	define  QSE_PIO_HND_NIL ((qse_pio_hnd_t)-1)
 | 
			
		||||
#	define  QSE_PIO_PID_NIL ((qse_pio_hnd_t)-1)
 | 
			
		||||
#	define  QSE_PIO_PID_NIL ((qse_pio_pid_t)-1)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct qse_pio_t qse_pio_t;
 | 
			
		||||
@ -133,21 +144,26 @@ struct qse_pio_pin_t
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_t type defines a pipe I/O type
 | 
			
		||||
 * The qse_pio_t type defines a structure to store status for piped I/O
 | 
			
		||||
 * to a child process. The qse_pio_xxx() funtions are written around this
 | 
			
		||||
 * type. Do not change the value of each field directly. 
 | 
			
		||||
 */
 | 
			
		||||
struct qse_pio_t
 | 
			
		||||
{
 | 
			
		||||
	QSE_DEFINE_COMMON_FIELDS(pio)
 | 
			
		||||
 | 
			
		||||
	int              flags;
 | 
			
		||||
	qse_pio_errnum_t errnum;
 | 
			
		||||
	qse_pio_pid_t    child;
 | 
			
		||||
	int              option;  /**< options */
 | 
			
		||||
	qse_pio_errnum_t errnum;  /**< error number */
 | 
			
		||||
	qse_pio_pid_t    child;   /**< handle to a child process */
 | 
			
		||||
	qse_pio_pin_t    pin[3];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** access the @a errnum field of the #qse_pio_t structure */
 | 
			
		||||
#define QSE_PIO_ERRNUM(pio)    ((pio)->errnum)
 | 
			
		||||
#define QSE_PIO_FLAGS(pio)      ((pio)->flags)
 | 
			
		||||
/** access the @a option field of the #qse_pio_t structure */
 | 
			
		||||
#define QSE_PIO_OPTION(pio)    ((pio)->option)
 | 
			
		||||
/** access the @a child field of the #qse_pio_t structure */
 | 
			
		||||
#define QSE_PIO_CHILD(pio)     ((pio)->child)
 | 
			
		||||
/** get the native handle from the #qse_pio_t structure */
 | 
			
		||||
#define QSE_PIO_HANDLE(pio,hid) ((pio)->pin[hid].handle)
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
@ -157,188 +173,172 @@ extern "C" {
 | 
			
		||||
QSE_DEFINE_COMMON_FUNCTIONS (pio)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_open() function opens pipes to a child process.
 | 
			
		||||
 * QSE_PIO_SHELL drives the function to execute the command via the default
 | 
			
		||||
 * shell of an underlying system: /bin/sh on *nix, cmd.exe on win32.
 | 
			
		||||
 * If @a flags is clear of QSE_PIO_SHELL, you should pass the full program path.
 | 
			
		||||
 * The qse_pio_open() function executes a command @cmd and establishes
 | 
			
		||||
 * pipes to it. #QSE_PIO_SHELL causes the function to execute @a cmd via 
 | 
			
		||||
 * the default shell of an underlying system: /bin/sh on *nix, cmd.exe on win32.
 | 
			
		||||
 * On *nix systems, a full path to the command is needed if it is not specified.
 | 
			
		||||
 * @return #qse_pio_t object on success, #QSE_NULL on failure
 | 
			
		||||
 */
 | 
			
		||||
qse_pio_t* qse_pio_open (
 | 
			
		||||
	qse_mmgr_t*       mmgr,  /**< a memory manager */
 | 
			
		||||
	qse_mmgr_t*       mmgr,  /**< memory manager */
 | 
			
		||||
	qse_size_t        ext,   /**< extension size */
 | 
			
		||||
	const qse_char_t* cmd,   /**< a command to execute */
 | 
			
		||||
	int               flags  /**< options */
 | 
			
		||||
	const qse_char_t* cmd,   /**< command to execute */
 | 
			
		||||
	int               oflags  /**< 0 or a number OR'ed of the
 | 
			
		||||
	                              #qse_pio_oflag_t enumerators*/
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_close() function closes pipes to a child process.
 | 
			
		||||
 * The qse_pio_close() function closes pipes to a child process and waits for
 | 
			
		||||
 * the child process to exit.
 | 
			
		||||
 */
 | 
			
		||||
void qse_pio_close (
 | 
			
		||||
	qse_pio_t* pio
 | 
			
		||||
	qse_pio_t* pio /**< pio object */
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_init() function initializes pipes to a child process.
 | 
			
		||||
 * The qse_pio_init() functions performs the same task as the qse_pio_open()
 | 
			
		||||
 * except that you need to allocate a #qse_pio_t structure and pass it to the
 | 
			
		||||
 * function.
 | 
			
		||||
 * @return @a pio on success, #QSE_NULL on failure
 | 
			
		||||
 */
 | 
			
		||||
qse_pio_t* qse_pio_init (
 | 
			
		||||
	qse_pio_t*        pio,
 | 
			
		||||
	qse_mmgr_t*       mmgr,
 | 
			
		||||
	const qse_char_t* path,
 | 
			
		||||
	int               flags
 | 
			
		||||
	qse_pio_t*        pio,    /**< pio object */
 | 
			
		||||
	qse_mmgr_t*       mmgr,   /**< memory manager */
 | 
			
		||||
	const qse_char_t* cmd,    /**< command to execute */
 | 
			
		||||
	int               oflags  /**< 0 or a number OR'ed of the
 | 
			
		||||
	                              #qse_pio_oflag_t enumerators*/
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_fini() function finalizes pipes to a child process.
 | 
			
		||||
 * The qse_pio_fini() function performs the same task as qse_pio_close()
 | 
			
		||||
 * except that it does not destroy a #qse_pio_t structure pointed to by @a pio.
 | 
			
		||||
 */
 | 
			
		||||
void qse_pio_fini (
 | 
			
		||||
	qse_pio_t* pio
 | 
			
		||||
	qse_pio_t* pio /**< pio object */
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
int qse_pio_getflags (
 | 
			
		||||
	qse_pio_t* pio
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_getoption() function gets the current option.
 | 
			
		||||
 * @return option number OR'ed of #qse_pio_option_t enumerators
 | 
			
		||||
 */
 | 
			
		||||
int qse_pio_getoption (
 | 
			
		||||
	qse_pio_t* pio    /**< pio object */
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
void qse_pio_setflags (
 | 
			
		||||
	qse_pio_t* pio,
 | 
			
		||||
	int        flags,
 | 
			
		||||
	int        opt
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_setoption() function sets the option.
 | 
			
		||||
 */ 
 | 
			
		||||
void qse_pio_setoption (
 | 
			
		||||
	qse_pio_t* pio, /**< pio object */
 | 
			
		||||
	int        opt  /**< 0 or a number OR'ed of #qse_pio_option_t
 | 
			
		||||
	                     enumerators */
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_geterrnum
 | 
			
		||||
 * NAME
 | 
			
		||||
 *  qse_pio_geterrnum - get an error code
 | 
			
		||||
 *
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_geterrnum() function returns the number of the last error 
 | 
			
		||||
 * occurred. 
 | 
			
		||||
 * @return error number
 | 
			
		||||
 */
 | 
			
		||||
qse_pio_errnum_t qse_pio_geterrnum (
 | 
			
		||||
	qse_pio_t* pio
 | 
			
		||||
	qse_pio_t* pio /**< pio object */
 | 
			
		||||
);
 | 
			
		||||
/******/
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_geterrmsg
 | 
			
		||||
 * NAME
 | 
			
		||||
 *  qse_pio_geterrmsg - transllate an error code to a string
 | 
			
		||||
 *
 | 
			
		||||
 * DESCRIPTION
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_geterrmsg() function returns the pointer to a constant string 
 | 
			
		||||
 * describing the last error occurred.
 | 
			
		||||
 *
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
 * @return error message
 | 
			
		||||
 */
 | 
			
		||||
const qse_char_t* qse_pio_geterrmsg (
 | 
			
		||||
	qse_pio_t* pio
 | 
			
		||||
	qse_pio_t* pio /**< pio object */
 | 
			
		||||
);
 | 
			
		||||
/******/
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_gethandle
 | 
			
		||||
 * NAME
 | 
			
		||||
 *  qse_pio_gethandle - get native handle
 | 
			
		||||
 *
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_gethandle() function gets a pipe handle.
 | 
			
		||||
 * @return pipe handle
 | 
			
		||||
 */
 | 
			
		||||
qse_pio_hnd_t qse_pio_gethandle (
 | 
			
		||||
	qse_pio_t*    pio,
 | 
			
		||||
	qse_pio_hid_t hid
 | 
			
		||||
	qse_pio_t*    pio, /**< pio object */
 | 
			
		||||
	qse_pio_hid_t hid  /**< handle ID */
 | 
			
		||||
);
 | 
			
		||||
/******/
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_getchild
 | 
			
		||||
 * NAME
 | 
			
		||||
 *  qse_pio_getchild - get the PID of a child process
 | 
			
		||||
 *
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_getchild() function gets a process handle.
 | 
			
		||||
 * @return process handle
 | 
			
		||||
 */
 | 
			
		||||
qse_pio_pid_t qse_pio_getchild (
 | 
			
		||||
	qse_pio_t*    pio
 | 
			
		||||
	qse_pio_t*    pio /**< pio object */
 | 
			
		||||
);
 | 
			
		||||
/******/
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_read
 | 
			
		||||
 * NAME
 | 
			
		||||
 *  qse_pio_read - read data
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_read() fucntion reads data.
 | 
			
		||||
 * @return -1 on failure, 0 on EOF, data length read on success
 | 
			
		||||
 */
 | 
			
		||||
qse_ssize_t qse_pio_read (
 | 
			
		||||
	qse_pio_t*    pio,
 | 
			
		||||
	void*         buf,
 | 
			
		||||
	qse_size_t    size,
 | 
			
		||||
	qse_pio_hid_t hid
 | 
			
		||||
	qse_pio_t*    pio,  /**< pio object */
 | 
			
		||||
	void*         buf,  /**< buffer to fill */
 | 
			
		||||
	qse_size_t    size, /**< buffer size */
 | 
			
		||||
	qse_pio_hid_t hid   /**< handle ID */
 | 
			
		||||
);
 | 
			
		||||
/******/
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_write
 | 
			
		||||
 * NAME 
 | 
			
		||||
 *  qse_pio_write - write data
 | 
			
		||||
 * DESCRIPTION
 | 
			
		||||
 *  If the parameter 'size' is zero, qse_pio_write() closes the the writing
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_write() function writes data.
 | 
			
		||||
 * If @a size is zero, qse_pio_write() closes the the writing
 | 
			
		||||
 * stream causing the child process reach the end of the stream.
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
 * @return -1 on failure, data length written on success
 | 
			
		||||
 */
 | 
			
		||||
qse_ssize_t qse_pio_write (
 | 
			
		||||
	qse_pio_t*    pio,
 | 
			
		||||
	const void*   data,
 | 
			
		||||
	qse_size_t    size,
 | 
			
		||||
	qse_pio_hid_t hid
 | 
			
		||||
	qse_pio_t*    pio,   /**< pio object */
 | 
			
		||||
	const void*   data,  /**< data to write */
 | 
			
		||||
	qse_size_t    size,  /**< data size */
 | 
			
		||||
	qse_pio_hid_t hid    /**< handle ID */
 | 
			
		||||
);
 | 
			
		||||
/******/
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_flush
 | 
			
		||||
 * NAME
 | 
			
		||||
 *  qse_pio_flush - flush data
 | 
			
		||||
 *
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_flush() flushes buffered data if #QSE_PIO_TEXT has been 
 | 
			
		||||
 * specified to qse_pio_open() and qse_pio_init().
 | 
			
		||||
 */
 | 
			
		||||
qse_ssize_t qse_pio_flush (
 | 
			
		||||
	qse_pio_t*    pio,
 | 
			
		||||
	qse_pio_hid_t hid
 | 
			
		||||
	qse_pio_t*    pio, /**< pio object */
 | 
			
		||||
	qse_pio_hid_t hid  /**< handle ID */
 | 
			
		||||
);
 | 
			
		||||
/*****/
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_end
 | 
			
		||||
 * NAME
 | 
			
		||||
 *  qse_pio_end - close native handle
 | 
			
		||||
 *
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_end() function closes a pipe to a child process
 | 
			
		||||
 */
 | 
			
		||||
void qse_pio_end (
 | 
			
		||||
	qse_pio_t*    pio,
 | 
			
		||||
	qse_pio_hid_t hid
 | 
			
		||||
	qse_pio_t*    pio, /**< pio object */
 | 
			
		||||
	qse_pio_hid_t hid  /**< handle ID */
 | 
			
		||||
);
 | 
			
		||||
/******/
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_wait
 | 
			
		||||
 * NAME
 | 
			
		||||
 *  qse_pio_wait - wait for a child process 
 | 
			
		||||
 * DESCRIPTION
 | 
			
		||||
 *  QSE_PIO_WAIT_NORETRY causes the function to return an error and set the 
 | 
			
		||||
 *  errnum field to QSE_PIO_EINTR if the underlying system call is interrupted.
 | 
			
		||||
 *
 | 
			
		||||
 *  When QSE_PIO_WAIT_NOBLOCK is used, the return value of 256 indicates that 
 | 
			
		||||
 *  the child process has not terminated. If the flag is not used, 256 is never 
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_wait() function waits for a child process to terminate.
 | 
			
		||||
 * #QSE_PIO_WAIT_NORETRY causes the function to return an error and set the 
 | 
			
		||||
 * @a pio->errnum field to #QSE_PIO_EINTR if the underlying system call has
 | 
			
		||||
 * been interrupted. If #QSE_PIO_WAIT_NOBLOCK is used, the return value of 256
 | 
			
		||||
 * indicates that the child process has not terminated. Otherwise, 256 is never
 | 
			
		||||
 * returned.
 | 
			
		||||
 * RETURN
 | 
			
		||||
 *  -1 on error, 256 if the child is alive and QSE_PIO_NOBLOCK is used,
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *  -1 on error, 256 if the child is alive and #QSE_PIO_WAIT_NOBLOCK is used,
 | 
			
		||||
 *  a number between 0 and 255 inclusive if the child process ends normally,
 | 
			
		||||
 *  256 + signal number if the child process is terminated by a signal.
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
 */
 | 
			
		||||
int qse_pio_wait (
 | 
			
		||||
	qse_pio_t* pio
 | 
			
		||||
	qse_pio_t* pio /**< pio object */
 | 
			
		||||
);
 | 
			
		||||
/******/
 | 
			
		||||
 | 
			
		||||
/****f* Common/qse_pio_kill
 | 
			
		||||
 * NAME
 | 
			
		||||
 *  qse_pio_kill - terminate the child process
 | 
			
		||||
 * NOTES
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_pio_kill() function terminates a child process by force.
 | 
			
		||||
 * You should know the danger of calling this function as the function can
 | 
			
		||||
 * kill a process that is not your child process if it has terminated but
 | 
			
		||||
 * there is a new process with the same process handle.
 | 
			
		||||
 * SYNOPSIS
 | 
			
		||||
 * @return 0 on success, -1 on failure
 | 
			
		||||
 */ 
 | 
			
		||||
int qse_pio_kill (
 | 
			
		||||
	qse_pio_t* pio
 | 
			
		||||
	qse_pio_t* pio /**< pio object */
 | 
			
		||||
);
 | 
			
		||||
/******/
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id: pio.c 242 2009-07-23 13:01:52Z hyunghwan.chung $
 | 
			
		||||
 * $Id: pio.c 244 2009-07-24 12:22:00Z hyunghwan.chung $
 | 
			
		||||
 *
 | 
			
		||||
   Copyright 2006-2009 Chung, Hyung-Hwan.
 | 
			
		||||
 | 
			
		||||
@ -35,8 +35,7 @@ static qse_ssize_t pio_input (int cmd, void* arg, void* buf, qse_size_t size);
 | 
			
		||||
static qse_ssize_t pio_output (int cmd, void* arg, void* buf, qse_size_t size);
 | 
			
		||||
 | 
			
		||||
qse_pio_t* qse_pio_open (
 | 
			
		||||
	qse_mmgr_t* mmgr, qse_size_t ext,
 | 
			
		||||
	const qse_char_t* path, int flags)
 | 
			
		||||
	qse_mmgr_t* mmgr, qse_size_t ext, const qse_char_t* path, int oflags)
 | 
			
		||||
{
 | 
			
		||||
	qse_pio_t* pio;
 | 
			
		||||
 | 
			
		||||
@ -53,7 +52,7 @@ qse_pio_t* qse_pio_open (
 | 
			
		||||
	pio = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_pio_t) + ext);
 | 
			
		||||
	if (pio == QSE_NULL) return QSE_NULL;
 | 
			
		||||
 | 
			
		||||
	if (qse_pio_init (pio, mmgr, path, flags) == QSE_NULL)
 | 
			
		||||
	if (qse_pio_init (pio, mmgr, path, oflags) == QSE_NULL)
 | 
			
		||||
	{
 | 
			
		||||
		QSE_MMGR_FREE (mmgr, pio);
 | 
			
		||||
		return QSE_NULL;
 | 
			
		||||
@ -69,7 +68,7 @@ void qse_pio_close (qse_pio_t* pio)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
qse_pio_t* qse_pio_init (
 | 
			
		||||
	qse_pio_t* pio, qse_mmgr_t* mmgr, const qse_char_t* cmd, int flags)
 | 
			
		||||
	qse_pio_t* pio, qse_mmgr_t* mmgr, const qse_char_t* cmd, int oflags)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	qse_pio_hnd_t handle[6] = 
 | 
			
		||||
@ -112,7 +111,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
	secattr.bInheritHandle = TRUE;
 | 
			
		||||
	secattr.lpSecurityDescriptor = QSE_NULL;
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_WRITEIN)
 | 
			
		||||
	if (oflags & QSE_PIO_WRITEIN)
 | 
			
		||||
	{
 | 
			
		||||
		/* child reads, parent writes */
 | 
			
		||||
		if (CreatePipe (
 | 
			
		||||
@ -126,7 +125,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
		minidx = 0; maxidx = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_READOUT)
 | 
			
		||||
	if (oflags & QSE_PIO_READOUT)
 | 
			
		||||
	{
 | 
			
		||||
		/* child writes, parent reads */
 | 
			
		||||
		if (CreatePipe (
 | 
			
		||||
@ -141,7 +140,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
		maxidx = 3;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_READERR)
 | 
			
		||||
	if (oflags & QSE_PIO_READERR)
 | 
			
		||||
	{
 | 
			
		||||
		/* child writes, parent reads */
 | 
			
		||||
		if (CreatePipe (
 | 
			
		||||
@ -156,9 +155,9 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
		maxidx = 5;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((flags & QSE_PIO_INTONUL) || 
 | 
			
		||||
	    (flags & QSE_PIO_OUTTONUL) ||
 | 
			
		||||
	    (flags & QSE_PIO_ERRTONUL))
 | 
			
		||||
	if ((oflags & QSE_PIO_INTONUL) || 
 | 
			
		||||
	    (oflags & QSE_PIO_OUTTONUL) ||
 | 
			
		||||
	    (oflags & QSE_PIO_ERRTONUL))
 | 
			
		||||
	{
 | 
			
		||||
		windevnul = CreateFile(
 | 
			
		||||
			QSE_T("NUL"), GENERIC_READ | GENERIC_WRITE,
 | 
			
		||||
@ -177,34 +176,34 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
	startup.hStdOutput = INVALID_HANDLE_VALUE;
 | 
			
		||||
	startup.hStdOutput = INVALID_HANDLE_VALUE;
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_WRITEIN) startup.hStdInput = handle[0];
 | 
			
		||||
	if (oflags & QSE_PIO_WRITEIN) startup.hStdInput = handle[0];
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_READOUT)
 | 
			
		||||
	if (oflags & QSE_PIO_READOUT)
 | 
			
		||||
	{
 | 
			
		||||
		startup.hStdOutput = handle[3];
 | 
			
		||||
		if (flags & QSE_PIO_ERRTOOUT) startup.hStdError = handle[3];
 | 
			
		||||
		if (oflags & QSE_PIO_ERRTOOUT) startup.hStdError = handle[3];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_READERR)
 | 
			
		||||
	if (oflags & QSE_PIO_READERR)
 | 
			
		||||
	{
 | 
			
		||||
		startup.hStdError = handle[5];
 | 
			
		||||
		if (flags & QSE_PIO_OUTTOERR) startup.hStdOutput = handle[5];
 | 
			
		||||
		if (oflags & QSE_PIO_OUTTOERR) startup.hStdOutput = handle[5];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_INTONUL) startup.hStdOutput = windevnul;
 | 
			
		||||
	if (flags & QSE_PIO_OUTTONUL) startup.hStdOutput = windevnul;
 | 
			
		||||
	if (flags & QSE_PIO_ERRTONUL) startup.hStdError = windevnul;
 | 
			
		||||
	if (oflags & QSE_PIO_INTONUL) startup.hStdOutput = windevnul;
 | 
			
		||||
	if (oflags & QSE_PIO_OUTTONUL) startup.hStdOutput = windevnul;
 | 
			
		||||
	if (oflags & QSE_PIO_ERRTONUL) startup.hStdError = windevnul;
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_DROPIN) startup.hStdInput = INVALID_HANDLE_VALUE;
 | 
			
		||||
	if (flags & QSE_PIO_DROPOUT) startup.hStdOutput = INVALID_HANDLE_VALUE;
 | 
			
		||||
	if (flags & QSE_PIO_DROPERR) startup.hStdError = INVALID_HANDLE_VALUE;
 | 
			
		||||
	if (oflags & QSE_PIO_DROPIN) startup.hStdInput = INVALID_HANDLE_VALUE;
 | 
			
		||||
	if (oflags & QSE_PIO_DROPOUT) startup.hStdOutput = INVALID_HANDLE_VALUE;
 | 
			
		||||
	if (oflags & QSE_PIO_DROPERR) startup.hStdError = INVALID_HANDLE_VALUE;
 | 
			
		||||
 | 
			
		||||
	startup.dwFlags |= STARTF_USESTDHANDLES;
 | 
			
		||||
 | 
			
		||||
	/* there is nothing to do for QSE_PIO_SHELL as CreateProcess
 | 
			
		||||
	 * takes the entire command line */
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_SHELL) 
 | 
			
		||||
	if (oflags & QSE_PIO_SHELL) 
 | 
			
		||||
	{
 | 
			
		||||
		dup = QSE_MMGR_ALLOC (
 | 
			
		||||
			mmgr, (11+qse_strlen(cmd)+1 )*QSE_SIZEOF(qse_char_t));
 | 
			
		||||
@ -237,17 +236,17 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
 | 
			
		||||
	if (x == FALSE) goto oops;
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_WRITEIN)
 | 
			
		||||
	if (oflags & QSE_PIO_WRITEIN)
 | 
			
		||||
	{
 | 
			
		||||
		CloseHandle (handle[0]);
 | 
			
		||||
		handle[0] = QSE_PIO_HND_NIL;
 | 
			
		||||
	}
 | 
			
		||||
	if (flags & QSE_PIO_READOUT)
 | 
			
		||||
	if (oflags & QSE_PIO_READOUT)
 | 
			
		||||
	{
 | 
			
		||||
		CloseHandle (handle[3]);
 | 
			
		||||
		handle[3] = QSE_PIO_HND_NIL;
 | 
			
		||||
	}
 | 
			
		||||
	if (flags & QSE_PIO_READERR)
 | 
			
		||||
	if (oflags & QSE_PIO_READERR)
 | 
			
		||||
	{
 | 
			
		||||
		CloseHandle (handle[5]);
 | 
			
		||||
		handle[5] = QSE_PIO_HND_NIL;
 | 
			
		||||
@ -257,22 +256,22 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
	pio->child = procinfo.hProcess;
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_WRITEIN)
 | 
			
		||||
	if (oflags & QSE_PIO_WRITEIN)
 | 
			
		||||
	{
 | 
			
		||||
		if (QSE_PIPE(&handle[0]) == -1) goto oops;
 | 
			
		||||
		if (QSE_PIPE(&handle[0]) <= -1) goto oops;
 | 
			
		||||
		minidx = 0; maxidx = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_READOUT)
 | 
			
		||||
	if (oflags & QSE_PIO_READOUT)
 | 
			
		||||
	{
 | 
			
		||||
		if (QSE_PIPE(&handle[2]) == -1) goto oops;
 | 
			
		||||
		if (QSE_PIPE(&handle[2]) <= -1) goto oops;
 | 
			
		||||
		if (minidx == -1) minidx = 2;
 | 
			
		||||
		maxidx = 3;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_READERR)
 | 
			
		||||
	if (oflags & QSE_PIO_READERR)
 | 
			
		||||
	{
 | 
			
		||||
		if (QSE_PIPE(&handle[4]) == -1) goto oops;
 | 
			
		||||
		if (QSE_PIPE(&handle[4]) <= -1) goto oops;
 | 
			
		||||
		if (minidx == -1) minidx = 4;
 | 
			
		||||
		maxidx = 5;
 | 
			
		||||
	}
 | 
			
		||||
@ -280,7 +279,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
	if (maxidx == -1) goto oops;
 | 
			
		||||
 | 
			
		||||
	pid = QSE_FORK();
 | 
			
		||||
	if (pid == -1) goto oops;
 | 
			
		||||
	if (pid <= -1) goto oops;
 | 
			
		||||
 | 
			
		||||
	if (pid == 0)
 | 
			
		||||
	{
 | 
			
		||||
@ -302,7 +301,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
		struct rlimit rlim;
 | 
			
		||||
		int fd;
 | 
			
		||||
 | 
			
		||||
		if (QSE_GETRLIMIT (RLIMIT_NOFILE, &rlim) == -1 ||
 | 
			
		||||
		if (QSE_GETRLIMIT (RLIMIT_NOFILE, &rlim) <= -1 ||
 | 
			
		||||
		    rlim.rlim_max == RLIM_INFINITY) 
 | 
			
		||||
		{
 | 
			
		||||
		#ifdef HAVE_SYSCONF
 | 
			
		||||
@ -323,77 +322,77 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
			    fd != handle[5]) QSE_CLOSE (fd);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (flags & QSE_PIO_WRITEIN)
 | 
			
		||||
		if (oflags & QSE_PIO_WRITEIN)
 | 
			
		||||
		{
 | 
			
		||||
			/* child should read */
 | 
			
		||||
			QSE_CLOSE (handle[1]);
 | 
			
		||||
			handle[1] = QSE_PIO_HND_NIL;
 | 
			
		||||
			if (QSE_DUP2 (handle[0], 0) == -1) goto child_oops;
 | 
			
		||||
			if (QSE_DUP2 (handle[0], 0) <= -1) goto child_oops;
 | 
			
		||||
			QSE_CLOSE (handle[0]);
 | 
			
		||||
			handle[0] = QSE_PIO_HND_NIL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (flags & QSE_PIO_READOUT)
 | 
			
		||||
		if (oflags & QSE_PIO_READOUT)
 | 
			
		||||
		{
 | 
			
		||||
			/* child should write */
 | 
			
		||||
			QSE_CLOSE (handle[2]);
 | 
			
		||||
			handle[2] = QSE_PIO_HND_NIL;
 | 
			
		||||
			if (QSE_DUP2 (handle[3], 1) == -1) goto child_oops;
 | 
			
		||||
			if (QSE_DUP2 (handle[3], 1) <= -1) goto child_oops;
 | 
			
		||||
 | 
			
		||||
			if (flags & QSE_PIO_ERRTOOUT)
 | 
			
		||||
			if (oflags & QSE_PIO_ERRTOOUT)
 | 
			
		||||
			{
 | 
			
		||||
				if (QSE_DUP2 (handle[3], 2) == -1) goto child_oops;
 | 
			
		||||
				if (QSE_DUP2 (handle[3], 2) <= -1) goto child_oops;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			QSE_CLOSE (handle[3]); 
 | 
			
		||||
			handle[3] = QSE_PIO_HND_NIL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (flags & QSE_PIO_READERR)
 | 
			
		||||
		if (oflags & QSE_PIO_READERR)
 | 
			
		||||
		{
 | 
			
		||||
			/* child should write */
 | 
			
		||||
			QSE_CLOSE (handle[4]); 
 | 
			
		||||
			handle[4] = QSE_PIO_HND_NIL;
 | 
			
		||||
			if (QSE_DUP2 (handle[5], 2) == -1) goto child_oops;
 | 
			
		||||
			if (QSE_DUP2 (handle[5], 2) <= -1) goto child_oops;
 | 
			
		||||
 | 
			
		||||
			if (flags & QSE_PIO_OUTTOERR)
 | 
			
		||||
			if (oflags & QSE_PIO_OUTTOERR)
 | 
			
		||||
			{
 | 
			
		||||
				if (QSE_DUP2 (handle[5], 1) == -1) goto child_oops;
 | 
			
		||||
				if (QSE_DUP2 (handle[5], 1) <= -1) goto child_oops;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			QSE_CLOSE (handle[5]);
 | 
			
		||||
			handle[5] = QSE_PIO_HND_NIL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ((flags & QSE_PIO_INTONUL) || 
 | 
			
		||||
		    (flags & QSE_PIO_OUTTONUL) ||
 | 
			
		||||
		    (flags & QSE_PIO_ERRTONUL))
 | 
			
		||||
		if ((oflags & QSE_PIO_INTONUL) || 
 | 
			
		||||
		    (oflags & QSE_PIO_OUTTONUL) ||
 | 
			
		||||
		    (oflags & QSE_PIO_ERRTONUL))
 | 
			
		||||
		{
 | 
			
		||||
		#ifdef O_LARGEFILE
 | 
			
		||||
			devnull = QSE_OPEN ("/dev/null", O_RDWR|O_LARGEFILE, 0);
 | 
			
		||||
		#else
 | 
			
		||||
			devnull = QSE_OPEN ("/dev/null", O_RDWR, 0);
 | 
			
		||||
		#endif
 | 
			
		||||
			if (devnull == -1) goto child_oops;
 | 
			
		||||
			if (devnull <= -1) goto child_oops;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ((flags & QSE_PIO_INTONUL)  &&
 | 
			
		||||
		    QSE_DUP2(devnull,0) == -1) goto child_oops;
 | 
			
		||||
		if ((flags & QSE_PIO_OUTTONUL) &&
 | 
			
		||||
		    QSE_DUP2(devnull,1) == -1) goto child_oops;
 | 
			
		||||
		if ((flags & QSE_PIO_ERRTONUL) &&
 | 
			
		||||
		    QSE_DUP2(devnull,2) == -1) goto child_oops;
 | 
			
		||||
		if ((oflags & QSE_PIO_INTONUL)  &&
 | 
			
		||||
		    QSE_DUP2(devnull,0) <= -1) goto child_oops;
 | 
			
		||||
		if ((oflags & QSE_PIO_OUTTONUL) &&
 | 
			
		||||
		    QSE_DUP2(devnull,1) <= -1) goto child_oops;
 | 
			
		||||
		if ((oflags & QSE_PIO_ERRTONUL) &&
 | 
			
		||||
		    QSE_DUP2(devnull,2) <= -1) goto child_oops;
 | 
			
		||||
 | 
			
		||||
		if ((flags & QSE_PIO_INTONUL) || 
 | 
			
		||||
		    (flags & QSE_PIO_OUTTONUL) ||
 | 
			
		||||
		    (flags & QSE_PIO_ERRTONUL)) QSE_CLOSE (devnull);
 | 
			
		||||
		if ((oflags & QSE_PIO_INTONUL) || 
 | 
			
		||||
		    (oflags & QSE_PIO_OUTTONUL) ||
 | 
			
		||||
		    (oflags & QSE_PIO_ERRTONUL)) QSE_CLOSE (devnull);
 | 
			
		||||
 | 
			
		||||
		if (flags & QSE_PIO_DROPIN) QSE_CLOSE(0);
 | 
			
		||||
		if (flags & QSE_PIO_DROPOUT) QSE_CLOSE(1);
 | 
			
		||||
		if (flags & QSE_PIO_DROPERR) QSE_CLOSE(2);
 | 
			
		||||
		if (oflags & QSE_PIO_DROPIN) QSE_CLOSE(0);
 | 
			
		||||
		if (oflags & QSE_PIO_DROPOUT) QSE_CLOSE(1);
 | 
			
		||||
		if (oflags & QSE_PIO_DROPERR) QSE_CLOSE(2);
 | 
			
		||||
 | 
			
		||||
	#ifdef QSE_CHAR_IS_MCHAR
 | 
			
		||||
		if (flags & QSE_PIO_SHELL) mcmd = (qse_char_t*)cmd;
 | 
			
		||||
		if (oflags & QSE_PIO_SHELL) mcmd = (qse_char_t*)cmd;
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			mcmd =  qse_strdup (cmd, pio->mmgr);
 | 
			
		||||
@ -408,7 +407,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	#else	
 | 
			
		||||
		if (flags & QSE_PIO_SHELL)
 | 
			
		||||
		if (oflags & QSE_PIO_SHELL)
 | 
			
		||||
		{
 | 
			
		||||
       			n = qse_wcstombslen (cmd, &mn);
 | 
			
		||||
			if (cmd[n] != QSE_WT('\0')) 
 | 
			
		||||
@ -453,7 +452,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
			if (mcmd == QSE_NULL) goto child_oops;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (flags & QSE_PIO_SHELL)
 | 
			
		||||
		if (oflags & QSE_PIO_SHELL)
 | 
			
		||||
		{
 | 
			
		||||
			/* qse_wcstombs() should succeed as 
 | 
			
		||||
			 * qse_wcstombslen() was successful above */
 | 
			
		||||
@ -471,7 +470,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
		}
 | 
			
		||||
	#endif
 | 
			
		||||
 | 
			
		||||
		if (flags & QSE_PIO_SHELL)
 | 
			
		||||
		if (oflags & QSE_PIO_SHELL)
 | 
			
		||||
		{
 | 
			
		||||
			const qse_mchar_t* argv[4];
 | 
			
		||||
 | 
			
		||||
@ -508,7 +507,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
	/* parent */
 | 
			
		||||
	pio->child = pid;
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_WRITEIN)
 | 
			
		||||
	if (oflags & QSE_PIO_WRITEIN)
 | 
			
		||||
	{
 | 
			
		||||
		/* 
 | 
			
		||||
		 * 012345
 | 
			
		||||
@ -519,7 +518,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
		QSE_CLOSE (handle[0]); handle[0] = QSE_PIO_HND_NIL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_READOUT)
 | 
			
		||||
	if (oflags & QSE_PIO_READOUT)
 | 
			
		||||
	{
 | 
			
		||||
		/* 
 | 
			
		||||
		 * 012345
 | 
			
		||||
@ -530,7 +529,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
		QSE_CLOSE (handle[3]); handle[3] = QSE_PIO_HND_NIL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_READERR)
 | 
			
		||||
	if (oflags & QSE_PIO_READERR)
 | 
			
		||||
	{
 | 
			
		||||
		/* 
 | 
			
		||||
		 * 012345
 | 
			
		||||
@ -553,7 +552,7 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
	pio->pin[QSE_PIO_OUT].handle = handle[2];
 | 
			
		||||
	pio->pin[QSE_PIO_ERR].handle = handle[4];
 | 
			
		||||
 | 
			
		||||
	if (flags & QSE_PIO_TEXT)
 | 
			
		||||
	if (oflags & QSE_PIO_TEXT)
 | 
			
		||||
	{
 | 
			
		||||
		for (i = 0; i < QSE_COUNTOF(tio); i++)
 | 
			
		||||
		{
 | 
			
		||||
@ -566,13 +565,13 @@ qse_pio_t* qse_pio_init (
 | 
			
		||||
				qse_tio_attachout (tio[i], pio_output, &pio->pin[i]):
 | 
			
		||||
				qse_tio_attachin (tio[i], pio_input, &pio->pin[i]);
 | 
			
		||||
 | 
			
		||||
			if (r == -1) goto oops;
 | 
			
		||||
			if (r <= -1) goto oops;
 | 
			
		||||
 | 
			
		||||
			pio->pin[i].tio = tio[i];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pio->flags = 0;
 | 
			
		||||
	pio->option = 0;
 | 
			
		||||
	return pio;
 | 
			
		||||
 | 
			
		||||
oops:
 | 
			
		||||
@ -599,26 +598,19 @@ void qse_pio_fini (qse_pio_t* pio)
 | 
			
		||||
	qse_pio_end (pio, QSE_PIO_OUT);
 | 
			
		||||
	qse_pio_end (pio, QSE_PIO_IN);
 | 
			
		||||
 | 
			
		||||
	qse_pio_setflags (pio, QSE_PIO_WAIT_NOBLOCK|QSE_PIO_WAIT_NORETRY, -1);
 | 
			
		||||
	pio->option &= ~QSE_PIO_WAIT_NOBLOCK;
 | 
			
		||||
	pio->option &= ~QSE_PIO_WAIT_NORETRY;
 | 
			
		||||
	qse_pio_wait (pio);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qse_pio_getflags (qse_pio_t* pio)
 | 
			
		||||
int qse_pio_getoption (qse_pio_t* pio)
 | 
			
		||||
{
 | 
			
		||||
	return pio->flags;
 | 
			
		||||
	return pio->option;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qse_pio_setflags (qse_pio_t* pio, int flags, int op)
 | 
			
		||||
void qse_pio_setoption (qse_pio_t* pio, int opt)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	op => set
 | 
			
		||||
	op => off
 | 
			
		||||
	op => on
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	if (op == 0) pio->flags = flags;
 | 
			
		||||
	else if (op > 0) pio->flags |= flags;
 | 
			
		||||
	else /*if (op < 0)*/ pio->flags &= ~flags;
 | 
			
		||||
	pio->option = opt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
qse_pio_errnum_t qse_pio_geterrnum (qse_pio_t* pio)
 | 
			
		||||
@ -626,8 +618,6 @@ qse_pio_errnum_t qse_pio_geterrnum (qse_pio_t* pio)
 | 
			
		||||
	return pio->errnum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* TODO: qse_pio_geterrmsg (qse_pio_t* pio) */
 | 
			
		||||
 | 
			
		||||
const qse_char_t* qse_pio_geterrmsg (qse_pio_t* pio)
 | 
			
		||||
{
 | 
			
		||||
	static const qse_char_t* __errstr[] =
 | 
			
		||||
@ -694,7 +684,7 @@ reread:
 | 
			
		||||
	{
 | 
			
		||||
		if (errno == EINTR)
 | 
			
		||||
		{
 | 
			
		||||
			if (pio->flags & QSE_PIO_READ_NORETRY) 
 | 
			
		||||
			if (pio->option & QSE_PIO_READ_NORETRY) 
 | 
			
		||||
				pio->errnum = QSE_PIO_EINTR;
 | 
			
		||||
			else goto reread;
 | 
			
		||||
		}
 | 
			
		||||
@ -755,7 +745,7 @@ rewrite:
 | 
			
		||||
	{
 | 
			
		||||
		if (errno == EINTR)
 | 
			
		||||
		{
 | 
			
		||||
			if (pio->flags & QSE_PIO_WRITE_NORETRY)
 | 
			
		||||
			if (pio->option & QSE_PIO_WRITE_NORETRY)
 | 
			
		||||
				pio->errnum = QSE_PIO_EINTR;
 | 
			
		||||
			else goto rewrite;
 | 
			
		||||
		}
 | 
			
		||||
@ -820,7 +810,7 @@ int qse_pio_wait (qse_pio_t* pio)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w = WaitForSingleObject (pio->child, 
 | 
			
		||||
		((pio->flags & QSE_PIO_WAIT_NOBLOCK)? 0: INFINITE)
 | 
			
		||||
		((pio->option & QSE_PIO_WAIT_NOBLOCK)? 0: INFINITE)
 | 
			
		||||
	);
 | 
			
		||||
	if (w == WAIT_TIMEOUT)
 | 
			
		||||
	{
 | 
			
		||||
@ -871,14 +861,14 @@ int qse_pio_wait (qse_pio_t* pio)
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pio->flags & QSE_PIO_WAIT_NOBLOCK) opt |= WNOHANG;
 | 
			
		||||
	if (pio->option & QSE_PIO_WAIT_NOBLOCK) opt |= WNOHANG;
 | 
			
		||||
 | 
			
		||||
	while (1)
 | 
			
		||||
	{
 | 
			
		||||
		int status, n;
 | 
			
		||||
 | 
			
		||||
		n = QSE_WAITPID (pio->child, &status, opt);
 | 
			
		||||
		if (n == -1)
 | 
			
		||||
		if (n <= -1)
 | 
			
		||||
		{
 | 
			
		||||
			if (errno == ECHILD)
 | 
			
		||||
			{
 | 
			
		||||
@ -889,7 +879,7 @@ int qse_pio_wait (qse_pio_t* pio)
 | 
			
		||||
			}
 | 
			
		||||
			else if (errno == EINTR)
 | 
			
		||||
			{
 | 
			
		||||
				if (pio->flags & QSE_PIO_WAIT_NORETRY) 
 | 
			
		||||
				if (pio->option & QSE_PIO_WAIT_NORETRY) 
 | 
			
		||||
					pio->errnum = QSE_PIO_EINTR;
 | 
			
		||||
				else continue;
 | 
			
		||||
			}
 | 
			
		||||
@ -901,7 +891,7 @@ int qse_pio_wait (qse_pio_t* pio)
 | 
			
		||||
		if (n == 0) 
 | 
			
		||||
		{
 | 
			
		||||
			/* when WNOHANG is not specified, 0 can't be returned */
 | 
			
		||||
			QSE_ASSERT (pio->flags & QSE_PIO_WAIT_NOBLOCK);
 | 
			
		||||
			QSE_ASSERT (pio->option & QSE_PIO_WAIT_NOBLOCK);
 | 
			
		||||
 | 
			
		||||
			ret = 255 + 1;
 | 
			
		||||
			/* the child process is still alive */
 | 
			
		||||
@ -963,7 +953,7 @@ int qse_pio_kill (qse_pio_t* pio)
 | 
			
		||||
	return 0;
 | 
			
		||||
#else
 | 
			
		||||
	n = QSE_KILL (pio->child, SIGKILL);
 | 
			
		||||
	if (n == -1) pio->errnum = QSE_PIO_ESUBSYS;
 | 
			
		||||
	if (n <= -1) pio->errnum = QSE_PIO_ESUBSYS;
 | 
			
		||||
	return n;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,9 @@
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#	include <windows.h>
 | 
			
		||||
#else
 | 
			
		||||
#	include <unistd.h>
 | 
			
		||||
#	include <sys/wait.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define R(f) \
 | 
			
		||||
@ -41,7 +44,10 @@ static int pio1 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid)
 | 
			
		||||
		if (n == 0) break;
 | 
			
		||||
		if (n <= -1)
 | 
			
		||||
		{
 | 
			
		||||
			qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrmsg(pio));
 | 
			
		||||
			qse_printf (
 | 
			
		||||
				QSE_T("qse_pio_read() returned error - %s\n"),
 | 
			
		||||
				qse_pio_geterrmsg(pio)
 | 
			
		||||
			);
 | 
			
		||||
			break;
 | 
			
		||||
		}	
 | 
			
		||||
 | 
			
		||||
@ -61,7 +67,8 @@ static int pio1 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid)
 | 
			
		||||
	qse_printf (QSE_T("qse_pio_wait returns %d\n"), x);
 | 
			
		||||
	if (x <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)qse_pio_geterrnum(pio), qse_pio_geterrmsg(pio));
 | 
			
		||||
		qse_printf (QSE_T("error code : %d, error string: %s\n"),
 | 
			
		||||
			(int)qse_pio_geterrnum(pio), qse_pio_geterrmsg(pio));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	qse_pio_close (pio);
 | 
			
		||||
@ -95,7 +102,10 @@ static int pio2 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid)
 | 
			
		||||
		if (n == 0) break;
 | 
			
		||||
		if (n < 0)
 | 
			
		||||
		{
 | 
			
		||||
			qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrmsg(pio));
 | 
			
		||||
			qse_printf (
 | 
			
		||||
				QSE_T("qse_pio_read() returned error - %s\n"),
 | 
			
		||||
				qse_pio_geterrmsg(pio)
 | 
			
		||||
			);
 | 
			
		||||
			break;
 | 
			
		||||
		}	
 | 
			
		||||
 | 
			
		||||
@ -111,7 +121,8 @@ static int pio2 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid)
 | 
			
		||||
	qse_printf (QSE_T("qse_pio_wait returns %d\n"), x);
 | 
			
		||||
	if (x <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)qse_pio_geterrnum(pio), qse_pio_geterrmsg(pio));
 | 
			
		||||
		qse_printf (QSE_T("error code : %d, error string: %s\n"),
 | 
			
		||||
			(int)qse_pio_geterrnum(pio), qse_pio_geterrmsg(pio));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	qse_pio_close (pio);
 | 
			
		||||
@ -216,9 +227,9 @@ static int test8 (void)
 | 
			
		||||
{
 | 
			
		||||
	return pio1 (
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
		QSE_T("sll.exe"), 
 | 
			
		||||
		QSE_T(".\\sll.exe"), 
 | 
			
		||||
#else
 | 
			
		||||
		QSE_T("ls -laF"), 
 | 
			
		||||
		QSE_T("/bin/ls -laF"), 
 | 
			
		||||
#endif
 | 
			
		||||
		QSE_PIO_READOUT|QSE_PIO_WRITEIN|
 | 
			
		||||
		QSE_PIO_OUTTONUL|QSE_PIO_ERRTONUL|QSE_PIO_INTONUL,
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user