From 1e7f2551e5c97371fa3cab5b8ca2f066a421ebb4 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 25 Jul 2009 06:22:00 +0000 Subject: [PATCH] touched up code a little --- qse/include/qse/cmn/pio.h | 290 +++++++++++++++++++------------------- qse/lib/cmn/pio.c | 176 +++++++++++------------ qse/samples/cmn/pio.c | 23 ++- 3 files changed, 245 insertions(+), 244 deletions(-) diff --git a/qse/include/qse/cmn/pio.h b/qse/include/qse/cmn/pio.h index 08cf89d7..41001772 100644 --- a/qse/include/qse/cmn/pio.h +++ b/qse/include/qse/cmn/pio.h @@ -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 /** @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 ( => 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]; }; -#define QSE_PIO_ERRNUM(pio) ((pio)->errnum) -#define QSE_PIO_FLAGS(pio) ((pio)->flags) -#define QSE_PIO_CHILD(pio) ((pio)->child) +/** access the @a errnum field of the #qse_pio_t structure */ +#define QSE_PIO_ERRNUM(pio) ((pio)->errnum) +/** 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 +/** + * The qse_pio_geterrmsg() function returns the pointer to a constant string + * describing the last error occurred. + * @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 - * stream causing the child process reach the end of the stream. - * SYNOPSIS +/** + * 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. + * @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. +/** + * 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. * - * 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 - * 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 - * 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 +/** + * 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. + * @return 0 on success, -1 on failure */ int qse_pio_kill ( - qse_pio_t* pio + qse_pio_t* pio /**< pio object */ ); -/******/ #ifdef __cplusplus } diff --git a/qse/lib/cmn/pio.c b/qse/lib/cmn/pio.c index 169f9913..c2a19114 100644 --- a/qse/lib/cmn/pio.c +++ b/qse/lib/cmn/pio.c @@ -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 } diff --git a/qse/samples/cmn/pio.c b/qse/samples/cmn/pio.c index 06f17c0e..a77e8317 100644 --- a/qse/samples/cmn/pio.c +++ b/qse/samples/cmn/pio.c @@ -6,6 +6,9 @@ #ifdef _WIN32 # include +#else +# include +# include #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,