PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/error.c

https://bitbucket.org/jkniiv/ash-plan9
C | 303 lines | 187 code | 34 blank | 82 comment | 14 complexity | 76a624a20f03b847e98572f9dbd9ab19 MD5 | raw file
  1. /* $NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $ */
  2. /*-
  3. * Copyright (c) 1991, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Kenneth Almquist.
  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. All advertising materials mentioning features or use of this software
  18. * must display the following acknowledgement:
  19. * This product includes software developed by the University of
  20. * California, Berkeley and its contributors.
  21. * 4. Neither the name of the University nor the names of its contributors
  22. * may be used to endorse or promote products derived from this software
  23. * without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35. * SUCH DAMAGE.
  36. */
  37. /* #include <sys/cdefs.h>
  38. #ifndef lint
  39. #if 0
  40. static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
  41. #else
  42. __RCSID("$NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $");
  43. #endif
  44. #endif
  45. */
  46. /*
  47. * Errors and exceptions.
  48. */
  49. #include <signal.h>
  50. #include <stdlib.h>
  51. #include <unistd.h>
  52. #include <errno.h>
  53. #include "shell.h"
  54. #include "main.h"
  55. #include "options.h"
  56. #include "output.h"
  57. #include "error.h"
  58. #include "show.h"
  59. /*
  60. * Code to handle exceptions in C.
  61. */
  62. struct jmploc *handler;
  63. int exception;
  64. volatile int suppressint;
  65. volatile int intpending;
  66. char *commandname;
  67. static void exverror(int, const char *, va_list)
  68. __attribute__((__noreturn__));
  69. /*
  70. * Called to raise an exception. Since C doesn't include exceptions, we
  71. * just do a longjmp to the exception handler. The type of exception is
  72. * stored in the global variable "exception".
  73. */
  74. void
  75. exraise(e)
  76. int e;
  77. {
  78. if (handler == NULL)
  79. abort();
  80. exception = e;
  81. longjmp(handler->loc, 1);
  82. }
  83. /*
  84. * Called from trap.c when a SIGINT is received. (If the user specifies
  85. * that SIGINT is to be trapped or ignored using the trap builtin, then
  86. * this routine is not called.) Suppressint is nonzero when interrupts
  87. * are held using the INTOFF macro. The call to _exit is necessary because
  88. * there is a short period after a fork before the signal handlers are
  89. * set to the appropriate value for the child. (The test for iflag is
  90. * just defensive programming.)
  91. */
  92. void
  93. onint() {
  94. sigset_t sigset;
  95. if (suppressint) {
  96. intpending++;
  97. return;
  98. }
  99. intpending = 0;
  100. sigemptyset(&sigset);
  101. sigprocmask(SIG_SETMASK, &sigset, NULL);
  102. if (rootshell && iflag)
  103. exraise(EXINT);
  104. else {
  105. signal(SIGINT, SIG_DFL);
  106. raise(SIGINT);
  107. }
  108. /* NOTREACHED */
  109. }
  110. /*
  111. * Exverror is called to raise the error exception. If the first argument
  112. * is not NULL then error prints an error message using printf style
  113. * formatting. It then raises the error exception.
  114. */
  115. static void
  116. exverror(cond, msg, ap)
  117. int cond;
  118. const char *msg;
  119. va_list ap;
  120. {
  121. CLEAR_PENDING_INT;
  122. INTOFF;
  123. #ifdef DEBUG
  124. if (msg)
  125. TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
  126. else
  127. TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
  128. #endif
  129. if (msg) {
  130. if (commandname)
  131. outfmt(&errout, "%s: ", commandname);
  132. doformat(&errout, msg, ap);
  133. out2c('\n');
  134. }
  135. flushall();
  136. exraise(cond);
  137. /* NOTREACHED */
  138. }
  139. #ifdef __STDC__
  140. void
  141. error(const char *msg, ...)
  142. #else
  143. void
  144. error(va_alist)
  145. va_dcl
  146. #endif
  147. {
  148. #ifndef __STDC__
  149. const char *msg;
  150. #endif
  151. va_list ap;
  152. #ifdef __STDC__
  153. va_start(ap, msg);
  154. #else
  155. va_start(ap);
  156. msg = va_arg(ap, const char *);
  157. #endif
  158. exverror(EXERROR, msg, ap);
  159. /* NOTREACHED */
  160. va_end(ap);
  161. }
  162. #ifdef __STDC__
  163. void
  164. exerror(int cond, const char *msg, ...)
  165. #else
  166. void
  167. exerror(va_alist)
  168. va_dcl
  169. #endif
  170. {
  171. #ifndef __STDC__
  172. int cond;
  173. const char *msg;
  174. #endif
  175. va_list ap;
  176. #ifdef __STDC__
  177. va_start(ap, msg);
  178. #else
  179. va_start(ap);
  180. cond = va_arg(ap, int);
  181. msg = va_arg(ap, const char *);
  182. #endif
  183. exverror(cond, msg, ap);
  184. /* NOTREACHED */
  185. va_end(ap);
  186. }
  187. /*
  188. * Table of error messages.
  189. */
  190. struct errname {
  191. short errcode; /* error number */
  192. short action; /* operation which encountered the error */
  193. const char *msg; /* text describing the error */
  194. };
  195. #define ALL (E_OPEN|E_CREAT|E_EXEC)
  196. STATIC const struct errname errormsg[] = {
  197. { EINTR, ALL, "interrupted" },
  198. { EACCES, ALL, "permission denied" },
  199. { EIO, ALL, "I/O error" },
  200. { ENOENT, E_OPEN, "no such file" },
  201. { ENOENT, E_CREAT,"directory nonexistent" },
  202. { ENOENT, E_EXEC, "not found" },
  203. { ENOTDIR, E_OPEN, "no such file" },
  204. { ENOTDIR, E_CREAT,"directory nonexistent" },
  205. { ENOTDIR, E_EXEC, "not found" },
  206. { EISDIR, ALL, "is a directory" },
  207. #ifdef notdef
  208. { EMFILE, ALL, "too many open files" },
  209. #endif
  210. { ENFILE, ALL, "file table overflow" },
  211. { ENOSPC, ALL, "file system full" },
  212. #ifdef EDQUOT
  213. { EDQUOT, ALL, "disk quota exceeded" },
  214. #endif
  215. #ifdef ENOSR
  216. { ENOSR, ALL, "no streams resources" },
  217. #endif
  218. { ENXIO, ALL, "no such device or address" },
  219. { EROFS, ALL, "read-only file system" },
  220. #ifdef ETXTBSY
  221. { ETXTBSY, ALL, "text busy" },
  222. #endif
  223. #ifdef SYSV
  224. { EAGAIN, E_EXEC, "not enough memory" },
  225. #endif
  226. { ENOMEM, ALL, "not enough memory" },
  227. #ifdef ENOLINK
  228. { ENOLINK, ALL, "remote access failed" },
  229. #endif
  230. #ifdef EMULTIHOP
  231. { EMULTIHOP, ALL, "remote access failed" },
  232. #endif
  233. #ifdef ECOMM
  234. { ECOMM, ALL, "remote access failed" },
  235. #endif
  236. #ifdef ESTALE
  237. { ESTALE, ALL, "remote access failed" },
  238. #endif
  239. #ifdef ETIMEDOUT
  240. { ETIMEDOUT, ALL, "remote access failed" },
  241. #endif
  242. #ifdef ELOOP
  243. { ELOOP, ALL, "symbolic link loop" },
  244. #endif
  245. { E2BIG, E_EXEC, "argument list too long" },
  246. #ifdef ELIBACC
  247. { ELIBACC, E_EXEC, "shared library missing" },
  248. #endif
  249. { 0, 0, NULL },
  250. };
  251. /*
  252. * Return a string describing an error. The returned string may be a
  253. * pointer to a static buffer that will be overwritten on the next call.
  254. * Action describes the operation that got the error.
  255. */
  256. const char *
  257. errmsg(e, action)
  258. int e;
  259. int action;
  260. {
  261. struct errname const *ep;
  262. static char buf[12];
  263. for (ep = errormsg ; ep->errcode ; ep++) {
  264. if (ep->errcode == e && (ep->action & action) != 0)
  265. return ep->msg;
  266. }
  267. fmtstr(buf, sizeof buf, "error %d", e);
  268. return buf;
  269. }