From 9fabea2cd24aee5ea577917bbeed1d0f20127d20 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 24 Jul 2009 07:01:52 +0000 Subject: [PATCH] enhanced pio for WIN32 --- qse/include/qse/cmn/pio.h | 8 +-- qse/lib/cmn/fio.c | 3 +- qse/lib/cmn/pio.c | 90 ++++++++++++++++++------- qse/samples/cmn/pio.c | 134 +++++++++++++++++++++++--------------- qse/samples/cmn/sio.c | 2 +- qse/samples/cmn/time.c | 44 +++++++++++-- 6 files changed, 195 insertions(+), 86 deletions(-) diff --git a/qse/include/qse/cmn/pio.h b/qse/include/qse/cmn/pio.h index 9a7cd36c..023e4259 100644 --- a/qse/include/qse/cmn/pio.h +++ b/qse/include/qse/cmn/pio.h @@ -1,5 +1,5 @@ /* - * $Id: pio.h 241 2009-07-22 12:47:13Z hyunghwan.chung $ + * $Id: pio.h 242 2009-07-23 13:01:52Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -36,15 +36,15 @@ enum qse_pio_open_flag_t QSE_PIO_TEXT = (1 << 0), /* invoke the command through a system shell - * (/bin/sh on *nix, command.com on windows) */ + * (/bin/sh on *nix, cmd.exe on windows) */ QSE_PIO_SHELL = (1 << 1), QSE_PIO_WRITEIN = (1 << 8), QSE_PIO_READOUT = (1 << 9), QSE_PIO_READERR = (1 << 10), - QSE_PIO_ERRTOOUT = (1 << 11), - QSE_PIO_OUTTOERR = (1 << 12), + QSE_PIO_ERRTOOUT = (1 << 11), /* require QSE_PIO_READOUT */ + QSE_PIO_OUTTOERR = (1 << 12), /* require QSE_PIO_READERR */ QSE_PIO_INTONUL = (1 << 13), QSE_PIO_ERRTONUL = (1 << 14), diff --git a/qse/lib/cmn/fio.c b/qse/lib/cmn/fio.c index c5bd3f7c..943488c3 100644 --- a/qse/lib/cmn/fio.c +++ b/qse/lib/cmn/fio.c @@ -1,5 +1,5 @@ /* - * $Id: fio.c 204 2009-06-18 12:08:06Z hyunghwan.chung $ + * $Id: fio.c 242 2009-07-23 13:01:52Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -392,7 +392,6 @@ qse_ssize_t qse_fio_flush (qse_fio_t* fio) static int get_devname_from_handle ( HANDLE handle, qse_char_t* buf, qse_size_t len) { - BOOL bSuccess = FALSE; HANDLE map = NULL; void* mem = NULL; DWORD olen; diff --git a/qse/lib/cmn/pio.c b/qse/lib/cmn/pio.c index 19b61a1b..169f9913 100644 --- a/qse/lib/cmn/pio.c +++ b/qse/lib/cmn/pio.c @@ -1,5 +1,5 @@ /* - * $Id: pio.c 241 2009-07-22 12:47:13Z hyunghwan.chung $ + * $Id: pio.c 242 2009-07-23 13:01:52Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -71,7 +71,6 @@ 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_pid_t pid; qse_pio_hnd_t handle[6] = { @@ -97,7 +96,10 @@ qse_pio_t* qse_pio_init ( PROCESS_INFORMATION procinfo; STARTUPINFO startup; qse_char_t* dup = QSE_NULL; + HANDLE windevnul = INVALID_HANDLE_VALUE; BOOL x; +#else + qse_pio_pid_t pid; #endif QSE_MEMSET (pio, 0, QSE_SIZEOF(*pio)); @@ -108,7 +110,7 @@ qse_pio_t* qse_pio_init ( secattr.nLength = QSE_SIZEOF(secattr); secattr.bInheritHandle = TRUE; - secattr.lpSecurityDescriptor = NULL; + secattr.lpSecurityDescriptor = QSE_NULL; if (flags & QSE_PIO_WRITEIN) { @@ -154,32 +156,68 @@ qse_pio_t* qse_pio_init ( maxidx = 5; } - /* TODO: handle QSE_PIO_DROPXXX , QSE_PIO_XXXTONUL - if (flags & QSE_PIO_INTONUL) ... - if (flags & QSE_PIO_OUTTONUL) ... - if (flags & QSE_PIO_ERRTONUL) ... - if (flags & QSE_PIO_DROPIN) ... - if (flags & QSE_PIO_DROPOUT) ... - if (flags & QSE_PIO_DROPERR) ... - */ + if ((flags & QSE_PIO_INTONUL) || + (flags & QSE_PIO_OUTTONUL) || + (flags & QSE_PIO_ERRTONUL)) + { + windevnul = CreateFile( + QSE_T("NUL"), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &secattr, OPEN_EXISTING, 0, NULL + ); + if (windevnul == INVALID_HANDLE_VALUE) goto oops; + } QSE_MEMSET (&procinfo, 0, QSE_SIZEOF(procinfo)); QSE_MEMSET (&startup, 0, QSE_SIZEOF(startup)); startup.cb = QSE_SIZEOF(startup); - startup.hStdInput = - (flags & QSE_PIO_WRITEIN)? handle[0]: INVALID_HANDLE_VALUE; - startup.hStdOutput = - (flags & QSE_PIO_READOUT)? handle[3]: INVALID_HANDLE_VALUE; - startup.hStdError = - (flags & QSE_PIO_READERR)? handle[5]: INVALID_HANDLE_VALUE; + + startup.hStdInput = INVALID_HANDLE_VALUE; + startup.hStdOutput = INVALID_HANDLE_VALUE; + startup.hStdOutput = INVALID_HANDLE_VALUE; + + if (flags & QSE_PIO_WRITEIN) startup.hStdInput = handle[0]; + + if (flags & QSE_PIO_READOUT) + { + startup.hStdOutput = handle[3]; + if (flags & QSE_PIO_ERRTOOUT) startup.hStdError = handle[3]; + } + + if (flags & QSE_PIO_READERR) + { + startup.hStdError = handle[5]; + if (flags & 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 (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; + startup.dwFlags |= STARTF_USESTDHANDLES; /* there is nothing to do for QSE_PIO_SHELL as CreateProcess * takes the entire command line */ - dup = qse_strdup (cmd, mmgr); - if (dup == QSE_NULL) goto oops; + if (flags & QSE_PIO_SHELL) + { + dup = QSE_MMGR_ALLOC ( + mmgr, (11+qse_strlen(cmd)+1 )*QSE_SIZEOF(qse_char_t)); + if (dup == QSE_NULL) goto oops; + + qse_strcpy (dup, QSE_T("cmd.exe /c ")); + qse_strcpy (&dup[11], cmd); + } + else + { + dup = qse_strdup (cmd, mmgr); + if (dup == QSE_NULL) goto oops; + } x = CreateProcess ( NULL, /* LPCTSTR lpApplicationName */ @@ -194,6 +232,9 @@ qse_pio_t* qse_pio_init ( &procinfo /* LPPROCESS_INFORMATION lpProcessInformation */ ); + QSE_MMGR_FREE (mmgr, dup); dup = QSE_NULL; + CloseHandle (windevnul); windevnul = INVALID_HANDLE_VALUE; + if (x == FALSE) goto oops; if (flags & QSE_PIO_WRITEIN) @@ -213,7 +254,7 @@ qse_pio_t* qse_pio_init ( } CloseHandle (procinfo.hThread); - pid = procinfo.hProcess; + pio->child = procinfo.hProcess; #else if (flags & QSE_PIO_WRITEIN) @@ -333,7 +374,7 @@ qse_pio_t* qse_pio_init ( #else devnull = QSE_OPEN ("/dev/null", O_RDWR, 0); #endif - if (devnull == -1) goto oops; + if (devnull == -1) goto child_oops; } if ((flags & QSE_PIO_INTONUL) && @@ -536,6 +577,7 @@ qse_pio_t* qse_pio_init ( oops: #ifdef _WIN32 + if (windevnul != INVALID_HANDLE_VALUE) CloseHandle (windevnul); if (dup != QSE_NULL) QSE_MMGR_FREE (mmgr, dup); #endif @@ -635,8 +677,10 @@ static qse_ssize_t pio_read ( if (size > QSE_TYPE_MAX(DWORD)) size = QSE_TYPE_MAX(DWORD); if (ReadFile(hnd, buf, size, &count, QSE_NULL) == FALSE) { - pio->errnum = (GetLastError() == ERROR_BROKEN_PIPE)? - QSE_PIO_EPIPE: QSE_PIO_ESUBSYS; + /* ReadFile receives ERROR_BROKEN_PIPE when the write end + * is closed in the child process */ + if (GetLastError() == ERROR_BROKEN_PIPE) return 0; + pio->errnum = QSE_PIO_ESUBSYS; return -1; } return (qse_ssize_t)count; diff --git a/qse/samples/cmn/pio.c b/qse/samples/cmn/pio.c index bcf0ded6..367bd75c 100644 --- a/qse/samples/cmn/pio.c +++ b/qse/samples/cmn/pio.c @@ -34,27 +34,32 @@ static int pio1 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid) while (1) { qse_byte_t buf[128]; + qse_ssize_t i; /*qse_pio_canread (pio, QSE_PIO_ERR, 1000)*/ qse_ssize_t n = qse_pio_read (pio, buf, sizeof(buf), rhid); if (n == 0) break; - if (n < 0) + if (n <= -1) { qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrmsg(pio)); break; } - qse_printf (QSE_T("N===> %d\n"), (int)n); + qse_printf (QSE_T("N===> %d buf => ["), (int)n); + for (i = 0; i < n; i++) + { #ifdef QSE_CHAR_IS_MCHAR - qse_printf (QSE_T("buf => [%.*s]\n"), (int)n, buf); + qse_printf (QSE_T("%c"), buf[i]); #else - qse_printf (QSE_T("buf => [%.*S]\n"), (int)n, buf); + qse_printf (QSE_T("%C"), buf[i]); #endif + } + qse_printf (QSE_T("]\n")); } x = qse_pio_wait (pio); 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)); } @@ -84,6 +89,7 @@ static int pio2 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid) while (1) { qse_char_t buf[128]; + qse_ssize_t i; qse_ssize_t n = qse_pio_read (pio, buf, QSE_COUNTOF(buf), rhid); if (n == 0) break; @@ -93,13 +99,17 @@ static int pio2 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid) break; } - qse_printf (QSE_T("N===> %d\n"), (int)n); - qse_printf (QSE_T("buf => [%.*s]\n"), (int)n, buf); + qse_printf (QSE_T("N===> %d buf => ["), (int)n); + for (i = 0; i < n; i++) + { + qse_printf (QSE_T("%c"), buf[i]); + } + qse_printf (QSE_T("]\n")); } x = qse_pio_wait (pio); 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)); } @@ -115,7 +125,7 @@ static int test1 (void) return pio1 ( #ifdef _WIN32 - QSE_T("lda.exe"), + QSE_T("sll.exe"), #else QSE_T("ls -laF"), #endif @@ -128,7 +138,7 @@ static int test2 (void) { return pio1 ( #ifdef _WIN32 - QSE_T("lda.exe"), + QSE_T("sll.exe"), #else QSE_T("ls -laF"), #endif @@ -139,67 +149,84 @@ static int test2 (void) static int test3 (void) { - return pio1 (QSE_T("/bin/ls -laF"), QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN, QSE_PIO_ERR); + return pio1 ( +#ifdef _WIN32 + QSE_T(".\\sll.exe"), +#else + QSE_T("/bin/ls -laF"), +#endif + QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN, + QSE_PIO_ERR + ); } static int test4 (void) { - return pio2 (QSE_T("ls -laF"), QSE_PIO_READOUT|QSE_PIO_WRITEIN|QSE_PIO_SHELL, QSE_PIO_OUT); + return pio2 ( +#ifdef _WIN32 + QSE_T("sll.exe"), +#else + QSE_T("ls -laF"), +#endif + QSE_PIO_READOUT|QSE_PIO_WRITEIN|QSE_PIO_SHELL, + QSE_PIO_OUT + ); } static int test5 (void) { - return pio2 (QSE_T("ls -laF"), QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN|QSE_PIO_SHELL, QSE_PIO_ERR); + return pio2 ( +#ifdef _WIN32 + QSE_T("sll.exe"), +#else + QSE_T("ls -laF"), +#endif + QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN|QSE_PIO_SHELL, + QSE_PIO_ERR + ); } static int test6 (void) { - return pio2 (QSE_T("/bin/ls -laF"), QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN, QSE_PIO_ERR); + return pio2 ( +#ifdef _WIN32 + QSE_T(".\\sll.exe"), +#else + QSE_T("/bin/ls -laF"), +#endif + QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN, + QSE_PIO_ERR + ); } static int test7 (void) { - qse_pio_t* pio; - int x; - - pio = qse_pio_open ( - QSE_NULL, - 0, - QSE_T("/bin/ls -laF"), - QSE_PIO_READOUT|QSE_PIO_ERRTOOUT|QSE_PIO_WRITEIN + return pio1 ( +#ifdef _WIN32 + QSE_T(".\\sll.exe"), +#else + QSE_T("/bin/ls -laF"), +#endif + QSE_PIO_READOUT|QSE_PIO_ERRTOOUT|QSE_PIO_WRITEIN, + QSE_PIO_OUT ); - if (pio == QSE_NULL) - { - qse_printf (QSE_T("cannot open program through pipe\n")); - return -1; - } - - while (1) - { - qse_byte_t buf[128]; - - /*qse_pio_canread (pio, QSE_PIO_ERR, 1000)*/ - qse_ssize_t n = qse_pio_read (pio, buf, sizeof(buf), QSE_PIO_OUT); - if (n == 0) break; - if (n < 0) - { - qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrmsg(pio)); - break; - } - } - - x = qse_pio_wait (pio); - 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_ERRNUM(pio), qse_pio_geterrmsg(pio)); - } - - qse_pio_close (pio); - return 0; } static int test8 (void) +{ + return pio1 ( +#ifdef _WIN32 + QSE_T("sll.exe"), +#else + QSE_T("ls -laF"), +#endif + QSE_PIO_READOUT|QSE_PIO_WRITEIN| + QSE_PIO_OUTTONUL|QSE_PIO_ERRTONUL|QSE_PIO_INTONUL, + QSE_PIO_OUT + ); +} + +static int test9 (void) { qse_pio_t* pio; int x; @@ -207,7 +234,11 @@ static int test8 (void) pio = qse_pio_open ( QSE_NULL, 0, +#ifdef _WIN32 + QSE_T(".\\sll.exe"), +#else QSE_T("/bin/ls -laF"), +#endif QSE_PIO_READOUT|QSE_PIO_READERR|QSE_PIO_WRITEIN ); if (pio == QSE_NULL) @@ -263,6 +294,7 @@ int main () R (test6); R (test7); R (test8); + R (test9); return 0; } diff --git a/qse/samples/cmn/sio.c b/qse/samples/cmn/sio.c index 9b442eeb..c1ea1d0f 100644 --- a/qse/samples/cmn/sio.c +++ b/qse/samples/cmn/sio.c @@ -54,7 +54,7 @@ static int test2 (void) qse_ssize_t n; qse_char_t buf[20]; - qse_sio_puts (qse_sio_out, QSE_T("type somthing...\n")); + qse_sio_puts (qse_sio_out, QSE_T("type something...\n")); while (1) { n = qse_sio_gets (qse_sio_in, buf, QSE_COUNTOF(buf)); diff --git a/qse/samples/cmn/time.c b/qse/samples/cmn/time.c index 2487e54f..70680ed2 100644 --- a/qse/samples/cmn/time.c +++ b/qse/samples/cmn/time.c @@ -14,7 +14,11 @@ void print_time (qse_ntime_t nt, const qse_btime_t* bt) { +#ifdef _WIN32 + qse_printf (QSE_T("TIME: %I64d\n"), (__int64)nt); +#else qse_printf (QSE_T("TIME: %lld\n"), (long long)nt); +#endif qse_printf (QSE_T("year: %d\n"), bt->year + QSE_BTIME_YEAR_BASE); qse_printf (QSE_T("mon: %d\n"), bt->mon + 1); qse_printf (QSE_T("mday: %d\n"), bt->mday); @@ -48,7 +52,11 @@ static int test1 (void) } else { +#ifdef _WIN32 + qse_printf (QSE_T("back to ntime: %I64d\n"), (__int64)nt); +#else qse_printf (QSE_T("back to ntime: %lld\n"), (long long)nt); +#endif qse_gmtime (nt, &bt); print_time (nt, &bt); qse_printf (QSE_T("-------------------------------\n")); @@ -63,19 +71,32 @@ static int test1 (void) for (nt = (qse_ntime_t)QSE_TYPE_MIN(int); nt <= (qse_ntime_t)QSE_TYPE_MAX(int); nt += QSE_SECS_PER_DAY) { +#ifdef _WIN32 + __time64_t t = (__time64_t)nt; +#else time_t t = (time_t)nt; +#endif qse_ntime_t qnt = nt * 1000; struct tm* tm; if (qnt >= 0) qnt += rand() % 1000; else qnt -= rand() % 1000; +#ifdef _WIN32 + tm = _gmtime64 (&t); +#else tm = gmtime (&t); - +#endif qse_gmtime (qnt, &bt); - qse_printf (QSE_T(">>> time %lld: "), (long long)qnt); - if (tm->tm_year != bt.year || +#ifdef _WIN32 + qse_printf (QSE_T(">>> time %I64d: "), (__int64)qnt); +#else + qse_printf (QSE_T(">>> time %lld: "), (long long)qnt); +#endif + + if (tm == QSE_NULL || + tm->tm_year != bt.year || tm->tm_mon != bt.mon || tm->tm_mday != bt.mday || tm->tm_wday != bt.wday || @@ -83,14 +104,18 @@ static int test1 (void) tm->tm_min != bt.min || tm->tm_sec != bt.sec) { +#ifdef _WIN32 + qse_printf (QSE_T("[GMTIME ERROR %I64d]\n"), (__int64)t); +#else qse_printf (QSE_T("[GMTIME ERROR %lld]\n"), (long long)t); +#endif + if (tm == QSE_NULL) qse_printf (QSE_T(">> GMTIME RETURNED NULL\n")); print_time (qnt, &bt); qse_printf (QSE_T("-------------------------------\n")); } else { qse_ntime_t xx; - qse_printf (QSE_T("[GMTIME OK]")); if (qse_timegm (&bt, &xx) == -1) @@ -100,8 +125,17 @@ static int test1 (void) else { if (xx == qnt) + { qse_printf (QSE_T("[TIMEGM OK %d/%d/%d %d:%d:%d]\n"), bt.year + QSE_BTIME_YEAR_BASE, bt.mon + 1, bt.mday, bt.hour, bt.min, bt.sec); - else qse_printf (QSE_T("[TIMEGM ERROR %lld, %d/%d/%d %d:%d:%d]\n"), (long long)xx, bt.year + QSE_BTIME_YEAR_BASE, bt.mon + 1, bt.mday, bt.hour, bt.min, bt.sec); + } + else + { +#ifdef _WIN32 + qse_printf (QSE_T("[TIMEGM ERROR %I64d, %d/%d/%d %d:%d:%d]\n"), (__int64)xx, bt.year + QSE_BTIME_YEAR_BASE, bt.mon + 1, bt.mday, bt.hour, bt.min, bt.sec); +#else + qse_printf (QSE_T("[TIMEGM ERROR %lld, %d/%d/%d %d:%d:%d]\n"), (long long)xx, bt.year + QSE_BTIME_YEAR_BASE, bt.mon + 1, bt.mday, bt.hour, bt.min, bt.sec); +#endif + } } }