1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2012 by Delphix. All rights reserved.
  24  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <sys/param.h>
  28 #include <sys/types.h>
  29 #include <sys/varargs.h>
  30 #include <sys/systm.h>
  31 #include <sys/cmn_err.h>
  32 #include <sys/log.h>
  33 
  34 #include <fakekernel.h>
  35 
  36 void    abort(void) __NORETURN;
  37 
  38 char *volatile panicstr;
  39 va_list  panicargs;
  40 char panicbuf[512];
  41 
  42 volatile int aok;
  43 
  44 static const int
  45 ce_flags[CE_IGNORE] = { SL_NOTE, SL_NOTE, SL_WARN, SL_FATAL };
  46 static const char
  47 ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
  48 static const char
  49 ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
  50 
  51 
  52 /*
  53  * This function is just a stub, exported NODIRECT so that
  54  * comsumers like fksmbd can provide their own.
  55  * (One that actually prints the messages.)
  56  *
  57  * It's used by fakekernel_cprintf() below.
  58  * The flags are SL_... from strlog.h
  59  */
  60 /* ARGSUSED */
  61 void
  62 fakekernel_putlog(char *msg, size_t len, int flags)
  63 {
  64 }
  65 
  66 /*
  67  * fakekernel_cprintf() corresponds to os/printf.c:cprintf()
  68  * This formats the message and calls fakekernel_putlog().
  69  * It's exported NODIRECT to allow replacment.
  70  * The flags are SL_... from strlog.h
  71  */
  72 void
  73 fakekernel_cprintf(const char *fmt, va_list adx, int flags,
  74         const char *prefix, const char *suffix)
  75 {
  76         size_t bufsize = LOG_MSGSIZE;
  77         char buf[LOG_MSGSIZE];
  78         char *bufp = buf;
  79         char *msgp, *bufend;
  80         size_t len;
  81 
  82         if (strchr("^!?", fmt[0]) != NULL) {
  83                 if (fmt[0] == '^')
  84                         flags |= SL_CONSONLY;
  85                 else if (fmt[0] == '!')
  86                         flags |= SL_LOGONLY;
  87                 fmt++;
  88         }
  89 
  90         bufend = bufp + bufsize;
  91         msgp = bufp;
  92         msgp += snprintf(msgp, bufend - msgp, "[fake_kernel] ");
  93         msgp += snprintf(msgp, bufend - msgp, prefix);
  94         msgp += vsnprintf(msgp, bufend - msgp, fmt, adx);
  95         msgp += snprintf(msgp, bufend - msgp, suffix);
  96         len = msgp - bufp;
  97 
  98         fakekernel_putlog(bufp, len, flags);
  99 }
 100 
 101 /*
 102  * "User-level crash dump", if you will.
 103  */
 104 void
 105 vpanic(const char *fmt, va_list adx)
 106 {
 107         va_list tmpargs;
 108 
 109         panicstr = (char *)fmt;
 110         va_copy(panicargs, adx);
 111 
 112         va_copy(tmpargs, adx);
 113         fakekernel_cprintf(fmt, tmpargs, SL_FATAL, "fatal: ", "\n");
 114 
 115         /* Call libc`assfail() so that mdb ::status works */
 116         (void) vsnprintf(panicbuf, sizeof (panicbuf), fmt, adx);
 117         assfail(panicbuf, "(panic)", 0);
 118 
 119         abort();        /* avoid "noreturn" warnings */
 120 }
 121 
 122 void
 123 panic(const char *fmt, ...)
 124 {
 125         va_list adx;
 126 
 127         va_start(adx, fmt);
 128         vpanic(fmt, adx);
 129         va_end(adx);
 130 }
 131 
 132 void
 133 vcmn_err(int ce, const char *fmt, va_list adx)
 134 {
 135 
 136         if (ce == CE_PANIC)
 137                 vpanic(fmt, adx);
 138         if (ce >= CE_IGNORE)
 139                 return;
 140 
 141         fakekernel_cprintf(fmt, adx, ce_flags[ce] | SL_CONSOLE,
 142             ce_prefix[ce], ce_suffix[ce]);
 143 }
 144 
 145 /*PRINTFLIKE2*/
 146 void
 147 cmn_err(int ce, const char *fmt, ...)
 148 {
 149         va_list adx;
 150 
 151         va_start(adx, fmt);
 152         vcmn_err(ce, fmt, adx);
 153         va_end(adx);
 154 }