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