summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/libsm/exc.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/libsm/exc.c')
-rw-r--r--contrib/sendmail/libsm/exc.c651
1 files changed, 0 insertions, 651 deletions
diff --git a/contrib/sendmail/libsm/exc.c b/contrib/sendmail/libsm/exc.c
deleted file mode 100644
index 0bcf17a..0000000
--- a/contrib/sendmail/libsm/exc.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers.
- * All rights reserved.
- *
- * By using this file, you agree to the terms and conditions set
- * forth in the LICENSE file which can be found at the top level of
- * the sendmail distribution.
- *
- */
-
-#include <sm/gen.h>
-SM_RCSID("@(#)$Id: exc.c,v 1.49 2006/12/19 19:28:09 ca Exp $")
-
-/*
-** exception handling
-** For documentation, see exc.html
-*/
-
-#include <ctype.h>
-#include <string.h>
-
-#include <sm/errstring.h>
-#include <sm/exc.h>
-#include <sm/heap.h>
-#include <sm/string.h>
-#include <sm/varargs.h>
-#include <sm/io.h>
-
-const char SmExcMagic[] = "sm_exc";
-const char SmExcTypeMagic[] = "sm_exc_type";
-
-/*
-** SM_ETYPE_PRINTF -- printf for exception types.
-**
-** Parameters:
-** exc -- exception.
-** stream -- file for output.
-**
-** Returns:
-** none.
-*/
-
-/*
-** A simple formatted print function that can be used as the print function
-** by most exception types. It prints the printcontext string, interpreting
-** occurrences of %0 through %9 as references to the argument vector.
-** If exception argument 3 is an int or long, then %3 will print the
-** argument in decimal, and %o3 or %x3 will print it in octal or hex.
-*/
-
-void
-sm_etype_printf(exc, stream)
- SM_EXC_T *exc;
- SM_FILE_T *stream;
-{
- size_t n = strlen(exc->exc_type->etype_argformat);
- const char *p, *s;
- char format;
-
- for (p = exc->exc_type->etype_printcontext; *p != '\0'; ++p)
- {
- if (*p != '%')
- {
- (void) sm_io_putc(stream, SM_TIME_DEFAULT, *p);
- continue;
- }
- ++p;
- if (*p == '\0')
- {
- (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%');
- break;
- }
- if (*p == '%')
- {
- (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%');
- continue;
- }
- format = '\0';
- if (isalpha(*p))
- {
- format = *p++;
- if (*p == '\0')
- {
- (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%');
- (void) sm_io_putc(stream, SM_TIME_DEFAULT,
- format);
- break;
- }
- }
- if (isdigit(*p))
- {
- size_t i = *p - '0';
- if (i < n)
- {
- switch (exc->exc_type->etype_argformat[i])
- {
- case 's':
- case 'r':
- s = exc->exc_argv[i].v_str;
- if (s == NULL)
- s = "(null)";
- sm_io_fputs(stream, SM_TIME_DEFAULT, s);
- continue;
- case 'i':
- sm_io_fprintf(stream,
- SM_TIME_DEFAULT,
- format == 'o' ? "%o"
- : format == 'x' ? "%x"
- : "%d",
- exc->exc_argv[i].v_int);
- continue;
- case 'l':
- sm_io_fprintf(stream,
- SM_TIME_DEFAULT,
- format == 'o' ? "%lo"
- : format == 'x' ? "%lx"
- : "%ld",
- exc->exc_argv[i].v_long);
- continue;
- case 'e':
- sm_exc_write(exc->exc_argv[i].v_exc,
- stream);
- continue;
- }
- }
- }
- (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%');
- if (format)
- (void) sm_io_putc(stream, SM_TIME_DEFAULT, format);
- (void) sm_io_putc(stream, SM_TIME_DEFAULT, *p);
- }
-}
-
-/*
-** Standard exception types.
-*/
-
-/*
-** SM_ETYPE_OS_PRINT -- Print OS related exception.
-**
-** Parameters:
-** exc -- exception.
-** stream -- file for output.
-**
-** Returns:
-** none.
-*/
-
-static void
-sm_etype_os_print __P((
- SM_EXC_T *exc,
- SM_FILE_T *stream));
-
-static void
-sm_etype_os_print(exc, stream)
- SM_EXC_T *exc;
- SM_FILE_T *stream;
-{
- int err = exc->exc_argv[0].v_int;
- char *syscall = exc->exc_argv[1].v_str;
- char *sysargs = exc->exc_argv[2].v_str;
-
- if (sysargs)
- sm_io_fprintf(stream, SM_TIME_DEFAULT, "%s: %s failed: %s",
- sysargs, syscall, sm_errstring(err));
- else
- sm_io_fprintf(stream, SM_TIME_DEFAULT, "%s failed: %s", syscall,
- sm_errstring(err));
-}
-
-/*
-** SmEtypeOs represents the failure of a Unix system call.
-** The three arguments are:
-** int errno (eg, ENOENT)
-** char *syscall (eg, "open")
-** char *sysargs (eg, NULL or "/etc/mail/sendmail.cf")
-*/
-
-const SM_EXC_TYPE_T SmEtypeOs =
-{
- SmExcTypeMagic,
- "E:sm.os",
- "isr",
- sm_etype_os_print,
- NULL,
-};
-
-/*
-** SmEtypeErr is a completely generic error which should only be
-** used in applications and test programs. Libraries should use
-** more specific exception codes.
-*/
-
-const SM_EXC_TYPE_T SmEtypeErr =
-{
- SmExcTypeMagic,
- "E:sm.err",
- "r",
- sm_etype_printf,
- "%0",
-};
-
-/*
-** SM_EXC_VNEW_X -- Construct a new exception object.
-**
-** Parameters:
-** etype -- type of exception.
-** ap -- varargs.
-**
-** Returns:
-** pointer to exception object.
-*/
-
-/*
-** This is an auxiliary function called by sm_exc_new_x and sm_exc_raisenew_x.
-**
-** If an exception is raised, then to avoid a storage leak, we must:
-** (a) Free all storage we have allocated.
-** (b) Free all exception arguments in the varargs list.
-** Getting this right is tricky.
-**
-** To see why (b) is required, consider the code fragment
-** SM_EXCEPT(exc, "*")
-** sm_exc_raisenew_x(&MyEtype, exc);
-** SM_END_TRY
-** In the normal case, sm_exc_raisenew_x will allocate and raise a new
-** exception E that owns exc. When E is eventually freed, exc is also freed.
-** In the exceptional case, sm_exc_raisenew_x must free exc before raising
-** an out-of-memory exception so that exc is not leaked.
-*/
-
-static SM_EXC_T *sm_exc_vnew_x __P((const SM_EXC_TYPE_T *, va_list SM_NONVOLATILE));
-
-static SM_EXC_T *
-sm_exc_vnew_x(etype, ap)
- const SM_EXC_TYPE_T *etype;
- va_list SM_NONVOLATILE ap;
-{
- /*
- ** All variables that are modified in the SM_TRY clause and
- ** referenced in the SM_EXCEPT clause must be declared volatile.
- */
-
- /* NOTE: Type of si, i, and argc *must* match */
- SM_EXC_T * volatile exc = NULL;
- int volatile si = 0;
- SM_VAL_T * volatile argv = NULL;
- int i, argc;
-
- SM_REQUIRE_ISA(etype, SmExcTypeMagic);
- argc = strlen(etype->etype_argformat);
- SM_TRY
- {
- /*
- ** Step 1. Allocate the exception structure.
- ** On failure, scan the varargs list and free all
- ** exception arguments.
- */
-
- exc = sm_malloc_x(sizeof(SM_EXC_T));
- exc->sm_magic = SmExcMagic;
- exc->exc_refcount = 1;
- exc->exc_type = etype;
- exc->exc_argv = NULL;
-
- /*
- ** Step 2. Allocate the argument vector.
- ** On failure, free exc, scan the varargs list and free all
- ** exception arguments. On success, scan the varargs list,
- ** and copy the arguments into argv.
- */
-
- argv = sm_malloc_x(argc * sizeof(SM_VAL_T));
- exc->exc_argv = argv;
- for (i = 0; i < argc; ++i)
- {
- switch (etype->etype_argformat[i])
- {
- case 'i':
- argv[i].v_int = SM_VA_ARG(ap, int);
- break;
- case 'l':
- argv[i].v_long = SM_VA_ARG(ap, long);
- break;
- case 'e':
- argv[i].v_exc = SM_VA_ARG(ap, SM_EXC_T*);
- break;
- case 's':
- argv[i].v_str = SM_VA_ARG(ap, char*);
- break;
- case 'r':
- SM_REQUIRE(etype->etype_argformat[i+1] == '\0');
- argv[i].v_str = SM_VA_ARG(ap, char*);
- break;
- default:
- sm_abort("sm_exc_vnew_x: bad argformat '%c'",
- etype->etype_argformat[i]);
- }
- }
-
- /*
- ** Step 3. Scan argv, and allocate space for all
- ** string arguments. si is the number of elements
- ** of argv that have been processed so far.
- ** On failure, free exc, argv, all the exception arguments
- ** and all of the strings that have been copied.
- */
-
- for (si = 0; si < argc; ++si)
- {
- switch (etype->etype_argformat[si])
- {
- case 's':
- {
- char *str = argv[si].v_str;
- if (str != NULL)
- argv[si].v_str = sm_strdup_x(str);
- }
- break;
- case 'r':
- {
- char *fmt = argv[si].v_str;
- if (fmt != NULL)
- argv[si].v_str = sm_vstringf_x(fmt, ap);
- }
- break;
- }
- }
- }
- SM_EXCEPT(e, "*")
- {
- if (exc == NULL || argv == NULL)
- {
- /*
- ** Failure in step 1 or step 2.
- ** Scan ap and free all exception arguments.
- */
-
- for (i = 0; i < argc; ++i)
- {
- switch (etype->etype_argformat[i])
- {
- case 'i':
- (void) SM_VA_ARG(ap, int);
- break;
- case 'l':
- (void) SM_VA_ARG(ap, long);
- break;
- case 'e':
- sm_exc_free(SM_VA_ARG(ap, SM_EXC_T*));
- break;
- case 's':
- case 'r':
- (void) SM_VA_ARG(ap, char*);
- break;
- }
- }
- }
- else
- {
- /*
- ** Failure in step 3. Scan argv and free
- ** all exception arguments and all string
- ** arguments that have been duplicated.
- ** Then free argv.
- */
-
- for (i = 0; i < argc; ++i)
- {
- switch (etype->etype_argformat[i])
- {
- case 'e':
- sm_exc_free(argv[i].v_exc);
- break;
- case 's':
- case 'r':
- if (i < si)
- sm_free(argv[i].v_str);
- break;
- }
- }
- sm_free(argv);
- }
- sm_free(exc);
- sm_exc_raise_x(e);
- }
- SM_END_TRY
-
- return exc;
-}
-
-/*
-** SM_EXC_NEW_X -- Construct a new exception object.
-**
-** Parameters:
-** etype -- type of exception.
-** ... -- varargs.
-**
-** Returns:
-** pointer to exception object.
-*/
-
-SM_EXC_T *
-#if SM_VA_STD
-sm_exc_new_x(
- const SM_EXC_TYPE_T *etype,
- ...)
-#else /* SM_VA_STD */
-sm_exc_new_x(etype, va_alist)
- const SM_EXC_TYPE_T *etype;
- va_dcl
-#endif /* SM_VA_STD */
-{
- SM_EXC_T *exc;
- SM_VA_LOCAL_DECL
-
- SM_VA_START(ap, etype);
- exc = sm_exc_vnew_x(etype, ap);
- SM_VA_END(ap);
- return exc;
-}
-
-/*
-** SM_EXC_FREE -- Destroy a reference to an exception object.
-**
-** Parameters:
-** exc -- exception object.
-**
-** Returns:
-** none.
-*/
-
-void
-sm_exc_free(exc)
- SM_EXC_T *exc;
-{
- if (exc == NULL)
- return;
- SM_REQUIRE(exc->sm_magic == SmExcMagic);
- if (exc->exc_refcount == 0)
- return;
- if (--exc->exc_refcount == 0)
- {
- int i, c;
-
- for (i = 0; (c = exc->exc_type->etype_argformat[i]) != '\0';
- ++i)
- {
- switch (c)
- {
- case 's':
- case 'r':
- sm_free(exc->exc_argv[i].v_str);
- break;
- case 'e':
- sm_exc_free(exc->exc_argv[i].v_exc);
- break;
- }
- }
- exc->sm_magic = NULL;
- sm_free(exc->exc_argv);
- sm_free(exc);
- }
-}
-
-/*
-** SM_EXC_MATCH -- Match exception category against a glob pattern.
-**
-** Parameters:
-** exc -- exception.
-** pattern -- glob pattern.
-**
-** Returns:
-** true iff match.
-*/
-
-bool
-sm_exc_match(exc, pattern)
- SM_EXC_T *exc;
- const char *pattern;
-{
- if (exc == NULL)
- return false;
- SM_REQUIRE(exc->sm_magic == SmExcMagic);
- return sm_match(exc->exc_type->etype_category, pattern);
-}
-
-/*
-** SM_EXC_WRITE -- Write exception message to a stream (wo trailing newline).
-**
-** Parameters:
-** exc -- exception.
-** stream -- file for output.
-**
-** Returns:
-** none.
-*/
-
-void
-sm_exc_write(exc, stream)
- SM_EXC_T *exc;
- SM_FILE_T *stream;
-{
- SM_REQUIRE_ISA(exc, SmExcMagic);
- exc->exc_type->etype_print(exc, stream);
-}
-
-/*
-** SM_EXC_PRINT -- Print exception message to a stream (with trailing newline).
-**
-** Parameters:
-** exc -- exception.
-** stream -- file for output.
-**
-** Returns:
-** none.
-*/
-
-void
-sm_exc_print(exc, stream)
- SM_EXC_T *exc;
- SM_FILE_T *stream;
-{
- SM_REQUIRE_ISA(exc, SmExcMagic);
- exc->exc_type->etype_print(exc, stream);
- (void) sm_io_putc(stream, SM_TIME_DEFAULT, '\n');
-}
-
-SM_EXC_HANDLER_T *SmExcHandler = NULL;
-static SM_EXC_DEFAULT_HANDLER_T SmExcDefaultHandler = NULL;
-
-/*
-** SM_EXC_NEWTHREAD -- Initialize exception handling for new process/thread.
-**
-** Parameters:
-** h -- default exception handler.
-**
-** Returns:
-** none.
-*/
-
-/*
-** Initialize a new process or a new thread by clearing the
-** exception handler stack and optionally setting a default
-** exception handler function. Call this at the beginning of main,
-** or in a new process after calling fork, or in a new thread.
-**
-** This function is a luxury, not a necessity.
-** If h != NULL then you can get the same effect by
-** wrapping the body of main, or the body of a forked child
-** or a new thread in SM_TRY ... SM_EXCEPT(e,"*") h(e); SM_END_TRY.
-*/
-
-void
-sm_exc_newthread(h)
- SM_EXC_DEFAULT_HANDLER_T h;
-{
- SmExcHandler = NULL;
- SmExcDefaultHandler = h;
-}
-
-/*
-** SM_EXC_RAISE_X -- Raise an exception.
-**
-** Parameters:
-** exc -- exception.
-**
-** Returns:
-** doesn't.
-*/
-
-void SM_DEAD_D
-sm_exc_raise_x(exc)
- SM_EXC_T *exc;
-{
- SM_REQUIRE_ISA(exc, SmExcMagic);
-
- if (SmExcHandler == NULL)
- {
- if (SmExcDefaultHandler != NULL)
- {
- SM_EXC_DEFAULT_HANDLER_T h;
-
- /*
- ** If defined, the default handler is expected
- ** to terminate the current thread of execution
- ** using exit() or pthread_exit().
- ** If it instead returns normally, then we fall
- ** through to the default case below. If it
- ** raises an exception, then sm_exc_raise_x is
- ** re-entered and, because we set SmExcDefaultHandler
- ** to NULL before invoking h, we will again
- ** end up in the default case below.
- */
-
- h = SmExcDefaultHandler;
- SmExcDefaultHandler = NULL;
- (*h)(exc);
- }
-
- /*
- ** No exception handler, so print the error and exit.
- ** To override this behaviour on a program wide basis,
- ** call sm_exc_newthread or put an exception handler in main().
- **
- ** XXX TODO: map the exception category to an exit code
- ** XXX from <sysexits.h>.
- */
-
- sm_exc_print(exc, smioerr);
- exit(255);
- }
-
- if (SmExcHandler->eh_value == NULL)
- SmExcHandler->eh_value = exc;
- else
- sm_exc_free(exc);
-
- sm_longjmp_nosig(SmExcHandler->eh_context, 1);
-}
-
-/*
-** SM_EXC_RAISENEW_X -- shorthand for sm_exc_raise_x(sm_exc_new_x(...))
-**
-** Parameters:
-** etype -- type of exception.
-** ap -- varargs.
-**
-** Returns:
-** none.
-*/
-
-void SM_DEAD_D
-#if SM_VA_STD
-sm_exc_raisenew_x(
- const SM_EXC_TYPE_T *etype,
- ...)
-#else
-sm_exc_raisenew_x(etype, va_alist)
- const SM_EXC_TYPE_T *etype;
- va_dcl
-#endif
-{
- SM_EXC_T *exc;
- SM_VA_LOCAL_DECL
-
- SM_VA_START(ap, etype);
- exc = sm_exc_vnew_x(etype, ap);
- SM_VA_END(ap);
- sm_exc_raise_x(exc);
-}
OpenPOWER on IntegriCloud