New test.
[mono.git] / eglib / src / gshell.c
1 /*
2  * Shell utility functions.
3  *
4  * Author:
5  *   Gonzalo Paniagua Javier (gonzalo@novell.com
6  *
7  * (C) 2006 Novell, Inc.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28 #define _GNU_SOURCE
29 #include <stdio.h>
30 #include <glib.h>
31
32 static int
33 split_cmdline (const gchar *cmdline, GPtrArray *array, GError **error)
34 {
35         gchar *ptr;
36         gchar c;
37         gboolean in_quote = FALSE;
38         gboolean escaped = FALSE;
39         gchar quote_char = '\0';
40         GString *str;
41
42         str = g_string_new ("");
43         ptr = (gchar *) cmdline;
44         while ((c = *ptr++) != '\0') {
45                 if (escaped) {
46                         escaped = FALSE;
47                         if (!g_ascii_isspace (c))
48                                 g_string_append_c (str, c);
49                 } else if (in_quote) {
50                         if (c == quote_char) {
51                                 in_quote = FALSE;
52                                 quote_char = '\0';
53                                 g_ptr_array_add (array, g_string_free (str, FALSE));
54                                 str = g_string_new ("");
55                         } else {
56                                 g_string_append_c (str, c);
57                         }
58                 } else if (g_ascii_isspace (c)) {
59                         if (str->len > 0) {
60                                 g_ptr_array_add (array, g_string_free (str, FALSE));
61                                 str = g_string_new ("");
62                         }
63                 } else if (c == '\\') {
64                         escaped = TRUE;
65                 } else if (c == '\'' || c == '"') {
66                         in_quote = TRUE;
67                         quote_char = c;
68                 } else {
69                         g_string_append_c (str, c);
70                 }
71         }
72
73         if (escaped) {
74                 if (error)
75                         *error = g_error_new (G_LOG_DOMAIN, 0, "Unfinished escape.");
76                 g_string_free (str, TRUE);
77                 return -1;
78         }
79
80         if (in_quote) {
81                 if (error)
82                         *error = g_error_new (G_LOG_DOMAIN, 0, "Unfinished quote.");
83                 g_string_free (str, TRUE);
84                 return -1;
85         }
86
87         if (str->len > 0) {
88                 g_ptr_array_add (array, g_string_free (str, FALSE));
89         } else {
90                 g_string_free (str, TRUE);
91         }
92         g_ptr_array_add (array, NULL);
93         return 0;
94 }
95
96 gboolean
97 g_shell_parse_argv (const gchar *command_line, gint *argcp, gchar ***argvp, GError **error)
98 {
99         GPtrArray *array;
100         gint argc;
101         gchar **argv;
102
103         g_return_val_if_fail (command_line, FALSE);
104         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
105
106         array = g_ptr_array_new();
107         if (split_cmdline (command_line, array, error)) {
108                 g_ptr_array_add (array, NULL);
109                 g_strfreev ((gchar **) array->pdata);
110                 g_ptr_array_free (array, FALSE);
111                 return FALSE;
112         }
113
114         argc = array->len;
115         argv = (gchar **) array->pdata;
116
117         if (argc == 1) {
118                 g_strfreev (argv);
119                 g_ptr_array_free (array, FALSE);
120                 return FALSE;
121         }
122
123         if (argcp) {
124                 *argcp = array->len - 1;
125         }
126
127         if (argvp) {
128                 *argvp = argv;
129         } else {
130                 g_strfreev (argv);
131         }
132
133         g_ptr_array_free (array, FALSE);
134         return TRUE;
135 }
136