OSDN Git Service

* cygheap_malloc.h: New file.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / winf.cc
1 /* winf.cc
2
3    Copyright 2003, 2004, 2005, 2006, 2008 Red Hat, Inc.
4
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
7 details. */
8
9 #include "winsup.h"
10 #include <stdlib.h>
11 #include "cygerrno.h"
12 #include "security.h"
13 #include "path.h"
14 #include "fhandler.h"
15 #include "dtable.h"
16 #include "cygheap.h"
17 #include "tls_pbuf.h"
18 #include "winf.h"
19 #include "sys/cygwin.h"
20
21 void
22 linebuf::finish (bool cmdlenoverflow_ok)
23 {
24   if (!ix)
25     add ("", 1);
26   else
27     {
28       if (ix-- > MAXCYGWINCMDLEN && cmdlenoverflow_ok)
29         ix = MAXCYGWINCMDLEN - 1;
30       buf[ix] = '\0';
31     }
32 }
33
34 void
35 linebuf::add (const char *what, int len)
36 {
37   size_t newix = ix + len;
38   if (newix >= alloced || !buf)
39     {
40       alloced += LINE_BUF_CHUNK + newix;
41       buf = (char *) realloc (buf, alloced + 1);
42     }
43   memcpy (buf + ix, what, len);
44   ix = newix;
45   buf[ix] = '\0';
46 }
47
48 void
49 linebuf::prepend (const char *what, int len)
50 {
51   int buflen;
52   size_t newix;
53   if ((newix = ix + len) >= alloced)
54     {
55       alloced += LINE_BUF_CHUNK + newix;
56       buf = (char *) realloc (buf, alloced + 1);
57       buf[ix] = '\0';
58     }
59   if ((buflen = strlen (buf)))
60       memmove (buf + len, buf, buflen + 1);
61   else
62       buf[newix] = '\0';
63   memcpy (buf, what, len);
64   ix = newix;
65 }
66
67 bool
68 linebuf::fromargv (av& newargv, const char *real_path, bool cmdlenoverflow_ok)
69 {
70   bool success = true;
71   for (int i = 0; i < newargv.argc; i++)
72     {
73       char *p = NULL;
74       const char *a;
75
76       newargv.dup_maybe (i);
77       a = i ? newargv[i] : (char *) real_path;
78       int len = strlen (a);
79       if (len != 0 && !strpbrk (a, " \t\n\r\""))
80         add (a, len);
81       else
82         {
83           add ("\"", 1);
84           /* Handle embedded special characters " and \.
85              A " is always preceded by a \.
86              A \ is not special unless it precedes a ".  If it does,
87              then all preceding \'s must be doubled to avoid having
88              the Windows command line parser interpret the \ as quoting
89              the ".  This rule applies to a string of \'s before the end
90              of the string, since cygwin/windows uses a " to delimit the
91              argument. */
92           for (; (p = strpbrk (a, "\"\\")); a = ++p)
93             {
94               add (a, p - a);
95               /* Find length of string of backslashes */
96               int n = strspn (p, "\\");
97               if (!n)
98                 add ("\\\"", 2);        /* No backslashes, so it must be a ".
99                                                The " has to be protected with a backslash. */
100               else
101                 {
102                   add (p, n);   /* Add the run of backslashes */
103                   /* Need to double up all of the preceding
104                      backslashes if they precede a quote or EOS. */
105                   if (!p[n] || p[n] == '"')
106                     add (p, n);
107                   p += n - 1;           /* Point to last backslash */
108                 }
109             }
110           if (*a)
111             add (a);
112           add ("\"", 1);
113         }
114       add (" ", 1);
115     }
116
117   finish (cmdlenoverflow_ok);
118
119   if (ix >= MAXWINCMDLEN)
120     {
121       debug_printf ("command line too long (>32K), return E2BIG");
122       set_errno (E2BIG);
123       success = false;
124     }
125
126   return success;
127 }
128
129 int
130 av::unshift (const char *what, int conv)
131 {
132   char **av;
133   av = (char **) crealloc (argv, (argc + 2) * sizeof (char *));
134   if (!av)
135     return 0;
136
137   argv = av;
138   memmove (argv + 1, argv, (argc + 1) * sizeof (char *));
139   tmp_pathbuf tp;
140   char *buf = tp.c_get ();
141   if (conv)
142     {
143       cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, what, buf,
144                         NT_MAX_PATH);
145       char *p = strchr (buf, '\0') - 4;
146       if (p > buf && ascii_strcasematch (p, ".exe"))
147         *p = '\0';
148       what = buf;
149     }
150   *argv = cstrdup1 (what);
151   calloced++;
152   argc++;
153   return 1;
154 }