#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/reboot.h>
#include <sys/msgbuf.h>
#include <sys/proc.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/tprintf.h>
#include <sys/syslog.h>
#include <stdarg.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/subr_prf.h>
#include <kern/cpu_number.h>
#include <machine/spl.h>
#include <libkern/libkern.h>
struct snprintf_arg {
char *str;
size_t remain;
};
extern const char *panicstr;
extern cnputc();
int (*v_putc)() = cnputc;
extern struct tty cons;
extern struct tty *constty;
extern int __doprnt(const char *fmt,
va_list *argp,
void (*putc)(int, void *arg),
void *arg,
int radix);
static void puts(const char *s, int flags, struct tty *ttyp);
static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld_size);
decl_simple_lock_data(,printf_lock)
#if NCPUS > 1
boolean_t new_printf_cpu_number;
#endif
extern void logwakeup();
extern void halt_cpu();
extern boot();
static void
snprintf_func(int ch, void *arg);
struct putchar_args {
int flags;
struct tty *tty;
};
static void putchar(int c, void *arg);
void
uprintf(const char *fmt, ...)
{
register struct proc *p = current_proc();
struct putchar_args pca;
va_list ap;
pca.flags = TOTTY;
pca.tty = (struct tty *)p->p_session->s_ttyp;
if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
va_start(ap, fmt);
__doprnt(fmt, &ap, putchar, &pca, 10);
va_end(ap);
}
}
tpr_t
tprintf_open(p)
register struct proc *p;
{
if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
SESSHOLD(p->p_session);
return ((tpr_t) p->p_session);
}
return ((tpr_t) NULL);
}
void
tprintf_close(sess)
tpr_t sess;
{
if (sess)
SESSRELE((struct session *) sess);
}
void
tprintf(tpr_t tpr, const char *fmt, ...)
{
register struct session *sess = (struct session *)tpr;
struct tty *tp = NULL;
int flags = TOLOG;
va_list ap;
struct putchar_args pca;
logpri(LOG_INFO);
if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
flags |= TOTTY;
tp = sess->s_ttyp;
}
if (tp != NULL) {
pca.flags = TOTTY;
pca.tty = tp;
va_start(ap, fmt);
__doprnt(fmt, &ap, putchar, &pca, 10);
va_end(ap);
}
logwakeup();
}
void
ttyprintf(struct tty *tp, const char *fmt, ...)
{
va_list ap;
if (tp != NULL) {
struct putchar_args pca;
pca.flags = TOTTY;
pca.tty = tp;
va_start(ap, fmt);
__doprnt(fmt, &ap, putchar, &pca, 10);
va_end(ap);
}
}
extern int log_open;
void
logpri(level)
int level;
{
struct putchar_args pca;
pca.flags = TOLOG;
pca.tty = NULL;
putchar('<', &pca);
printn((u_long)level, 10, TOLOG, (struct tty *)0, 0, 0);
putchar('>', &pca);
}
void
addlog(const char *fmt, ...)
{
register s = splhigh();
va_list ap;
struct putchar_args pca;
pca.flags = TOLOG;
pca.tty = NULL;
va_start(ap, fmt);
__doprnt(fmt, &ap, putchar, &pca, 10);
splx(s);
if (!log_open) {
pca.flags = TOCONS;
__doprnt(fmt, &ap, putchar, &pca, 10);
}
va_end(ap);
logwakeup();
}
void _printf(int flags, struct tty *ttyp, const char *format, ...)
{
va_list ap;
struct putchar_args pca;
pca.flags = flags;
pca.tty = ttyp;
va_start(ap, format);
__doprnt(format, &ap, putchar, &pca, 10);
va_end(ap);
}
int prf(const char *fmt, va_list ap, int flags, struct tty *ttyp)
{
struct putchar_args pca;
pca.flags = flags;
pca.tty = ttyp;
#if NCPUS > 1
int cpun = cpu_number();
if(ttyp == 0) {
simple_lock(&printf_lock);
} else
TTY_LOCK(ttyp);
if (cpun != master_cpu)
new_printf_cpu_number = TRUE;
if (new_printf_cpu_number) {
putchar('{', flags, ttyp);
printn((u_long)cpun, 10, flags, ttyp, 0, 0);
putchar('}', flags, ttyp);
}
#endif
__doprnt(fmt, &ap, putchar, &pca, 10);
#if NCPUS > 1
if(ttyp == 0) {
simple_unlock(&printf_lock);
} else
TTY_UNLOCK(ttyp);
#endif
return 0;
}
static void puts(const char *s, int flags, struct tty *ttyp)
{
register char c;
struct putchar_args pca;
pca.flags = flags;
pca.tty = ttyp;
while ((c = *s++))
putchar(c, &pca);
}
static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld_size)
{
char prbuf[11];
register char *cp;
struct putchar_args pca;
pca.flags = flags;
pca.tty = ttyp;
if (b == 10 && (int)n < 0) {
putchar('-', &pca);
n = (unsigned)(-(int)n);
}
cp = prbuf;
do {
*cp++ = "0123456789abcdef"[n%b];
n /= b;
} while (n);
if (fld_size) {
for (fld_size -= cp - prbuf; fld_size > 0; fld_size--)
if (zf)
putchar('0', &pca);
else
putchar(' ', &pca);
}
do
putchar(*--cp, &pca);
while (cp > prbuf);
}
void tablefull(const char *tab)
{
log(LOG_ERR, "%s: table is full\n", tab);
}
void
putchar(int c, void *arg)
{
struct putchar_args *pca = arg;
register struct msgbuf *mbp;
char **sp = (char**) pca->tty;
if (panicstr)
constty = 0;
if ((pca->flags & TOCONS) && pca->tty == NULL && constty) {
pca->tty = constty;
pca->flags |= TOTTY;
}
if ((pca->flags & TOTTY) && pca->tty && tputchar(c, pca->tty) < 0 &&
(pca->flags & TOCONS) && pca->tty == constty)
constty = 0;
if ((pca->flags & TOLOG) && c != '\0' && c != '\r' && c != 0177)
log_putc(c);
if ((pca->flags & TOCONS) && constty == 0 && c != '\0')
(*v_putc)(c);
if (pca->flags & TOSTR) {
**sp = c;
(*sp)++;
}
}
int
vsprintf(char *buf, const char *cfmt, va_list ap)
{
int retval;
struct snprintf_arg info;
info.str = buf;
info.remain = 999999;
retval = __doprnt(cfmt, &ap, snprintf_func, &info, 10);
if (info.remain >= 1) {
*info.str++ = '\0';
}
return 0;
}
int
snprintf(char *str, size_t size, const char *format, ...)
{
int retval;
va_list ap;
va_start(ap, format);
retval = vsnprintf(str, size, format, ap);
va_end(ap);
return(retval);
}
int
vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
struct snprintf_arg info;
int retval;
info.str = str;
info.remain = size;
retval = __doprnt(format, &ap, snprintf_func, &info, 10);
if (info.remain >= 1)
*info.str++ = '\0';
return retval;
}
static void
snprintf_func(int ch, void *arg)
{
struct snprintf_arg *const info = arg;
if (info->remain >= 2) {
*info->str++ = ch;
info->remain--;
}
}
int
kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
{
__doprnt(fmt, &ap, func, arg, radix);
return 0;
}