| /* winf.cc |
| |
| 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 "path.h" |
| #include "fhandler.h" |
| #include "dtable.h" |
| #include "cygheap.h" |
| #include "tls_pbuf.h" |
| #include "winf.h" |
| #include "sys/cygwin.h" |
| |
| void |
| linebuf::finish (bool cmdlenoverflow_ok) |
| { |
| if (!ix) |
| add ("", 1); |
| else |
| { |
| if (ix-- > MAXCYGWINCMDLEN && cmdlenoverflow_ok) |
| ix = MAXCYGWINCMDLEN - 1; |
| buf[ix] = '\0'; |
| } |
| } |
| |
| 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 |
| linebuf::fromargv (av& newargv, const char *real_path, bool cmdlenoverflow_ok) |
| { |
| bool success = true; |
| for (int i = 0; i < newargv.argc; i++) |
| { |
| char *p = NULL; |
| const char *a; |
| |
| 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); |
| } |
| |
| finish (cmdlenoverflow_ok); |
| |
| 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) |
| { |
| char **av; |
| av = (char **) crealloc (argv, (argc + 2) * sizeof (char *)); |
| if (!av) |
| return 0; |
| |
| argv = av; |
| memmove (argv + 1, argv, (argc + 1) * sizeof (char *)); |
| *argv = cstrdup1 (what); |
| calloced++; |
| argc++; |
| return 1; |
| } |