github.com/golang-haiku/go-1.4.3@v0.0.0-20190609233734-1f5ae41cc308/src/lib9/run_windows.c (about)

     1  // Copyright 2013 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include <u.h>
     6  #include <windows.h>
     7  #define NOPLAN9DEFINES
     8  #include <libc.h>
     9  #include "win.h"
    10  
    11  int
    12  runcmd(char **argv)
    13  {
    14  	// Mostly copied from ../cmd/dist/windows.c.
    15  	// If there's a bug here, fix the logic there too.
    16  	int i, j, nslash;
    17  	Fmt fmt;
    18  	char *q;
    19  	WinRune *r;
    20  	STARTUPINFOW si;
    21  	PROCESS_INFORMATION pi;
    22  	DWORD code;
    23  
    24  	fmtstrinit(&fmt);
    25  	for(i=0; argv[i]; i++) {
    26  		if(i > 0)
    27  			fmtprint(&fmt, " ");
    28  		q = argv[i];
    29  		if(strstr(q, " ") || strstr(q, "\t") || strstr(q, "\"") || strstr(q, "\\\\") || (strlen(q) > 0 && q[strlen(q)-1] == '\\')) {
    30  			fmtprint(&fmt, "\"");
    31  			nslash = 0;
    32  			for(; *q; q++) {
    33  				if(*q == '\\') {
    34  					nslash++;
    35  					continue;
    36  				}
    37  				if(*q == '"') {
    38  					for(j=0; j<2*nslash+1; j++)
    39  						fmtprint(&fmt, "\\");
    40  					nslash = 0;
    41  				}
    42  				for(j=0; j<nslash; j++)
    43  					fmtprint(&fmt, "\\");
    44  				nslash = 0;
    45  				fmtprint(&fmt, "\"");
    46  			}
    47  			for(j=0; j<2*nslash; j++)
    48  				fmtprint(&fmt, "\\");
    49  			fmtprint(&fmt, "\"");
    50  		} else {
    51  			fmtprint(&fmt, "%s", q);
    52  		}
    53  	}
    54  	
    55  	q = fmtstrflush(&fmt);
    56  	r = torune(q);
    57  	free(q);
    58  
    59  	memset(&si, 0, sizeof si);
    60  	si.cb = sizeof si;
    61  	si.dwFlags = STARTF_USESTDHANDLES;
    62  	si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    63  	si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
    64  
    65  	if(!CreateProcessW(nil, r, nil, nil, TRUE, 0, nil, nil, &si, &pi)) {
    66  		free(r);
    67  		return -1;
    68  	}
    69  
    70  	free(r);
    71  	if(WaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE) != 0)
    72  		return -1;
    73  	i = GetExitCodeProcess(pi.hProcess, &code);
    74  	CloseHandle(pi.hProcess);
    75  	CloseHandle(pi.hThread);
    76  	if(!i)
    77  		return -1;
    78  	if(code != 0) {
    79  		werrstr("unsuccessful exit status: %d", (int)code);
    80  		return -1;
    81  	}
    82  	return 0;
    83  }