aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2014-10-24 10:22:38 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2015-12-17 15:25:24 +0200
commit9dcef9e579d2e06f294dabe7918fe6753054e6cb (patch)
tree6f9b91acf9df5f6f3b1881cc031bcad2fdd98f16 /src
parent49b4b7e2e45bd22992df25ab999cb8c3ed73930f (diff)
downloadgrecs-9dcef9e579d2e06f294dabe7918fe6753054e6cb.tar.gz
grecs-9dcef9e579d2e06f294dabe7918fe6753054e6cb.tar.bz2
wordsplit: implement tilde and pathname expansion
* src/wordsplit.c (wordsplit_tildexpand) (wordsplit_pathexpand): New functions. (wordsplit_process_list): Run tilde and pathname expansion if WRDSF_PATHEXPAND flag is set. * src/wordsplit.h (wordsplit)<ws_options>: New member. (WRDSF_PATHEXPAND): New flag. (WRDSO_NULLGLOB,WRDSO_FAILGLOB) (WRDSO_DOTGLOB): New defines. * tests/wsp.c: New options pathexpand, nullglob, failglob, dotglob. Fix help output.
Diffstat (limited to 'src')
-rw-r--r--src/wordsplit.c214
-rw-r--r--src/wordsplit.h13
2 files changed, 225 insertions, 2 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c
index f0170e1..6b01887 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -25,6 +25,8 @@
25#include <string.h> 25#include <string.h>
26#include <stdio.h> 26#include <stdio.h>
27#include <stdarg.h> 27#include <stdarg.h>
28#include <pwd.h>
29#include <glob.h>
28 30
29#if ENABLE_NLS 31#if ENABLE_NLS
30# include <gettext.h> 32# include <gettext.h>
@@ -1210,6 +1212,195 @@ wordsplit_trimws (struct wordsplit *wsp)
1210} 1212}
1211 1213
1212static int 1214static int
1215wordsplit_tildexpand (struct wordsplit *wsp)
1216{
1217 struct wordsplit_node *p;
1218 char *uname = NULL;
1219 size_t usize = 0;
1220
1221 for (p = wsp->ws_head; p; p = p->next)
1222 {
1223 const char *str;
1224
1225 if (p->flags & _WSNF_QUOTE)
1226 continue;
1227
1228 str = wsnode_ptr (wsp, p);
1229 if (str[0] == '~')
1230 {
1231 size_t i, size, dlen;
1232 size_t slen = wsnode_len (p);
1233 char *dir;
1234 struct passwd *pw;
1235 char *newstr;
1236
1237 for (i = 1; i < slen && str[i] != '/'; i++)
1238 ;
1239 if (i == slen)
1240 continue;
1241 if (i > 1)
1242 {
1243 if (i > usize)
1244 {
1245 char *p = realloc (uname, i);
1246 if (!p)
1247 {
1248 free (uname);
1249 return _wsplt_nomem (wsp);
1250 }
1251 uname = p;
1252 usize = i;
1253 }
1254 --i;
1255 memcpy (uname, str + 1, i);
1256 uname[i] = 0;
1257 pw = getpwnam (uname);
1258 }
1259 else
1260 pw = getpwuid (getuid ());
1261
1262 if (!pw)
1263 continue;
1264
1265 dlen = strlen (pw->pw_dir);
1266 size = slen - i + dlen;
1267 newstr = malloc (size);
1268 if (!newstr)
1269 {
1270 free (uname);
1271 return _wsplt_nomem (wsp);
1272 }
1273 --size;
1274
1275 memcpy (newstr, pw->pw_dir, dlen);
1276 memcpy (newstr + dlen, str + i + 1, slen - i - 1);
1277 newstr[size] = 0;
1278 if (p->flags & _WSNF_WORD)
1279 free (p->v.word);
1280 p->v.word = newstr;
1281 p->flags |= _WSNF_WORD;
1282 }
1283 }
1284 free (uname);
1285}
1286
1287static int
1288isglob (const char *s, int l)
1289{
1290 while (l--)
1291 {
1292 if (strchr ("*?[", *s++))
1293 return 1;
1294 }
1295 return 0;
1296}
1297
1298static int
1299wordsplit_pathexpand (struct wordsplit *wsp)
1300{
1301 struct wordsplit_node *p, *next;
1302 char *pattern = NULL;
1303 size_t patsize = 0;
1304 size_t slen;
1305 char *str;
1306 int flags = 0;
1307
1308#ifdef GLOB_PERIOD
1309 if (wsp->ws_options & WRDSO_DOTGLOB)
1310 flags = GLOB_PERIOD;
1311#endif
1312
1313 for (p = wsp->ws_head; p; p = next)
1314 {
1315 const char *str;
1316
1317 next = p->next;
1318
1319 if (p->flags & _WSNF_QUOTE)
1320 continue;
1321
1322 str = wsnode_ptr (wsp, p);
1323 slen = wsnode_len (p);
1324
1325 if (isglob (str, slen))
1326 {
1327 int i;
1328 glob_t g;
1329 struct wordsplit_node *prev;
1330
1331 if (slen + 1 > patsize)
1332 {
1333 char *p = realloc (pattern, slen + 1);
1334 if (!p)
1335 return _wsplt_nomem (wsp);
1336 pattern = p;
1337 patsize = slen + 1;
1338 }
1339 memcpy (pattern, str, slen);
1340 pattern[slen] = 0;
1341
1342 switch (glob (pattern, flags, NULL, &g))
1343 {
1344 case 0:
1345 break;
1346
1347 case GLOB_NOSPACE:
1348 free (pattern);
1349 return _wsplt_nomem (wsp);
1350
1351 case GLOB_NOMATCH:
1352 if (wsp->ws_options & WRDSO_NULLGLOB)
1353 {
1354 wsnode_remove (wsp, p);
1355 wsnode_free (p);
1356 }
1357 else if (wsp->ws_options & WRDSO_FAILGLOB)
1358 {
1359 char buf[128];
1360 if (wsp->ws_errno == WRDSE_USERERR)
1361 free (wsp->ws_usererr);
1362 snprintf (buf, sizeof (buf), _("no files match pattern %s"),
1363 pattern);
1364 free (pattern);
1365 wsp->ws_usererr = strdup (buf);
1366 if (!wsp->ws_usererr)
1367 return _wsplt_nomem (wsp);
1368 else
1369 return _wsplt_seterr (wsp, WRDSE_USERERR);
1370 }
1371 continue;
1372
1373 default:
1374 free (pattern);
1375 return _wsplt_seterr (wsp, WRDSE_GLOBERR);
1376 }
1377
1378 prev = p;
1379 for (i = 0; i < g.gl_pathc; i++)
1380 {
1381 struct wordsplit_node *newnode;
1382 char *newstr;
1383
1384 if (wsnode_new (wsp, &newnode))
1385 return 1;
1386 newstr = strdup (g.gl_pathv[i]);
1387 if (!newstr)
1388 return _wsplt_nomem (wsp);
1389 newnode->v.word = newstr;
1390 newnode->flags |= _WSNF_WORD|_WSNF_QUOTE;
1391 wsnode_insert (wsp, newnode, prev, 0);
1392 prev = newnode;
1393 }
1394 globfree (&g);
1395
1396 wsnode_remove (wsp, p);
1397 wsnode_free (p);
1398 }
1399 }
1400 free (pattern);
1401}
1402
1403static int
1213skip_sed_expr (const char *command, size_t i, size_t len) 1404skip_sed_expr (const char *command, size_t i, size_t len)
1214{ 1405{
1215 int state; 1406 int state;
@@ -1653,6 +1844,16 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
1653 } 1844 }
1654 } 1845 }
1655 1846
1847 if (wsp->ws_flags & WRDSF_PATHEXPAND)
1848 {
1849 wordsplit_tildexpand (wsp);
1850 if (wsp->ws_flags & WRDSF_SHOWDBG)
1851 {
1852 wsp->ws_debug ("After tilde expansion:");
1853 wordsplit_dump_nodes (wsp);
1854 }
1855 }
1856
1656 /* Expand variables */ 1857 /* Expand variables */
1657 if (!(wsp->ws_flags & WRDSF_NOVAR)) 1858 if (!(wsp->ws_flags & WRDSF_NOVAR))
1658 { 1859 {
@@ -1709,6 +1910,16 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
1709 wordsplit_dump_nodes (wsp); 1910 wordsplit_dump_nodes (wsp);
1710 } 1911 }
1711 1912
1913 if (wsp->ws_flags & WRDSF_PATHEXPAND)
1914 {
1915 wordsplit_pathexpand (wsp);
1916 if (wsp->ws_flags & WRDSF_SHOWDBG)
1917 {
1918 wsp->ws_debug ("After path expan