]> git.ipfire.org Git - thirdparty/bash.git/blame - bracecomp.c
add more overflow handling for printf builtin; start incorporating C23 stdckdint...
[thirdparty/bash.git] / bracecomp.c
CommitLineData
726f6388
JA
1/* bracecomp.c -- Complete a filename with the possible completions enclosed
2 in csh-style braces such that the list of completions is available to the
3 shell. */
4
5/* Original version by tromey@cns.caltech.edu, Fri Feb 7 1992. */
6
81e3a4fb 7/* Copyright (C) 1993-2020,2022 Free Software Foundation, Inc.
726f6388
JA
8
9 This file is part of GNU Bash, the Bourne Again SHell.
10
2e4498b3
CR
11 Bash is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
726f6388 15
2e4498b3
CR
16 Bash is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
726f6388 20
2e4498b3
CR
21 You should have received a copy of the GNU General Public License
22 along with Bash. If not, see <http://www.gnu.org/licenses/>.
23*/
726f6388 24
ccc6cda3 25#include "config.h"
2e4498b3 26
ccc6cda3
JA
27#if defined (BRACE_EXPANSION) && defined (READLINE)
28
726f6388
JA
29#include <stdio.h>
30
ccc6cda3 31#if defined (HAVE_UNISTD_H)
cce855bc
JA
32# ifdef _MINIX
33# include <sys/types.h>
34# endif
ccc6cda3
JA
35# include <unistd.h>
36#endif
37
d166f048 38#include "bashansi.h"
d356441f 39#include "shmbutil.h"
726f6388
JA
40
41#include "shell.h"
42#include <readline/readline.h>
43
81e3a4fb 44static int _strcompare (const char **, const char **);
d356441f 45
726f6388
JA
46/* Find greatest common prefix of two strings. */
47static int
81e3a4fb 48string_gcd (char *s1, char *s2)
726f6388
JA
49{
50 register int i;
51
52 if (s1 == NULL || s2 == NULL)
53 return (0);
54
55 for (i = 0; *s1 && *s2; ++s1, ++s2, ++i)
56 {
57 if (*s1 != *s2)
58 break;
59 }
60
61 return (i);
62}
63
64static char *
81e3a4fb 65really_munge_braces (char **array, int real_start, int real_end, int gcd_zero)
726f6388
JA
66{
67 int start, end, gcd;
e8ce775d 68 char *result, *subterm, *x;
8fd8cd8f
CR
69 size_t result_size;
70 int flag, tlen;
726f6388
JA
71
72 flag = 0;
73
74 if (real_start == real_end)
75 {
8360b906
CR
76 x = array[real_start] ? sh_backslash_quote (array[real_start] + gcd_zero, 0, 0)
77 : sh_backslash_quote (array[0], 0, 0);
e8ce775d 78 return x;
726f6388
JA
79 }
80
f73dda09 81 result = (char *)xmalloc (result_size = 16);
726f6388
JA
82 *result = '\0';
83
84 for (start = real_start; start < real_end; start = end + 1)
85 {
86 gcd = strlen (array[start]);
87 for (end = start + 1; end < real_end; end++)
88 {
89 int temp;
90
91 temp = string_gcd (array[start], array[end]);
92
93 if (temp <= gcd_zero)
94 break;
95
96 gcd = temp;
97 }
98 end--;
99
100 if (gcd_zero == 0 && start == real_start && end != (real_end - 1))
101 {
102 /* In this case, add in a leading '{', because we are at
103 top level, and there isn't a consistent prefix. */
104 result_size += 1;
f73dda09 105 result = (char *)xrealloc (result, result_size);
d166f048 106 result[0] = '{'; result[1] = '\0';
726f6388
JA
107 flag++;
108 }
109
e8ce775d
JA
110 /* Make sure we backslash quote every substring we insert into the
111 resultant brace expression. This is so the default filename
112 quoting function won't inappropriately quote the braces. */
726f6388 113 if (start == end)
e8ce775d
JA
114 {
115 x = savestring (array[start] + gcd_zero);
8360b906 116 subterm = sh_backslash_quote (x, 0, 0);
e8ce775d
JA
117 free (x);
118 }
726f6388
JA
119 else
120 {
121 /* If there is more than one element in the subarray,
e8ce775d
JA
122 insert the (quoted) prefix and an opening brace. */
123 tlen = gcd - gcd_zero;
f73dda09 124 x = (char *)xmalloc (tlen + 1);
e8ce775d
JA
125 strncpy (x, array[start] + gcd_zero, tlen);
126 x[tlen] = '\0';
8360b906 127 subterm = sh_backslash_quote (x, 0, 0);
e8ce775d
JA
128 free (x);
129 result_size += strlen (subterm) + 1;
f73dda09 130 result = (char *)xrealloc (result, result_size);
e8ce775d
JA
131 strcat (result, subterm);
132 free (subterm);
726f6388
JA
133 strcat (result, "{");
134 subterm = really_munge_braces (array, start, end + 1, gcd);
135 subterm[strlen (subterm) - 1] = '}';
136 }
137
138 result_size += strlen (subterm) + 1;
f73dda09 139 result = (char *)xrealloc (result, result_size);
726f6388
JA
140 strcat (result, subterm);
141 strcat (result, ",");
142 free (subterm);
143 }
144
145 if (gcd_zero == 0)
146 result[strlen (result) - 1] = flag ? '}' : '\0';
147 return (result);
148}
149
d356441f 150static int
81e3a4fb 151_strcompare (const char **s1, const char **s2)
d356441f
CR
152{
153 int result;
154
155 result = **s1 - **s2;
156 if (result == 0)
157 result = strcmp (*s1, *s2);
158
159 return result;
160}
161
28ef6c31 162static int
81e3a4fb 163hack_braces_completion (char **names)
726f6388
JA
164{
165 register int i;
166 char *temp;
167
d356441f
CR
168 i = strvec_len (names);
169 if (MB_CUR_MAX > 1 && i > 2)
170 qsort (names+1, i-1, sizeof (char *), (QSFUNC *)_strcompare);
171
172 temp = really_munge_braces (names, 1, i, 0);
726f6388
JA
173
174 for (i = 0; names[i]; ++i)
175 {
176 free (names[i]);
177 names[i] = NULL;
178 }
179 names[0] = temp;
28ef6c31 180 return 0;
726f6388
JA
181}
182
e8ce775d
JA
183/* We handle quoting ourselves within hack_braces_completion, so we turn off
184 rl_filename_quoting_desired and rl_filename_quoting_function. */
28ef6c31 185int
81e3a4fb 186bash_brace_completion (int count, int ignore)
726f6388 187{
28ef6c31
JA
188 rl_compignore_func_t *orig_ignore_func;
189 rl_compentry_func_t *orig_entry_func;
190 rl_quote_func_t *orig_quoting_func;
191 rl_completion_func_t *orig_attempt_func;
192 int orig_quoting_desired, r;
726f6388
JA
193
194 orig_ignore_func = rl_ignore_some_completions_function;
195 orig_attempt_func = rl_attempted_completion_function;
196 orig_entry_func = rl_completion_entry_function;
e8ce775d
JA
197 orig_quoting_func = rl_filename_quoting_function;
198 orig_quoting_desired = rl_filename_quoting_desired;
726f6388 199
28ef6c31
JA
200 rl_completion_entry_function = rl_filename_completion_function;
201 rl_attempted_completion_function = (rl_completion_func_t *)NULL;
202 rl_ignore_some_completions_function = hack_braces_completion;
203 rl_filename_quoting_function = (rl_quote_func_t *)NULL;
e8ce775d 204 rl_filename_quoting_desired = 0;
726f6388 205
28ef6c31 206 r = rl_complete_internal (TAB);
726f6388
JA
207
208 rl_ignore_some_completions_function = orig_ignore_func;
209 rl_attempted_completion_function = orig_attempt_func;
210 rl_completion_entry_function = orig_entry_func;
e8ce775d
JA
211 rl_filename_quoting_function = orig_quoting_func;
212 rl_filename_quoting_desired = orig_quoting_desired;
28ef6c31
JA
213
214 return r;
726f6388 215}
ccc6cda3 216#endif /* BRACE_EXPANSION && READLINE */