aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-05-15 16:41:28 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-05-15 16:41:28 +0300
commit4c2792654a68b8680b6f4b8dc0e0d6ebc0daf770 (patch)
tree93fbf66778f9fcb0aad645127c97144d0dc3c549
parentcdcc7119e408ad143202a5e626804e042525f028 (diff)
downloadrush-4c2792654a68b8680b6f4b8dc0e0d6ebc0daf770.tar.gz
rush-4c2792654a68b8680b6f4b8dc0e0d6ebc0daf770.tar.bz2
Report names of undefined variables
* lib/wordsplit.c: Import from grecs 20899f65 * lib/wordsplit.h: Likewise. * src/map.c (rush_ws_error): New function. (rush_expand_string): Set ws.ws_error. Use error context when reporting WRDSE_UNDEF. * src/rush.c (main): Use reparse_cmdline. * src/rush.h (rush_ws_error): New proto. * tests/undef.at: Update.
-rw-r--r--lib/wordsplit.c48
-rw-r--r--lib/wordsplit.h6
-rw-r--r--src/map.c14
-rw-r--r--src/rush.c16
-rw-r--r--src/rush.h1
-rw-r--r--tests/undef.at2
6 files changed, 67 insertions, 20 deletions
diff --git a/lib/wordsplit.c b/lib/wordsplit.c
index 4e633fa..6dba914 100644
--- a/lib/wordsplit.c
+++ b/lib/wordsplit.c
@@ -107,6 +107,30 @@ _wsplt_nomem (struct wordsplit *wsp)
return wsp->ws_errno;
}
+static void
+_wsplt_store_errctx (struct wordsplit *wsp, char const *str, size_t len)
+{
+ free (wsp->ws_errctx);
+ wsp->ws_errctx = malloc (len + 1);
+ if (!wsp->ws_errctx)
+ {
+ wsp->ws_error ("%s",
+ _("memory exhausted while trying to store error subject"));
+ }
+ else
+ {
+ memcpy (wsp->ws_errctx, str, len);
+ wsp->ws_errctx[len] = 0;
+ }
+}
+
+static inline int
+_wsplt_setctxerr (struct wordsplit *wsp, int ec, char const *str, size_t len)
+{
+ _wsplt_store_errctx (wsp, str, len);
+ return _wsplt_seterr (wsp, ec);
+}
+
static int wordsplit_run (const char *command, size_t length,
struct wordsplit *wsp,
int flags, int lvl);
@@ -307,6 +331,8 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
wordsplit_free_nodes (wsp);
wsp->ws_head = wsp->ws_tail = NULL;
+ wsp->ws_errctx = NULL;
+
wordsplit_init0 (wsp);
return 0;
@@ -837,7 +863,7 @@ wordsplit_finish (struct wordsplit *wsp)
}
else
{
- wsp->ws_error = WRDSE_EOF;
+ wsp->ws_errno = WRDSE_EOF;
return WRDSE_EOF;
}
goto again;
@@ -1163,7 +1189,7 @@ wsplt_assign_param (struct wordsplit *wsp, int param_idx, char *value)
char *v;
if (param_idx < 0)
- return WRDSE_BADPARAM;
+ return _wsplt_seterr (wsp, WRDSE_BADPARAM);
if (param_idx == wsp->ws_paramc)
{
char **parambuf;
@@ -1210,7 +1236,7 @@ wsplt_assign_param (struct wordsplit *wsp, int param_idx, char *value)
wsp->ws_paramc = param_idx + 1;
}
else if (param_idx > wsp->ws_paramc)
- return WRDSE_BADPARAM;
+ return _wsplt_seterr (wsp, WRDSE_BADPARAM);
v = strdup (value);
if (!v)
@@ -1575,7 +1601,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
}
else if (wsp->ws_flags & WRDSF_UNDEF)
{
- _wsplt_seterr (wsp, WRDSE_UNDEF);
+ _wsplt_setctxerr (wsp, WRDSE_UNDEF, str, *pend - str + 1);
return 1;
}
else
@@ -1680,7 +1706,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
static int
begin_var_p (int c)
{
- return memchr("{#@*", c, 4) != NULL || ISVARBEG (c) || ISDIGIT (c);
+ return memchr ("{#@*", c, 4) != NULL || ISVARBEG (c) || ISDIGIT (c);
}
static int
@@ -2098,7 +2124,7 @@ wordsplit_pathexpand (struct wordsplit *wsp)
default:
free (pattern);
- return _wsplt_seterr (wsp, WRDSE_GLOBERR);
+ return _wsplt_setctxerr (wsp, WRDSE_GLOBERR, pattern, slen);
}
prev = p;
@@ -2754,12 +2780,17 @@ wordsplit_clearerr (struct wordsplit *ws)
if (ws->ws_errno == WRDSE_USERERR)
free (ws->ws_usererr);
ws->ws_usererr = NULL;
+
+ free (ws->ws_errctx);
+ ws->ws_errctx = NULL;
+
ws->ws_errno = WRDSE_OK;
}
void
wordsplit_free (struct wordsplit *ws)
{
+ wordsplit_clearerr (ws);
wordsplit_free_nodes (ws);
wordsplit_free_words (ws);
free (ws->ws_wordv);
@@ -2823,6 +2854,9 @@ wordsplit_perror (struct wordsplit *wsp)
break;
default:
- wsp->ws_error ("%s", wordsplit_strerror (wsp));
+ if (wsp->ws_errctx)
+ wsp->ws_error ("%s: %s", wordsplit_strerror (wsp), wsp->ws_errctx);
+ else
+ wsp->ws_error ("%s", wordsplit_strerror (wsp));
}
}
diff --git a/lib/wordsplit.h b/lib/wordsplit.h
index 2fac3c6..0d6eef3 100644
--- a/lib/wordsplit.h
+++ b/lib/wordsplit.h
@@ -110,7 +110,7 @@ struct wordsplit
See ws_getvar for a discussion of possible
return values. */
- const char *ws_input; /* Input string (the S argument to wordsplit. */
+ const char *ws_input; /* Input string (the S argument to wordsplit). */
size_t ws_len; /* Length of ws_input. */
size_t ws_endp; /* Points past the last processed byte in
ws_input. */
@@ -118,6 +118,10 @@ struct wordsplit
char *ws_usererr; /* Points to textual description of
the error, if ws_errno is WRDSE_USERERR. Must
be allocated with malloc(3). */
+ char *ws_errctx; /* Context in which the error occurred:
+ For WRDSE_UNDEF - name of the undefined variable,
+ For WRDSE_GLOBERR - pattern that caused error.
+ */
struct wordsplit_node *ws_head, *ws_tail;
/* Doubly-linked list of parsed out nodes. */
char ws_sep[2]; /* Temporary storage used during splitting */
diff --git a/src/map.c b/src/map.c
index 37fa252..bc190bb 100644
--- a/src/map.c
+++ b/src/map.c
@@ -255,6 +255,15 @@ getvar(char **ret, const char *var, size_t len, void *clos)
return WRDSE_OK;
}
+void
+rush_ws_error (const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vlogmsg(LOG_ERR, fmt, ap);
+ va_end(ap);
+}
+
char *
rush_expand_string(const char *string, struct rush_request *req)
{
@@ -264,6 +273,7 @@ rush_expand_string(const char *string, struct rush_request *req)
| (expand_undefined ? 0: WRDSF_UNDEF)
| WRDSF_GETVAR
| WRDSF_CLOSURE
+ | WRDSF_ERROR
| WRDSF_OPTIONS;
char *result;
@@ -271,6 +281,7 @@ rush_expand_string(const char *string, struct rush_request *req)
ws.ws_closure = req;
ws.ws_paramv = (char const**) req->argv;
ws.ws_paramc = req->argc;
+ ws.ws_error = rush_ws_error;
ws.ws_options = WRDSO_BSKEEP_QUOTE | WRDSO_NOCMDSPLIT
| WRDSO_PARAMV | WRDSO_PARAM_NEGIDX;
if (req->var_kv) {
@@ -283,7 +294,8 @@ rush_expand_string(const char *string, struct rush_request *req)
case 0:
break;
case WRDSE_UNDEF:
- die(config_error, &req->i18n, "%s", wordsplit_strerror(&ws));
+ die(config_error, &req->i18n, "%s: %s",
+ wordsplit_strerror(&ws), ws.ws_errctx);
break;
default:
die(system_error, &req->i18n, "%s", wordsplit_strerror(&ws));
diff --git a/src/rush.c b/src/rush.c
index 241c0ca..9e43871 100644
--- a/src/rush.c
+++ b/src/rush.c
@@ -658,6 +658,11 @@ rush_transform(struct transform_node *node, struct rush_request *req)
/* Environment variable */
die(system_error, NULL,
_("environment transformation is not yet implemented"));
+
+ case target_readonly:
+ die(system_error, NULL,
+ _("INTERNAL ERROR at %s:%d: can't modify read-only target"),
+ __FILE__, __LINE__);
}
switch (node->type) {
@@ -1033,7 +1038,6 @@ main(int argc, char **argv)
uid_t uid;
struct rush_rule *rule;
struct rush_request req;
- struct wordsplit ws;
rush_set_program_name(argv[0]);
rush_i18n_init();
@@ -1110,16 +1114,8 @@ main(int argc, char **argv)
}
req.cmdline = xstrdup(command);
-
- ws.ws_options = WRDSO_NOVARSPLIT | WRDSO_NOCMDSPLIT;
- if (wordsplit(req.cmdline, &ws, WRDSF_DEFFLAGS|WRDSF_OPTIONS))
- die(system_error, NULL,
- _("wordsplit(%s) failed: %s"),
- req.cmdline, wordsplit_strerror(&ws));
- wordsplit_get_words(&ws, &req.argc, &req.argv);
- wordsplit_free(&ws);
-
request_set_env(&req);
+ reparse_cmdline(&req);
req.pw = rush_pw;
req.umask = 022;
diff --git a/src/rush.h b/src/rush.h
index 4f901e5..3eeaff4 100644
--- a/src/rush.h
+++ b/src/rush.h
@@ -362,6 +362,7 @@ char *rush_expand_string(const char *string, struct rush_request *req);
char **rush_getvarptr(struct rush_request *req, char const *varname);
void rush_request_delvar(struct rush_request *req, char const *varname);
enum transform_target_type rush_variable_target(char const *varname);
+void rush_ws_error (const char *fmt, ...);
/* dump.c */
void dump_request(struct rush_request *req, FILE *fp);
diff --git a/tests/undef.at b/tests/undef.at
index 015dd52..bb79176 100644
--- a/tests/undef.at
+++ b/tests/undef.at
@@ -27,7 +27,7 @@ rule first
[ls],
[1],
[],
-[rush: Error: undefined variable
+[rush: Error: undefined variable: COMMAND
])
AT_RUSH_TEST([

Return to:

Send suggestions and report system problems to the System administrator.