OSDN Git Service

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