Esempio n. 1
0
/*
 * Peek at the full contents of a message buffer without marking any
 * data as read. `seqp' should point to an unsigned integer that
 * msgbuf_peekbytes() can use to retain state between calls so that
 * the whole message buffer can be read in multiple short reads.
 * To initialise this variable to the start of the message buffer,
 * call msgbuf_peekbytes() with a NULL `buf' parameter.
 *
 * Returns the number of characters that were placed in `buf'.
 */
int
msgbuf_peekbytes(struct msgbuf *mbp, char *buf, int buflen, u_int *seqp)
{
    u_int len, pos, wseq;

    mtx_lock_spin(&mbp->msg_lock);

    if (buf == NULL) {
        /* Just initialise *seqp. */
        *seqp = MSGBUF_SEQNORM(mbp, mbp->msg_wseq - mbp->msg_size);
        mtx_unlock_spin(&mbp->msg_lock);
        return (0);
    }

    wseq = mbp->msg_wseq;
    len = MSGBUF_SEQSUB(mbp, wseq, *seqp);
    if (len == 0) {
        mtx_unlock_spin(&mbp->msg_lock);
        return (0);
    }
    if (len > mbp->msg_size) {
        *seqp = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
        len = mbp->msg_size;
    }
    pos = MSGBUF_SEQ_TO_POS(mbp, *seqp);
    len = min(len, mbp->msg_size - pos);
    len = min(len, (u_int)buflen);
    bcopy(&mbp->msg_ptr[MSGBUF_SEQ_TO_POS(mbp, *seqp)], buf, len);
    *seqp = MSGBUF_SEQNORM(mbp, *seqp + len);

    mtx_unlock_spin(&mbp->msg_lock);

    return (len);
}
Esempio n. 2
0
/*
 * Read and mark as read a number of characters from a message buffer.
 * Returns the number of characters that were placed in `buf'.
 */
int
msgbuf_getbytes(struct msgbuf *mbp, char *buf, int buflen)
{
    u_int len, pos, wseq;

    mtx_lock_spin(&mbp->msg_lock);

    wseq = mbp->msg_wseq;
    len = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_rseq);
    if (len == 0) {
        mtx_unlock_spin(&mbp->msg_lock);
        return (0);
    }
    if (len > mbp->msg_size) {
        mbp->msg_rseq = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
        len = mbp->msg_size;
    }
    pos = MSGBUF_SEQ_TO_POS(mbp, mbp->msg_rseq);
    len = min(len, mbp->msg_size - pos);
    len = min(len, (u_int)buflen);

    bcopy(&mbp->msg_ptr[pos], buf, len);
    mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq + len);

    mtx_unlock_spin(&mbp->msg_lock);

    return (len);
}
Esempio n. 3
0
static void
msgbuf_do_addchar(struct msgbuf * const mbp, u_int * const seq, const int c)
{
    u_int pos;

    /* Make sure we properly wrap the sequence number. */
    pos = MSGBUF_SEQ_TO_POS(mbp, *seq);
    mbp->msg_cksum += (u_int)(u_char)c -
                      (u_int)(u_char)mbp->msg_ptr[pos];
    mbp->msg_ptr[pos] = c;
    *seq = MSGBUF_SEQNORM(mbp, *seq + 1);
}
/*
 * Append a character to a message buffer.  This function can be
 * considered fully reentrant so long as the number of concurrent
 * callers is less than the number of characters in the buffer.
 * However, the message buffer is only guaranteed to be consistent
 * for reading when there are no callers in this function.
 */
void
msgbuf_addchar(struct msgbuf *mbp, int c)
{
	u_int new_seq, pos, seq;

	do {
		seq = mbp->msg_wseq;
		new_seq = MSGBUF_SEQNORM(mbp, seq + 1);
	} while (atomic_cmpset_rel_int(&mbp->msg_wseq, seq, new_seq) == 0);
	pos = MSGBUF_SEQ_TO_POS(mbp, seq);
	atomic_add_int(&mbp->msg_cksum, (u_int)(u_char)c -
	    (u_int)(u_char)mbp->msg_ptr[pos]);
	mbp->msg_ptr[pos] = c;
}
Esempio n. 5
0
void
kgdb_dmesg(void)
{
	CORE_ADDR bufp;
	int size, rseq, wseq;
	char c;

	/*
	 * Display the unread portion of the message buffer. This gives the
	 * user a some initial data to work from.
	 */
	if (quiet)
		return;
	bufp = kgdb_parse("msgbufp->msg_ptr");
	size = (int)kgdb_parse("msgbufp->msg_size");
	if (bufp == 0 || size == 0)
		return;
	rseq = (int)kgdb_parse("msgbufp->msg_rseq");
	wseq = (int)kgdb_parse("msgbufp->msg_wseq");
	rseq = MSGBUF_SEQ_TO_POS(size, rseq);
	wseq = MSGBUF_SEQ_TO_POS(size, wseq);
	if (rseq == wseq)
		return;

	printf("\nUnread portion of the kernel message buffer:\n");
	while (rseq < wseq) {
		read_memory(bufp + rseq, &c, 1);
		putchar(c);
		rseq++;
		if (rseq == size)
			rseq = 0;
	}
	if (c != '\n')
		putchar('\n');
	putchar('\n');
}
/*
 * Read and mark as read a character from a message buffer.
 * Returns the character, or -1 if no characters are available.
 */
int
msgbuf_getchar(struct msgbuf *mbp)
{
	u_int len, wseq;
	int c;

	wseq = mbp->msg_wseq;
	len = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_rseq);
	if (len == 0)
		return (-1);
	if (len > mbp->msg_size)
		mbp->msg_rseq = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
	c = (u_char)mbp->msg_ptr[MSGBUF_SEQ_TO_POS(mbp, mbp->msg_rseq)];
	mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq + 1);
	return (c);
}
Esempio n. 7
0
int
main(int argc, char *argv[])
{
    struct msgbuf *bufp, cur;
    char *bp, *ep, *memf, *nextp, *nlistf, *p, *q, *visbp;
    kvm_t *kd;
    size_t buflen, bufpos;
    long pri;
    int ch, clear;
    bool all;

    all = false;
    clear = false;
    (void) setlocale(LC_CTYPE, "");
    memf = nlistf = NULL;
    while ((ch = getopt(argc, argv, "acM:N:")) != -1)
        switch(ch) {
        case 'a':
            all = true;
            break;
        case 'c':
            clear = true;
            break;
        case 'M':
            memf = optarg;
            break;
        case 'N':
            nlistf = optarg;
            break;
        case '?':
        default:
            usage();
        }
    argc -= optind;
    if (argc != 0)
        usage();

    if (memf == NULL) {
        /*
         * Running kernel.  Use sysctl.  This gives an unwrapped
         * buffer as a side effect.
         */
        if (sysctlbyname("kern.msgbuf", NULL, &buflen, NULL, 0) == -1)
            err(1, "sysctl kern.msgbuf");
        if ((bp = malloc(buflen + 2)) == NULL)
            errx(1, "malloc failed");
        if (sysctlbyname("kern.msgbuf", bp, &buflen, NULL, 0) == -1)
            err(1, "sysctl kern.msgbuf");
        if (clear)
            if (sysctlbyname("kern.msgbuf_clear", NULL, NULL, &clear, sizeof(int)))
                err(1, "sysctl kern.msgbuf_clear");
    } else {
        /* Read in kernel message buffer and do sanity checks. */
        kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg");
        if (kd == NULL)
            exit (1);
        if (kvm_nlist(kd, nl) == -1)
            errx(1, "kvm_nlist: %s", kvm_geterr(kd));
        if (nl[X_MSGBUF].n_type == 0)
            errx(1, "%s: msgbufp not found",
                 nlistf ? nlistf : "namelist");
        if (KREAD(nl[X_MSGBUF].n_value, bufp) || KREAD((long)bufp, cur))
            errx(1, "kvm_read: %s", kvm_geterr(kd));
        if (cur.msg_magic != MSG_MAGIC)
            errx(1, "kernel message buffer has different magic "
                 "number");
        if ((bp = malloc(cur.msg_size + 2)) == NULL)
            errx(1, "malloc failed");

        /* Unwrap the circular buffer to start from the oldest data. */
        bufpos = MSGBUF_SEQ_TO_POS(&cur, cur.msg_wseq);
        if (kvm_read(kd, (long)&cur.msg_ptr[bufpos], bp,
                     cur.msg_size - bufpos) != (ssize_t)(cur.msg_size - bufpos))
            errx(1, "kvm_read: %s", kvm_geterr(kd));
        if (bufpos != 0 && kvm_read(kd, (long)cur.msg_ptr,
                                    &bp[cur.msg_size - bufpos], bufpos) != (ssize_t)bufpos)
            errx(1, "kvm_read: %s", kvm_geterr(kd));
        kvm_close(kd);
        buflen = cur.msg_size;
    }

    /*
     * Ensure that the buffer ends with a newline and a \0 to avoid
     * complications below.  We left space above.
     */
    if (buflen == 0 || bp[buflen - 1] != '\n')
        bp[buflen++] = '\n';
    bp[buflen] = '\0';

    if ((visbp = malloc(4 * buflen + 1)) == NULL)
        errx(1, "malloc failed");

    /*
     * The message buffer is circular, but has been unwrapped so that
     * the oldest data comes first.  The data will be preceded by \0's
     * if the message buffer was not full.
     */
    p = bp;
    ep = &bp[buflen];
    if (*p == '\0') {
        /* Strip leading \0's */
        while (*p == '\0')
            p++;
    } else if (!all) {
        /* Skip the first line, since it is probably incomplete. */
        p = memchr(p, '\n', ep - p);
        p++;
    }
    for (; p < ep; p = nextp) {
        nextp = memchr(p, '\n', ep - p);
        nextp++;

        /* Skip ^<[0-9]+> syslog sequences. */
        if (*p == '<' && isdigit(*(p+1))) {
            errno = 0;
            pri = strtol(p + 1, &q, 10);
            if (*q == '>' && pri >= 0 && pri < INT_MAX &&
                    errno == 0) {
                if (LOG_FAC(pri) != LOG_KERN && !all)
                    continue;
                p = q + 1;
            }
        }

        (void)strvisx(visbp, p, nextp - p, 0);
        (void)printf("%s", visbp);
    }
    exit(0);
}