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