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  * Copyright 2017 RackTop Systems.
  26  * Copyright (c) 2018, Joyent, Inc.
  27  */
  28 
  29 #include <sys/param.h>
  30 #include <sys/types.h>
  31 #include <sys/varargs.h>
  32 #include <sys/systm.h>
  33 #include <sys/cmn_err.h>
  34 #include <sys/log.h>
  35 
  36 #include <fakekernel.h>
  37 
  38 void    abort(void) __NORETURN;
  39 
  40 char *volatile panicstr;
  41 va_list  panicargs;
  42 char panicbuf[512];
  43 
  44 volatile int aok;
  45 
  46 static const int
  47 ce_flags[CE_IGNORE] = { SL_NOTE, SL_NOTE, SL_WARN, SL_FATAL };
  48 static const char
  49 ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
  50 static const char
  51 ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
  52 
  53 
  54 /*
  55  * This function is just a stub, exported NODIRECT so that
  56  * comsumers like fksmbd can provide their own.
  57  * (One that actually prints the messages.)
  58  *
  59  * It's used by fakekernel_cprintf() below.
  60  * The flags are SL_... from strlog.h
  61  */
  62 /* ARGSUSED */
  63 void
  64 fakekernel_putlog(char *msg, size_t len, int flags)
  65 {
  66 }
  67 
  68 /*
  69  * fakekernel_cprintf() corresponds to os/printf.c:cprintf()
  70  * This formats the message and calls fakekernel_putlog().
  71  * It's exported NODIRECT to allow replacment.
  72  * The flags are SL_... from strlog.h
  73  */
  74 void
  75 fakekernel_cprintf(const char *fmt, va_list adx, int flags,
  76     const char *prefix, const char *suffix)
  77 {
  78         size_t bufsize = LOG_MSGSIZE;
  79         char buf[LOG_MSGSIZE];
  80         char *bufp = buf;
  81         char *msgp, *bufend;
  82         size_t len;
  83 
  84         if (strchr("^!?", fmt[0]) != NULL) {
  85                 if (fmt[0] == '^')
  86                         flags |= SL_CONSONLY;
  87                 else if (fmt[0] == '!')
  88                         flags |= SL_LOGONLY;
  89                 fmt++;
  90         }
  91 
  92         bufend = bufp + bufsize;
  93         msgp = bufp;
  94         msgp += snprintf(msgp, bufend - msgp, "[fake_kernel] ");
  95         msgp += snprintf(msgp, bufend - msgp, prefix);
  96         msgp += vsnprintf(msgp, bufend - msgp, fmt, adx);
  97         msgp += snprintf(msgp, bufend - msgp, suffix);
  98         len = msgp - bufp;
  99 
 100         fakekernel_putlog(bufp, len, flags);
 101 }
 102 
 103 /*
 104  * "User-level crash dump", if you will.
 105  */
 106 void
 107 vpanic(const char *fmt, va_list adx)
 108 {
 109         va_list tmpargs;
 110 
 111         panicstr = (char *)fmt;
 112         va_copy(panicargs, adx);
 113 
 114         va_copy(tmpargs, adx);
 115         fakekernel_cprintf(fmt, tmpargs, SL_FATAL, "fatal: ", "\n");
 116 
 117         /* Call libc`assfail() so that mdb ::status works */
 118         (void) vsnprintf(panicbuf, sizeof (panicbuf), fmt, adx);
 119         (void) assfail(panicbuf, "(panic)", 0);
 120 
 121         abort();        /* avoid "noreturn" warnings */
 122 }
 123 
 124 void
 125 panic(const char *fmt, ...)
 126 {
 127         va_list adx;
 128 
 129         va_start(adx, fmt);
 130         vpanic(fmt, adx);
 131         va_end(adx);
 132 }
 133 
 134 void
 135 fm_panic(const char *fmt, ...)
 136 {
 137         va_list adx;
 138 
 139         va_start(adx, fmt);
 140         vpanic(fmt, adx);
 141         va_end(adx);
 142 }
 143 
 144 void
 145 vcmn_err(int ce, const char *fmt, va_list adx)
 146 {
 147 
 148         if (ce == CE_PANIC)
 149                 vpanic(fmt, adx);
 150         if (ce >= CE_IGNORE)
 151                 return;
 152 
 153         fakekernel_cprintf(fmt, adx, ce_flags[ce] | SL_CONSOLE,
 154             ce_prefix[ce], ce_suffix[ce]);
 155 }
 156 
 157 /*PRINTFLIKE2*/
 158 void
 159 cmn_err(int ce, const char *fmt, ...)
 160 {
 161         va_list adx;
 162 
 163         va_start(adx, fmt);
 164         vcmn_err(ce, fmt, adx);
 165         va_end(adx);
 166 }