/contrib/tcsh/sh.err.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 656 lines · 520 code · 51 blank · 85 comment · 34 complexity · 17fe85a39e95bc757bb5df02d1e806b8 MD5 · raw file

  1. /* $Header: /p/tcsh/cvsroot/tcsh/sh.err.c,v 3.55 2011/02/25 23:58:34 christos Exp $ */
  2. /*
  3. * sh.err.c: Error printing routines.
  4. */
  5. /*-
  6. * Copyright (c) 1980, 1991 The Regents of the University of California.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #define _h_sh_err /* Don't redefine the errors */
  34. #include "sh.h"
  35. #include <assert.h>
  36. RCSID("$tcsh: sh.err.c,v 3.55 2011/02/25 23:58:34 christos Exp $")
  37. /*
  38. * C Shell
  39. */
  40. #ifdef lint
  41. #undef va_arg
  42. #define va_arg(a, b) (a ? (b) 0 : (b) 0)
  43. #endif
  44. char *seterr = NULL; /* Holds last error if there was one */
  45. #define ERR_FLAGS 0xf0000000
  46. #define ERR_NAME 0x10000000
  47. #define ERR_SILENT 0x20000000
  48. #define ERR_OLD 0x40000000
  49. #define ERR_INTERRUPT 0x80000000
  50. #define ERR_SYNTAX 0
  51. #define ERR_NOTALLOWED 1
  52. #define ERR_WTOOLONG 2
  53. #define ERR_LTOOLONG 3
  54. #define ERR_DOLZERO 4
  55. #define ERR_INCBR 5
  56. #define ERR_EXPORD 6
  57. #define ERR_BADMOD 7
  58. #define ERR_SUBSCRIPT 8
  59. #define ERR_BADNUM 9
  60. #define ERR_NOMORE 10
  61. #define ERR_FILENAME 11
  62. #define ERR_GLOB 12
  63. #define ERR_COMMAND 13
  64. #define ERR_TOOFEW 14
  65. #define ERR_TOOMANY 15
  66. #define ERR_DANGER 16
  67. #define ERR_EMPTYIF 17
  68. #define ERR_IMPRTHEN 18
  69. #define ERR_NOPAREN 19
  70. #define ERR_NOTFOUND 20
  71. #define ERR_MASK 21
  72. #define ERR_LIMIT 22
  73. #define ERR_TOOLARGE 23
  74. #define ERR_SCALEF 24
  75. #define ERR_UNDVAR 25
  76. #define ERR_DEEP 26
  77. #define ERR_BADSIG 27
  78. #define ERR_UNKSIG 28
  79. #define ERR_VARBEGIN 29
  80. #define ERR_VARTOOLONG 30
  81. #define ERR_VARALNUM 31
  82. #define ERR_JOBCONTROL 32
  83. #define ERR_EXPRESSION 33
  84. #define ERR_NOHOMEDIR 34
  85. #define ERR_CANTCHANGE 35
  86. #define ERR_NULLCOM 36
  87. #define ERR_ASSIGN 37
  88. #define ERR_UNKNOWNOP 38
  89. #define ERR_AMBIG 39
  90. #define ERR_EXISTS 40
  91. #define ERR_ARGC 41
  92. #define ERR_INTR 42
  93. #define ERR_RANGE 43
  94. #define ERR_OVERFLOW 44
  95. #define ERR_NOSUCHJOB 45
  96. #define ERR_TERMINAL 46
  97. #define ERR_NOTWHILE 47
  98. #define ERR_NOPROC 48
  99. #define ERR_NOMATCH 49
  100. #define ERR_MISSING 50
  101. #define ERR_UNMATCHED 51
  102. #define ERR_NOMEM 52
  103. #define ERR_PIPE 53
  104. #define ERR_SYSTEM 54
  105. #define ERR_STRING 55
  106. #define ERR_JOBS 56
  107. #define ERR_JOBARGS 57
  108. #define ERR_JOBCUR 58
  109. #define ERR_JOBPREV 59
  110. #define ERR_JOBPAT 60
  111. #define ERR_NESTING 61
  112. #define ERR_JOBCTRLSUB 62
  113. #define ERR_SYNC 63
  114. #define ERR_STOPPED 64
  115. #define ERR_NODIR 65
  116. #define ERR_EMPTY 66
  117. #define ERR_BADDIR 67
  118. #define ERR_DIRUS 68
  119. #define ERR_HFLAG 69
  120. #define ERR_NOTLOGIN 70
  121. #define ERR_DIV0 71
  122. #define ERR_MOD0 72
  123. #define ERR_BADSCALE 73
  124. #define ERR_SUSPLOG 74
  125. #define ERR_UNKUSER 75
  126. #define ERR_NOHOME 76
  127. #define ERR_HISTUS 77
  128. #define ERR_SPDOLLT 78
  129. #define ERR_NEWLINE 79
  130. #define ERR_SPSTAR 80
  131. #define ERR_DIGIT 81
  132. #define ERR_VARILL 82
  133. #define ERR_NLINDEX 83
  134. #define ERR_EXPOVFL 84
  135. #define ERR_VARSYN 85
  136. #define ERR_BADBANG 86
  137. #define ERR_NOSUBST 87
  138. #define ERR_BADSUBST 88
  139. #define ERR_LHS 89
  140. #define ERR_RHSLONG 90
  141. #define ERR_BADBANGMOD 91
  142. #define ERR_MODFAIL 92
  143. #define ERR_SUBOVFL 93
  144. #define ERR_BADBANGARG 94
  145. #define ERR_NOSEARCH 95
  146. #define ERR_NOEVENT 96
  147. #define ERR_TOOMANYRP 97
  148. #define ERR_TOOMANYLP 98
  149. #define ERR_BADPLP 99
  150. #define ERR_MISRED 100
  151. #define ERR_OUTRED 101
  152. #define ERR_REDPAR 102
  153. #define ERR_INRED 103
  154. #define ERR_BADPLPS 104
  155. #define ERR_ALIASLOOP 105
  156. #define ERR_NOWATCH 106
  157. #define ERR_NOSCHED 107
  158. #define ERR_SCHEDUSAGE 108
  159. #define ERR_SCHEDEV 109
  160. #define ERR_SCHEDCOM 110
  161. #define ERR_SCHEDTIME 111
  162. #define ERR_SCHEDREL 112
  163. #define ERR_TCNOSTR 113
  164. #define ERR_SETTCUS 114
  165. #define ERR_TCCAP 115
  166. #define ERR_TCPARM 116
  167. #define ERR_TCARGS 117
  168. #define ERR_TCNARGS 118
  169. #define ERR_TCUSAGE 119
  170. #define ERR_ARCH 120
  171. #define ERR_HISTLOOP 121
  172. #define ERR_FILEINQ 122
  173. #define ERR_SELOVFL 123
  174. #define ERR_TCSHUSAGE 124
  175. #define ERR_COMPCOM 125
  176. #define ERR_COMPINV 126
  177. #define ERR_COMPMIS 127
  178. #define ERR_COMPINC 128
  179. #define ERR_MFLAG 129
  180. #define ERR_ULIMUS 130
  181. #define ERR_READONLY 131
  182. #define ERR_BADJOB 132
  183. #define ERR_INVALID 133
  184. #define ERR_BADCOLORVAR 134
  185. #define ERR_EOF 135
  186. #define NO_ERRORS 136
  187. static const char *elst[NO_ERRORS] INIT_ZERO_STRUCT;
  188. /*
  189. * Init the elst depending on the locale
  190. */
  191. void
  192. errinit(void)
  193. {
  194. #ifdef NLS_CATALOGS
  195. size_t i;
  196. for (i = 0; i < NO_ERRORS; i++)
  197. xfree((char *)(intptr_t)elst[i]);
  198. # if defined(__FreeBSD__) || defined(hpux) || defined(__MidnightBSD__)
  199. # define NLS_MAXSET 30
  200. for (i = 1; i <= NLS_MAXSET; i++)
  201. CGETS(i, 1, "" );
  202. # endif
  203. #endif
  204. elst[ERR_SYNTAX] = CSAVS(1, 1, "Syntax Error");
  205. elst[ERR_NOTALLOWED] = CSAVS(1, 2, "%s is not allowed");
  206. elst[ERR_WTOOLONG] = CSAVS(1, 3, "Word too long");
  207. elst[ERR_LTOOLONG] = CSAVS(1, 4, "$< line too long");
  208. elst[ERR_DOLZERO] = CSAVS(1, 5, "No file for $0");
  209. elst[ERR_INCBR] = CSAVS(1, 6, "Incomplete [] modifier");
  210. elst[ERR_EXPORD] = CSAVS(1, 7, "$ expansion must end before ]");
  211. elst[ERR_BADMOD] = CSAVS(1, 8, "Bad : modifier in $ (%c)");
  212. elst[ERR_SUBSCRIPT] = CSAVS(1, 9, "Subscript error");
  213. elst[ERR_BADNUM] = CSAVS(1, 10, "Badly formed number");
  214. elst[ERR_NOMORE] = CSAVS(1, 11, "No more words");
  215. elst[ERR_FILENAME] = CSAVS(1, 12, "Missing file name");
  216. elst[ERR_GLOB] = CSAVS(1, 13, "Internal glob error");
  217. elst[ERR_COMMAND] = CSAVS(1, 14, "Command not found");
  218. elst[ERR_TOOFEW] = CSAVS(1, 15, "Too few arguments");
  219. elst[ERR_TOOMANY] = CSAVS(1, 16, "Too many arguments");
  220. elst[ERR_DANGER] = CSAVS(1, 17, "Too dangerous to alias that");
  221. elst[ERR_EMPTYIF] = CSAVS(1, 18, "Empty if");
  222. elst[ERR_IMPRTHEN] = CSAVS(1, 19, "Improper then");
  223. elst[ERR_NOPAREN] = CSAVS(1, 20, "Words not parenthesized");
  224. elst[ERR_NOTFOUND] = CSAVS(1, 21, "%s not found");
  225. elst[ERR_MASK] = CSAVS(1, 22, "Improper mask");
  226. elst[ERR_LIMIT] = CSAVS(1, 23, "No such limit");
  227. elst[ERR_TOOLARGE] = CSAVS(1, 24, "Argument too large");
  228. elst[ERR_SCALEF] = CSAVS(1, 25, "Improper or unknown scale factor");
  229. elst[ERR_UNDVAR] = CSAVS(1, 26, "Undefined variable");
  230. elst[ERR_DEEP] = CSAVS(1, 27, "Directory stack not that deep");
  231. elst[ERR_BADSIG] = CSAVS(1, 28, "Bad signal number");
  232. elst[ERR_UNKSIG] = CSAVS(1, 29, "Unknown signal; kill -l lists signals");
  233. elst[ERR_VARBEGIN] = CSAVS(1, 30, "Variable name must begin with a letter");
  234. elst[ERR_VARTOOLONG] = CSAVS(1, 31, "Variable name too long");
  235. elst[ERR_VARALNUM] = CSAVS(1, 32,
  236. "Variable name must contain alphanumeric characters");
  237. elst[ERR_JOBCONTROL] = CSAVS(1, 33, "No job control in this shell");
  238. elst[ERR_EXPRESSION] = CSAVS(1, 34, "Expression Syntax");
  239. elst[ERR_NOHOMEDIR] = CSAVS(1, 35, "No home directory");
  240. elst[ERR_CANTCHANGE] = CSAVS(1, 36, "Can't change to home directory");
  241. elst[ERR_NULLCOM] = CSAVS(1, 37, "Invalid null command");
  242. elst[ERR_ASSIGN] = CSAVS(1, 38, "Assignment missing expression");
  243. elst[ERR_UNKNOWNOP] = CSAVS(1, 39, "Unknown operator");
  244. elst[ERR_AMBIG] = CSAVS(1, 40, "Ambiguous");
  245. elst[ERR_EXISTS] = CSAVS(1, 41, "%s: File exists");
  246. elst[ERR_ARGC] = CSAVS(1, 42, "Argument for -c ends in backslash");
  247. elst[ERR_INTR] = CSAVS(1, 43, "Interrupted");
  248. elst[ERR_RANGE] = CSAVS(1, 44, "Subscript out of range");
  249. elst[ERR_OVERFLOW] = CSAVS(1, 45, "Line overflow");
  250. elst[ERR_NOSUCHJOB] = CSAVS(1, 46, "No such job");
  251. elst[ERR_TERMINAL] = CSAVS(1, 47, "Can't from terminal");
  252. elst[ERR_NOTWHILE] = CSAVS(1, 48, "Not in while/foreach");
  253. elst[ERR_NOPROC] = CSAVS(1, 49, "No more processes");
  254. elst[ERR_NOMATCH] = CSAVS(1, 50, "No match");
  255. elst[ERR_MISSING] = CSAVS(1, 51, "Missing %c");
  256. elst[ERR_UNMATCHED] = CSAVS(1, 52, "Unmatched %c");
  257. elst[ERR_NOMEM] = CSAVS(1, 53, "Out of memory");
  258. elst[ERR_PIPE] = CSAVS(1, 54, "Can't make pipe");
  259. elst[ERR_SYSTEM] = CSAVS(1, 55, "%s: %s");
  260. elst[ERR_STRING] = CSAVS(1, 56, "%s");
  261. elst[ERR_JOBS] = CSAVS(1, 57, "Usage: jobs [ -l ]");
  262. elst[ERR_JOBARGS] = CSAVS(1, 58, "Arguments should be jobs or process id's");
  263. elst[ERR_JOBCUR] = CSAVS(1, 59, "No current job");
  264. elst[ERR_JOBPREV] = CSAVS(1, 60, "No previous job");
  265. elst[ERR_JOBPAT] = CSAVS(1, 61, "No job matches pattern");
  266. elst[ERR_NESTING] = CSAVS(1, 62, "Fork nesting > %d; maybe `...` loop");
  267. elst[ERR_JOBCTRLSUB] = CSAVS(1, 63, "No job control in subshells");
  268. elst[ERR_SYNC] = CSAVS(1, 64, "Sync fault: Process %d not found");
  269. elst[ERR_STOPPED] =
  270. #ifdef SUSPENDED
  271. CSAVS(1, 65, "%sThere are suspended jobs");
  272. #else
  273. CSAVS(1, 66, "%sThere are stopped jobs");
  274. #endif /* SUSPENDED */
  275. elst[ERR_NODIR] = CSAVS(1, 67, "No other directory");
  276. elst[ERR_EMPTY] = CSAVS(1, 68, "Directory stack empty");
  277. elst[ERR_BADDIR] = CSAVS(1, 69, "Bad directory");
  278. elst[ERR_DIRUS] = CSAVS(1, 70, "Usage: %s [-%s]%s");
  279. elst[ERR_HFLAG] = CSAVS(1, 71, "No operand for -h flag");
  280. elst[ERR_NOTLOGIN] = CSAVS(1, 72, "Not a login shell");
  281. elst[ERR_DIV0] = CSAVS(1, 73, "Division by 0");
  282. elst[ERR_MOD0] = CSAVS(1, 74, "Mod by 0");
  283. elst[ERR_BADSCALE] = CSAVS(1, 75, "Bad scaling; did you mean \"%s\"?");
  284. elst[ERR_SUSPLOG] = CSAVS(1, 76, "Can't suspend a login shell (yet)");
  285. elst[ERR_UNKUSER] = CSAVS(1, 77, "Unknown user: %s");
  286. elst[ERR_NOHOME] = CSAVS(1, 78, "No $home variable set");
  287. elst[ERR_HISTUS] = CSAVS(1, 79,
  288. "Usage: history [-%s] [# number of events]");
  289. elst[ERR_SPDOLLT] = CSAVS(1, 80, "$, ! or < not allowed with $# or $?");
  290. elst[ERR_NEWLINE] = CSAVS(1, 81, "Newline in variable name");
  291. elst[ERR_SPSTAR] = CSAVS(1, 82, "* not allowed with $# or $?");
  292. elst[ERR_DIGIT] = CSAVS(1, 83, "$?<digit> or $#<digit> not allowed");
  293. elst[ERR_VARILL] = CSAVS(1, 84, "Illegal variable name");
  294. elst[ERR_NLINDEX] = CSAVS(1, 85, "Newline in variable index");
  295. elst[ERR_EXPOVFL] = CSAVS(1, 86, "Expansion buffer overflow");
  296. elst[ERR_VARSYN] = CSAVS(1, 87, "Variable syntax");
  297. elst[ERR_BADBANG] = CSAVS(1, 88, "Bad ! form");
  298. elst[ERR_NOSUBST] = CSAVS(1, 89, "No previous substitute");
  299. elst[ERR_BADSUBST] = CSAVS(1, 90, "Bad substitute");
  300. elst[ERR_LHS] = CSAVS(1, 91, "No previous left hand side");
  301. elst[ERR_RHSLONG] = CSAVS(1, 92, "Right hand side too long");
  302. elst[ERR_BADBANGMOD] = CSAVS(1, 93, "Bad ! modifier: %c");
  303. elst[ERR_MODFAIL] = CSAVS(1, 94, "Modifier failed");
  304. elst[ERR_SUBOVFL] = CSAVS(1, 95, "Substitution buffer overflow");
  305. elst[ERR_BADBANGARG] = CSAVS(1, 96, "Bad ! arg selector");
  306. elst[ERR_NOSEARCH] = CSAVS(1, 97, "No prev search");
  307. elst[ERR_NOEVENT] = CSAVS(1, 98, "%s: Event not found");
  308. elst[ERR_TOOMANYRP] = CSAVS(1, 99, "Too many )'s");
  309. elst[ERR_TOOMANYLP] = CSAVS(1, 100, "Too many ('s");
  310. elst[ERR_BADPLP] = CSAVS(1, 101, "Badly placed (");
  311. elst[ERR_MISRED] = CSAVS(1, 102, "Missing name for redirect");
  312. elst[ERR_OUTRED] = CSAVS(1, 103, "Ambiguous output redirect");
  313. elst[ERR_REDPAR] = CSAVS(1, 104, "Can't << within ()'s");
  314. elst[ERR_INRED] = CSAVS(1, 105, "Ambiguous input redirect");
  315. elst[ERR_BADPLPS] = CSAVS(1, 106, "Badly placed ()'s");
  316. elst[ERR_ALIASLOOP] = CSAVS(1, 107, "Alias loop");
  317. elst[ERR_NOWATCH] = CSAVS(1, 108, "No $watch variable set");
  318. elst[ERR_NOSCHED] = CSAVS(1, 109, "No scheduled events");
  319. elst[ERR_SCHEDUSAGE] = CSAVS(1, 110,
  320. "Usage: sched -<item#>.\nUsage: sched [+]hh:mm <command>");
  321. elst[ERR_SCHEDEV] = CSAVS(1, 111, "Not that many scheduled events");
  322. elst[ERR_SCHEDCOM] = CSAVS(1, 112, "No command to run");
  323. elst[ERR_SCHEDTIME] = CSAVS(1, 113, "Invalid time for event");
  324. elst[ERR_SCHEDREL] = CSAVS(1, 114, "Relative time inconsistent with am/pm");
  325. elst[ERR_TCNOSTR] = CSAVS(1, 115, "Out of termcap string space");
  326. elst[ERR_SETTCUS] = CSAVS(1, 116, "Usage: settc %s [yes|no]");
  327. elst[ERR_TCCAP] = CSAVS(1, 117, "Unknown capability `%s'");
  328. elst[ERR_TCPARM] = CSAVS(1, 118, "Unknown termcap parameter `%%%c'");
  329. elst[ERR_TCARGS] = CSAVS(1, 119, "Too many arguments for `%s' (%d)");
  330. elst[ERR_TCNARGS] = CSAVS(1, 120, "`%s' requires %d arguments");
  331. elst[ERR_TCUSAGE] = CSAVS(1, 121,
  332. "Usage: echotc [-v|-s] [<capability> [<args>]]");
  333. elst[ERR_ARCH] = CSAVS(1, 122, "%s: %s. Binary file not executable");
  334. elst[ERR_HISTLOOP] = CSAVS(1, 123, "!# History loop");
  335. elst[ERR_FILEINQ] = CSAVS(1, 124, "Malformed file inquiry");
  336. elst[ERR_SELOVFL] = CSAVS(1, 125, "Selector overflow");
  337. #ifdef apollo
  338. elst[ERR_TCSHUSAGE] = CSAVS(1, 126,
  339. "Unknown option: `-%s'\nUsage: %s [ -bcdefilmnqstvVxX -Dname[=value] ] [ argument ... ]");
  340. #else /* !apollo */
  341. # ifdef convex
  342. elst[ERR_TCSHUSAGE] = CSAVS(1, 127,
  343. "Unknown option: `-%s'\nUsage: %s [ -bcdefFilmnqstvVxX ] [ argument ... ]");
  344. # else /* rest */
  345. elst[ERR_TCSHUSAGE] = CSAVS(1, 128,
  346. "Unknown option: `-%s'\nUsage: %s [ -bcdefilmnqstvVxX ] [ argument ... ]");
  347. # endif /* convex */
  348. #endif /* apollo */
  349. elst[ERR_COMPCOM] = CSAVS(1, 129, "\nInvalid completion: \"%s\"");
  350. elst[ERR_COMPINV] = CSAVS(1, 130, "\nInvalid %s: '%c'");
  351. elst[ERR_COMPMIS] = CSAVS(1, 131,
  352. "\nMissing separator '%c' after %s \"%s\"");
  353. elst[ERR_COMPINC] = CSAVS(1, 132, "\nIncomplete %s: \"%s\"");
  354. elst[ERR_MFLAG] = CSAVS(1, 133, "No operand for -m flag");
  355. elst[ERR_ULIMUS] = CSAVS(1, 134, "Usage: unlimit [-fh] [limits]");
  356. elst[ERR_READONLY] = CSAVS(1, 135, "$%S is read-only");
  357. elst[ERR_BADJOB] = CSAVS(1, 136, "No such job (badjob)");
  358. elst[ERR_BADCOLORVAR] = CSAVS(1, 137, "Unknown colorls variable `%c%c'");
  359. elst[ERR_EOF] = CSAVS(1, 138, "Unexpected end of file");
  360. }
  361. /* Cleanup data. */
  362. struct cleanup_entry
  363. {
  364. void *var;
  365. void (*fn) (void *);
  366. #ifdef CLEANUP_DEBUG
  367. const char *file;
  368. size_t line;
  369. #endif
  370. };
  371. static struct cleanup_entry *cleanup_stack; /* = NULL; */
  372. static size_t cleanup_sp; /* = 0; Next free entry */
  373. static size_t cleanup_mark; /* = 0; Last entry to handle before unwinding */
  374. static size_t cleanup_stack_size; /* = 0 */
  375. /* fn() will be run with all signals blocked, so it should not do anything
  376. risky. */
  377. void
  378. cleanup_push_internal(void *var, void (*fn) (void *)
  379. #ifdef CLEANUP_DEBUG
  380. , const char *file, size_t line
  381. #endif
  382. )
  383. {
  384. struct cleanup_entry *ce;
  385. if (cleanup_sp == cleanup_stack_size) {
  386. if (cleanup_stack_size == 0)
  387. cleanup_stack_size = 64; /* Arbitrary */
  388. else
  389. cleanup_stack_size *= 2;
  390. cleanup_stack = xrealloc(cleanup_stack,
  391. cleanup_stack_size * sizeof (*cleanup_stack));
  392. }
  393. ce = cleanup_stack + cleanup_sp;
  394. ce->var = var;
  395. ce->fn = fn;
  396. #ifdef CLEANUP_DEBUG
  397. ce->file = file;
  398. ce->line = line;
  399. #endif
  400. cleanup_sp++;
  401. }
  402. static void
  403. cleanup_ignore_fn(void *dummy)
  404. {
  405. USE(dummy);
  406. }
  407. void
  408. cleanup_ignore(void *var)
  409. {
  410. struct cleanup_entry *ce;
  411. ce = cleanup_stack + cleanup_sp;
  412. while (ce != cleanup_stack) {
  413. ce--;
  414. if (ce->var == var) {
  415. ce->fn = cleanup_ignore_fn;
  416. return;
  417. }
  418. }
  419. abort();
  420. }
  421. void
  422. cleanup_until(void *last_var)
  423. {
  424. while (cleanup_sp != 0) {
  425. struct cleanup_entry ce;
  426. cleanup_sp--;
  427. ce = cleanup_stack[cleanup_sp];
  428. ce.fn(ce.var);
  429. if (ce.var == last_var)
  430. return;
  431. }
  432. abort();
  433. }
  434. int
  435. cleanup_reset(void)
  436. {
  437. return cleanup_sp > cleanup_mark;
  438. }
  439. void
  440. cleanup_until_mark(void)
  441. {
  442. while (cleanup_sp > cleanup_mark) {
  443. struct cleanup_entry ce;
  444. cleanup_sp--;
  445. ce = cleanup_stack[cleanup_sp];
  446. ce.fn(ce.var);
  447. }
  448. }
  449. size_t
  450. cleanup_push_mark(void)
  451. {
  452. size_t old_mark;
  453. old_mark = cleanup_mark;
  454. cleanup_mark = cleanup_sp;
  455. return old_mark;
  456. }
  457. void
  458. cleanup_pop_mark(size_t mark)
  459. {
  460. assert (mark <= cleanup_sp);
  461. cleanup_mark = mark;
  462. }
  463. void
  464. sigint_cleanup(void *xsa)
  465. {
  466. const struct sigaction *sa;
  467. sa = xsa;
  468. sigaction(SIGINT, sa, NULL);
  469. }
  470. void
  471. sigprocmask_cleanup(void *xmask)
  472. {
  473. sigset_t *mask;
  474. mask = xmask;
  475. sigprocmask(SIG_SETMASK, mask, NULL);
  476. }
  477. void
  478. open_cleanup(void *xptr)
  479. {
  480. int *ptr;
  481. ptr = xptr;
  482. xclose(*ptr);
  483. }
  484. void
  485. opendir_cleanup(void *xdir)
  486. {
  487. DIR *dir;
  488. dir = xdir;
  489. xclosedir(dir);
  490. }
  491. void
  492. xfree_indirect(void *xptr)
  493. {
  494. void **ptr; /* This is actually type punning :( */
  495. ptr = xptr;
  496. xfree(*ptr);
  497. }
  498. void
  499. reset(void)
  500. {
  501. cleanup_until_mark();
  502. _reset();
  503. abort();
  504. }
  505. /*
  506. * The parser and scanner set up errors for later by calling seterr,
  507. * which sets the variable err as a side effect; later to be tested,
  508. * e.g. in process.
  509. */
  510. void
  511. /*VARARGS1*/
  512. seterror(unsigned int id, ...)
  513. {
  514. if (seterr == 0) {
  515. va_list va;
  516. va_start(va, id);
  517. if (id >= sizeof(elst) / sizeof(elst[0]))
  518. id = ERR_INVALID;
  519. seterr = xvasprintf(elst[id], va);
  520. va_end(va);
  521. }
  522. }
  523. void
  524. fixerror(void)
  525. {
  526. didfds = 0; /* Forget about 0,1,2 */
  527. /*
  528. * Go away if -e or we are a child shell
  529. */
  530. if (!exitset || exiterr || child)
  531. xexit(1);
  532. /*
  533. * Reset the state of the input. This buffered seek to end of file will
  534. * also clear the while/foreach stack.
  535. */
  536. btoeof();
  537. setcopy(STRstatus, STR1, VAR_READWRITE);/*FIXRESET*/
  538. #ifdef BSDJOBS
  539. if (tpgrp > 0)
  540. (void) tcsetpgrp(FSHTTY, tpgrp);
  541. #endif
  542. }
  543. /*
  544. * Print the error with the given id.
  545. *
  546. * Special ids:
  547. * ERR_SILENT: Print nothing.
  548. * ERR_OLD: Print the previously set error
  549. * ERR_NAME: If this bit is set, print the name of the function
  550. * in bname
  551. *
  552. * This routine always resets or exits. The flag haderr
  553. * is set so the routine who catches the unwind can propogate
  554. * it if they want.
  555. *
  556. * Note that any open files at the point of error will eventually
  557. * be closed in the routine process in sh.c which is the only
  558. * place error unwinds are ever caught.
  559. */
  560. void
  561. /*VARARGS*/
  562. stderror(unsigned int id, ...)
  563. {
  564. va_list va;
  565. int flags;
  566. va_start(va, id);
  567. /*
  568. * Reset don't free flag for buggy os's
  569. */
  570. dont_free = 0;
  571. flags = (int) id & ERR_FLAGS;
  572. id &= ~ERR_FLAGS;
  573. /* Pyramid's OS/x has a subtle bug in <varargs.h> which prevents calling
  574. * va_end more than once in the same function. -- sterling@netcom.com
  575. */
  576. assert(!((flags & ERR_OLD) && seterr == NULL));
  577. if (id >= sizeof(elst) / sizeof(elst[0]))
  578. id = ERR_INVALID;
  579. if (!(flags & ERR_SILENT)) {
  580. /*
  581. * Must flush before we print as we wish output before the error
  582. * to go on (some form of) standard output, while output after
  583. * goes on (some form of) diagnostic output. If didfds then output
  584. * will go to 1/2 else to FSHOUT/FSHDIAG. See flush in sh.print.c.
  585. */
  586. flush();/*FIXRESET*/
  587. haderr = 1; /* Now to diagnostic output */
  588. if (flags & ERR_NAME)
  589. xprintf("%s: ", bname);/*FIXRESET*/
  590. if ((flags & ERR_OLD)) {
  591. /* Old error. */
  592. xprintf("%s.\n", seterr);/*FIXRESET*/
  593. } else {
  594. xvprintf(elst[id], va);/*FIXRESET*/
  595. xprintf(".\n");/*FIXRESET*/
  596. }
  597. }
  598. va_end(va);
  599. if (seterr) {
  600. xfree(seterr);
  601. seterr = NULL;
  602. }
  603. fixerror();
  604. reset(); /* Unwind */
  605. }