VirtualBox

Changeset 2838 in kBuild


Ignore:
Timestamp:
Aug 25, 2016 9:46:25 PM (9 years ago)
Author:
bird
Message:

kWorker: A little more hacking.

Location:
trunk
Files:
1 added
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Config.kmk

    r2819 r2838  
    385385
    386386
    387 LIB_KDEP = $(PATH_OBJ)/kDep/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kDep$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
     387#
     388# Template for static threaded binaries (windows).
     389#
     390TEMPLATE_BIN-STATIC-THREADED = Threaded command line binary
     391TEMPLATE_BIN-STATIC-THREADED_EXTENDS  = BIN-THREADED
     392ifeq ($(filter-out win nt,$(KBUILD_TARGET)),)
     393 TEMPLATE_BIN-STATIC-THREADED_CFLAGS  = $(filter-out -MD,$(TEMPLATE_BIN-THREADED_CFLAGS)) -MT
     394 TEMPLATE_BIN-STATIC-THREADED_LIBS    = $(filter-out %/msvcrt.lib,$(TEMPLATE_BIN-THREADED_LIBS)) \
     395        $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcmt.lib \
     396        $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcpmt.lib
     397else
     398 TEMPLATE_BIN-STATIC-THREADED_CFLAGS  = $(TEMPLATE_BIN-THREADED_CFLAGS) -static
     399 TEMPLATE_BIN-STATIC-THREADED_LDFLAGS = $(TEMPLATE_BIN-THREADED_LDFLAGS) -static
     400endif
     401
     402#
     403# Template for static threaded libraries.
     404#
     405TEMPLATE_LIB-STATIC-THREADED = Threaded command line library
     406TEMPLATE_LIB-STATIC-THREADED_EXTENDS  = BIN-STATIC-THREADED
     407TEMPLATE_LIB-STATIC-THREADED_INST     = lib/
     408
     409
     410#
     411# Library macros.
     412#
     413LIB_KDEP  = $(PATH_OBJ)/kDep/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kDep$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
    388414LIB_KUTIL = $(PATH_OBJ)/kUtil/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kUtil$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
    389415
  • trunk/src/kWorker/Makefile.kmk

    r2836 r2838  
    2424#
    2525
    26 ## @todo fixme!!!
    27 KBUILD_WITH_STATIC_MSVCRT = 1
    2826
    2927SUB_DEPTH = ../..
     
    3230
    3331PROGRAMS += kWorker
    34 kWorker_TEMPLATE = BIN
     32kWorker_TEMPLATE = BIN-STATIC-THREADED
    3533kWorker_INCS = kStuff/include
    3634kWorker_DEFS.debug = K_STRICT
     
    3937kWorker_LIBS = \
    4038        $(kStuff_1_TARGET) \
    41         $(LIB_KDEP) \
    42         $(LIB_KUTIL)
     39        $(kWorkerLib_1_TARGET)
    4340include $(KBUILD_PATH)/sdks/WINDDK71.kmk
    4441kWorker_LIBS.win = \
    45         $(TEMPLATE_BIN_LIBS) \
     42        $(TEMPLATE_BIN-STATIC-THREADED_LIBS) \
    4643        $(PATH_SDK_WINDDK71_LIB_WNET)/ntdll.lib
    4744kWorker_LDFLAGS.win = \
     
    5047
    5148#
     49# Stuff from ../libs.  Need to rebuilt it with static CRT.
     50#
     51LIBRARIES += kWorkerLib
     52kWorkerLib_TEMPLATE = LIB-STATIC-THREADED
     53kWorkerLib_DEFPATH = ../lib # Need fix from r2837.
     54kWorkerLib_DEFPATH := $(PATH_SUB_CURRENT)/../lib
     55kWorkerLib_SOURCES = \
     56        crc32.c \
     57        md5.c
     58kWorkerLib_SOURCES.win = \
     59        nt_fullpath.c \
     60        quoted_spawn.c \
     61       nt/nthlpcore.c \
     62       nt/nthlpfs.c \
     63       nt/ntdir.c \
     64       nt/ntstat.c \
     65       nt/ntunlink.c
     66
     67#
    5268# kStuff library.
    5369#
    5470LIBRARIES += kStuff
    55 kStuff_TEMPLATE = LIB
     71kStuff_TEMPLATE = LIB-STATIC-THREADED
    5672kStuff_DEFS.debug = K_STRICT
    5773kStuff_INCS = kStuff/include
  • trunk/src/kWorker/kWorker.c

    r2836 r2838  
    49224922#else
    49234923// Skylake (W10/amd64, only stdandard MS defender):
    4924 //     run 4: 32.67/1024 = 0x0 (0.031904296875)
    4925 //     run 3: 32.77/1024 = 0x0 (0.032001953125)
    4926 //     run 2: 34/1024 = 0x0 (0.033203125)
    4927 //     run 1: 37/1024 = 0x0 (0.0361328125)
    4928 //     kmk 1: 44/1024 = 0x0 (0.04296875)
    4929 //     cmd 1: 48/1024 = 0x0 (0.046875)
     4924//     cmd 1:  48    /1024 = 0x0 (0.046875)        [for /l %i in (1,1,1024) do ...]
     4925//     kmk 1:  44    /1024 = 0x0 (0.04296875)      [all: ; 1024 x cl.exe]
     4926//     run 1:  37    /1024 = 0x0 (0.0361328125)    [just process creation gain]
     4927//     run 2:  34    /1024 = 0x0 (0.033203125)     [get file attribs]
     4928//     run 3:  32.77 /1024 = 0x0 (0.032001953125)  [read caching of headers]
     4929//     run 4:  32.67 /1024 = 0x0 (0.031904296875)  [loader tweaking]
     4930//     run 5:  29.144/1024 = 0x0 (0.0284609375)    [with temp files in memory]
    49304931// Dell (W7/amd64, infected by mcafee):
    49314932//     kmk 1: 285.278/1024 = 0x0 (0.278591796875)
  • trunk/src/lib/Makefile.kmk

    r2713 r2838  
    4242kUtil_SOURCES.win = \
    4343        nt_fullpath.c \
     44        quote_argv.c \
    4445        quoted_spawn.c \
    4546       nt/nthlpcore.c \
  • trunk/src/lib/quote_argv.c

    r2837 r2838  
    11/* $Id$ */
    22/** @file
    3  * kmk_redirect - Do simple program <-> file redirection (++).
     3 * quote_argv - Correctly quote argv for spawn, windows specific.
    44 */
    55
     
    2727*   Header Files                                                               *
    2828*******************************************************************************/
    29 #ifdef __APPLE__
    30 # define _POSIX_C_SOURCE 1 /* 10.4 sdk and unsetenv */
    31 #endif
    32 #include "config.h"
    33 #include <stdio.h>
     29#include "quote_argv.h"
    3430#include <stdlib.h>
    3531#include <string.h>
    36 #include <errno.h>
    37 #include <fcntl.h>
    38 #if defined(_MSC_VER)
    39 # include <ctype.h>
    40 # include <io.h>
    41 # include <direct.h>
    42 # include <process.h>
    43 #else
    44 # include <unistd.h>
     32#include <ctype.h>
     33
     34#ifndef KBUILD_OS_WINDOWS
     35# error "KBUILD_OS_WINDOWS not defined"
    4536#endif
    4637
    47 #ifdef __OS2__
    48 # define INCL_BASE
    49 # include <os2.h>
    50 # ifndef LIBPATHSTRICT
    51 #  define LIBPATHSTRICT 3
    52 # endif
    53 #endif
    54 
    55 
    56 /*********************************************************************************************************************************
    57 *   Global Variables                                                                                                             *
    58 *********************************************************************************************************************************/
    59 /** Number of times the '-v' switch was seen. */
    60 static unsigned g_cVerbosity = 0;
    61 
    62 
    63 #if defined(_MSC_VER)
    6438
    6539/**
     
    9771 * Replaces arguments in need of quoting.
    9872 *
    99  * This will "leak" the original and/or the replacement string, depending on
    100  * how you look at it.
    101  *
    10273 * For details on how MSC parses the command line, see "Parsing C Command-Line
    10374 * Arguments": http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
     
    10879 *                              OpenWatcom tools.  They seem to follow some
    10980 *                              ancient or home made quoting convention.
    110  * @param   pStdErr             For verbose debug info.
    111  */
    112 static void quoteArguments(int argc, char **argv, int fWatcomBrainDamage, FILE *pStdErr)
     81 * @param   fFreeOrLeak         Whether to free replaced argv members
     82 *                              (non-zero), or just leak them (zero).  This
     83 *                              depends on which argv you're working on.
     84 *                              Suggest doing the latter if it's main()'s argv.
     85 */
     86void quote_argv(int argc, char **argv, int fWatcomBrainDamage, int fFreeOrLeak)
    11387{
    11488    int i;
    11589    for (i = 0; i < argc; i++)
    11690    {
    117         const char *pszOrgOrg = argv[i];
     91        char *const pszOrgOrg = argv[i];
    11892        const char *pszOrg    = pszOrgOrg;
    11993        size_t      cchOrg    = strlen(pszOrg);
     
    219193            *pszNew++ = '"';
    220194            *pszNew = '\0';
    221         }
    222 
    223         if (g_cVerbosity > 0)
    224         {
    225             if (argv[i] == pszOrgOrg)
    226                 fprintf(pStdErr, "kmk_redirect: debug: argv[%i]=%s<eos>\n", i, pszOrgOrg);
    227             else
    228             {
    229                 fprintf(pStdErr, "kmk_redirect: debug: argv[%i]=%s<eos>\n", i, argv[i]);
    230                 fprintf(pStdErr, "kmk_redirect: debug:(orig[%i]=%s<eos>)\n", i, pszOrgOrg);
    231             }
     195
     196            if (fFreeOrLeak)
     197                free(pszOrgOrg);
    232198        }
    233199    }
     
    236202}
    237203
    238 
    239 /** Used by safeCloseFd. */
    240 static void __cdecl ignore_invalid_parameter(const wchar_t *a, const wchar_t *b, const wchar_t *c, unsigned d, uintptr_t e)
    241 {
    242 }
    243 
    244 #endif /* _MSC_VER */
    245 
    246 
    247 /**
    248  * Safely works around MS CRT's pedantic close() function.
    249  *
    250  * @param   fd      The file handle.
    251  */
    252 static void safeCloseFd(int fd)
    253 {
    254 #ifdef _MSC_VER
    255     _invalid_parameter_handler pfnOld = _get_invalid_parameter_handler();
    256     _set_invalid_parameter_handler(ignore_invalid_parameter);
    257     close(fd);
    258     _set_invalid_parameter_handler(pfnOld);
    259 #else
    260     close(fd);
    261 #endif
    262 }
    263 
    264 
    265 static const char *name(const char *pszName)
    266 {
    267     const char *psz = strrchr(pszName, '/');
    268 #if defined(_MSC_VER) || defined(__OS2__)
    269     const char *psz2 = strrchr(pszName, '\\');
    270     if (!psz2)
    271         psz2 = strrchr(pszName, ':');
    272     if (psz2 && (!psz || psz2 > psz))
    273         psz = psz2;
    274 #endif
    275     return psz ? psz + 1 : pszName;
    276 }
    277 
    278 
    279 static int usage(FILE *pOut,  const char *argv0)
    280 {
    281     fprintf(pOut,
    282             "usage: %s [-[rwa+tb]<fd> <file>] [-c<fd>] [-Z] [-E <var=val>] [-C <dir>] [--wcc-brain-damage] [-v] -- <program> [args]\n"
    283             "   or: %s --help\n"
    284             "   or: %s --version\n"
    285             "\n"
    286             "The rwa+tb is like for fopen, if not specified it defaults to w+.\n"
    287             "The <fd> is either a number or an alias for the standard handles:\n"
    288             "   i = stdin\n"
    289             "   o = stdout\n"
    290             "   e = stderr\n"
    291             "\n"
    292             "The -c switch will close the specified file descriptor.\n"
    293             "\n"
    294             "The -Z switch zaps the environment.\n"
    295             "\n"
    296             "The -E switch is for making changes to the environment in a putenv\n"
    297             "fashion.\n"
    298             "\n"
    299             "The -C switch is for changing the current directory. This takes immediate\n"
    300             "effect, so be careful where you put it.\n"
    301             "\n"
    302             "The --wcc-brain-damage switch is to work around wcc and wcc386 (Open Watcom)\n"
    303             "not following normal quoting conventions on Windows, OS/2, and DOS.\n"
    304             "\n"
    305             "The -v switch is for making the thing more verbose.\n"
    306             "\n"
    307             "This command was originally just a quick hack to avoid invoking the shell\n"
    308             "on Windows (cygwin) where forking is very expensive and has exhibited\n"
    309             "stability issues on SMP machines.  It has since grown into something like\n"
    310             "/usr/bin/env on steroids.\n"
    311             ,
    312             argv0, argv0, argv0);
    313     return 1;
    314 }
    315 
    316 
    317 int main(int argc, char **argv, char **envp)
    318 {
    319     int i;
    320 #if defined(_MSC_VER)
    321     intptr_t rc;
    322 #else
    323     int j;
    324 #endif
    325     FILE *pStdErr = stderr;
    326     FILE *pStdOut = stdout;
    327     int fWatcomBrainDamage = 0;
    328 
    329     /*
    330      * Parse arguments.
    331      */
    332     if (argc <= 1)
    333         return usage(pStdErr, name(argv[0]));
    334     for (i = 1; i < argc; i++)
    335     {
    336         if (argv[i][0] == '-')
    337         {
    338             int fd;
    339             int fdOpened;
    340             int fOpen;
    341             char *psz = &argv[i][1];
    342             if (*psz == '-')
    343             {
    344                 /* '--' ? */
    345                 if (!psz[1])
    346                 {
    347                     i++;
    348                     break;
    349                 }
    350 
    351                 /* convert to short. */
    352                 if (!strcmp(psz, "-help"))
    353                     psz = "h";
    354                 else if (!strcmp(psz, "-version"))
    355                     psz = "V";
    356                 else if (!strcmp(psz, "-env"))
    357                     psz = "E";
    358                 else if (!strcmp(psz, "-chdir"))
    359                     psz = "C";
    360                 else if (!strcmp(psz, "-zap-env"))
    361                     psz = "Z";
    362                 else if (!strcmp(psz, "-close"))
    363                     psz = "c";
    364                 else if (!strcmp(psz, "-wcc-brain-damage"))
    365                 {
    366                     fWatcomBrainDamage = 1;
    367                     continue;
    368                 }
    369             }
    370 
    371             /*
    372              * Deal with the obligatory help and version switches first.
    373              */
    374             if (*psz == 'h')
    375             {
    376                 usage(pStdOut, name(argv[0]));
    377                 return 0;
    378             }
    379             if (*psz == 'V')
    380             {
    381                 printf("kmk_redirect - kBuild version %d.%d.%d (r%u)\n"
    382                        "Copyright (C) 2007-2012 knut st. osmundsen\n",
    383                        KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH,
    384                        KBUILD_SVN_REV);
    385                 return 0;
    386             }
    387 
    388             /*
    389              * Environment switch?
    390              */
    391             if (*psz == 'E')
    392             {
    393                 psz++;
    394                 if (*psz == ':' || *psz == '=')
    395                     psz++;
    396                 else
    397                 {
    398                     if (i + 1 >= argc)
    399                     {
    400                         fprintf(pStdErr, "%s: syntax error: no argument for %s\n", name(argv[0]), argv[i]);
    401                         return 1;
    402                     }
    403                     psz = argv[++i];
    404                 }
    405 #ifdef __OS2__
    406                 if (    !strncmp(psz, "BEGINLIBPATH=",  sizeof("BEGINLIBPATH=") - 1)
    407                     ||  !strncmp(psz, "ENDLIBPATH=",    sizeof("ENDLIBPATH=") - 1)
    408                     ||  !strncmp(psz, "LIBPATHSTRICT=", sizeof("LIBPATHSTRICT=") - 1))
    409                 {
    410                     ULONG ulVar = *psz == 'B' ? BEGIN_LIBPATH
    411                                 : *psz == 'E' ? END_LIBPATH
    412                                 :               LIBPATHSTRICT;
    413                     const char *pszVal = strchr(psz, '=') + 1;
    414                     APIRET rc = DosSetExtLIBPATH(pszVal, ulVar);
    415                     if (rc)
    416                     {
    417                         fprintf(pStdErr, "%s: error: DosSetExtLibPath(\"%s\", %.*s (%lu)): %lu\n",
    418                                 name(argv[0]), pszVal, pszVal - psz - 1, psz, ulVar, rc);
    419                         return 1;
    420                     }
    421                 }
    422                 else
    423 #endif /* __OS2__ */
    424                 {
    425                     const char *pchEqual = strchr(psz, '=');
    426                     if (pchEqual && pchEqual[1] != '\0')
    427                     {
    428                         if (putenv(psz))
    429                         {
    430                             fprintf(pStdErr, "%s: error: putenv(\"%s\"): %s\n", name(argv[0]), psz, strerror(errno));
    431                             return 1;
    432                         }
    433                     }
    434                     else
    435                     {
    436                         size_t cchVar = pchEqual ? (size_t)(pchEqual - psz) : strlen(psz);
    437                         char *pszCopy = (char *)malloc(cchVar + 2);
    438                         memcpy(pszCopy, psz, cchVar);
    439 
    440 #if defined(_MSC_VER) || defined(__OS2__)
    441                         pszCopy[cchVar] = '=';
    442                         pszCopy[cchVar + 1] = '\0';
    443                         if (putenv(pszCopy))
    444                         {
    445                             fprintf(pStdErr, "%s: error: putenv(\"%s\"): %s\n", name(argv[0]), pszCopy, strerror(errno));
    446                             return 1;
    447                         }
    448 #else
    449                         pszCopy[cchVar] = '\0';
    450                         if (unsetenv(pszCopy))
    451                         {
    452                             fprintf(pStdErr, "%s: error: unsetenv(\"%s\"): %s\n", name(argv[0]), pszCopy, strerror(errno));
    453                             return 1;
    454                         }
    455 #endif
    456                         free(pszCopy);
    457                     }
    458                 }
    459                 continue;
    460             }
    461 
    462             /*
    463              * Change directory switch?
    464              */
    465             if (*psz == 'C')
    466             {
    467                 psz++;
    468                 if (*psz == ':' || *psz == '=')
    469                     psz++;
    470                 else
    471                 {
    472                     if (i + 1 >= argc)
    473                     {
    474                         fprintf(pStdErr, "%s: syntax error: no argument for %s\n", name(argv[0]), argv[i]);
    475                         return 1;
    476                     }
    477                     psz = argv[++i];
    478                 }
    479                 if (!chdir(psz))
    480                     continue;
    481 #ifdef _MSC_VER
    482                 {
    483                     /* drop trailing slash if any. */
    484                     size_t cch = strlen(psz);
    485                     if (    cch > 2
    486                         &&  (psz[cch - 1] == '/' || psz[cch - 1] == '\\')
    487                         &&  psz[cch - 1] != ':')
    488                     {
    489                         int rc2;
    490                         char *pszCopy = strdup(psz);
    491                         do  pszCopy[--cch] = '\0';
    492                         while (    cch > 2
    493                                &&  (pszCopy[cch - 1] == '/' || pszCopy[cch - 1] == '\\')
    494                                &&  pszCopy[cch - 1] != ':');
    495                         rc2 = chdir(pszCopy);
    496                         free(pszCopy);
    497                         if (!rc2)
    498                             continue;
    499                     }
    500                 }
    501 #endif
    502                 fprintf(pStdErr, "%s: error: chdir(\"%s\"): %s\n", name(argv[0]), psz, strerror(errno));
    503                 return 1;
    504             }
    505 
    506             /*
    507              * Zap environment switch?
    508              * This is a bit of a hack.
    509              */
    510             if (*psz == 'Z')
    511             {
    512                 unsigned j = 0;
    513                 while (envp[j] != NULL)
    514                     j++;
    515                 while (j-- > 0)
    516                 {
    517                     char *pszEqual = strchr(envp[j], '=');
    518                     char *pszCopy;
    519 
    520                     if (pszEqual)
    521                         *pszEqual = '\0';
    522                     pszCopy = strdup(envp[j]);
    523                     if (pszEqual)
    524                         *pszEqual = '=';
    525 
    526 #if defined(_MSC_VER) || defined(__OS2__)
    527                     putenv(pszCopy);
    528 #else
    529                     unsetenv(pszCopy);
    530 #endif
    531                     free(pszCopy);
    532                 }
    533                 continue;
    534             }
    535 
    536             /*
    537              * Verbose operation switch?
    538              */
    539             if (*psz == 'v')
    540             {
    541                 g_cVerbosity++;
    542                 continue;
    543             }
    544 
    545             /*
    546              * Close the specified file descriptor (no stderr/out/in aliases).
    547              */
    548             if (*psz == 'c')
    549             {
    550                 psz++;
    551                 if (!*psz)
    552                 {
    553                     i++;
    554                     if (i >= argc)
    555                     {
    556                         fprintf(pStdErr, "%s: syntax error: missing filename argument.\n", name(argv[0]));
    557                         return 1;
    558                     }
    559                     psz = argv[i];
    560                 }
    561 
    562                 fd = (int)strtol(psz, &psz, 0);
    563                 if (!fd || *psz)
    564                 {
    565                     fprintf(pStdErr, "%s: error: failed to convert '%s' to a number\n", name(argv[0]), argv[i]);
    566                     return 1;
    567 
    568                 }
    569                 if (fd < 0)
    570                 {
    571                     fprintf(pStdErr, "%s: error: negative fd %d (%s)\n", name(argv[0]), fd, argv[i]);
    572                     return 1;
    573                 }
    574                 /** @todo deal with stderr */
    575                 safeCloseFd(fd);
    576                 continue;
    577             }
    578 
    579             /*
    580              * Parse a file descriptor argument.
    581              */
    582 
    583             /* mode */
    584             switch (*psz)
    585             {
    586                 case 'r':
    587                     psz++;
    588                     if (*psz == '+')
    589                     {
    590                         fOpen = O_RDWR;
    591                         psz++;
    592                     }
    593                     else
    594                         fOpen = O_RDONLY;
    595                     break;
    596 
    597                 case 'w':
    598                     psz++;
    599                     if (*psz == '+')
    600                     {
    601                         psz++;
    602                         fOpen = O_RDWR | O_CREAT | O_TRUNC;
    603                     }
    604                     else
    605                         fOpen = O_WRONLY | O_CREAT | O_TRUNC;
    606                     break;
    607 
    608                 case 'a':
    609                     psz++;
    610                     if (*psz == '+')
    611                     {
    612                         psz++;
    613                         fOpen = O_RDWR | O_CREAT | O_APPEND;
    614                     }
    615                     else
    616                         fOpen = O_WRONLY | O_CREAT | O_APPEND;
    617                     break;
    618 
    619                 case 'i': /* make sure stdin is read-only. */
    620                     fOpen = O_RDONLY;
    621                     break;
    622 
    623                 case '+':
    624                     fprintf(pStdErr, "%s: syntax error: Unexpected '+' in '%s'\n", name(argv[0]), argv[i]);
    625                     return 1;
    626 
    627                 default:
    628                     fOpen = O_RDWR | O_CREAT | O_TRUNC;
    629                     break;
    630             }
    631 
    632             /* binary / text modifiers */
    633             switch (*psz)
    634             {
    635                 case 'b':
    636 #ifdef O_BINARY
    637                     fOpen |= O_BINARY;
    638 #endif
    639                     psz++;
    640                     break;
    641 
    642                 case 't':
    643 #ifdef O_TEXT
    644                     fOpen |= O_TEXT;
    645 #endif
    646                     psz++;
    647                     break;
    648 
    649                 default:
    650 #ifdef O_BINARY
    651                     fOpen |= O_BINARY;
    652 #endif
    653                     break;
    654 
    655             }
    656 
    657             /* convert to file descriptor number */
    658             switch (*psz)
    659             {
    660                 case 'i':
    661                     fd = 0;
    662                     psz++;
    663                     break;
    664 
    665                 case 'o':
    666                     fd = 1;
    667                     psz++;
    668                     break;
    669 
    670                 case 'e':
    671                     fd = 2;
    672                     psz++;
    673                     break;
    674 
    675                 case '0':
    676                     if (!psz[1])
    677                     {
    678                         fd = 0;
    679                         psz++;
    680                         break;
    681                     }
    682                 case '1':
    683                 case '2':
    684                 case '3':
    685                 case '4':
    686                 case '5':
    687                 case '6':
    688                 case '7':
    689                 case '8':
    690                 case '9':
    691                     fd = (int)strtol(psz, &psz, 0);
    692                     if (!fd)
    693                     {
    694                         fprintf(pStdErr, "%s: error: failed to convert '%s' to a number\n", name(argv[0]), argv[i]);
    695                         return 1;
    696 
    697                     }
    698                     if (fd < 0)
    699                     {
    700                         fprintf(pStdErr, "%s: error: negative fd %d (%s)\n", name(argv[0]), fd, argv[i]);
    701                         return 1;
    702                     }
    703                     break;
    704 
    705                 /*
    706                  * Invalid argument.
    707                  */
    708                 default:
    709                     fprintf(pStdErr, "%s: error: failed to convert '%s' ('%s') to a file descriptor\n", name(argv[0]), psz, argv[i]);
    710                     return 1;
    711             }
    712 
    713             /*
    714              * Check for the filename.
    715              */
    716             if (*psz)
    717             {
    718                 if (*psz != ':' && *psz != '=')
    719                 {
    720                     fprintf(pStdErr, "%s: syntax error: characters following the file descriptor: '%s' ('%s')\n", name(argv[0]), psz, argv[i]);
    721                     return 1;
    722                 }
    723                 psz++;
    724             }
    725             else
    726             {
    727                 i++;
    728                 if (i >= argc)
    729                 {
    730                     fprintf(pStdErr, "%s: syntax error: missing filename argument.\n", name(argv[0]));
    731                     return 1;
    732                 }
    733                 psz = argv[i];
    734             }
    735 
    736             /*
    737              * Setup the redirection.
    738              */
    739             if (fd == fileno(pStdErr))
    740             {
    741                 /*
    742                  * Move stderr to a new location, making it close on exec.
    743                  * If pStdOut has already teamed up with pStdErr, update it too.
    744                  */
    745                 FILE *pNew;
    746                 fdOpened = dup(fileno(pStdErr));
    747                 if (fdOpened == -1)
    748                 {
    749                     fprintf(pStdErr, "%s: error: failed to dup stderr (%d): %s\n", name(argv[0]), fileno(pStdErr), strerror(errno));
    750                     return 1;
    751                 }
    752 #ifdef _MSC_VER
    753                 /** @todo figure out how to make the handle close-on-exec. We'll simply close it for now.
    754                  * SetHandleInformation + set FNOINHERIT in CRT.
    755                  */
    756 #else
    757                 if (fcntl(fdOpened, F_SETFD, FD_CLOEXEC) == -1)
    758                 {
    759                     fprintf(pStdErr, "%s: error: failed to make stderr (%d) close-on-exec: %s\n", name(argv[0]), fdOpened, strerror(errno));
    760                     return 1;
    761                 }
    762 #endif
    763 
    764                 pNew = fdopen(fdOpened, "w");
    765                 if (!pNew)
    766                 {
    767                     fprintf(pStdErr, "%s: error: failed to fdopen the new stderr (%d): %s\n", name(argv[0]), fdOpened, strerror(errno));
    768                     return 1;
    769                 }
    770                 if (pStdOut == pStdErr)
    771                     pStdOut = pNew;
    772                 pStdErr = pNew;
    773             }
    774             else if (fd == 1 && pStdOut != pStdErr)
    775                 pStdOut = pStdErr;
    776 
    777             /*
    778              * Close and open the new file descriptor.
    779              */
    780             safeCloseFd(fd);
    781 #if defined(_MSC_VER)
    782             if (!strcmp(psz, "/dev/null"))
    783                 psz = (char *)"nul";
    784 #endif
    785             fdOpened = open(psz, fOpen, 0666);
    786             if (fdOpened == -1)
    787             {
    788                 fprintf(pStdErr, "%s: error: failed to open '%s' as %d: %s\n", name(argv[0]), psz, fd, strerror(errno));
    789                 return 1;
    790             }
    791             if (fdOpened != fd)
    792             {
    793                 /* move it (dup2 returns 0 on MSC). */
    794                 if (dup2(fdOpened, fd) == -1)
    795                 {
    796                     fprintf(pStdErr, "%s: error: failed to dup '%s' as %d: %s\n", name(argv[0]), psz, fd, strerror(errno));
    797                     return 1;
    798                 }
    799                 close(fdOpened);
    800             }
    801         }
    802         else
    803         {
    804             fprintf(pStdErr, "%s: syntax error: Invalid argument '%s'.\n", name(argv[0]), argv[i]);
    805             return usage(pStdErr, name(argv[0]));
    806         }
    807     }
    808 
    809     /*
    810      * Make sure there's something to execute.
    811      */
    812     if (i >= argc)
    813     {
    814         fprintf(pStdErr, "%s: syntax error: nothing to execute!\n", name(argv[0]));
    815         return usage(pStdErr, name(argv[0]));
    816     }
    817 
    818 #if defined(_MSC_VER)
    819     if (fileno(pStdErr) != 2) /* no close-on-exec flag on windows */
    820     {
    821         fclose(pStdErr);
    822         pStdErr = NULL;
    823     }
    824 
    825     /* MSC is a PITA since it refuses to quote the arguments... */
    826     quoteArguments(argc - i, &argv[i], fWatcomBrainDamage, pStdErr);
    827     rc = _spawnvp(_P_WAIT, argv[i], &argv[i]);
    828     if (rc == -1 && pStdErr)
    829     {
    830         fprintf(pStdErr, "%s: error: _spawnvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno));
    831         rc = 1;
    832     }
    833     return rc;
    834 #else
    835     if (g_cVerbosity > 0)
    836         for (j = i; j < argc; j++)
    837             fprintf(pStdErr, "kmk_redirect: debug: argv[%i]=%s<eos>\n", j - i, argv[j]);
    838     execvp(argv[i], &argv[i]);
    839     fprintf(pStdErr, "%s: error: _execvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno));
    840     return 1;
    841 #endif
    842 }
    843 
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette