PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/error.c

https://github.com/CyanogenMod/android_external_bash
C | 489 lines | 352 code | 93 blank | 44 comment | 39 complexity | dee0e6ef9dab28dc31649ca186f4e7dc MD5 | raw file
Possible License(s): GPL-3.0
  1. /* error.c -- Functions for handling errors. */
  2. /* Copyright (C) 1993-2009 Free Software Foundation, Inc.
  3. This file is part of GNU Bash, the Bourne Again SHell.
  4. Bash is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Bash is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with Bash. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "config.h"
  16. #include "bashtypes.h"
  17. #include <fcntl.h>
  18. #if defined (HAVE_UNISTD_H)
  19. # include <unistd.h>
  20. #endif
  21. #if defined (PREFER_STDARG)
  22. # include <stdarg.h>
  23. #else
  24. # include <varargs.h>
  25. #endif
  26. #include <stdio.h>
  27. #include <errno.h>
  28. #if !defined (errno)
  29. #include <errno.h>
  30. #endif /* !errno */
  31. #include "bashansi.h"
  32. #include "bashintl.h"
  33. #include "shell.h"
  34. #include "flags.h"
  35. #include "input.h"
  36. #if defined (HISTORY)
  37. # include "bashhist.h"
  38. #endif
  39. extern int executing_line_number __P((void));
  40. extern int last_command_exit_value;
  41. extern char *shell_name;
  42. #if defined (JOB_CONTROL)
  43. extern pid_t shell_pgrp;
  44. extern int give_terminal_to __P((pid_t, int));
  45. #endif /* JOB_CONTROL */
  46. #if defined (ARRAY_VARS)
  47. extern const char * const bash_badsub_errmsg;
  48. #endif
  49. static void error_prolog __P((int));
  50. /* The current maintainer of the shell. You change this in the
  51. Makefile. */
  52. #if !defined (MAINTAINER)
  53. #define MAINTAINER "bash-maintainers@gnu.org"
  54. #endif
  55. const char * const the_current_maintainer = MAINTAINER;
  56. int gnu_error_format = 0;
  57. static void
  58. error_prolog (print_lineno)
  59. int print_lineno;
  60. {
  61. char *ename;
  62. int line;
  63. ename = get_name_for_error ();
  64. line = (print_lineno && interactive_shell == 0) ? executing_line_number () : -1;
  65. if (line > 0)
  66. fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), line);
  67. else
  68. fprintf (stderr, "%s: ", ename);
  69. }
  70. /* Return the name of the shell or the shell script for error reporting. */
  71. char *
  72. get_name_for_error ()
  73. {
  74. char *name;
  75. #if defined (ARRAY_VARS)
  76. SHELL_VAR *bash_source_v;
  77. ARRAY *bash_source_a;
  78. #endif
  79. name = (char *)NULL;
  80. if (interactive_shell == 0)
  81. {
  82. #if defined (ARRAY_VARS)
  83. bash_source_v = find_variable ("BASH_SOURCE");
  84. if (bash_source_v && array_p (bash_source_v) &&
  85. (bash_source_a = array_cell (bash_source_v)))
  86. name = array_reference (bash_source_a, 0);
  87. if (name == 0 || *name == '\0') /* XXX - was just name == 0 */
  88. #endif
  89. name = dollar_vars[0];
  90. }
  91. if (name == 0 && shell_name && *shell_name)
  92. name = base_pathname (shell_name);
  93. if (name == 0)
  94. #if defined (PROGRAM)
  95. name = PROGRAM;
  96. #else
  97. name = "bash";
  98. #endif
  99. return (name);
  100. }
  101. /* Report an error having to do with FILENAME. This does not use
  102. sys_error so the filename is not interpreted as a printf-style
  103. format string. */
  104. void
  105. file_error (filename)
  106. const char *filename;
  107. {
  108. report_error ("%s: %s", filename, strerror (errno));
  109. }
  110. void
  111. #if defined (PREFER_STDARG)
  112. programming_error (const char *format, ...)
  113. #else
  114. programming_error (format, va_alist)
  115. const char *format;
  116. va_dcl
  117. #endif
  118. {
  119. va_list args;
  120. char *h;
  121. #if defined (JOB_CONTROL)
  122. give_terminal_to (shell_pgrp, 0);
  123. #endif /* JOB_CONTROL */
  124. SH_VA_START (args, format);
  125. vfprintf (stderr, format, args);
  126. fprintf (stderr, "\n");
  127. va_end (args);
  128. #if defined (HISTORY)
  129. if (remember_on_history)
  130. {
  131. h = last_history_line ();
  132. fprintf (stderr, _("last command: %s\n"), h ? h : "(null)");
  133. }
  134. #endif
  135. #if 0
  136. fprintf (stderr, "Report this to %s\n", the_current_maintainer);
  137. #endif
  138. fprintf (stderr, _("Aborting..."));
  139. fflush (stderr);
  140. abort ();
  141. }
  142. /* Print an error message and, if `set -e' has been executed, exit the
  143. shell. Used in this file by file_error and programming_error. Used
  144. outside this file mostly to report substitution and expansion errors,
  145. and for bad invocation options. */
  146. void
  147. #if defined (PREFER_STDARG)
  148. report_error (const char *format, ...)
  149. #else
  150. report_error (format, va_alist)
  151. const char *format;
  152. va_dcl
  153. #endif
  154. {
  155. va_list args;
  156. error_prolog (1);
  157. SH_VA_START (args, format);
  158. vfprintf (stderr, format, args);
  159. fprintf (stderr, "\n");
  160. va_end (args);
  161. if (exit_immediately_on_error)
  162. {
  163. if (last_command_exit_value == 0)
  164. last_command_exit_value = 1;
  165. exit_shell (last_command_exit_value);
  166. }
  167. }
  168. void
  169. #if defined (PREFER_STDARG)
  170. fatal_error (const char *format, ...)
  171. #else
  172. fatal_error (format, va_alist)
  173. const char *format;
  174. va_dcl
  175. #endif
  176. {
  177. va_list args;
  178. error_prolog (0);
  179. SH_VA_START (args, format);
  180. vfprintf (stderr, format, args);
  181. fprintf (stderr, "\n");
  182. va_end (args);
  183. sh_exit (2);
  184. }
  185. void
  186. #if defined (PREFER_STDARG)
  187. internal_error (const char *format, ...)
  188. #else
  189. internal_error (format, va_alist)
  190. const char *format;
  191. va_dcl
  192. #endif
  193. {
  194. va_list args;
  195. error_prolog (1);
  196. SH_VA_START (args, format);
  197. vfprintf (stderr, format, args);
  198. fprintf (stderr, "\n");
  199. va_end (args);
  200. }
  201. void
  202. #if defined (PREFER_STDARG)
  203. internal_warning (const char *format, ...)
  204. #else
  205. internal_warning (format, va_alist)
  206. const char *format;
  207. va_dcl
  208. #endif
  209. {
  210. va_list args;
  211. error_prolog (1);
  212. fprintf (stderr, _("warning: "));
  213. SH_VA_START (args, format);
  214. vfprintf (stderr, format, args);
  215. fprintf (stderr, "\n");
  216. va_end (args);
  217. }
  218. void
  219. #if defined (PREFER_STDARG)
  220. sys_error (const char *format, ...)
  221. #else
  222. sys_error (format, va_alist)
  223. const char *format;
  224. va_dcl
  225. #endif
  226. {
  227. int e;
  228. va_list args;
  229. e = errno;
  230. error_prolog (0);
  231. SH_VA_START (args, format);
  232. vfprintf (stderr, format, args);
  233. fprintf (stderr, ": %s\n", strerror (e));
  234. va_end (args);
  235. }
  236. /* An error from the parser takes the general form
  237. shell_name: input file name: line number: message
  238. The input file name and line number are omitted if the shell is
  239. currently interactive. If the shell is not currently interactive,
  240. the input file name is inserted only if it is different from the
  241. shell name. */
  242. void
  243. #if defined (PREFER_STDARG)
  244. parser_error (int lineno, const char *format, ...)
  245. #else
  246. parser_error (lineno, format, va_alist)
  247. int lineno;
  248. const char *format;
  249. va_dcl
  250. #endif
  251. {
  252. va_list args;
  253. char *ename, *iname;
  254. ename = get_name_for_error ();
  255. iname = yy_input_name ();
  256. if (interactive)
  257. fprintf (stderr, "%s: ", ename);
  258. else if (interactive_shell)
  259. fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
  260. else if (STREQ (ename, iname))
  261. fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), lineno);
  262. else
  263. fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
  264. SH_VA_START (args, format);
  265. vfprintf (stderr, format, args);
  266. fprintf (stderr, "\n");
  267. va_end (args);
  268. if (exit_immediately_on_error)
  269. exit_shell (last_command_exit_value = 2);
  270. }
  271. #ifdef DEBUG
  272. /* This assumes ASCII and is suitable only for debugging */
  273. char *
  274. strescape (str)
  275. const char *str;
  276. {
  277. char *r, *result;
  278. unsigned char *s;
  279. r = result = (char *)xmalloc (strlen (str) * 2 + 1);
  280. for (s = (unsigned char *)str; s && *s; s++)
  281. {
  282. if (*s < ' ')
  283. {
  284. *r++ = '^';
  285. *r++ = *s+64;
  286. }
  287. else if (*s == 127)
  288. {
  289. *r++ = '^';
  290. *r++ = '?';
  291. }
  292. else
  293. *r++ = *s;
  294. }
  295. *r = '\0';
  296. return result;
  297. }
  298. void
  299. #if defined (PREFER_STDARG)
  300. itrace (const char *format, ...)
  301. #else
  302. itrace (format, va_alist)
  303. const char *format;
  304. va_dcl
  305. #endif
  306. {
  307. va_list args;
  308. fprintf(stderr, "TRACE: pid %ld: ", (long)getpid());
  309. SH_VA_START (args, format);
  310. vfprintf (stderr, format, args);
  311. fprintf (stderr, "\n");
  312. va_end (args);
  313. fflush(stderr);
  314. }
  315. /* A trace function for silent debugging -- doesn't require a control
  316. terminal. */
  317. void
  318. #if defined (PREFER_STDARG)
  319. trace (const char *format, ...)
  320. #else
  321. trace (format, va_alist)
  322. const char *format;
  323. va_dcl
  324. #endif
  325. {
  326. va_list args;
  327. static FILE *tracefp = (FILE *)NULL;
  328. if (tracefp == NULL)
  329. tracefp = fopen("/tmp/bash-trace.log", "a+");
  330. if (tracefp == NULL)
  331. tracefp = stderr;
  332. else
  333. fcntl (fileno (tracefp), F_SETFD, 1); /* close-on-exec */
  334. fprintf(tracefp, "TRACE: pid %ld: ", (long)getpid());
  335. SH_VA_START (args, format);
  336. vfprintf (tracefp, format, args);
  337. fprintf (tracefp, "\n");
  338. va_end (args);
  339. fflush(tracefp);
  340. }
  341. #endif /* DEBUG */
  342. /* **************************************************************** */
  343. /* */
  344. /* Common error reporting */
  345. /* */
  346. /* **************************************************************** */
  347. static const char * const cmd_error_table[] = {
  348. N_("unknown command error"), /* CMDERR_DEFAULT */
  349. N_("bad command type"), /* CMDERR_BADTYPE */
  350. N_("bad connector"), /* CMDERR_BADCONN */
  351. N_("bad jump"), /* CMDERR_BADJUMP */
  352. 0
  353. };
  354. void
  355. command_error (func, code, e, flags)
  356. const char *func;
  357. int code, e, flags; /* flags currently unused */
  358. {
  359. if (code > CMDERR_LAST)
  360. code = CMDERR_DEFAULT;
  361. programming_error ("%s: %s: %d", func, _(cmd_error_table[code]), e);
  362. }
  363. char *
  364. command_errstr (code)
  365. int code;
  366. {
  367. if (code > CMDERR_LAST)
  368. code = CMDERR_DEFAULT;
  369. return (_(cmd_error_table[code]));
  370. }
  371. #ifdef ARRAY_VARS
  372. void
  373. err_badarraysub (s)
  374. const char *s;
  375. {
  376. report_error ("%s: %s", s, _(bash_badsub_errmsg));
  377. }
  378. #endif
  379. void
  380. err_unboundvar (s)
  381. const char *s;
  382. {
  383. report_error (_("%s: unbound variable"), s);
  384. }
  385. void
  386. err_readonly (s)
  387. const char *s;
  388. {
  389. report_error (_("%s: readonly variable"), s);
  390. }