home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / sh / error.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-15  |  6.0 KB  |  250 lines

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