Author: mladen.turk(a)jboss.com
Date: 2008-04-01 14:39:17 -0400 (Tue, 01 Apr 2008)
New Revision: 1493
Modified:
trunk/build/install/xtool/xtool.c
Log:
Add mktemp and exec tools
Modified: trunk/build/install/xtool/xtool.c
===================================================================
--- trunk/build/install/xtool/xtool.c 2008-04-01 14:03:40 UTC (rev 1492)
+++ trunk/build/install/xtool/xtool.c 2008-04-01 18:39:17 UTC (rev 1493)
@@ -88,7 +88,10 @@
#define DEFAULT_HASH_SIZE 256
/* Maximum size for environment expansion */
#define INFO_BUFFER_SIZE 32767
+/* This is used to cache lengths in x_strvcat */
+#define MAX_SAVED_LENGTHS 8
+
/*
* Alignment macros
*/
@@ -169,7 +172,7 @@
int utf8_to_unicode(wchar_t *, size_t, const char *);
int unicode_to_utf8(char *, size_t, const wchar_t* srcstr);
int x_wfullpath(wchar_t *, size_t, const char *);
-
+char *x_forwardslash(char *);
/*
* ---------------------------------------------------------------------
* end of forward declrations
@@ -291,7 +294,7 @@
static void *x_malloc(size_t size)
{
- void *p = malloc(size);
+ void *p = calloc(1, size);
if (p == NULL) {
perror("malloc");
_exit(ENOMEM);
@@ -319,6 +322,43 @@
return m;
}
+static char **a_alloc(size_t size)
+{
+ if (size)
+ return (char **)x_malloc((size + 1) * sizeof(char *));
+ else {
+ errno = EINVAL;
+ return NULL;
+ }
+}
+
+static void a_free(char **array)
+{
+ char **ptr = array;
+
+ if (!array)
+ return;
+ while (*ptr != NULL) {
+ x_free(*(ptr++));
+ }
+ x_free(array);
+}
+
+static size_t a_size(const char **array)
+{
+ const char **ptr = array;
+ if (array) {
+ size_t siz = 0;
+ while (*ptr != NULL) {
+ ptr++;
+ siz++;
+ }
+ return siz;
+ }
+ else
+ return 0;
+}
+
static char *x_strdup(const char *s)
{
char *p;
@@ -334,6 +374,19 @@
return p;
}
+static char *x_strndup(const char *s, size_t size)
+{
+ char *p;
+
+ if (s == NULL)
+ return NULL;
+ if (strlen(s) < size)
+ size = strlen(s);
+ p = (char *)x_malloc(size + 2);
+ memcpy(p, s, size);
+ return p;
+}
+
static wchar_t *x_wstrdup_utf8(const char *str)
{
int len;
@@ -407,29 +460,51 @@
static char *x_strvcat(const char *str, ...)
{
- char *dst = NULL;
- const char *ptr = str;
- size_t len = 0;
- va_list v;
- if (!str)
- return NULL;
- va_start(v, str);
- while (ptr) {
- len += strlen(ptr);
- ptr = va_arg(v, const char *);
+ char *cp, *argp, *res;
+ size_t saved_lengths[MAX_SAVED_LENGTHS];
+ int nargs = 0;
+
+ /* Pass one --- find length of required string */
+
+ size_t len = strlen(str);
+ va_list adummy;
+
+ va_start(adummy, str);
+ saved_lengths[nargs++] = len;
+ while ((cp = va_arg(adummy, char *)) != NULL) {
+ size_t cplen = strlen(cp);
+ if (nargs < MAX_SAVED_LENGTHS) {
+ saved_lengths[nargs++] = cplen;
+ }
+ len += cplen;
}
- va_end(v);
- dst = x_malloc(len + 2);
- *dst = '\0';
- ptr = str;
- va_start(v, str);
- while (ptr) {
- strcat(dst, ptr);
- ptr = va_arg(v, const char *);
+ va_end(adummy);
+
+ /* Allocate the required string */
+ res = (char *)x_malloc(len + 2);
+ cp = res;
+
+ /* Pass two --- copy the argument strings into the result space */
+ va_start(adummy, str);
+
+ nargs = 0;
+ len = saved_lengths[nargs++];
+ memcpy(cp, str, len);
+ cp += len;
+
+ while ((argp = va_arg(adummy, char *)) != NULL) {
+ if (nargs < MAX_SAVED_LENGTHS) {
+ len = saved_lengths[nargs++];
+ }
+ else {
+ len = strlen(argp);
+ }
+ memcpy(cp, argp, len);
+ cp += len;
}
- va_end(v);
- dst[len + 1] = '\0';
- return dst;
+
+ va_end(adummy);
+ return res;
}
static char *x_strcat(char *dst, const char *add)
@@ -540,7 +615,8 @@
/* Match = 0, NoMatch = 1, Abort = -1
* Based loosely on sections of wildmat.c by Rich Salz
*/
-static int wildchar_match(const char *str, const char *exp, int icase)
+static int wchrmatch(const char *str, const char *exp,
+ size_t *match, int icase)
{
int x, y;
@@ -553,16 +629,22 @@
return 0;
while (str[x]) {
int ret;
- if ((ret = wildchar_match(&str[x++], &exp[y], icase)) != 1)
+ if (match)
+ *match = (size_t)x;
+ if ((ret = wchrmatch(&str[x++], &exp[y], match, icase)) != 1)
return ret;
}
+ if (match)
+ *match = 0;
return -1;
}
else if (exp[y] != '?') {
- if (icase && (tolower(str[x]) != tolower(exp[y])))
+ if (icase) {
+ if (tolower((unsigned char)str[x]) != tolower((unsigned char)exp[y]))
+ return 1;
+ }
+ else if (str[x] != exp[y])
return 1;
- else if (!icase && str[x] != exp[y])
- return 1;
}
}
return (str[x] != '\0');
@@ -600,7 +682,7 @@
/* Reject all ctrl codes... Escape \n and \r (ascii 10 and 13) */
0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = >
? */
- 1,1,2,1,3,3,3,3,3,3,2,1,1,1,1,0, 1,1,1,1,1,1,1,1,1,1,0,3,2,1,2,2,
+ 1,1,2,1,3,3,3,3,3,3,2,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,0,3,2,1,2,2,
/* @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,3,2,3,3,1,
/* ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ */
@@ -692,6 +774,319 @@
/*
* ---------------------------------------------------------------------
+ * begin of path utilities
+ * ---------------------------------------------------------------------
+ */
+
+static const char *posixmatch[] = {
+ "/cygdrive/?/*",
+ "/dev/fs/?/*",
+ "/bin/*",
+ "/dev/*",
+ "/etc/*",
+ "/home/*",
+ "/lib/*",
+ "/opt/*",
+ "/proc/*",
+ "/usr/*",
+ "/tmp/*",
+ "/var/*",
+ NULL
+};
+
+static char windrive[] = { '\0', ':', '\\',
'\0'};
+static char *posixroot = NULL;
+static char *msvcpath = NULL;
+
+static int checkposix(const char *str)
+{
+ const char *equ;
+ const char **mp = posixmatch;
+
+ if ((equ = strchr(str, '='))) {
+ /* Special case for environment variables */
+ if (*(equ + 1) == '/' && equ < strchr(str, '/'))
+ str = equ + 1;
+ }
+ while (*mp) {
+ if (wchrmatch(str, *mp, NULL, 1) == 0) {
+ return 1;
+ }
+ mp++;
+ }
+
+ return 0;
+}
+
+static char **tokenizepath(const char *str, size_t *tokens)
+{
+ size_t c = 1;
+ char **array = NULL;
+ const char *b;
+ const char *e;
+ const char *s;
+
+ b = s = str;
+ while ((e = strchr(b, ':'))) {
+ int ch = *(e + 1);
+ if (ch == '/' || ch == '.' || ch == ':' ||
+ ch == '\0') {
+ /* Is the previous token path or flag */
+ if (checkposix(s)) {
+ c++;
+ s = e + 1;
+ }
+ }
+ b = e + 1;
+ }
+ array = a_alloc(c);
+ c = 0;
+ b = s = str;
+ while ((e = strchr(b, ':'))) {
+ int ch = *(e + 1);
+ if (ch == '/' || ch == '.' || ch == ':' ||
+ ch == '\0') {
+ /* Is the previous token path or flag */
+ if (checkposix(s)) {
+ array[c++] = x_strndup(b, e - b);
+ s = e + 1;
+ }
+ }
+ b = e + 1;
+ }
+ array[c++] = x_strdup(s);
+ if (tokens)
+ *tokens = c;
+ return array;
+}
+
+static char *mergepaths(char * const *paths)
+{
+ size_t len = 0;
+ char *rv;
+ char *const *pp;
+
+ pp = paths;
+ while (*pp) {
+ len += (strlen(*pp) + 1);
+ pp++;
+ }
+ rv = x_malloc(len + 1);
+
+ len = 0;
+ pp = paths;
+ while (*pp) {
+ if (len++)
+ strcat(rv, ";");
+ strcat(rv, *pp);
+ pp++;
+ }
+ return rv;
+}
+
+static char *posix2win(const char *str, int reverse)
+{
+ char *rv = NULL;
+ char **pa;
+ size_t i, tokens;
+
+ pa = tokenizepath(str, &tokens);
+ for (i = 0; i < tokens; i++) {
+ size_t mx = 0;
+ char *pp;
+ char *ep = NULL;
+ const char **mp = posixmatch;
+
+ if ((pp = strchr(pa[i], '='))) {
+ /* Special case for environment variables */
+ if (*(pp + 1) == '/' && pp < strchr(pa[i], '/'))
{
+ ep = pa[i];
+ *(pp++) = '\0';
+ }
+ else
+ pp = pa[i];
+ }
+ else
+ pp = pa[i];
+ while (*mp) {
+ size_t match = 0;
+ if (wchrmatch(pp, *mp, &match, 1) == 0) {
+ char *lp = pp + match;
+ const char *wp;
+ if (mx < 2) {
+ /* Absolute path */
+ wp = windrive;
+ lp += (strlen(*mp) - 1);
+ }
+ else {
+ /* Posix internal path */
+ wp = posixroot;
+ }
+ if (reverse) {
+ char *rp = lp;
+ while (IS_FNCHAR(*rp)) {
+ if (*rp == '/')
+ *rp = '\\';
+ rp++;
+ }
+ }
+ rv = pa[i];
+ if (ep)
+ pa[i] = x_strvcat(ep, "=", wp, lp, NULL);
+ else
+ pa[i] = x_strvcat(wp, lp, NULL);
+ x_free(rv);
+ break;
+ }
+ mx++;
+ mp++;
+ }
+
+ }
+ rv = mergepaths(pa);
+ a_free(pa);
+ return rv;
+}
+
+static void reprelative(char *str)
+{
+ size_t match;
+
+ while (wchrmatch(str, "*./*", &match, 1) == 0) {
+ char *ep = str + match;
+ /* Replace till the end of path element */
+ while (IS_FNCHAR(*ep)) {
+ if (*ep == '/')
+ *ep = '\\';
+ ep++;
+ }
+ if (*ep)
+ strcat(str, ep);
+ }
+}
+
+static char *findlibpath(const char *name)
+{
+ HMODULE handle;
+ UINT em;
+
+ em = SetErrorMode(SEM_FAILCRITICALERRORS);
+ if (!(handle = LoadLibraryExA(name, NULL, 0))) {
+ handle = LoadLibraryExA(name, NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH);
+ }
+ SetErrorMode(em);
+
+ if (handle) {
+ char name[MAX_PATH] = { 0 };
+ char *ptr;
+ GetModuleFileNameA(handle, name, MAX_PATH);
+ FreeLibrary(handle);
+ if (ptr = strrchr(name, '\\')) {
+ *ptr = '\0';
+ if (name[1] == ':') {
+ char *rv = x_strdup(name);
+ *rv = toupper((unsigned char)*rv);
+ return rv;
+ }
+ }
+ }
+ return NULL;
+}
+
+static char *getcygdrive(int *drive, int back)
+{
+
+ if (posixroot)
+ return posixroot;
+ posixroot = findlibpath("bash.exe");
+
+ if (posixroot) {
+ char *ptr;
+ if (ptr = strrchr(posixroot, '\\')) {
+ if (!stricmp(ptr, "\\bin")) {
+ *ptr = '\0';
+ if (drive)
+ *drive = *posixroot;
+ if (!back)
+ x_forwardslash(posixroot);
+ }
+ else {
+ x_free(posixroot);
+ posixroot = NULL;
+ }
+ }
+ }
+ return posixroot;
+}
+
+static char *getsuadrive(int *drive, int back)
+{
+ char *sr;
+ if (posixroot)
+ return posixroot;
+
+ if ((sr = getenv("SUA_ROOT"))) {
+ if (strstr(sr, "/dev/fs/")) {
+ char *r;
+ char d[3] = { '\0', ':', '\0' };
+
+ d[0] = *(sr + 8);
+ posixroot = x_strvcat(d, sr + 9, NULL);
+ r = posixroot;
+ while (*r) {
+ if (*r == '/')
+ *r = '\\';
+ r++;
+ }
+ if (*(r - 1) == '\\')
+ *(r - 1) = '\0';
+ if (drive)
+ *drive = d[0];
+ if (!back)
+ x_forwardslash(posixroot);
+ }
+ }
+ return posixroot;
+}
+
+static char *getmsvcpath()
+{
+
+ if (msvcpath)
+ return msvcpath;
+ return (msvcpath = findlibpath("cl.exe"));
+}
+
+static int checkbinary(const char *exe)
+{
+ HMODULE handle;
+ UINT em;
+
+ em = SetErrorMode(SEM_FAILCRITICALERRORS);
+ if (!(handle = LoadLibraryExA(exe, NULL, 0))) {
+ handle = LoadLibraryExA(exe, NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH);
+ }
+ SetErrorMode(em);
+ if (handle) {
+ FreeLibrary(handle);
+ return 1;
+ }
+ else {
+ errno = ENOENT;
+ return 0;
+ }
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * end of path utilities
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * ---------------------------------------------------------------------
* begin of hash
* ---------------------------------------------------------------------
*/
@@ -887,7 +1282,6 @@
CloseHandle(fh);
return NULL;
}
- printf("Opened %S\n", fname);
return f;
}
@@ -1077,15 +1471,15 @@
}
/*
- * Convert all forward slashes to backward slashes
+ * Convert all backward slashes to forward slashes
* in place.
*/
-static char *fixslash(char *s)
+static char *x_forwardslash(char *s)
{
char *c = s;
for (; *c; c++) {
- if (*c == '/')
- *c = '\\';
+ if (*c == '\\')
+ *c = '/';
}
return s;
}
@@ -1862,6 +2256,8 @@
"mkdir", "Creates a new directory(ies)",
"rmdir", "Removes directory(ies)",
"touch", "Change file timestamps",
+ "exec", "Execute program",
+ "mktemp", "Make temporary filename (unique)",
NULL, NULL
};
@@ -1949,6 +2345,34 @@
return retval;
}
+static int prog_exec_usage(int retval)
+{
+ fprintf(stderr, "Usage: %s [OPTION]... program [ARGUMENTS]\n", progname);
+ fprintf(stderr, "Execute program.\n\n");
+ fprintf(stderr, " -c, -C, Replace cygwin paths.\n");
+ fprintf(stderr, " -s, -S, Replace SUA paths.\n");
+ fprintf(stderr, " -r, -R, Replace relative paths.\n");
+ fprintf(stderr, " -e, -E, Keep existing environment.\n");
+ fprintf(stderr, " -f, -F, Use forward slashes.\n\n");
+ fprintf(stderr, " -v, -V, --verbose explain what is being done.\n");
+ fprintf(stderr, " --version output version information and
exit.\n");
+ fprintf(stderr, " -h, -H, --help display this help and exit.\n\n");
+ return retval;
+}
+
+static int prog_mktemp_usage(int retval)
+{
+ fprintf(stderr, "Usage: %s [OPTION]... [TEMPLATE]\n", progname);
+ fprintf(stderr, "Execute program.\n\n");
+ fprintf(stderr, " -d, -D, Make a directory instead file.\n");
+ fprintf(stderr, " -q, -Q, Be quiet.\n");
+ fprintf(stderr, " -u, -U, Unlink file or directory befor
exiting.\n\n");
+ fprintf(stderr, " -v, -V, --verbose explain what is being done.\n");
+ fprintf(stderr, " --version output version information and
exit.\n");
+ fprintf(stderr, " -h, -H, --help display this help and exit.\n\n");
+ return retval;
+}
+
/*
* ---------------------------------------------------------------------
* end of programs usage
@@ -2244,6 +2668,337 @@
return rv;
}
+static BOOL WINAPI console_handler(DWORD ctrl)
+{
+ switch (ctrl) {
+ case CTRL_BREAK_EVENT:
+ return FALSE;
+ case CTRL_C_EVENT:
+ case CTRL_CLOSE_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ return TRUE;
+ break;
+ }
+ return FALSE;
+}
+
+static int prog_exec(int argc, const char **argv, const char **env)
+{
+ int i, ch, rv = 0;
+ int drive = 0;
+ int cygwin = 0;
+ int suawin = 0;
+ int keepenv = 0;
+ int relpath = 0;
+ int back = 1;
+ size_t l, envsize;
+ char **mainenvp = NULL;
+ char **mainargv = NULL;
+ char wcpath[MAX_PATH + 32] = { 0 };
+
+ x_free(__pname);
+ __pname = "exec";
+ while ((ch = getopt(argc, argv, "cCeEfFrRsShHvV")) != EOF) {
+ switch (ch) {
+ case '.':
+ if (!strcmp(optarg, "verbose"))
+ verbose = 1;
+ else if (!strcmp(optarg, "version"))
+ return print_banner(1);
+ else if (!strcmp(optarg, "help"))
+ return prog_exec_usage(0);
+ else
+ return prog_exec_usage(EINVAL);
+ break;
+ case 'v':
+ case 'V':
+ verbose = 1;
+ break;
+ case 'h':
+ case 'H':
+ return prog_exec_usage(0);
+ break;
+ case 'c':
+ case 'C':
+ cygwin = 1;
+ break;
+ case 's':
+ case 'S':
+ suawin = 1;
+ break;
+ case 'e':
+ case 'E':
+ keepenv = 1;
+ break;
+ case 'r':
+ case 'R':
+ relpath = 1;
+ break;
+ case 'f':
+ case 'F':
+ back = 0;
+ windrive[2] = '/';
+ break;
+ case '?':
+ return EINVAL;
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc < 1) {
+ return prog_exec_usage(EINVAL);
+ }
+ if (!stricmp(argv[0], "java") ||
+ !stricmp(argv[0], "jar") ||
+ !stricmp(argv[0], "javac")) {
+ char *jhome = x_strdup(getenv("JAVA_HOME"));
+ if (!jhome) {
+ /* TODO: Figure out the paths from
+ * the registry
+ */
+ rv = errno = ENOENT;
+ perror("JAVA_HOME environment");
+ goto cleanup;
+ }
+ strcpy(wcpath, jhome);
+ strcat(wcpath, "\\bin\\");
+ strcat(wcpath, argv[0]);
+ strcat(wcpath, ".exe");
+ x_free(jhome);
+ }
+ else if (!stricmp(argv[0], "cc") ||
+ !stricmp(argv[0], "make") ||
+ !stricmp(argv[0], "lib") ||
+ !stricmp(argv[0], "link")) {
+ if (!getmsvcpath()) {
+ rv = errno = ENOENT;
+ perror("Microsoft compiler");
+ goto cleanup;
+ }
+ strcpy(wcpath, getmsvcpath());
+ if (!stricmp(argv[0], "cc"))
+ strcat(wcpath, "\\cl.exe");
+ else if (!stricmp(argv[0], "make"))
+ strcat(wcpath, "\\nmake.exe");
+ else if (!stricmp(argv[0], "lib"))
+ strcat(wcpath, "\\lib.exe");
+ else
+ strcat(wcpath, "\\link.exe");
+ }
+
+ if (cygwin) {
+ if (!(posixroot = getcygdrive(&drive, back))) {
+ rv = errno = ENOENT;
+ perror("Cygwing drive");
+ goto cleanup;
+ }
+ }
+ else if (suawin) {
+ if (!(posixroot = getsuadrive(&drive, back))) {
+ rv = errno = ENOENT;
+ perror("Posix drive");
+ goto cleanup;
+ }
+ }
+ windrive[0] = drive;
+ if (wcpath[0]) {
+ *argv = wcpath;
+ }
+ mainargv = a_alloc(argc);
+ for (i = 0; i < argc ; i++) {
+ if (cygwin || suawin)
+ mainargv[i] = posix2win(argv[i], back);
+ else {
+ mainargv[i] = x_strdup(argv[i]);
+ if (!back)
+ x_forwardslash(mainargv[i]);
+ }
+ if (relpath && back)
+ reprelative(mainargv[i]);
+ }
+ envsize = a_size(env);
+ mainenvp = a_alloc(envsize);
+ for (l = 0; l < envsize; l++) {
+ if (keepenv)
+ mainenvp[l] = x_strdup(env[l]);
+ else {
+ if (cygwin || suawin)
+ mainenvp[l] = posix2win(env[l], back);
+ else {
+ mainenvp[l] = x_strdup(env[l]);
+ if (!back)
+ x_forwardslash(mainenvp[l]);
+ }
+ }
+ }
+ /* We have a valid environment. Install the console handler */
+ SetConsoleCtrlHandler((PHANDLER_ROUTINE)console_handler, TRUE);
+
+ if (checkbinary(mainargv[0])) {
+ if (verbose)
+ fprintf(stdout, "Executing %s\n", mainargv[0]);
+ rv = _spawnvpe(_P_WAIT, mainargv[0], mainargv, mainenvp);
+ if (verbose)
+ fprintf(stdout, "%s: exit(%d)\n", mainargv[0], rv);
+ }
+ else {
+ rv = errno = ENOENT;
+ perror(mainargv[0]);
+ }
+
+cleanup:
+ a_free(mainenvp);
+ a_free(mainargv);
+ x_free(posixroot);
+ x_free(msvcpath);
+ return rv;
+}
+
+static const unsigned char padchar[] =
+"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static int randseed = 0;
+
+static int prog_mktemp(int argc, const char **argv, const char **env)
+{
+ int ch, rv = 0;
+ char path[MAX_PATH] = { 0 };
+ int silent = 0;
+ int mdir = 0;
+ int unsafe = 0;
+ int randnum;
+ char patern[MAX_PATH];
+ register char *start, *trv, *suffp;
+
+ x_free(__pname);
+ __pname = "mktemp";
+ while ((ch = getopt(argc, argv, "dDqQhHuUvV")) != EOF) {
+ switch (ch) {
+ case '.':
+ if (!strcmp(optarg, "verbose"))
+ verbose = 1;
+ else if (!strcmp(optarg, "version"))
+ return print_banner(1);
+ else if (!strcmp(optarg, "help"))
+ return prog_mktemp_usage(0);
+ else
+ return prog_mktemp_usage(1);
+ break;
+ case 'v':
+ case 'V':
+ verbose = 1;
+ break;
+ case 'h':
+ case 'H':
+ return prog_mktemp_usage(0);
+ break;
+ case 'd':
+ case 'D':
+ mdir = 1;
+ break;
+ case 'q':
+ case 'Q':
+ silent = 1;
+ break;
+ case 'u':
+ case 'U':
+ unsafe = 1;
+ break;
+ case '?':
+ return 1;
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc > 0)
+ x_strncpy(patern, argv[0], MAX_PATH);
+ else
+ strcpy(patern, "tmp.XXXXXXXX");
+
+ if (GetTempPathA(MAX_PATH - strlen(patern) - 1, path) == 0) {
+ if (!silent)
+ perror("Temp Path");
+ return 1;
+ }
+ strcat(path, patern);
+ x_backslash(path);
+ printf("Temp base %s\n", path);
+ for (trv = path; *trv; ++trv)
+ ;
+ suffp = trv;
+ --trv;
+ if (trv < path) {
+ if (!silent) {
+ errno = EINVAL;
+ perror("Temp Path");
+ }
+ return 1;
+ }
+
+ if (randseed == 0) {
+ randseed = (int)time(NULL);
+ srand(randseed);
+ }
+ /* Fill space with random characters */
+ while (*trv == 'X') {
+ randnum = rand() % (sizeof(padchar) - 1);
+ *trv-- = padchar[randnum];
+ }
+ start = trv + 1;
+
+ for (;;) {
+ if (access(path, 0)) {
+ if (errno == ENOENT) {
+ if (mdir) {
+ if (mkdir(path)) {
+ if (!silent)
+ perror(path);
+ return 1;
+ }
+ if (unsafe)
+ rmdir(path);
+ }
+ else {
+ FILE *fp = fopen(path, "w");
+ if (!fp) {
+ if (!silent)
+ perror(path);
+ return 1;
+ }
+ fclose(fp);
+ if (unsafe)
+ unlink(path);
+ }
+ fputs(path, stdout);
+ return 0;
+ }
+ }
+ /* If we have a collision, cycle through the space of filenames */
+ for (trv = start;;) {
+ char *pad;
+ if (*trv == '\0' || trv == suffp) {
+ if (!silent) {
+ errno = EINVAL;
+ perror("Temp Path");
+ }
+ return 1;
+ }
+ pad = strchr((char *)padchar, *trv);
+ if (pad == NULL || !*++pad) {
+ *trv++ = padchar[0];
+ }
+ else {
+ *trv++ = *pad;
+ break;
+ }
+ }
+
+ }
+ return rv;
+}
+
/*
* ---------------------------------------------------------------------
* end of programs
@@ -2274,6 +3029,10 @@
return prog_rmdir(--argc, ++argv, env);
else if (!stricmp(argv[1], "touch"))
return prog_touch(--argc, ++argv, env);
+ else if (!stricmp(argv[1], "exec"))
+ return prog_exec(--argc, ++argv, env);
+ else if (!stricmp(argv[1], "mktemp"))
+ return prog_mktemp(--argc, ++argv, env);
else if (!stricmp(argv[1], "test")) {
argc -= 2;
argv += 2;
@@ -2304,6 +3063,15 @@
}
}
+static void cleanup(void)
+{
+ static int cleared = 0;
+
+ if (cleared++)
+ return;
+ /* Make any cleanup here */
+}
+
int wmain(int argc, const wchar_t **wargv, const wchar_t **wenv)
{
char **argv;
@@ -2312,6 +3080,7 @@
int dupenv;
int rv;
+ atexit(cleanup);
/* Find on what we are running */
GetSystemInfo(&win_osinf);
win_osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);