+
+
+/*
+ * log_putc
+ *
+ * Decription: Output a character to the log; assumes the LOG_LOCK() is NOT
+ * held by the caller.
+ *
+ * Parameters: c Character to output
+ *
+ * Returns: (void)
+ *
+ * Notes: This function is used for syingle byte output to the log. It
+ * primarily exists to maintain binary backward compatibility.
+ */
+void
+log_putc(char c)
+{
+ if (!log_inited) {
+ panic("bsd log is not inited");
+ }
+ LOG_LOCK();
+ log_putc_locked(c);
+ LOG_UNLOCK();
+}
+
+
+/*
+ * it is possible to increase the kernel log buffer size by adding
+ * msgbuf=n
+ * to the kernel command line, and to read the current size using
+ * sysctl kern.msgbuf
+ * If there is no parameter on the kernel command line, the buffer is
+ * allocated statically and is MSG_BSIZE characters in size, otherwise
+ * memory is dynamically allocated.
+ * This function may only be called once, during kernel initialization.
+ * Memory management must already be up. The buffer must not have
+ * overflown yet.
+ */
+void
+log_setsize(long size) {
+ char *new_logdata;
+ if (msgbufp->msg_size!=MSG_BSIZE) {
+ printf("log_setsize: attempt to change size more than once\n");
+ return;
+ }
+ if (size==MSG_BSIZE)
+ return;
+ if (size<MSG_BSIZE) { /* we don't support reducing the log size */
+ printf("log_setsize: can't decrease log size\n");
+ return;
+ }
+ if (!(new_logdata = (char*)kalloc(size))) {
+ printf("log_setsize: unable to allocate memory\n");
+ return;
+ }
+ LOG_LOCK();
+ bcopy(smsg_bufc, new_logdata, MSG_BSIZE);
+ bzero(new_logdata+MSG_BSIZE, size - MSG_BSIZE);
+ /* this memory is now dead - clear it so that it compresses better
+ in case of suspend to disk etc. */
+ bzero(smsg_bufc, MSG_BSIZE);
+ msgbufp->msg_size = size;
+ msgbufp->msg_bufc = new_logdata;
+ LOG_UNLOCK();
+ printf("set system log size to %ld bytes\n", msgbufp->msg_size);
+}
+
+SYSCTL_LONG(_kern, OID_AUTO, msgbuf, CTLFLAG_RD, &temp_msgbuf.msg_size, "");
+
+/*
+ * This should be called by single user mode /sbin/dmesg only.
+ * It returns as much data still in the buffer as possible.
+ */
+int
+log_dmesg(user_addr_t buffer, uint32_t buffersize, register_t * retval) {
+ unsigned long i;
+ int error = 0, newl, skip;
+ char *localbuff, *p, *copystart, ch;
+ long localbuff_size = msgbufp->msg_size+2, copysize;
+
+ if (!(localbuff = (char *)kalloc(localbuff_size))) {
+ printf("log_dmesg: unable to allocate memory\n");
+ return (ENOMEM);
+ }
+ /* in between here, the log could become bigger, but that's fine */
+ LOG_LOCK();
+
+ /*
+ * The message buffer is circular; start at the write pointer, and
+ * make one loop up to write pointer - 1.
+ */
+ p = msgbufp->msg_bufc + msgbufp->msg_bufx;
+ for (i = newl = skip = 0; p != msgbufp->msg_bufc + msgbufp->msg_bufx - 1; ++p) {
+ if (p >= msgbufp->msg_bufc + msgbufp->msg_size)
+ p = msgbufp->msg_bufc;
+ ch = *p;
+ /* Skip "\n<.*>" syslog sequences. */
+ if (skip) {
+ if (ch == '>')
+ newl = skip = 0;
+ continue;
+ }
+ if (newl && ch == '<') {
+ skip = 1;
+ continue;
+ }
+ if (ch == '\0')
+ continue;
+ newl = ch == '\n';
+ localbuff[i++] = ch;
+ }
+ if (!newl)
+ localbuff[i++] = '\n';
+ localbuff[i++] = 0;
+
+ if (buffersize >= i) {
+ copystart = localbuff;
+ copysize = i;
+ } else {
+ copystart = localbuff + i - buffersize;
+ copysize = buffersize;
+ }
+
+ LOG_UNLOCK();
+
+ error = copyout(copystart, buffer, copysize);
+ if (!error)
+ *retval = copysize;
+
+ kfree(localbuff, localbuff_size);
+ return (error);
+}