2006-04-12 23:53:22 +08:00
|
|
|
/* winf.cc
|
|
|
|
|
|
|
|
Copyright 2003, 2004, 2005, 2006 Red Hat, Inc.
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
|
|
|
#include "winsup.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "cygerrno.h"
|
|
|
|
#include "security.h"
|
|
|
|
#include "sync.h"
|
|
|
|
#include "path.h"
|
|
|
|
#include "fhandler.h"
|
|
|
|
#include "dtable.h"
|
|
|
|
#include "cygheap.h"
|
|
|
|
#include "winf.h"
|
|
|
|
#include "sys/cygwin.h"
|
|
|
|
|
|
|
|
void
|
2006-04-13 09:37:00 +08:00
|
|
|
linebuf::finish (bool cmdlenoverflow_ok)
|
2006-04-12 23:53:22 +08:00
|
|
|
{
|
|
|
|
if (!ix)
|
|
|
|
add ("", 1);
|
|
|
|
else
|
2006-04-13 09:37:00 +08:00
|
|
|
{
|
|
|
|
if (ix-- > MAXCYGWINCMDLEN && cmdlenoverflow_ok)
|
|
|
|
ix = MAXCYGWINCMDLEN - 1;
|
|
|
|
buf[ix] = '\0';
|
|
|
|
}
|
2006-04-12 23:53:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
linebuf::add (const char *what, int len)
|
|
|
|
{
|
|
|
|
size_t newix = ix + len;
|
|
|
|
if (newix >= alloced || !buf)
|
|
|
|
{
|
|
|
|
alloced += LINE_BUF_CHUNK + newix;
|
|
|
|
buf = (char *) realloc (buf, alloced + 1);
|
|
|
|
}
|
|
|
|
memcpy (buf + ix, what, len);
|
|
|
|
ix = newix;
|
|
|
|
buf[ix] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
linebuf::prepend (const char *what, int len)
|
|
|
|
{
|
|
|
|
int buflen;
|
|
|
|
size_t newix;
|
|
|
|
if ((newix = ix + len) >= alloced)
|
|
|
|
{
|
|
|
|
alloced += LINE_BUF_CHUNK + newix;
|
|
|
|
buf = (char *) realloc (buf, alloced + 1);
|
|
|
|
buf[ix] = '\0';
|
|
|
|
}
|
|
|
|
if ((buflen = strlen (buf)))
|
|
|
|
memmove (buf + len, buf, buflen + 1);
|
|
|
|
else
|
|
|
|
buf[newix] = '\0';
|
|
|
|
memcpy (buf, what, len);
|
|
|
|
ix = newix;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2006-04-13 09:37:00 +08:00
|
|
|
linebuf::fromargv (av& newargv, char *real_path, bool cmdlenoverflow_ok)
|
2006-04-12 23:53:22 +08:00
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
for (int i = 0; i < newargv.argc; i++)
|
|
|
|
{
|
|
|
|
char *p = NULL;
|
|
|
|
const char *a;
|
|
|
|
|
|
|
|
newargv.dup_maybe (i);
|
|
|
|
a = i ? newargv[i] : (char *) real_path;
|
|
|
|
int len = strlen (a);
|
|
|
|
if (len != 0 && !strpbrk (a, " \t\n\r\""))
|
|
|
|
add (a, len);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
add ("\"", 1);
|
|
|
|
/* Handle embedded special characters " and \.
|
|
|
|
A " is always preceded by a \.
|
|
|
|
A \ is not special unless it precedes a ". If it does,
|
|
|
|
then all preceding \'s must be doubled to avoid having
|
|
|
|
the Windows command line parser interpret the \ as quoting
|
|
|
|
the ". This rule applies to a string of \'s before the end
|
|
|
|
of the string, since cygwin/windows uses a " to delimit the
|
|
|
|
argument. */
|
|
|
|
for (; (p = strpbrk (a, "\"\\")); a = ++p)
|
|
|
|
{
|
|
|
|
add (a, p - a);
|
|
|
|
/* Find length of string of backslashes */
|
|
|
|
int n = strspn (p, "\\");
|
|
|
|
if (!n)
|
|
|
|
add ("\\\"", 2); /* No backslashes, so it must be a ".
|
|
|
|
The " has to be protected with a backslash. */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
add (p, n); /* Add the run of backslashes */
|
|
|
|
/* Need to double up all of the preceding
|
|
|
|
backslashes if they precede a quote or EOS. */
|
|
|
|
if (!p[n] || p[n] == '"')
|
|
|
|
add (p, n);
|
|
|
|
p += n - 1; /* Point to last backslash */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (*a)
|
|
|
|
add (a);
|
|
|
|
add ("\"", 1);
|
|
|
|
}
|
|
|
|
add (" ", 1);
|
|
|
|
}
|
|
|
|
|
2006-04-13 09:37:00 +08:00
|
|
|
finish (cmdlenoverflow_ok);
|
2006-04-12 23:53:22 +08:00
|
|
|
|
|
|
|
if (ix >= MAXWINCMDLEN)
|
|
|
|
{
|
|
|
|
debug_printf ("command line too long (>32K), return E2BIG");
|
|
|
|
set_errno (E2BIG);
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
av::unshift (const char *what, int conv)
|
|
|
|
{
|
|
|
|
char **av;
|
|
|
|
av = (char **) crealloc (argv, (argc + 2) * sizeof (char *));
|
|
|
|
if (!av)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
argv = av;
|
|
|
|
memmove (argv + 1, argv, (argc + 1) * sizeof (char *));
|
|
|
|
char buf[CYG_MAX_PATH];
|
|
|
|
if (conv)
|
|
|
|
{
|
|
|
|
cygwin_conv_to_posix_path (what, buf);
|
|
|
|
char *p = strchr (buf, '\0') - 4;
|
|
|
|
if (p > buf && strcasematch (p, ".exe"))
|
|
|
|
*p = '\0';
|
|
|
|
what = buf;
|
|
|
|
}
|
|
|
|
*argv = cstrdup1 (what);
|
|
|
|
calloced++;
|
|
|
|
argc++;
|
|
|
|
return 1;
|
|
|
|
}
|