summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/systat/Makefile8
-rw-r--r--usr.bin/systat/cache.c297
-rw-r--r--usr.bin/systat/cache.h56
-rw-r--r--usr.bin/systat/config.h85
-rw-r--r--usr.bin/systat/disks.c98
-rw-r--r--usr.bin/systat/engine.c1204
-rw-r--r--usr.bin/systat/engine.h167
-rw-r--r--usr.bin/systat/extern.h141
-rw-r--r--usr.bin/systat/fetch.c54
-rw-r--r--usr.bin/systat/if.c261
-rw-r--r--usr.bin/systat/iostat.c307
-rw-r--r--usr.bin/systat/keyboard.c165
-rw-r--r--usr.bin/systat/main.c672
-rw-r--r--usr.bin/systat/mbufs.c181
-rw-r--r--usr.bin/systat/netcmds.c360
-rw-r--r--usr.bin/systat/netstat.c669
-rw-r--r--usr.bin/systat/pf.c326
-rw-r--r--usr.bin/systat/pftop.c2160
-rw-r--r--usr.bin/systat/pigs.c319
-rw-r--r--usr.bin/systat/sensors.c237
-rw-r--r--usr.bin/systat/swap.c212
-rw-r--r--usr.bin/systat/systat.h57
-rw-r--r--usr.bin/systat/vmstat.c119
23 files changed, 6067 insertions, 2088 deletions
diff --git a/usr.bin/systat/Makefile b/usr.bin/systat/Makefile
index 68ab8380e0b..3cc4ff83bcf 100644
--- a/usr.bin/systat/Makefile
+++ b/usr.bin/systat/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.19 2007/12/15 17:46:23 deraadt Exp $
+# $OpenBSD: Makefile,v 1.20 2008/06/12 22:26:01 canacar Exp $
PROG= systat
@@ -6,8 +6,10 @@ PROG= systat
CFLAGS+=-DNOKVM
CPPFLAGS+=-I${.CURDIR}/../../usr.bin/vmstat
-SRCS= cmds.c cmdtab.c disks.c dkstats.c fetch.c if.c iostat.c keyboard.c \
- main.c mbufs.c netcmds.c netstat.c pigs.c sensors.c swap.c vmstat.c
+CPPFLAGS+=-I${.CURDIR}/../../sbin/pfctl
+SRCS= dkstats.c engine.c if.c iostat.c main.c mbufs.c netstat.c \
+ pigs.c sensors.c swap.c vmstat.c pftop.c cache.c pf.c
+
DPADD= ${LIBCURSES} ${LIBM} ${LIBKVM}
LDADD= -lcurses -lm -lkvm
BINGRP= kmem
diff --git a/usr.bin/systat/cache.c b/usr.bin/systat/cache.c
new file mode 100644
index 00000000000..136f8871435
--- /dev/null
+++ b/usr.bin/systat/cache.c
@@ -0,0 +1,297 @@
+/* $Id: cache.c,v 1.1 2008/06/12 22:26:01 canacar Exp $ */
+/*
+ * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <netinet/tcp_fsm.h>
+#ifdef TEST_COMPAT
+#include "pfvarmux.h"
+#else
+#include <net/pfvar.h>
+#endif
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "cache.h"
+
+/* prototypes */
+void update_state(struct sc_ent *, pf_state_t *, double);
+struct sc_ent *cache_state(pf_state_t *);
+static __inline int sc_cmp(struct sc_ent *s1, struct sc_ent *s2);
+
+/* initialize the tree and queue */
+RB_HEAD(sc_tree, sc_ent) sctree;
+TAILQ_HEAD(sc_queue, sc_ent) scq1, scq2, scq_free;
+RB_GENERATE(sc_tree, sc_ent, tlink, sc_cmp);
+
+struct sc_queue *scq_act = NULL;
+struct sc_queue *scq_exp = NULL;
+
+int cache_max = 0;
+int cache_size = 0;
+
+struct sc_ent *sc_store = NULL;
+
+/* preallocate the cache and insert into the 'free' queue */
+int
+cache_init(int max)
+{
+ int n;
+ static int initialized = 0;
+
+ if (max < 0 || initialized)
+ return (1);
+
+ if (max == 0) {
+ sc_store = NULL;
+ } else {
+ sc_store = malloc(max * sizeof(struct sc_ent));
+ if (sc_store == NULL)
+ return (1);
+ }
+
+ RB_INIT(&sctree);
+ TAILQ_INIT(&scq1);
+ TAILQ_INIT(&scq2);
+ TAILQ_INIT(&scq_free);
+
+ scq_act = &scq1;
+ scq_exp = &scq2;
+
+ for (n = 0; n < max; n++)
+ TAILQ_INSERT_HEAD(&scq_free, sc_store + n, qlink);
+
+ cache_size = cache_max = max;
+ initialized++;
+
+ return (0);
+}
+
+void
+update_state(struct sc_ent *prev, pf_state_t *new, double rate)
+{
+ assert (prev != NULL && new != NULL);
+ prev->t = time(NULL);
+ prev->rate = rate;
+#ifdef HAVE_INOUT_COUNT
+ prev->bytes = COUNTER(new->bytes[0]) + COUNTER(new->bytes[1]);
+#else
+ prev->bytes = COUNTER(new->bytes);
+#endif
+ if (prev->peak < rate)
+ prev->peak = rate;
+}
+
+void
+add_state(pf_state_t *st)
+{
+ struct sc_ent *ent;
+ assert(st != NULL);
+
+ if (cache_max == 0)
+ return;
+
+ if (TAILQ_EMPTY(&scq_free))
+ return;
+
+ ent = TAILQ_FIRST(&scq_free);
+ TAILQ_REMOVE(&scq_free, ent, qlink);
+
+ cache_size--;
+
+#ifdef HAVE_PFSYNC_STATE
+ ent->id[0] = st->id[0];
+ ent->id[1] = st->id[1];
+#else
+ ent->addr[0] = st->lan.addr;
+ ent->port[0] = st->lan.port;
+ ent->addr[1] = st->ext.addr;
+ ent->port[1] = st->ext.port;
+ ent->af = st->af;
+ ent->proto = st->proto;
+#endif
+#ifdef HAVE_INOUT_COUNT
+ ent->bytes = COUNTER(st->bytes[0]) + COUNTER(st->bytes[1]);
+#else
+ ent->bytes = st->bytes;
+#endif
+ ent->peak = 0;
+ ent->rate = 0;
+ ent->t = time(NULL);
+
+ RB_INSERT(sc_tree, &sctree, ent);
+ TAILQ_INSERT_HEAD(scq_act, ent, qlink);
+}
+
+/* must be called only once for each state before cache_endupdate */
+struct sc_ent *
+cache_state(pf_state_t *st)
+{
+ struct sc_ent ent, *old;
+ double sd, td, r;
+
+ if (cache_max == 0)
+ return (NULL);
+
+#ifdef HAVE_PFSYNC_STATE
+ ent.id[0] = st->id[0];
+ ent.id[1] = st->id[1];
+#else
+ ent.addr[0] = st->lan.addr;
+ ent.port[0] = st->lan.port;
+ ent.addr[1] = st->ext.addr;
+ ent.port[1] = st->ext.port;
+ ent.af = st->af;
+ ent.proto = st->proto;
+#endif
+ old = RB_FIND(sc_tree, &sctree, &ent);
+
+ if (old == NULL) {
+ add_state(st);
+ return (NULL);
+ }
+
+#ifdef HAVE_INOUT_COUNT
+ if (COUNTER(st->bytes[0]) + COUNTER(st->bytes[1]) < old->bytes)
+ return (NULL);
+
+ sd = COUNTER(st->bytes[0]) + COUNTER(st->bytes[1]) - old->bytes;
+#else
+ if (st->bytes < old->bytes)
+ return (NULL);
+
+ sd = st->bytes - old->bytes;
+#endif
+
+ td = time(NULL) - old->t;
+
+ if (td > 0) {
+ r = sd/td;
+ update_state(old, st, r);
+ }
+
+ /* move to active queue */
+ TAILQ_REMOVE(scq_exp, old, qlink);
+ TAILQ_INSERT_HEAD(scq_act, old, qlink);
+
+ return (old);
+}
+
+/* remove the states that are not updated in this cycle */
+void
+cache_endupdate(void)
+{
+ struct sc_queue *tmp;
+ struct sc_ent *ent;
+
+ while (! TAILQ_EMPTY(scq_exp)) {
+ ent = TAILQ_FIRST(scq_exp);
+ TAILQ_REMOVE(scq_exp, ent, qlink);
+ RB_REMOVE(sc_tree, &sctree, ent);
+ TAILQ_INSERT_HEAD(&scq_free, ent, qlink);
+ cache_size++;
+ }
+
+ tmp = scq_act;
+ scq_act = scq_exp;
+ scq_exp = tmp;
+}
+
+static __inline int
+sc_cmp(struct sc_ent *a, struct sc_ent *b)
+{
+#ifdef HAVE_PFSYNC_STATE
+ if (a->id[0] > b->id[0])
+ return (1);
+ if (a->id[0] < b->id[0])
+ return (-1);
+ if (a->id[1] > b->id[1])
+ return (1);
+ if (a->id[1] < b->id[1])
+ return (-1);
+#else
+ int diff;
+
+ if ((diff = a->proto - b->proto) != 0)
+ return (diff);
+ if ((diff = a->af - b->af) != 0)
+ return (diff);
+ switch (a->af) {
+ case AF_INET:
+ if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
+ return (1);
+ if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
+ return (-1);
+ if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
+ return (1);
+ if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
+ return (-1);
+ break;
+ case AF_INET6:
+ if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
+ return (1);
+ if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
+ return (-1);
+ if (a->addr[0].addr32[1] > b->addr[0].addr32[1])
+ return (1);
+ if (a->addr[0].addr32[1] < b->addr[0].addr32[1])
+ return (-1);
+ if (a->addr[0].addr32[2] > b->addr[0].addr32[2])
+ return (1);
+ if (a->addr[0].addr32[2] < b->addr[0].addr32[2])
+ return (-1);
+ if (a->addr[0].addr32[3] > b->addr[0].addr32[3])
+ return (1);
+ if (a->addr[0].addr32[3] < b->addr[0].addr32[3])
+ return (-1);
+ if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
+ return (1);
+ if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
+ return (-1);
+ if (a->addr[1].addr32[1] > b->addr[1].addr32[1])
+ return (1);
+ if (a->addr[1].addr32[1] < b->addr[1].addr32[1])
+ return (-1);
+ if (a->addr[1].addr32[2] > b->addr[1].addr32[2])
+ return (1);
+ if (a->addr[1].addr32[2] < b->addr[1].addr32[2])
+ return (-1);
+ if (a->addr[1].addr32[3] > b->addr[1].addr32[3])
+ return (1);
+ if (a->addr[1].addr32[3] < b->addr[1].addr32[3])
+ return (-1);
+ break;
+ default:
+ return 1;
+ }
+
+ if ((diff = a->port[0] - b->port[0]) != 0)
+ return (diff);
+ if ((diff = a->port[1] - b->port[1]) != 0)
+ return (diff);
+#endif
+ return (0);
+}
diff --git a/usr.bin/systat/cache.h b/usr.bin/systat/cache.h
new file mode 100644
index 00000000000..5e499b15e01
--- /dev/null
+++ b/usr.bin/systat/cache.h
@@ -0,0 +1,56 @@
+/* $Id: cache.h,v 1.1 2008/06/12 22:26:01 canacar Exp $ */
+/*
+ * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _CACHE_H_
+#define _CACHE_H_
+
+#include "config.h"
+
+#include <sys/queue.h>
+#ifdef HAVE_TREE_H
+#include <sys/tree.h>
+#else
+#include "tree.h"
+#endif
+
+
+struct sc_ent {
+ RB_ENTRY(sc_ent) tlink;
+ TAILQ_ENTRY(sc_ent) qlink;
+#ifdef HAVE_PFSYNC_STATE
+ u_int32_t id[2];
+#else
+ struct pf_addr addr[2];
+#endif
+ double peak;
+ double rate;
+ time_t t;
+ u_int32_t bytes;
+#ifndef HAVE_PFSYNC_STATE
+ u_int16_t port[2];
+ u_int8_t af;
+ u_int8_t proto;
+#endif
+};
+
+int cache_init(int);
+void cache_endupdate(void);
+struct sc_ent *cache_state(pf_state_t *);
+extern int cache_max, cache_size;
+
+
+#endif
diff --git a/usr.bin/systat/config.h b/usr.bin/systat/config.h
new file mode 100644
index 00000000000..53e112ded2a
--- /dev/null
+++ b/usr.bin/systat/config.h
@@ -0,0 +1,85 @@
+/* $Id: config.h,v 1.1 2008/06/12 22:26:01 canacar Exp $ */
+/*
+ * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+
+/* OS_LEVEL > 30 */
+#define HAVE_STATE_NOROUTE
+#define HAVE_DEVICE_RO
+#define HAVE_TREE_H
+#define HAVE_QUEUE_H
+#define HAVE_PF_ROUTE
+#define HAVE_RULE_LABELS
+
+/* OS_LEVEL > 31 */
+#define HAVE_RULE_NUMBER
+#define HAVE_ADDR_WRAP
+#define HAVE_RULE_STATES
+#define HAVE_RULE_IFNOT
+#define HAVE_PROTO_NAMES
+#define HAVE_MAX_STATES
+#define HAVE_MAX_MSS
+#define HAVE_RULE_UGID
+
+/* OS_LEVEL > 32 */
+#define HAVE_ADDR_MASK
+#define HAVE_ADDR_TYPE
+#define HAVE_ALTQ
+#define HAVE_RULE_TOS
+#define HAVE_OP_RRG
+
+/* OS_LEVEL > 33 */
+#define HAVE_INOUT_COUNT
+#define HAVE_TAGS
+#define HAVE_RULE_NATPASS
+
+/* OS_LEVEL > 34 */
+#define HAVE_STATE_IFNAME
+
+/* OS_LEVEL > 35 */
+#define HAVE_NEG
+#define HAVE_RULESETS
+
+/* OS_LEVEL > 37 */
+#define HAVE_INOUT_COUNT_RULES
+
+/* OS_LEVEL > 38 */
+#define HAVE_STATE_COUNT_64
+
+/* OS_LEVEL > 41 */
+#define HAVE_PFSYNC_STATE
+
+/* OS_LEVEL > 43 */
+#define HAVE_PFSYNC_KEY
+
+#ifdef HAVE_PFSYNC_STATE
+typedef struct pfsync_state pf_state_t;
+typedef struct pfsync_state_host pf_state_host_t;
+typedef struct pfsync_state_peer pf_state_peer_t;
+#define COUNTER(c) ((((u_int64_t) c[0])<<32) + c[1])
+#define pfs_ifname ifname
+#else
+typedef struct pf_state pf_state_t;
+typedef struct pf_state_host pf_state_host_t;
+typedef struct pf_state_peer pf_state_peer_t;
+#define COUNTER(c) (c)
+#define pfs_ifname u.ifname
+#endif
+
+#endif
diff --git a/usr.bin/systat/disks.c b/usr.bin/systat/disks.c
index c08bbbef200..e69de29bb2d 100644
--- a/usr.bin/systat/disks.c
+++ b/usr.bin/systat/disks.c
@@ -1,98 +0,0 @@
-/* $OpenBSD: disks.c,v 1.17 2007/09/11 15:47:17 gilles Exp $ */
-/* $NetBSD: disks.c,v 1.4 1996/05/10 23:16:33 thorpej Exp $ */
-
-/*-
- * Copyright (c) 1980, 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)disks.c 8.1 (Berkeley) 6/6/93";
-#endif
-static char rcsid[] = "$OpenBSD: disks.c,v 1.17 2007/09/11 15:47:17 gilles Exp $";
-#endif /* not lint */
-
-#include <string.h>
-#include <ctype.h>
-#include <signal.h>
-#include "systat.h"
-#include "extern.h"
-static void dkselect(char *args, int truefalse, int selections[]);
-
-
-int
-dkcmd(char *cmd, char *args)
-{
- if (prefix(cmd, "display") || prefix(cmd, "add")) {
- dkselect(args, 1, dk_select);
- return (1);
- }
- if (prefix(cmd, "ignore") || prefix(cmd, "delete")) {
- dkselect(args, 0, dk_select);
- return (1);
- }
- if (prefix(cmd, "drives")) {
- int i;
-
- move(CMDLINE, 0);
- clrtoeol();
- for (i = 0; i < dk_ndrive; i++)
- printw("%s ", dr_name[i]);
- return (1);
- }
- return (0);
-}
-
-static void
-dkselect(char *args, int truefalse, int selections[])
-{
- char *cp;
- int i;
-
- args[strcspn(args, "\n")] = '\0';
-
- for (;;) {
- for (cp = args; isspace(*cp); cp++)
- ;
- args = cp;
- for (; *cp && !isspace(*cp); cp++)
- ;
- if (*cp)
- *cp++ = '\0';
- if (cp - args == 0)
- break;
- for (i = 0; i < dk_ndrive; i++)
- if (strcmp(args, dr_name[i]) == 0) {
- selections[i] = truefalse;
- break;
- }
- if (i >= dk_ndrive)
- error("%s: unknown drive", args);
- args = cp;
- }
-}
diff --git a/usr.bin/systat/engine.c b/usr.bin/systat/engine.c
new file mode 100644
index 00000000000..f8a6d73094a
--- /dev/null
+++ b/usr.bin/systat/engine.c
@@ -0,0 +1,1204 @@
+/* $Id: engine.c,v 1.1 2008/06/12 22:26:01 canacar Exp $ */
+/*
+ * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <ctype.h>
+#include <curses.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "engine.h"
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+/* circular linked list of views */
+CIRCLEQ_HEAD(view_list, view_ent) view_head =
+ CIRCLEQ_HEAD_INITIALIZER(view_head);
+struct view_ent {
+ field_view *view;
+ CIRCLEQ_ENTRY(view_ent) entries;
+};
+
+useconds_t udelay = 5000000;
+int dispstart = 0;
+int interactive = 1;
+int maxprint = 0;
+int paused = 0;
+int rawmode = 0;
+int rawwidth = DEFAULT_WIDTH;
+int sortdir = 1;
+int columns, lines;
+u_int32_t num_disp = 0;
+int max_disp = -1;
+
+volatile sig_atomic_t gotsig_close = 0;
+volatile sig_atomic_t gotsig_resize = 0;
+volatile sig_atomic_t gotsig_alarm = 0;
+int need_update = 0;
+int need_sort = 0;
+
+SCREEN *screen;
+
+field_view *curr_view = NULL;
+struct view_ent *curr_view_ent = NULL;
+struct view_manager *curr_mgr = NULL;
+
+int curr_line = 0;
+int home_line = 0;
+
+/* line buffer for raw mode */
+char linebuf[MAX_LINE_BUF];
+int linepos = 0;
+
+/* temp storage for state printing */
+char tmp_buf[MAX_LINE_BUF];
+
+char cmdbuf[MAX_LINE_BUF];
+int cmd_len = -1;
+struct command *curr_cmd = NULL;
+char *curr_message = NULL;
+
+void print_cmdline(void);
+
+
+/* screen output functions */
+
+char * tb_ptr = NULL;
+int tb_len = 0;
+
+void
+tb_start(void)
+{
+ tb_ptr = tmp_buf;
+ tb_len = sizeof(tmp_buf);
+ tb_ptr[0] = '\0';
+}
+
+void
+tb_end(void)
+{
+ tb_ptr = NULL;
+ tb_len = 0;
+}
+
+int
+tbprintf(char *format, ...)
+ GCC_PRINTFLIKE(1,2) /* defined in curses.h */
+{
+ int len;
+ va_list arg;
+
+ if (tb_ptr == NULL || tb_len <= 0)
+ return 0;
+
+ va_start(arg, format);
+ len=vsnprintf(tb_ptr, tb_len, format, arg);
+ va_end(arg);
+
+ if (len > tb_len)
+ tb_end();
+ else if (len > 0) {
+ tb_ptr += len;
+ tb_len -= len;
+ }
+
+ return len;
+}
+
+void
+move_horiz(int offset)
+{
+ if (rawmode) {
+ if (offset <= 0)
+ linepos = 0;
+ else if (offset >= MAX_LINE_BUF)
+ linepos = MAX_LINE_BUF - 1;
+ else
+ linepos = offset;
+ } else {
+ move(curr_line, offset);
+ }
+}
+
+void
+print_str(int len, const char *str)
+{
+ if (len <= 0)
+ return;
+
+ if (rawmode) {
+ int length = MIN(len, MAX_LINE_BUF - linepos);
+ if (length <= 0)
+ return;
+ bcopy(str, &linebuf[linepos], length);
+ linepos += length;
+ } else
+ addnstr(str, len);
+}
+
+void
+clear_linebuf(void)
+{
+ memset(linebuf, ' ', MAX_LINE_BUF);
+}
+
+void
+end_line(void)
+{
+ if (rawmode) {
+ linebuf[rawwidth] = '\0';
+ printf("%s\n", linebuf);
+ clear_linebuf();
+ }
+ curr_line++;
+}
+
+void
+end_page(void)
+{
+ if (rawmode) {
+ linepos = 0;
+ clear_linebuf();
+ } else {
+ move(home_line, 0);
+ print_cmdline();
+ refresh();
+ }
+ curr_line = 0;
+}
+
+void
+rawaddstr(char *s)
+{
+ if (rawmode)
+ printf("%s", s);
+ else
+ addstr(s);
+}
+
+/* field output functions */
+
+void
+print_fld_str(field_def *fld, const char *str)
+{
+ int len, move;
+ char *cpos;
+
+ if (str == NULL || fld == NULL)
+ return;
+
+ if (fld->start < 0)
+ return;
+
+ len = strlen(str);
+
+ if (len >= fld->width) {
+ move_horiz(fld->start);
+ print_str(fld->width, str);
+ } else {
+ switch (fld->align) {
+ case FLD_ALIGN_RIGHT:
+ move_horiz(fld->start + (fld->width - len));
+ break;
+ case FLD_ALIGN_CENTER:
+ move_horiz(fld->start + (fld->width - len) / 2);
+ break;
+ case FLD_ALIGN_COLUMN:
+ if ((cpos = strchr(str, ':')) == NULL) {
+ move = (fld->width - len) / 2;
+ } else {
+ move = (fld->width / 2) - (cpos - str);
+ if (move < 0)
+ move = 0;
+ else if (move > (fld->width - len))
+ move = fld->width - len;
+ }
+ move_horiz(fld->start + move);
+ break;
+ default:
+ move_horiz(fld->start);
+ break;
+ }
+ print_str(len, str);
+ }
+}
+
+void
+print_bar_title(field_def *fld)
+{
+ char buf[16];
+ int len, div, i, tr, tw, val, pos, cur;
+
+ int divs[] = {20, 10, 5, 4, 3, 2, 1, 0};
+
+ if (fld->width < 1)
+ return;
+
+ len = snprintf(buf, sizeof(buf), " %d\\", fld->arg);
+ if (len >= sizeof(buf))
+ return;
+
+ for (i = 0; divs[i]; i++)
+ if (divs[i] * len <= fld->width)
+ break;
+
+ if (divs[i] == 0) {
+ print_fld_str(fld, "*****");
+ return;
+ }
+
+ div = divs[i];
+
+ val = 0;
+ pos = 0;
+ tr = fld->arg % div;
+ tw = fld->width % div;
+
+ tb_start();
+ cur = 0;
+ for(i = 0; i < div; i++) {
+ tw += fld->width;
+ tr += fld->arg;
+
+ while (tr >= div) {
+ val++;
+ tr -= div;
+ }
+ while (tw >= div) {
+ pos++;
+ tw -= div;
+ }
+
+ len = snprintf(buf, sizeof(buf), "%d\\", val);
+ while (cur < pos - len) {
+ tbprintf(" ");
+ cur++;
+ }
+ tbprintf("%s", buf);
+ cur += len;
+ }
+
+ print_fld_tb(fld);
+}
+
+void
+print_fld_bar(field_def *fld, int value)
+{
+ int i, tw, val, cur;
+
+ if (fld->width < 1)
+ return;
+
+ val = 0;
+ tw = fld->arg / 2;
+
+ tb_start();
+ cur = 0;
+ for(i = 0; i < fld->width; i++) {
+ tw += fld->arg;
+
+ while (tw >= fld->width) {
+ val++;
+ tw -= fld->width;
+ }
+ if (val > value)
+ break;
+ tbprintf("#");
+ }
+
+ print_fld_tb(fld);
+}
+
+void
+print_fld_tb(field_def *fld)
+{
+ print_fld_str(fld, tmp_buf);
+ tb_end();
+}
+
+void
+print_title(void)
+{
+ field_def **fp;
+
+ if (curr_view != NULL && curr_view->view != NULL) {
+ for (fp = curr_view->view; *fp != NULL; fp++) {
+ switch((*fp)->align) {
+ case FLD_ALIGN_LEFT:
+ case FLD_ALIGN_RIGHT:
+ case FLD_ALIGN_CENTER:
+ case FLD_ALIGN_COLUMN:
+ print_fld_str(*fp, (*fp)->title);
+ break;
+ case FLD_ALIGN_BAR:
+ print_bar_title(*fp);
+ break;
+ }
+ }
+ }
+ end_line();
+}
+
+/* view related functions */
+void
+hide_field(field_def *fld)
+{
+ if (fld == NULL)
+ return;
+
+ fld->flags |= FLD_FLAG_HIDDEN;
+}
+
+void
+show_field(field_def *fld)
+{
+ if (fld == NULL)
+ return;
+
+ fld->flags &= ~((unsigned int) FLD_FLAG_HIDDEN);
+}
+
+void
+reset_fields(void)
+{
+ field_def **fp;
+ field_def *fld;
+
+ if (curr_view == NULL)
+ return;
+
+ if (curr_view->view == NULL)
+ return;
+
+ for (fp = curr_view->view; *fp != NULL; fp++) {
+ fld = *fp;
+ fld->start = -1;
+ fld->width = fld->norm_width;
+ }
+}
+
+void
+field_setup(void)
+{
+ field_def **fp;
+ field_def *fld;
+ int st, fwid, change;
+ int width = columns;
+
+ reset_fields();
+
+ dispstart = 0;
+ st = 0;
+
+ for (fp = curr_view->view; *fp != NULL; fp++) {
+ fld = *fp;
+ if (fld->flags & FLD_FLAG_HIDDEN)
+ continue;
+
+ if (width <= 1)
+ break;
+
+ if (st != 1)
+ width--;
+
+ fld->start = 1;
+ fwid = fld->width;
+ st++;
+ if (fwid >= width) {
+ fld->width = width;
+ width = 0;
+ } else
+ width -= fwid;
+ }
+
+ change = 0;
+ while (width > 0) {
+ change = 0;
+ for (fp = curr_view->view; *fp != NULL; fp++) {
+ fld = *fp;
+ if (fld->flags & FLD_FLAG_HIDDEN)
+ continue;
+ if ((fld->width < fld->max_width) &&
+ (fld->increment <= width)) {
+ int w = fld->width + fld->increment;
+ if (w > fld->max_width)
+ w = fld->max_width;
+ width += fld->width - w;
+ fld->width = w;
+ change = 1;
+ }
+ if (width <= 0) break;
+ }
+ if (change == 0) break;
+ }
+
+ st = 0;
+ for (fp = curr_view->view; *fp != NULL; fp++) {
+ fld = *fp;
+ if (fld->flags & FLD_FLAG_HIDDEN)
+ continue;
+ if (fld->start < 0) break;
+ fld->start = st;
+ st += fld->width + 1;
+ }
+}
+
+void
+set_curr_view(struct view_ent *ve)
+{
+ field_view *v;
+
+ reset_fields();
+
+ if (ve == NULL) {
+ curr_view_ent = NULL;
+ curr_view = NULL;
+ curr_mgr = NULL;
+ return;
+ }
+
+ v = ve->view;
+
+ if ((curr_view != NULL) && (curr_mgr != v->mgr)) {
+ gotsig_alarm = 1;
+ if (v->mgr != NULL && v->mgr->select_fn != NULL)
+ v->mgr->select_fn();
+ }
+
+ curr_view_ent = ve;
+ curr_view = v;
+ curr_mgr = v->mgr;
+ field_setup();
+ need_update = 1;
+}
+
+void
+add_view(field_view *fv)
+{
+ struct view_ent *ent;
+
+ if (fv == NULL)
+ return;
+
+ if (fv->view == NULL || fv->name == NULL || fv->mgr == NULL)
+ return;
+
+ ent = malloc(sizeof(struct view_ent));
+ if (ent == NULL)
+ return;
+
+ ent->view = fv;
+ CIRCLEQ_INSERT_TAIL(&view_head, ent, entries);
+
+ if (curr_view == NULL)
+ set_curr_view(ent);
+}
+
+int
+set_view(char *opt)
+{
+ struct view_ent *ve, *vm = NULL;
+ field_view *v;
+ int len;
+
+ if (opt == NULL || (len = strlen(opt)) == 0)
+ return 1;
+
+ CIRCLEQ_FOREACH(ve, &view_head, entries) {
+ v = ve->view;
+ if (strncasecmp(opt, v->name, len) == 0) {
+ if (vm)
+ return 1;
+ vm = ve;
+ }
+ }
+
+ if (vm) {
+ set_curr_view(vm);
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+foreach_view(void (*callback)(field_view *))
+{
+ struct view_ent *ve;
+
+ CIRCLEQ_FOREACH(ve, &view_head, entries) {
+ callback(ve->view);
+ }
+}
+
+int
+set_view_hotkey(int ch)
+{
+ struct view_ent *ve;
+ field_view *v;
+ int key = tolower(ch);
+
+ CIRCLEQ_FOREACH(ve, &view_head, entries) {
+ v = ve->view;
+ if (key == v->hotkey) {
+ set_curr_view(ve);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void
+next_view(void)
+{
+ struct view_ent *ve;
+
+ if (CIRCLEQ_EMPTY(&view_head) || curr_view_ent == NULL)
+ return;
+
+ ve = CIRCLEQ_NEXT(curr_view_ent, entries);
+ if (ve == CIRCLEQ_END(&view_head))
+ ve = CIRCLEQ_FIRST(&view_head);
+
+ set_curr_view(ve);
+}
+
+void
+prev_view(void)
+{
+ struct view_ent *ve;
+
+ if (CIRCLEQ_EMPTY(&view_head) || curr_view_ent == NULL)
+ return;
+
+ ve = CIRCLEQ_PREV(curr_view_ent, entries);
+ if (ve == CIRCLEQ_END(&view_head))
+ ve = CIRCLEQ_LAST(&view_head);
+
+ set_curr_view(ve);
+}
+
+/* generic field printing */
+
+void
+print_fld_age(field_def *fld, unsigned int age)
+{
+ int len;
+ unsigned int h, m, s;
+
+ if (fld == NULL)
+ return;
+ len = fld->width;
+
+ if (len < 1)
+ return;
+
+ s = age % 60;
+ m = age / 60;
+ h = m / 60;
+ m %= 60;
+
+ tb_start();
+ if (tbprintf("%02u:%02u:%02u", h, m, s) <= len)
+ goto ok;
+
+ if (tbprintf("%u", age) <= len)
+ goto ok;
+
+ age /= 60;
+ if (tbprintf("%um", age) <= len)
+ goto ok;
+ if (age == 0)
+ goto err;
+
+ age /= 60;
+ if (tbprintf("%uh", age) <= len)
+ goto ok;
+ if (age == 0)
+ goto err;
+
+ age /= 24;
+ if (tbprintf("%ud", age) <= len)
+ goto ok;
+
+ err:
+ print_fld_str(fld, "*");
+ tb_end();
+ return;
+
+ ok:
+ print_fld_tb(fld);
+}
+
+void
+print_fld_sdiv(field_def *fld, u_int64_t size, int div)
+{
+ int len;
+
+ if (fld == NULL)
+ return;
+
+ len = fld->width;
+ if (len < 1)
+ return;
+
+ tb_start();
+ if (tbprintf("%llu", size) <= len)
+ goto ok;
+
+ size /= div;
+ if (tbprintf("%lluK", size) <= len)
+ goto ok;
+ if (size == 0)
+ goto err;
+
+ size /= div;
+ if (tbprintf("%lluM", size) <= len)
+ goto ok;
+ if (size == 0)
+ goto err;
+
+ size /= div;
+ if (tbprintf("%lluG", size) <= len)
+ goto ok;
+
+err:
+ print_fld_str(fld, "*");
+ tb_end();
+ return;
+
+ok:
+ print_fld_tb(fld);
+}
+
+void
+print_fld_size(field_def *fld, u_int64_t size)
+{
+ print_fld_sdiv(fld, size, 1024);
+}
+
+void
+print_fld_rate(field_def *fld, double rate)
+{
+ if (rate < 0) {
+ print_fld_str(fld, "*");
+ } else {
+ print_fld_size(fld, rate);
+ }
+}
+
+void
+print_fld_bw(field_def *fld, double bw)
+{
+ if (bw < 0) {
+ print_fld_str(fld, "*");
+ } else {
+ print_fld_sdiv(fld, bw, 1000);
+ }
+}
+
+void
+print_fld_uint(field_def *fld, unsigned int size)
+{
+ int len;
+
+ if (fld == NULL)
+ return;
+
+ len = fld->width;
+ if (len < 1)
+ return;
+
+ tb_start();
+ if (tbprintf("%u", size) > len)
+ print_fld_str(fld, "*");
+ else
+ print_fld_tb(fld);
+ tb_end();
+}
+
+
+/* ordering */
+
+void
+set_order(char *opt)
+{
+ order_type *o;
+
+ if (curr_view == NULL || curr_view->mgr == NULL)
+ return;
+
+ curr_view->mgr->order_curr = curr_view->mgr->order_list;
+
+ if (opt == NULL)
+ return;
+
+ o = curr_view->mgr->order_list;
+
+ if (o == NULL)
+ return;
+
+ for (;o->name != NULL; o++) {
+ if (strcasecmp(opt, o->match) == 0) {
+ curr_view->mgr->order_curr = o;
+ return;
+ }
+ }
+}
+
+int
+set_order_hotkey(int ch)
+{
+ order_type *o;
+ int key = ch;
+
+ if (curr_view == NULL || curr_view->mgr == NULL)
+ return 0;
+
+ o = curr_view->mgr->order_list;
+
+ if (o == NULL)
+ return 0;
+
+ for (;o->name != NULL; o++) {
+ if (key == o->hotkey) {
+ if (curr_view->mgr->order_curr == o) {
+ sortdir *= -1;
+ } else {
+ curr_view->mgr->order_curr = o;
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void
+next_order(void)
+{
+ order_type *o, *oc;
+
+ oc = curr_view->mgr->order_curr;
+
+ for (o = curr_view->mgr->order_list; o->name != NULL; o++) {
+ if (oc == o) {
+ o++;
+ if (o->name == NULL)
+ break;
+ curr_view->mgr->order_curr = o;
+ return;
+ }
+ }
+
+ curr_view->mgr->order_curr = curr_view->mgr->order_list;
+}
+
+
+/* main program functions */
+
+int
+read_view(void)
+{
+ if (curr_mgr == NULL)
+ return (0);
+
+ if (paused)
+ return (0);
+
+ if (curr_mgr->read_fn != NULL)
+ return (curr_mgr->read_fn());
+
+ return (0);
+}
+
+
+int
+disp_update(void)
+{
+ int lines;
+
+ if (maxprint < 0)
+ dispstart = 0;
+ else if (dispstart + maxprint > num_disp)
+ dispstart = num_disp - maxprint;
+
+ if (dispstart < 0)
+ dispstart = 0;
+
+ if (curr_view == NULL)
+ return 0;
+
+ if (curr_mgr != NULL) {
+ curr_line = 0;
+
+ if (curr_mgr->header_fn != NULL) {
+ lines = curr_mgr->header_fn();
+ if (lines < 0)
+ return (1);
+// home_line = lines++;
+ curr_line = ++lines;
+ home_line = lines + maxprint + 1;
+ }
+
+ print_title();
+
+ if (curr_mgr->print_fn != NULL)
+ curr_mgr->print_fn();
+ }
+
+ return (0);
+}
+
+void
+sort_view(void)
+{
+ if (curr_mgr != NULL)
+ if (curr_mgr->sort_fn != NULL)
+ curr_mgr->sort_fn();
+}
+
+void
+sig_close(int signal)
+{
+ gotsig_close = 1;
+}
+
+void
+sig_resize(int signal)
+{
+ gotsig_resize = 1;
+}
+
+void
+sig_alarm(int signal)
+{
+ gotsig_alarm = 1;
+}
+
+void
+setup_term(int dmax)
+{
+ max_disp = dmax;
+ maxprint = dmax;
+
+ if (rawmode) {
+ columns = rawwidth;
+ lines = DEFAULT_HEIGHT;
+ clear_linebuf();
+ } else {
+ if (dmax < 0)
+ dmax = 0;
+
+ screen = newterm(NULL, stdout, stdin);
+ if (screen == NULL) {
+ rawmode = 1;
+ interactive = 0;
+ setup_term(dmax);
+ return;
+ }
+ columns = COLS;
+ lines = LINES;
+
+ if (maxprint > lines - HEADER_LINES)
+ maxprint = lines - HEADER_LINES;
+
+ nonl();
+ keypad(stdscr, TRUE);
+ intrflush(stdscr, FALSE);
+
+ halfdelay(10);
+ noecho();
+ }
+
+ if (dmax == 0)
+ maxprint = lines - HEADER_LINES;
+
+ field_setup();
+}
+
+struct command *
+command_set(struct command *cmd, const char *init)
+{
+ struct command *prev = curr_cmd;
+
+ if (cmd) {
+ if (init) {
+ cmd_len = strlcpy(cmdbuf, init, sizeof(cmdbuf));
+ if (cmd_len >= sizeof(cmdbuf)) {
+ cmdbuf[0] = '\0';
+ cmd_len = 0;
+ }
+ } else {
+ cmd_len = 0;
+ cmdbuf[0] = 0;
+ }
+ }
+ curr_message = NULL;
+ curr_cmd = cmd;
+ need_update = 1;
+ return prev;
+}
+
+const char *
+message_set(const char *msg) {
+ char *prev = curr_message;
+ if (msg)
+ curr_message = strdup(msg);
+ else
+ curr_message = NULL;
+ free(prev);
+ return NULL;
+}
+
+void
+print_cmdline(void)
+{
+ if (curr_cmd) {
+ attron(A_STANDOUT);
+ mvprintw(home_line, 0, "%s: ", curr_cmd->prompt);
+ attroff(A_STANDOUT);
+ printw("%s", cmdbuf);
+ } else if (curr_message) {
+ mvprintw(home_line, 0, "> %s", curr_message);
+ }
+ clrtoeol();
+}
+
+
+void
+cmd_keyboard(int ch)
+{
+ if (curr_cmd == NULL)
+ return;
+
+ if (ch > 0 && isprint(ch)) {
+ if (cmd_len < sizeof(cmdbuf) - 1) {
+ cmdbuf[cmd_len++] = ch;
+ cmdbuf[cmd_len] = 0;
+ } else
+ beep();
+ }
+
+ switch (ch) {
+ case KEY_ENTER:
+ case 0x0a:
+ case 0x0d:
+ {
+ struct command * c = command_set(NULL, NULL);
+ c->exec();
+ break;
+ }
+ case KEY_BACKSPACE:
+ case KEY_DC:
+ case CTRL_H:
+ if (cmd_len > 0) {
+ cmdbuf[--cmd_len] = 0;
+ } else
+ beep();
+ break;
+ case 0x1b:
+ case CTRL_G:
+ if (cmd_len > 0) {
+ cmdbuf[0] = '\0';
+ cmd_len = 0;
+ } else
+ command_set(NULL, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+keyboard(void)
+{
+ int ch;
+
+ ch = getch();
+
+ if (curr_cmd) {
+ cmd_keyboard(ch);
+ print_cmdline();
+ return;
+ }
+
+ if (curr_mgr != NULL)
+ if (curr_mgr->key_fn != NULL)
+ if (curr_mgr->key_fn(ch))
+ return;
+
+ if (curr_message != NULL) {
+ if (ch > 0) {
+ curr_message = NULL;
+ need_update = 1;
+ }
+ }
+
+ switch (ch) {
+ case ' ':
+ gotsig_alarm = 1;
+ break;
+ case 'o':
+ next_order();
+ need_sort = 1;
+ break;
+ case 'p':
+ paused = !paused;
+ gotsig_alarm = 1;
+ break;
+ case 'q':
+ gotsig_close = 1;
+ break;
+ case 'r':
+ sortdir *= -1;
+ need_sort = 1;
+ break;
+ case 'v':
+ /* FALLTHROUGH */
+ case KEY_RIGHT:
+ /* FALLTHROUGH */
+ case CTRL_F:
+ next_view();
+ break;
+ case KEY_LEFT:
+ /* FALLTHROUGH */
+ case CTRL_B:
+ prev_view();
+ break;
+ case KEY_DOWN:
+ /* FALLTHROUGH */
+ case CTRL_N:
+ dispstart++;
+ need_update = 1;
+ break;
+ case KEY_UP:
+ /* FALLTHROUGH */
+ case CTRL_P:
+ dispstart--;
+ need_update = 1;
+ break;
+ case KEY_NPAGE:
+ /* FALLTHROUGH */
+ case CTRL_V:
+ dispstart += maxprint;
+ need_update = 1;
+ break;
+ case KEY_PPAGE:
+ /* FALLTHROUGH */
+ case META_V:
+ dispstart -= maxprint;
+ need_update = 1;
+ break;
+ case KEY_HOME:
+ /* FALLTHROUGH */
+ case CTRL_A:
+ dispstart = 0;
+ need_update = 1;
+ break;
+ case KEY_END:
+ /* FALLTHROUGH */
+ case CTRL_E:
+ dispstart = num_disp;
+ need_update = 1;
+ break;
+ case CTRL_L:
+ clear();
+ need_update = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (set_order_hotkey(ch))
+ need_sort = 1;
+ else
+ set_view_hotkey(ch);
+}
+
+void
+engine_initialize(void)
+{
+ signal(SIGTERM, sig_close);
+ signal(SIGINT, sig_close);
+ signal(SIGQUIT, sig_close);
+ signal(SIGWINCH, sig_resize);
+ signal(SIGALRM, sig_alarm);
+}
+
+void
+engine_loop(int countmax)
+{
+ int count = 0;
+
+ for (;;) {
+ if (gotsig_alarm) {
+ read_view();
+ need_sort = 1;
+ gotsig_alarm = 0;
+ ualarm(udelay, 0);
+ }
+
+ if (need_sort) {
+ sort_view();
+ need_sort = 0;
+ need_update = 1;
+
+ /* XXX if sort took too long */
+ if (gotsig_alarm) {
+ gotsig_alarm = 0;
+ ualarm(udelay, 0);
+ }
+ }
+
+ if (need_update) {
+ erase();
+ disp_update();
+ end_page();
+ need_update = 0;
+ if (countmax && ++count >= countmax)
+ break;
+ }
+
+ if (gotsig_close)
+ break;
+ if (gotsig_resize) {
+ if (rawmode == 0)
+ endwin();
+ setup_term(max_disp);
+ gotsig_resize = 0;
+ need_update = 1;
+ }
+
+ if (interactive && need_update == 0)
+ keyboard();
+ else if (interactive == 0)
+ usleep(udelay);
+ }
+
+ if (rawmode == 0)
+ endwin();
+}
diff --git a/usr.bin/systat/engine.h b/usr.bin/systat/engine.h
new file mode 100644
index 00000000000..fd3d7e91a01
--- /dev/null
+++ b/usr.bin/systat/engine.h
@@ -0,0 +1,167 @@
+/* $Id: engine.h,v 1.1 2008/06/12 22:26:01 canacar Exp $ */
+/*
+ * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _ENGINE_H_
+#define _ENGINE_H_
+
+#include <curses.h>
+
+#define DEFAULT_WIDTH 80
+#define DEFAULT_HEIGHT 25
+
+/* XXX do not hardcode! */
+#define HEADER_LINES 4
+
+
+#define CTRL_A 1
+#define CTRL_B 2
+#define CTRL_E 5
+#define CTRL_F 6
+#define CTRL_G 7
+#define CTRL_H 8
+#define CTRL_L 12
+#define CTRL_N 14
+#define CTRL_P 16
+#define CTRL_V 22
+
+#define META_V 246
+
+#define MAX_LINE_BUF 1024
+
+
+#define FLD_ALIGN_LEFT 0
+#define FLD_ALIGN_RIGHT 1
+#define FLD_ALIGN_CENTER 2
+#define FLD_ALIGN_COLUMN 3
+#define FLD_ALIGN_BAR 4
+
+#define FLD_FLAG_HIDDEN 1
+
+
+typedef struct {
+ char *title;
+ int norm_width;
+ int max_width;
+ int increment;
+ int align;
+ int start;
+ int width;
+ unsigned flags;
+ int arg;
+} field_def;
+
+typedef struct {
+ char *name;
+ char *match;
+ int hotkey;
+ int (*func) (const void *, const void *);
+} order_type;
+
+struct view_manager {
+ char *name;
+ int (*select_fn) (void);
+ int (*read_fn) (void);
+ void (*sort_fn) (void);
+ int (*header_fn) (void);
+ void (*print_fn) (void);
+ int (*key_fn) (int);
+ order_type *order_list;
+ order_type *order_curr;
+};
+
+typedef struct {
+ field_def **view;
+ char *name;
+ int hotkey;
+ struct view_manager *mgr;
+} field_view;
+
+struct command {
+ char *prompt;
+ void ( *exec)(void);
+};
+
+
+void tb_start(void);
+
+void tb_end(void);
+
+int tbprintf(char *format, ...) GCC_PRINTFLIKE(1,2);
+
+void end_line(void);
+void end_page(void);
+
+void print_fld_str(field_def *fld, const char *str);
+void print_fld_age(field_def *fld, unsigned int age);
+void print_fld_sdiv(field_def *fld, u_int64_t size, int div);
+void print_fld_size(field_def *fld, u_int64_t size);
+void print_fld_bw(field_def *fld, double bw);
+void print_fld_rate(field_def *fld, double rate);
+void print_fld_uint(field_def *fld, unsigned int size);
+void print_fld_bar(field_def *fld, int value);
+void print_fld_tb(field_def *fld);
+
+void print_title(void);
+
+void hide_field(field_def *fld);
+void show_field(field_def *fld);
+void field_setup(void);
+
+void add_view(field_view *fv);
+int set_view(char *opt);
+void next_view(void);
+void prev_view(void);
+
+void set_order(char *opt);
+void next_order(void);
+
+void setup_term(int maxpr);
+
+void engine_initialize(void);
+void engine_loop(int countmax);
+
+struct command *command_set(struct command *cmd, const char *init);
+const char *message_set(const char *msg);
+
+void foreach_view(void (*callback)(field_view *));
+
+extern int sortdir;
+extern useconds_t udelay;
+extern int dispstart;
+extern int interactive;
+extern int maxprint;
+extern int paused;
+extern int rawmode;
+extern int rawwidth;
+extern int columns, lines;
+
+extern int need_update;
+extern int need_sort;
+
+extern volatile sig_atomic_t gotsig_close;
+extern volatile sig_atomic_t gotsig_resize;
+extern volatile sig_atomic_t gotsig_alarm;
+
+extern field_view *curr_view;
+extern struct view_manager *curr_mgr;
+
+extern char tmp_buf[MAX_LINE_BUF];
+extern char cmdbuf[MAX_LINE_BUF];
+
+extern int curr_line; /* XXX temp */
+extern u_int32_t num_disp;
+#endif
diff --git a/usr.bin/systat/extern.h b/usr.bin/systat/extern.h
index 264827da14a..e69de29bb2d 100644
--- a/usr.bin/systat/extern.h
+++ b/usr.bin/systat/extern.h
@@ -1,141 +0,0 @@
-/* $OpenBSD: extern.h,v 1.19 2007/08/09 02:38:09 ray Exp $ */
-/* $NetBSD: extern.h,v 1.3 1996/05/10 23:16:34 thorpej Exp $ */
-
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)extern.h 8.1 (Berkeley) 6/6/93
- */
-
-#include <sys/cdefs.h>
-#include <fcntl.h>
-#include <kvm.h>
-
-extern struct cmdtab *curcmd;
-extern struct cmdtab cmdtab[];
-extern WINDOW *wnd;
-extern char **dr_name;
-extern char hostname[];
-extern double avenrun[3];
-extern kvm_t *kd;
-extern long ntext;
-extern int *dk_select;
-extern int CMDLINE;
-extern int dk_ndrive;
-extern int hz, stathz;
-extern double naptime;
-extern size_t nhosts;
-extern size_t nports;
-extern int protos;
-extern int verbose;
-extern int nflag;
-
-struct inpcb;
-
-int checkhost(struct inpcb *);
-int checkport(struct inpcb *);
-void closeifstat(WINDOW *);
-void closeiostat(WINDOW *);
-void closekre(WINDOW *);
-void closembufs(WINDOW *);
-void closenetstat(WINDOW *);
-void closepigs(WINDOW *);
-void closesensors(WINDOW *);
-void closeswap(WINDOW *);
-int cmdifstat(char *, char *);
-int cmdiostat(char *, char *);
-int cmdkre(char *, char *);
-int cmdnetstat(char *, char *);
-struct cmdtab *lookup(char *);
-void command(char *);
-void sigdie(int);
-void sigtstp(int);
-void die(void);
-void sigdisplay(int);
-void display(void);
-int dkinit(int);
-int dkcmd(char *, char *);
-void error(const char *fmt, ...);
-void fetchifstat(void);
-void fetchiostat(void);
-void fetchkre(void);
-void fetchmbufs(void);
-void fetchnetstat(void);
-void fetchpigs(void);
-void fetchsensors(void);
-void fetchswap(void);
-int initifstat(void);
-int initiostat(void);
-int initkre(void);
-int initmbufs(void);
-int initnetstat(void);
-int initpigs(void);
-int initsensors(void);
-int initswap(void);
-void keyboard(void);
-int kvm_ckread(void *, void *, size_t);
-void labelifstat(void);
-void labeliostat(void);
-void labelkre(void);
-void labelmbufs(void);
-void labelnetstat(void);
-void labelpigs(void);
-void labels(void);
-void labelsensors(void);
-void labelswap(void);
-void load(void);
-int netcmd(char *, char *);
-void nlisterr(struct nlist []);
-WINDOW *openifstat(void);
-WINDOW *openiostat(void);
-WINDOW *openkre(void);
-WINDOW *openmbufs(void);
-WINDOW *opennetstat(void);
-WINDOW *openpigs(void);
-WINDOW *opensensors(void);
-WINDOW *openswap(void);
-int prefix(char *, char *);
-void sigwinch(int);
-void showifstat(void);
-void showiostat(void);
-void showkre(void);
-void showmbufs(void);
-void shownetstat(void);
-void showpigs(void);
-void showsensors(void);
-void showswap(void);
-void status(void);
-void gethz(void);
-
-extern volatile sig_atomic_t gotdie;
-extern volatile sig_atomic_t gotdisplay;
-extern volatile sig_atomic_t gotwinch;
-extern volatile sig_atomic_t gottstp;
-
-extern double dellave;
-extern WINDOW *wload;
diff --git a/usr.bin/systat/fetch.c b/usr.bin/systat/fetch.c
index ce0cd54871d..e69de29bb2d 100644
--- a/usr.bin/systat/fetch.c
+++ b/usr.bin/systat/fetch.c
@@ -1,54 +0,0 @@
-/* $OpenBSD: fetch.c,v 1.8 2006/03/31 04:10:59 deraadt Exp $ */
-/* $NetBSD: fetch.c,v 1.2 1995/01/20 08:51:56 jtc Exp $ */
-
-/*-
- * Copyright (c) 1980, 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)fetch.c 8.1 (Berkeley) 6/6/93";
-#endif
-static char rcsid[] = "$OpenBSD: fetch.c,v 1.8 2006/03/31 04:10:59 deraadt Exp $";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <signal.h>
-#include "systat.h"
-#include "extern.h"
-
-int
-kvm_ckread(void *a, void *b, size_t l)
-{
- if (kvm_read(kd, (u_long)a, b, l) != l) {
- if (verbose)
- error("error reading kmem at %x\n", a);
- return (0);
- } else
- return (1);
-}
diff --git a/usr.bin/systat/if.c b/usr.bin/systat/if.c
index ce56da5c5d1..2e56471f68f 100644
--- a/usr.bin/systat/if.c
+++ b/usr.bin/systat/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.11 2007/09/05 20:31:34 mk Exp $ */
+/* $OpenBSD: if.c,v 1.12 2008/06/12 22:26:01 canacar Exp $ */
/*
* Copyright (c) 2004 Markus Friedl <markus@openbsd.org>
*
@@ -26,7 +26,6 @@
#include <string.h>
#include "systat.h"
-#include "extern.h"
static enum state { BOOT, TIME, RUN } state = TIME;
@@ -50,32 +49,73 @@ struct ifstat {
} *ifstats;
static int nifs = 0;
+static int num_ifs = 0;
-const char *showlinkstate(int);
+void print_if(void);
+int read_if(void);
+int select_if(void);
+int if_keyboard_callback(int);
-WINDOW *
-openifstat(void)
-{
+static void fetchifstat(void);
+static void showifstat(struct ifstat *);
+static void showtotal(void);
- return (subwin(stdscr, LINES-1-1, 0, 1, 0));
-}
-void
-closeifstat(WINDOW *w)
-{
+/* Define fields */
+field_def fields_if[] = {
+ {"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"STATE", 10, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"IPKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"IBYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"IERRS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"OPKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"OBYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"OERRS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"COLLS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+};
+
+
+#define FIELD_ADDR(x) (&fields_if[x])
+
+#define FLD_IF_IFACE FIELD_ADDR(0)
+#define FLD_IF_STATE FIELD_ADDR(1)
+#define FLD_IF_IPKTS FIELD_ADDR(2)
+#define FLD_IF_IBYTES FIELD_ADDR(3)
+#define FLD_IF_IERRS FIELD_ADDR(4)
+#define FLD_IF_OPKTS FIELD_ADDR(5)
+#define FLD_IF_OBYTES FIELD_ADDR(6)
+#define FLD_IF_OERRS FIELD_ADDR(7)
+#define FLD_IF_COLLS FIELD_ADDR(8)
+
+
+/* Define views */
+field_def *view_if_0[] = {
+ FLD_IF_IFACE, FLD_IF_STATE, FLD_IF_IPKTS, FLD_IF_IBYTES,
+ FLD_IF_IERRS, FLD_IF_OPKTS, FLD_IF_OBYTES, FLD_IF_OERRS,
+ FLD_IF_COLLS, NULL
+};
+
+/* Define view managers */
+
+struct view_manager ifstat_mgr = {
+ "Ifstat", select_if, read_if, NULL, print_header,
+ print_if, if_keyboard_callback, NULL, NULL
+};
+
+field_view views_if[] = {
+ {view_if_0, "ifstat", '1', &ifstat_mgr},
+ {NULL, NULL, 0, NULL}
+};
- if (w == NULL)
- return;
- wclear(w);
- wrefresh(w);
- delwin(w);
-}
int
initifstat(void)
{
+ field_view *v;
+ read_if();
+ for (v = views_if; v->name != NULL; v++)
+ add_view(v);
- fetchifstat();
return(1);
}
@@ -105,7 +145,45 @@ rt_getaddrinfo(struct sockaddr *sa, int addrs, struct sockaddr **info)
}
}
+
+
+int
+select_if(void)
+{
+ num_disp = num_ifs + 1;
+ return (0);
+}
+
+int
+read_if(void)
+{
+ fetchifstat();
+ num_disp = num_ifs + 1;
+
+ return 0;
+}
+
void
+print_if(void)
+{
+ int n, i, count = 0;
+
+ for (n = 0, i = 0; n < nifs; n++) {
+ if (ifstats[n].ifs_name[0] == '\0')
+ continue;
+ if (i++ < dispstart)
+ continue;
+ if (i == num_disp)
+ break;
+ showifstat(ifstats + n);
+ if (maxprint > 0 && ++count >= maxprint)
+ return;
+ }
+ showtotal();
+}
+
+
+static void
fetchifstat(void)
{
struct ifstat *newstats, *ifs;
@@ -133,6 +211,7 @@ fetchifstat(void)
}
bzero(&sum, sizeof(sum));
+ num_ifs = 0;
lim = buf + need;
for (next = buf; next < lim; next += ifm.ifm_msglen) {
@@ -141,12 +220,12 @@ fetchifstat(void)
!(ifm.ifm_addrs & RTA_IFP))
continue;
if (ifm.ifm_index >= nifs) {
- if ((newstats = realloc(ifstats, (ifm.ifm_index + 4) *
- sizeof(struct ifstat))) == NULL)
+ if ((newstats = realloc(ifstats, (ifm.ifm_index + 4)
+ * sizeof(struct ifstat))) == NULL)
continue;
ifstats = newstats;
for (; nifs < ifm.ifm_index + 4; nifs++)
- ifstats[nifs].ifs_name[0] = '\0';
+ bzero(&ifstats[nifs], sizeof(*ifstats));
}
ifs = &ifstats[ifm.ifm_index];
if (ifs->ifs_name[0] == '\0') {
@@ -165,6 +244,7 @@ fetchifstat(void)
if (ifs->ifs_name[0] == '\0')
continue;
}
+ num_ifs++;
UPDATE(ifc_ip, ifm_data.ifi_ipackets);
UPDATE(ifc_ib, ifm_data.ifi_ibytes);
UPDATE(ifc_ie, ifm_data.ifi_ierrors);
@@ -178,107 +258,88 @@ fetchifstat(void)
free(buf);
}
-#define INSET 0
-void
-labelifstat(void)
+static void
+showifstat(struct ifstat *ifs)
{
+ print_fld_str(FLD_IF_IFACE, ifs->ifs_name);
- wmove(wnd, 0, 0);
- wclrtobot(wnd);
-
- mvwaddstr(wnd, 1, INSET, "Iface");
- mvwaddstr(wnd, 1, INSET+9, "State");
- mvwaddstr(wnd, 1, INSET+19, "Ibytes");
- mvwaddstr(wnd, 1, INSET+29, "Ipkts");
- mvwaddstr(wnd, 1, INSET+36, "Ierrs");
- mvwaddstr(wnd, 1, INSET+48, "Obytes");
- mvwaddstr(wnd, 1, INSET+58, "Opkts");
- mvwaddstr(wnd, 1, INSET+65, "Oerrs");
- mvwaddstr(wnd, 1, INSET+74, "Colls");
-}
-
-#define FMT "%-8.8s %2s%2s %10llu %8llu %6llu %10llu %8llu %6llu %6llu "
+ tb_start();
+ tbprintf("%s", ifs->ifs_cur.ifc_flags & IFF_UP ?
+ "up" : "dn");
-const char *
-showlinkstate(int state)
-{
- switch (state) {
+ switch (ifs->ifs_cur.ifc_state) {
case LINK_STATE_UP:
case LINK_STATE_HALF_DUPLEX:
case LINK_STATE_FULL_DUPLEX:
- return (":U");
+ tbprintf(":U");
+ break;
case LINK_STATE_DOWN:
- return (":D");
- case LINK_STATE_UNKNOWN:
- default:
- return ("");
+ tbprintf (":D");
+ break;
}
+
+ print_fld_tb(FLD_IF_STATE);
+
+ print_fld_size(FLD_IF_IBYTES, ifs->ifs_cur.ifc_ib);
+ print_fld_size(FLD_IF_IPKTS, ifs->ifs_cur.ifc_ip);
+ print_fld_size(FLD_IF_IERRS, ifs->ifs_cur.ifc_ie);
+
+ print_fld_size(FLD_IF_OBYTES, ifs->ifs_cur.ifc_ob);
+ print_fld_size(FLD_IF_OPKTS, ifs->ifs_cur.ifc_op);
+ print_fld_size(FLD_IF_OERRS, ifs->ifs_cur.ifc_oe);
+
+ print_fld_size(FLD_IF_COLLS, ifs->ifs_cur.ifc_co);
+
+ end_line();
}
-void
-showifstat(void)
+static void
+showtotal(void)
{
- int row;
- struct ifstat *ifs;
+ print_fld_str(FLD_IF_IFACE, "Totals");
+
+ print_fld_size(FLD_IF_IBYTES, sum.ifc_ib);
+ print_fld_size(FLD_IF_IPKTS, sum.ifc_ip);
+ print_fld_size(FLD_IF_IERRS, sum.ifc_ie);
+
+ print_fld_size(FLD_IF_OBYTES, sum.ifc_ob);
+ print_fld_size(FLD_IF_OPKTS, sum.ifc_op);
+ print_fld_size(FLD_IF_OERRS, sum.ifc_oe);
+
+ print_fld_size(FLD_IF_COLLS, sum.ifc_co);
+
+ end_line();
- row = 2;
- wmove(wnd, 0, 0);
- wclrtoeol(wnd);
- for (ifs = ifstats; ifs < ifstats + nifs; ifs++) {
- if (ifs->ifs_name[0] == '\0')
- continue;
- mvwprintw(wnd, row++, INSET, FMT,
- ifs->ifs_name,
- ifs->ifs_cur.ifc_flags & IFF_UP ? "up" : "dn",
- showlinkstate(ifs->ifs_cur.ifc_state),
- ifs->ifs_cur.ifc_ib,
- ifs->ifs_cur.ifc_ip,
- ifs->ifs_cur.ifc_ie,
- ifs->ifs_cur.ifc_ob,
- ifs->ifs_cur.ifc_op,
- ifs->ifs_cur.ifc_oe,
- ifs->ifs_cur.ifc_co);
- }
- mvwprintw(wnd, row++, INSET, FMT,
- "Totals",
- "", "",
- sum.ifc_ib,
- sum.ifc_ip,
- sum.ifc_ie,
- sum.ifc_ob,
- sum.ifc_op,
- sum.ifc_oe,
- sum.ifc_co);
}
int
-cmdifstat(char *cmd, char *args)
+if_keyboard_callback(int ch)
{
struct ifstat *ifs;
- if (prefix(cmd, "run")) {
- if (state != RUN)
- for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
- ifs->ifs_old = ifs->ifs_now;
+ switch (ch) {
+ case 'r':
+ for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
+ ifs->ifs_old = ifs->ifs_now;
state = RUN;
- return (1);
- }
- if (prefix(cmd, "boot")) {
+ gotsig_alarm = 1;
+
+ break;
+ case 'b':
state = BOOT;
for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
bzero(&ifs->ifs_old, sizeof(ifs->ifs_old));
- return (1);
- }
- if (prefix(cmd, "time")) {
+ gotsig_alarm = 1;
+ break;
+ case 't':
state = TIME;
- return (1);
- }
- if (prefix(cmd, "zero")) {
- if (state == RUN)
- for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
- ifs->ifs_old = ifs->ifs_now;
- return (1);
- }
- return (1);
+ gotsig_alarm = 1;
+ break;
+ default:
+ return keyboard_callback(ch);
+ };
+
+ return 1;
}
+
diff --git a/usr.bin/systat/iostat.c b/usr.bin/systat/iostat.c
index dde4cbcc93d..da2b7b1f973 100644
--- a/usr.bin/systat/iostat.c
+++ b/usr.bin/systat/iostat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: iostat.c,v 1.29 2008/06/12 17:53:49 beck Exp $ */
+/* $OpenBSD: iostat.c,v 1.30 2008/06/12 22:26:01 canacar Exp $ */
/* $NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $ */
/*
@@ -30,13 +30,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93";
-#endif
-static char rcsid[] = "$OpenBSD: iostat.c,v 1.29 2008/06/12 17:53:49 beck Exp $";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/dkstat.h>
#include <sys/buf.h>
@@ -48,7 +41,6 @@ static char rcsid[] = "$OpenBSD: iostat.c,v 1.29 2008/06/12 17:53:49 beck Exp $"
#include <stdlib.h>
#include <paths.h>
#include "systat.h"
-#include "extern.h"
#include "dkstats.h"
extern struct _disk cur, last;
@@ -56,158 +48,150 @@ struct bcachestats bclast, bccur;
static double etime;
-static void numlabels(void);
+void showtotal(void);
+void showdrive(int);
+void print_io(void);
+int read_io(void);
+int select_io(void);
+void showbcache(void);
#define ATIME(x,y) ((double)x[y].tv_sec + \
((double)x[y].tv_usec / (double)1000000))
-#define NFMT "%-6.6s %8.0f %8.0f %6.0f %6.0f %4.1f"
-#define SFMT "%-6.6s %8s %8s %6s %6s %4s"
-#define BCSCOL 50
-WINDOW *
-openiostat(void)
-{
- bzero(&bccur, sizeof(bccur));
- return (subwin(stdscr, LINES-1-1, 0, 1, 0));
-}
+field_def fields_io[] = {
+ {"DEVICE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"READ", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"WRITE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"RTPS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"WTPS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"SEC", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"", 8, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"STATS", 12, 15, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}
+};
+
+#define FIELD_ADDR(x) (&fields_io[x])
+
+#define FLD_IO_DEVICE FIELD_ADDR(0)
+#define FLD_IO_READ FIELD_ADDR(1)
+#define FLD_IO_WRITE FIELD_ADDR(2)
+#define FLD_IO_RTPS FIELD_ADDR(3)
+#define FLD_IO_WTPS FIELD_ADDR(4)
+#define FLD_IO_SEC FIELD_ADDR(5)
+
+/* This is a hack that stuffs bcache statistics to the last two columns! */
+#define FLD_IO_SVAL FIELD_ADDR(6)
+#define FLD_IO_SSTR FIELD_ADDR(7)
+
+/* Define views */
+field_def *view_io_0[] = {
+ FLD_IO_DEVICE, FLD_IO_READ, FLD_IO_WRITE, FLD_IO_RTPS,
+ FLD_IO_WTPS, FLD_IO_SEC, FLD_IO_SVAL, FLD_IO_SSTR, NULL
+};
+
+
+/* Define view managers */
+struct view_manager iostat_mgr = {
+ "Iostat", select_io, read_io, NULL, print_header,
+ print_io, keyboard_callback, NULL, NULL
+};
+
+
+field_view views_io[] = {
+ {view_io_0, "iostat", '2', &iostat_mgr},
+ {NULL, NULL, 0, NULL}
+};
-void
-closeiostat(WINDOW *w)
-{
- if (w == NULL)
- return;
- wclear(w);
- wrefresh(w);
- delwin(w);
-}
int
-initiostat(void)
+select_io(void)
{
- dkinit(1);
- dkreadstats();
- return (1);
+ num_disp = cur.dk_ndrive + 1;
+ return (0);
}
-void
-fetchiostat(void)
+int
+read_io(void)
{
int mib[3];
size_t size;
- if (cur.dk_ndrive == 0)
- return;
dkreadstats();
+ dkswap();
+ num_disp = cur.dk_ndrive + 1;
bclast = bccur;
mib[0] = CTL_VFS;
mib[1] = VFS_GENERIC;
mib[2] = VFS_BCACHESTAT;
size = sizeof(bccur);
+
if (sysctl(mib, 3, &bccur, &size, NULL, 0) < 0)
- mvwaddstr(wnd, 20, 0, "cannot get vfs.bcachestat");
+ error("cannot get vfs.bcachestat");
+
if (bclast.numbufs == 0)
bclast = bccur;
-}
-void
-labeliostat(void)
-{
- mvwprintw(wnd, 1, 0, SFMT, "Device", "rKBytes", "wKBytes", "rtps",
- "wtps", "sec");
- mvwprintw(wnd, 1, BCSCOL + 16, "numbufs");
- mvwprintw(wnd, 2, BCSCOL + 16, "freebufs");
- mvwprintw(wnd, 3, BCSCOL + 16, "numbufpages");
- mvwprintw(wnd, 4, BCSCOL + 16, "numfreepages");
- mvwprintw(wnd, 5, BCSCOL + 16, "numdirtypages");
- mvwprintw(wnd, 6, BCSCOL + 16, "numcleanpages");
- mvwprintw(wnd, 7, BCSCOL + 16, "pendingwrites");
- mvwprintw(wnd, 8, BCSCOL + 16, "pendingreads");
- mvwprintw(wnd, 9, BCSCOL + 16, "numwrites");
- mvwprintw(wnd, 10, BCSCOL + 16, "numreads");
- mvwprintw(wnd, 11, BCSCOL + 16, "cachehits");
+ return 0;
}
+
void
-showiostat(void)
+print_io(void)
{
- int i;
+ int n, count = 0;
- dkswap();
+ int i, curr;
etime = 0.0;
- for (i = 0; i < CPUSTATES; i++) {
+ for (i = 0; i < CPUSTATES; i++)
etime += cur.cp_time[i];
- }
if (etime == 0.0)
etime = 1.0;
etime /= (float) hz;
- if (last.dk_ndrive != cur.dk_ndrive)
- labeliostat();
-
- if (cur.dk_ndrive == 0)
- return;
-
- numlabels();
-
- mvwprintw(wnd, 1, BCSCOL, "%15ld", bccur.numbufs);
- mvwprintw(wnd, 2, BCSCOL, "%15ld", bccur.freebufs);
- mvwprintw(wnd, 3, BCSCOL, "%15ld", bccur.numbufpages);
- if (bccur.numfreepages)
- mvwprintw(wnd, 4, BCSCOL, "%15ld", bccur.numfreepages);
- else
- mvwprintw(wnd, 4, BCSCOL, "%15s", "");
- if (bccur.numdirtypages)
- mvwprintw(wnd, 5, BCSCOL, "%15ld", bccur.numdirtypages);
- else
- mvwprintw(wnd, 5, BCSCOL, "%15s", "");
- if (bccur.numcleanpages)
- mvwprintw(wnd, 6, BCSCOL, "%15ld", bccur.numcleanpages);
- else
- mvwprintw(wnd, 6, BCSCOL, "%15s", "");
- if (bccur.pendingwrites)
- mvwprintw(wnd, 7, BCSCOL, "%15ld", bccur.pendingwrites);
- else
- mvwprintw(wnd, 7, BCSCOL, "%15s", "");
- if (bccur.pendingreads)
- mvwprintw(wnd, 8, BCSCOL, "%15ld", bccur.pendingreads);
- else
- mvwprintw(wnd, 8, BCSCOL, "%15s", "");
- if (bccur.numwrites - bclast.numwrites)
- mvwprintw(wnd, 9, BCSCOL, "%15ld",
- bccur.numwrites - bclast.numwrites);
- else
- mvwprintw(wnd, 9, BCSCOL, "%15s", "");
- if (bccur.numreads - bclast.numreads)
- mvwprintw(wnd, 10, BCSCOL, "%15ld",
- bccur.numreads - bclast.numreads);
- else
- mvwprintw(wnd, 10, BCSCOL, "%15s", "");
- if (bccur.cachehits - bclast.cachehits)
- mvwprintw(wnd, 11, BCSCOL, "%15ld",
- bccur.cachehits - bclast.cachehits);
- else
- mvwprintw(wnd, 11, BCSCOL, "%15s", "");
+
+ /* XXX engine internals: save and restore curr_line for bcache */
+ curr = curr_line;
+
+ for (n = dispstart; n < num_disp - 1; n++) {
+ showdrive(n);
+ count++;
+ if (maxprint > 0 && count >= maxprint)
+ break;
+ }
+
+
+ if (maxprint == 0 || count < maxprint)
+ showtotal();
+
+ curr_line = curr;
+ showbcache();
}
-void
-numlabels(void)
+int
+initiostat(void)
{
- double rsum, wsum, rtsum, wtsum, mssum;
- int row, dn;
+ field_view *v;
- row = 2;
- wmove(wnd, 0, 0);
- wclrtoeol(wnd);
+ dkinit(1);
+ dkreadstats();
- if (cur.dk_ndrive == 0) {
- mvwaddstr(wnd, row, 0, "No drives attached.");
- return;
- }
+ bzero(&bccur, sizeof(bccur));
+
+ for (v = views_io; v->name != NULL; v++)
+ add_view(v);
+
+ return(1);
+}
+
+void
+showtotal(void)
+{
+ double rsum, wsum, rtsum, wtsum, mssum;
+ int dn;
rsum = wsum = rtsum = wtsum = mssum = 0.0;
@@ -217,23 +201,84 @@ numlabels(void)
rtsum += cur.dk_rxfer[dn] / etime;
wtsum += cur.dk_wxfer[dn] / etime;
mssum += ATIME(cur.dk_time, dn) / etime;
- mvwprintw(wnd, row++, 0, NFMT,
- cur.dk_name[dn],
- cur.dk_rbytes[dn] / 1024.0 / etime,
- cur.dk_wbytes[dn] / 1024.0 / etime,
- cur.dk_rxfer[dn] / etime,
- cur.dk_wxfer[dn] / etime,
- ATIME(cur.dk_time, dn) / etime);
}
- mvwprintw(wnd, row++, 0, NFMT,
- "Totals", rsum / 1024.0, wsum / 1024.0, rtsum, wtsum, mssum);
+
+ print_fld_str(FLD_IO_DEVICE, "Totals");
+ print_fld_size(FLD_IO_READ, rsum);
+ print_fld_size(FLD_IO_WRITE, wsum);
+ print_fld_size(FLD_IO_RTPS, rtsum);
+ print_fld_size(FLD_IO_WTPS, wtsum);
+ print_fld_size(FLD_IO_SEC, mssum);
+
+ end_line();
}
-int
-cmdiostat(char *cmd, char *args)
+void
+showdrive(int dn)
{
- wclear(wnd);
- labeliostat();
- refresh();
- return (1);
+ print_fld_str(FLD_IO_DEVICE, cur.dk_name[dn]);
+ print_fld_size(FLD_IO_READ, cur.dk_rbytes[dn]/etime);
+ print_fld_size(FLD_IO_WRITE, cur.dk_wbytes[dn]/ etime);
+ print_fld_size(FLD_IO_RTPS, cur.dk_rxfer[dn] / etime);
+ print_fld_size(FLD_IO_WTPS, cur.dk_wxfer[dn] / etime);
+ print_fld_size(FLD_IO_SEC, ATIME(cur.dk_time, dn) / etime);
+
+ end_line();
+}
+
+
+#define ENDLINE do { \
+ count++; \
+ if (maxprint > 0 && count >= maxprint) \
+ return; \
+ } while(0)
+
+void
+showbcache(void)
+{
+ int count = 0;
+
+ print_fld_str(FLD_IO_SSTR, "numbufs");
+ print_fld_size(FLD_IO_SVAL, bccur.numbufs);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "freebufs");
+ print_fld_size(FLD_IO_SVAL, bccur.freebufs);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "numbufpages");
+ print_fld_size(FLD_IO_SVAL, bccur.numbufpages);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "numfreepages");
+ print_fld_size(FLD_IO_SVAL, bccur.numfreepages);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "numdirtypages");
+ print_fld_size(FLD_IO_SVAL, bccur.numdirtypages);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "numcleanpages");
+ print_fld_size(FLD_IO_SVAL, bccur.numcleanpages);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "pendingwrites");
+ print_fld_size(FLD_IO_SVAL, bccur.pendingwrites);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "pendingreads");
+ print_fld_size(FLD_IO_SVAL, bccur.pendingreads);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "numwrites");
+ print_fld_size(FLD_IO_SVAL, bccur.numwrites - bclast.numwrites);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "numreads");
+ print_fld_size(FLD_IO_SVAL, bccur.numreads - bclast.numreads);
+ end_line();
+
+ print_fld_str(FLD_IO_SSTR, "cachehits");
+ print_fld_size(FLD_IO_SVAL, bccur.cachehits - bclast.cachehits);
+ end_line();
}
diff --git a/usr.bin/systat/keyboard.c b/usr.bin/systat/keyboard.c
index 03b85760af2..e69de29bb2d 100644
--- a/usr.bin/systat/keyboard.c
+++ b/usr.bin/systat/keyboard.c
@@ -1,165 +0,0 @@
-/* $OpenBSD: keyboard.c,v 1.19 2007/04/15 16:25:08 matthieu Exp $ */
-/* $NetBSD: keyboard.c,v 1.2 1995/01/20 08:51:59 jtc Exp $ */
-
-/*-
- * Copyright (c) 1980, 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)keyboard.c 8.1 (Berkeley) 6/6/93";
-#endif
-static char rcsid[] = "$OpenBSD: keyboard.c,v 1.19 2007/04/15 16:25:08 matthieu Exp $";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <ctype.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <termios.h>
-#include <errno.h>
-
-#include "systat.h"
-#include "extern.h"
-
-void
-keyboard(void)
-{
- char line[80];
- sigset_t mask, omask;
- int ch, col;
-
- for (;;) {
- col = 0;
- move(CMDLINE, 0);
- do {
- if (gottstp) {
- endwin();
- signal(SIGTSTP, SIG_DFL);
- kill(getpid(), SIGTSTP);
- signal(SIGTSTP, sigtstp);
- siginterrupt(SIGTSTP, 1);
- gotwinch = 1;
- gottstp = 0;
- }
- if (gotdisplay) {
- display();
- gotdisplay = 0;
- }
- if (gotdie) {
- die();
- }
- if (gotwinch) {
- clearok(curscr, TRUE);
- wrefresh(curscr);
- gotwinch = 0;
- }
-
- refresh();
- if ((ch = getch()) == ERR) {
- if (errno == EINTR)
- continue;
- exit(1);
- }
- ch &= 0177;
- if (ch == 0177 && ferror(stdin)) {
- clearerr(stdin);
- continue;
- }
- if (ch >= 'A' && ch <= 'Z')
- ch += 'a' - 'A';
- if (col == 0) {
- switch (ch) {
- case CTRL('l'):
- case CTRL('g'):
- sigemptyset(&mask);
- sigaddset(&mask, SIGALRM);
- sigprocmask(SIG_BLOCK, &mask, &omask);
- if (ch == CTRL('l'))
- wrefresh(curscr);
- else
- status();
- sigprocmask(SIG_SETMASK, &omask, NULL);
- continue;
- case ':':
- break;
- case 'q':
- gotdie=1;
- break;
- default:
- continue;
- }
- move(CMDLINE, 0);
- clrtoeol();
- }
- if (ch == erasechar() && col > 0) {
- if (col == 1 && line[0] == ':')
- continue;
- col--;
- goto doerase;
- }
- if (ch == CTRL('w') && col > 0) {
- while (--col >= 0 && isspace(line[col]))
- ;
- col++;
- while (--col >= 0 && !isspace(line[col]))
- if (col == 0 && line[0] == ':')
- break;
- col++;
- goto doerase;
- }
- if (ch == killchar() && col > 0) {
- col = 0;
- if (line[0] == ':')
- col++;
- doerase:
- move(CMDLINE, col);
- clrtoeol();
- continue;
- }
- if (col >= sizeof(line) - 1) {
- /* line too long */
- beep();
- continue;
- }
- if (isprint(ch) || ch == ' ') {
- line[col] = ch;
- mvaddch(CMDLINE, col, (chtype)ch);
- col++;
- }
- } while (col == 0 || (ch != '\r' && ch != '\n'));
- line[col] = '\0';
- sigemptyset(&mask);
- sigaddset(&mask, SIGALRM);
- sigprocmask(SIG_BLOCK, &mask, &omask);
- command(line + 1);
- sigprocmask(SIG_SETMASK, &omask, NULL);
- }
- /*NOTREACHED*/
-}
diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c
index 5676b83235b..3896455ab82 100644
--- a/usr.bin/systat/main.c
+++ b/usr.bin/systat/main.c
@@ -1,65 +1,57 @@
-/* $OpenBSD: main.c,v 1.37 2007/05/21 21:15:37 cnst Exp $ */
-/* $NetBSD: main.c,v 1.8 1996/05/10 23:16:36 thorpej Exp $ */
-
-/*-
- * Copyright (c) 1980, 1992, 1993
- * The Regents of the University of California. All rights reserved.
+/* $Id: main.c,v 1.38 2008/06/12 22:26:01 canacar Exp $ */
+/*
+ * Copyright (c) 2001, 2007 Can Erkin Acar
+ * Copyright (c) 2001 Daniel Hartmeier
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
*/
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright (c) 1980, 1992, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
-#endif
-static char rcsid[] = "$OpenBSD: main.c,v 1.37 2007/05/21 21:15:37 cnst Exp $";
-#endif /* not lint */
-
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
+
+#include <ctype.h>
+#include <curses.h>
#include <err.h>
-#include <nlist.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
#include <signal.h>
-#include <ctype.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#include <unistd.h>
#include <utmp.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <stdarg.h>
+#include "engine.h"
#include "systat.h"
-#include "extern.h"
double dellave;
@@ -69,300 +61,450 @@ char *memf = NULL;
double avenrun[3];
double naptime = 5.0;
int verbose = 1; /* to report kvm read errs */
-int nflag = 0;
+int nflag = 1;
int ut, hz, stathz;
char hostname[MAXHOSTNAMELEN];
WINDOW *wnd;
int CMDLINE;
-WINDOW *wload; /* one line window for load average */
+#define TIMEPOS 55
+
+/* command prompt */
+
+void cmd_delay(void);
+void cmd_count(void);
+void cmd_compat(void);
+
+struct command cm_compat = {"Command", cmd_compat};
+struct command cm_delay = {"Seconds to delay", cmd_delay};
+struct command cm_count = {"Number of lines to display", cmd_count};
-static void usage(void);
+
+/* display functions */
int
-main(int argc, char *argv[])
+print_header(void)
{
- char errbuf[_POSIX2_LINE_MAX];
- gid_t gid;
- int ch;
+ struct tm *tp;
+ time_t t;
+ order_type *ordering;
- ut = open(_PATH_UTMP, O_RDONLY);
- if (ut < 0) {
- error("No utmp");
- exit(1);
- }
+ int start = dispstart + 1;
+ int end = dispstart + maxprint;
- kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
- if (kd == NULL) {
- error("%s", errbuf);
- exit(1);
+ if (end > num_disp)
+ end = num_disp;
+
+ tb_start();
+
+#if 0
+ if (curr_mgr && curr_mgr->sort_fn != NULL) {
+ ordering = curr_mgr->order_curr;
+ if (ordering != NULL) {
+ tbprintf(", Order: %s", ordering->name);
+ if (sortdir < 0 && ordering->func != NULL)
+ tbprintf(" (rev)");
+ }
}
+#endif
- gid = getgid();
- if (setresgid(gid, gid, gid) == -1)
- err(1, "setresgid");
+ getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
+ extern int ucount();
+ char tbuf[26];
+ time_t now;
- while ((ch = getopt(argc, argv, "nw:")) != -1)
- switch (ch) {
- case 'n':
- nflag = 1;
- break;
- case 'w':
+ time(&now);
+ strlcpy(tbuf, ctime(&now), sizeof tbuf);
+ tbprintf(" %d users", ucount());
+ tbprintf(" Load %.2f %.2f %.2f", avenrun[0], avenrun[1], avenrun[2]);
+ if (num_disp && (start > 1 || end != num_disp))
+ tbprintf(" (%u-%u of %u)", start, end, num_disp);
- naptime = strtod(optarg, NULL);
- if (naptime < 0.09 || naptime > 1000.0)
- errx(1, "invalid interval: %s", optarg);
- break;
- default:
- usage();
- }
- argc -= optind;
- argv += optind;
+ if (paused)
+ tbprintf(" PAUSED");
- while (argc > 0) {
- if (isdigit(argv[0][0])) {
- naptime = strtod(argv[0], NULL);
- if (naptime < 0.09 || naptime > 1000.0)
- naptime = 5.0;
- } else {
- struct cmdtab *p;
-
- p = lookup(&argv[0][0]);
- if (p == (struct cmdtab *)-1)
- errx(1, "ambiguous request: %s", &argv[0][0]);
- if (p == 0)
- errx(1, "unknown request: %s", &argv[0][0]);
- curcmd = p;
- }
- argc--;
- argv++;
- }
+ if (rawmode)
+ printf("\n\n%s\n", tmp_buf);
+ else
+ mvprintw(0, 0, "%s", tmp_buf);
- signal(SIGINT, sigdie);
- siginterrupt(SIGINT, 1);
- signal(SIGQUIT, sigdie);
- siginterrupt(SIGQUIT, 1);
- signal(SIGTERM, sigdie);
- siginterrupt(SIGTERM, 1);
- signal(SIGTSTP, sigtstp);
- siginterrupt(SIGTSTP, 1);
-
- /*
- * Initialize display. Load average appears in a one line
- * window of its own. Current command's display appears in
- * an overlapping sub-window of stdscr configured by the display
- * routines to minimize update work by curses.
- */
- if (initscr() == NULL) {
- warnx("couldn't initialize screen");
- exit(0);
- }
+ mvprintw(0, TIMEPOS, "%s", tbuf);
- CMDLINE = LINES - 1;
- wnd = (*curcmd->c_open)();
- if (wnd == NULL) {
- warnx("couldn't initialize display");
- die();
- }
- wload = newwin(1, 0, 1, 20);
- if (wload == NULL) {
- warnx("couldn't set up load average window");
- die();
- }
- gethostname(hostname, sizeof (hostname));
- gethz();
- (*curcmd->c_init)();
- curcmd->c_flags |= CF_INIT;
- labels();
-
- dellave = 0.0;
-
- signal(SIGALRM, sigdisplay);
- siginterrupt(SIGALRM, 1);
- signal(SIGWINCH, sigwinch);
- siginterrupt(SIGWINCH, 1);
- gotdisplay = 1;
- noecho();
- crmode();
- keyboard();
- /*NOTREACHED*/
+
+ return (1);
}
+/* compatibility functions, rearrange later */
void
-gethz(void)
+error(const char *fmt, ...)
{
- struct clockinfo cinf;
- size_t size = sizeof(cinf);
- int mib[2];
+ va_list ap;
+ char buf[MAX_LINE_BUF];
- mib[0] = CTL_KERN;
- mib[1] = KERN_CLOCKRATE;
- if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
- return;
- stathz = cinf.stathz;
- hz = cinf.hz;
-}
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof buf, fmt, ap);
+ va_end(ap);
-static void
-usage(void)
-{
- fprintf(stderr, "usage: systat [-n] [-w wait] [display] [refresh-interval]\n");
- exit(1);
+ message_set(buf);
}
-
void
-labels(void)
+nlisterr(struct nlist namelist[])
{
- if (curcmd->c_flags & CF_LOADAV)
- mvprintw(0, 2 + 4, "users Load");
- (*curcmd->c_label)();
-#ifdef notdef
- mvprintw(21, 25, "CPU usage on %s", hostname);
-#endif
+ int i, n;
+
+ n = 0;
+ clear();
+ mvprintw(2, 10, "systat: nlist: can't find following symbols:");
+ for (i = 0;
+ namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
+ if (namelist[i].n_value == 0)
+ mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
+ move(CMDLINE, 0);
+ clrtoeol();
refresh();
+ endwin();
+ exit(1);
}
-/*ARGSUSED*/
void
-sigdisplay(int signo)
+die(void)
{
- gotdisplay = 1;
+ if (!rawmode)
+ endwin();
+ exit(0);
}
-void
-display(void)
+
+int
+prefix(char *s1, char *s2)
{
- /* Get the load average over the last minute. */
- (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
- (*curcmd->c_fetch)();
- if (curcmd->c_flags & CF_LOADAV) {
- extern int ucount();
- char tbuf[26];
- time_t now;
-
- time(&now);
- strlcpy(tbuf, ctime(&now), sizeof tbuf);
-
- putint(ucount(), 0, 2, 3);
- putfloat(avenrun[0], 0, 2 + 17, 6, 2, 0);
- putfloat(avenrun[1], 0, 2 + 23, 6, 2, 0);
- putfloat(avenrun[2], 0, 2 + 29, 6, 2, 0);
- mvaddstr(0, 2 + 53, tbuf);
+
+ while (*s1 == *s2) {
+ if (*s1 == '\0')
+ return (1);
+ s1++, s2++;
}
- (*curcmd->c_refresh)();
- if (curcmd->c_flags & CF_LOADAV)
- wrefresh(wload);
- wrefresh(wnd);
- move(CMDLINE, 0);
- refresh();
- ualarm(naptime * 1000000, 0);
+ return (*s1 == '\0');
}
-void
-load(void)
+/* calculate number of users on the system */
+int
+ucount(void)
{
+ int nusers = 0;
+ struct utmp utmp;
- (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0]));
- mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f",
- avenrun[0], avenrun[1], avenrun[2]);
- clrtoeol();
+ if (ut < 0)
+ return (0);
+ lseek(ut, (off_t)0, SEEK_SET);
+ while (read(ut, &utmp, sizeof(utmp)))
+ if (utmp.ut_name[0] != '\0')
+ nusers++;
+
+ return (nusers);
}
-volatile sig_atomic_t gotdie;
-volatile sig_atomic_t gotdisplay;
-volatile sig_atomic_t gotwinch;
-volatile sig_atomic_t gottstp;
+/* main program functions */
-/*ARGSUSED*/
void
-sigdie(int signo)
+usage()
{
- gotdie = 1;
+ extern char *__progname;
+ fprintf(stderr, "usage: %s [-abhir] [-c cache] [-d cnt]", __progname);
+ fprintf(stderr, " [-o field] [-s time] [-w width] [view] [num]\n");
+ exit(1);
}
-/*ARGSUSED*/
+
void
-sigtstp(int signo)
+add_view_tb(field_view *v)
{
- gottstp = 1;
+ if (curr_view == v)
+ tbprintf("[%s] ", v->name);
+ else
+ tbprintf("%s ", v->name);
}
void
-die(void)
+show_help(void)
{
- if (wnd) {
- move(CMDLINE, 0);
- clrtoeol();
- refresh();
- endwin();
+ int line = 0;
+
+ if (rawmode)
+ return;
+
+ tb_start();
+ foreach_view(add_view_tb);
+ tb_end();
+ message_set(tmp_buf);
+
+#if 0
+ erase();
+ mvprintw(line, 2, "Systat Help");
+ line += 2;
+ mvprintw(line, 5, " h - Help (this page)");
+ mvprintw(line++, 40, " l - set number of Lines");
+ mvprintw(line, 5, " p - Pause display");
+ mvprintw(line++, 40, " s - Set update interval");
+ mvprintw(line, 5, " v - next View");
+ mvprintw(line++, 40, " q - Quit");
+ line++;
+ mvprintw(line++, 5, "0-7 - select view directly");
+ mvprintw(line++, 5, "SPC - update immediately");
+ mvprintw(line++, 5, "^L - refresh display");
+ line++;
+ mvprintw(line++, 5, "cursor keys - scroll display");
+ line++;
+ mvprintw(line++, 3, "Netstat specific keys::");
+ mvprintw(line, 5, " t - toggle TCP display");
+ mvprintw(line++, 40, " u - toggle UDP display");
+ mvprintw(line++, 5, " n - toggle Name resolution");
+ line++;
+ mvprintw(line++, 3, "Ifstat specific keys::");
+ mvprintw(line, 5, " r - initialize RUN mode");
+ mvprintw(line++, 40, " b - set BOOT mode");
+ mvprintw(line, 5, " t - set TIME mode (default)");
+ line++;
+ line++;
+ mvprintw(line++, 3, "VMstat specific keys::");
+ mvprintw(line, 5, " r - initialize RUN mode");
+ mvprintw(line++, 40, " b - set BOOT mode");
+ mvprintw(line, 5, " t - set TIME mode (default)");
+ mvprintw(line++, 40, " z - zero in RUN mode");
+ line++;
+ mvprintw(line++, 6, "press any key to continue ...");
+
+ while (getch() == ERR) {
+ if (gotsig_close)
+ break;
}
- exit(0);
+#endif
}
-/*ARGSUSED*/
void
-sigwinch(int signo)
+cmd_compat(void)
{
- gotwinch = 1;
+ char *s;
+
+ if (strcasecmp(cmdbuf, "help") == 0) {
+ show_help();
+ need_update = 1;
+ return;
+ }
+ if (strcasecmp(cmdbuf, "quit") == 0) {
+ gotsig_close = 1;
+ return;
+ }
+
+ for (s = cmdbuf; *s && strchr("0123456789+-.eE", *s) != NULL; s++)
+ ;
+ if (*s) {
+ if (set_view(cmdbuf))
+ error("Invalid/ambigious view: %s", cmdbuf);
+ } else
+ cmd_delay();
}
void
-error(const char *fmt, ...)
+cmd_delay(void)
{
- va_list ap;
- char buf[255];
- int oy, ox;
-
- va_start(ap, fmt);
- if (wnd) {
- getyx(stdscr, oy, ox);
- (void) vsnprintf(buf, sizeof buf, fmt, ap);
- clrtoeol();
- standout();
- mvaddstr(CMDLINE, 0, buf);
- standend();
- move(oy, ox);
- refresh();
- } else {
- (void) vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
+ double del;
+ del = atof(cmdbuf);
+ error("delay: %g", del);
+ if (del > 0) {
+ udelay = (useconds_t)(del * 1000000);
+ gotsig_alarm = 1;
}
- va_end(ap);
}
void
-nlisterr(struct nlist namelist[])
+cmd_count(void)
{
- int i, n;
+ int ms;
+ ms = atoi(cmdbuf);
- n = 0;
- clear();
- mvprintw(2, 10, "systat: nlist: can't find following symbols:");
- for (i = 0;
- namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
- if (namelist[i].n_value == 0)
- mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
- move(CMDLINE, 0);
- clrtoeol();
- refresh();
- endwin();
- exit(1);
+ if (ms <= 0 || ms > lines - HEADER_LINES)
+ maxprint = lines - HEADER_LINES;
+ else
+ maxprint = ms;
}
-/* calculate number of users on the system */
+
int
-ucount(void)
+keyboard_callback(int ch)
{
- int nusers = 0;
- struct utmp utmp;
+ switch (ch) {
+ case '?':
+ /* FALLTHROUGH */
+ case 'h':
+ show_help();
+ need_update = 1;
+ break;
+ case 'l':
+ command_set(&cm_count, NULL);
+ break;
+ case 's':
+ command_set(&cm_delay, NULL);
+ break;
+ case ':':
+ command_set(&cm_compat, NULL);
+ break;
+ default:
+ return 0;
+ };
+
+ return 1;
+}
- if (ut < 0)
- return (0);
- lseek(ut, (off_t)0, SEEK_SET);
- while (read(ut, &utmp, sizeof(utmp)))
- if (utmp.ut_name[0] != '\0')
- nusers++;
+void
+initialize(void)
+{
+ engine_initialize();
+
+ initvmstat();
+ initpigs();
+ initifstat();
+ initiostat();
+ initsensors();
+ initmembufs();
+ initnetstat();
+ initswap();
+ initpftop();
+ initpf();
+}
- return (nusers);
+void
+gethz(void)
+{
+ struct clockinfo cinf;
+ size_t size = sizeof(cinf);
+ int mib[2];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CLOCKRATE;
+ if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
+ return;
+ stathz = cinf.stathz;
+ hz = cinf.hz;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char errbuf[_POSIX2_LINE_MAX];
+ extern char *optarg;
+ extern int optind;
+ double delay = 5;
+
+ char *viewstr = NULL;
+
+ gid_t gid;
+ int countmax = 0;
+ int maxlines = 0;
+
+ int ch;
+
+ ut = open(_PATH_UTMP, O_RDONLY);
+ if (ut < 0) {
+ warn("No utmp");
+ }
+
+ kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
+ if (kd == NULL)
+ warnx("kvm_openfiles: %s", errbuf);
+
+ gid = getgid();
+ if (setresgid(gid, gid, gid) == -1)
+ err(1, "setresgid");
+
+ while ((ch = getopt(argc, argv, "abd:hins:S:w:")) != -1) {
+ switch (ch) {
+ case 'a':
+ maxlines = -1;
+ break;
+ case 'b':
+ rawmode = 1;
+ interactive = 0;
+ break;
+ case 'd':
+ countmax = atoi(optarg);
+ if (countmax < 0)
+ countmax = 0;
+ break;
+ case 'i':
+ interactive = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 's':
+ delay = atof(optarg);
+ if (delay < 0)
+ delay = 5;
+ break;
+ case 'S':
+ dispstart = atoi(optarg);
+ if (dispstart < 0)
+ dispstart = 0;
+ break;
+ case 'w':
+ rawwidth = atoi(optarg);
+ if (rawwidth < 1)
+ rawwidth = DEFAULT_WIDTH;
+ if (rawwidth >= MAX_LINE_BUF)
+ rawwidth = MAX_LINE_BUF - 1;
+ break;
+ case 'h':
+ /* FALLTHROUGH */
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 1) {
+ double del = atof(argv[0]);
+ if (del == 0)
+ viewstr = argv[0];
+ else
+ delay = del;
+ } else if (argc == 2) {
+ viewstr = argv[0];
+ delay = atof(argv[1]);
+ }
+
+ udelay = (useconds_t)(delay * 1000000.0);
+ if (udelay < 1)
+ udelay = 1;
+
+ gethostname(hostname, sizeof (hostname));
+ gethz();
+
+ initialize();
+
+ set_order(NULL);
+ if (viewstr && set_view(viewstr)) {
+ fprintf(stderr, "Unknown/ambigious view name: %s\n", viewstr);
+ return 1;
+ }
+
+ if (!isatty(STDOUT_FILENO)) {
+ rawmode = 1;
+ interactive = 0;
+ }
+
+ setup_term(maxlines);
+
+ if (rawmode && countmax == 0)
+ countmax = 1;
+
+ gotsig_alarm = 1;
+
+ engine_loop(countmax);
+
+ return 0;
}
diff --git a/usr.bin/systat/mbufs.c b/usr.bin/systat/mbufs.c
index 357dc9126bf..b947c97489d 100644
--- a/usr.bin/systat/mbufs.c
+++ b/usr.bin/systat/mbufs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mbufs.c,v 1.17 2007/02/25 18:21:24 deraadt Exp $ */
+/* $OpenBSD: mbufs.c,v 1.18 2008/06/12 22:26:01 canacar Exp $ */
/* $NetBSD: mbufs.c,v 1.2 1995/01/20 08:52:02 jtc Exp $ */
/*-
@@ -30,13 +30,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)mbufs.c 8.1 (Berkeley) 6/6/93";
-#endif
-static char rcsid[] = "$OpenBSD: mbufs.c,v 1.17 2007/02/25 18:21:24 deraadt Exp $";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/mbuf.h>
@@ -47,7 +40,12 @@ static char rcsid[] = "$OpenBSD: mbufs.c,v 1.17 2007/02/25 18:21:24 deraadt Exp
#include <err.h>
#include <paths.h>
#include "systat.h"
-#include "extern.h"
+
+
+void print_mb(void);
+int read_mb(void);
+int select_mb(void);
+static void showmbuf(int);
static struct mbstat mb;
@@ -68,85 +66,128 @@ char *mtnames[] = {
"ifaddrs",
};
+#define NUM_TYPES (sizeof(mb.m_mtypes) / sizeof(mb.m_mtypes[0]))
#define NNAMES (sizeof (mtnames) / sizeof (mtnames[0]))
-WINDOW *
-openmbufs(void)
-{
- return (subwin(stdscr, LINES-1-2, 0, 2, 0));
-}
+int mb_index[NUM_TYPES];
+int mbuf_cnt = 0;
-void
-closembufs(WINDOW *w)
+
+field_def fields_mb[] = {
+ {"TYPE", 6, 16, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"VALUE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"", 40, 80, 1, FLD_ALIGN_BAR, -1, 0, 0, 60},
+};
+
+#define FIELD_ADDR(x) (&fields_mb[x])
+
+#define FLD_MB_NAME FIELD_ADDR(0)
+#define FLD_MB_VALUE FIELD_ADDR(1)
+#define FLD_MB_BAR FIELD_ADDR(2)
+
+/* Define views */
+field_def *view_mb_0[] = {
+ FLD_MB_NAME, FLD_MB_VALUE, FLD_MB_BAR, NULL
+};
+
+
+/* Define view managers */
+struct view_manager mbuf_mgr = {
+ "Mbufs", select_mb, read_mb, NULL, print_header,
+ print_mb, keyboard_callback, NULL, NULL
+};
+
+field_view views_mb[] = {
+ {view_mb_0, "mbufs", '4', &mbuf_mgr},
+ {NULL, NULL, 0, NULL}
+};
+
+
+int
+select_mb(void)
{
- if (w == NULL)
- return;
- wclear(w);
- wrefresh(w);
- delwin(w);
+ int i, w = 50;
+
+ read_mb();
+ for (i = 0; i < NUM_TYPES; i++)
+ if (w < (5 * mb.m_mtypes[i] / 4))
+ w = 5 * mb.m_mtypes[i] / 4;
+
+ w -= w % 10;
+ FLD_MB_BAR->arg = w;
+
+ return (0);
}
-void
-labelmbufs(void)
+int
+read_mb(void)
{
- wmove(wnd, 0, 0);
- wclrtoeol(wnd);
- mvwaddstr(wnd, 0, 10,
- "/0 /5 /10 /15 /20 /25 /30 /35 /40 /45 /50 /55 /60");
+ int mib[2], i;
+ size_t size = sizeof (mb);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_MBSTAT;
+
+ if (sysctl(mib, 2, &mb, &size, NULL, 0) < 0) {
+ error("sysctl(KERN_MBSTAT) failed");
+ return 1;
+ }
+
+ mbuf_cnt = 0;
+ memset(mb_index, 0, sizeof(mb_index));
+
+ for (i = 0; i < NUM_TYPES; i++) {
+ if (mb.m_mtypes[i])
+ mb_index[mbuf_cnt++] = i;
+ }
+
+ num_disp = mbuf_cnt;
+
+ return 0;
}
+
void
-showmbufs(void)
+print_mb(void)
{
- int i, j, max, ind;
- char buf[13];
-
- for (j = 0; j < wnd->_maxy; j++) {
- max = 0, ind = -1;
- for (i = 0; i < wnd->_maxy; i++)
- if (mb.m_mtypes[i] > max) {
- max = mb.m_mtypes[i];
- ind = i;
- }
- if (max == 0)
+ int n, count = 0;
+
+ for (n = dispstart; n < num_disp; n++) {
+ showmbuf(n);
+ count++;
+ if (maxprint > 0 && count >= maxprint)
break;
- if (j > NNAMES)
- mvwprintw(wnd, 1+j, 0, "%10d", ind);
- else
- mvwprintw(wnd, 1+j, 0, "%-10.10s", mtnames[ind]);
- wmove(wnd, 1 + j, 10);
- if (max > 60) {
- snprintf(buf, sizeof buf, " %d", max);
- max = 60;
- while (max--)
- waddch(wnd, 'X');
- waddstr(wnd, buf);
- } else {
- while (max--)
- waddch(wnd, 'X');
- wclrtoeol(wnd);
- }
- mb.m_mtypes[ind] = 0;
}
- wmove(wnd, 1+j, 0);
- wclrtobot(wnd);
}
-
-void
-fetchmbufs(void)
+int
+initmembufs(void)
{
- int mib[2];
- size_t size = sizeof (mb);
+ field_view *v;
- mib[0] = CTL_KERN;
- mib[1] = KERN_MBSTAT;
- if (sysctl(mib, 2, &mb, &size, NULL, 0) < 0)
- err(1, "sysctl(KERN_MBSTAT) failed");
+ for (v = views_mb; v->name != NULL; v++)
+ add_view(v);
+
+ return(1);
}
-int
-initmbufs(void)
+
+static void
+showmbuf(int m)
{
- return (1);
+ int i;
+
+ i = mb_index[m];
+
+ if (i < NNAMES)
+ print_fld_str(FLD_MB_NAME, mtnames[i]);
+ else
+ print_fld_uint(FLD_MB_NAME, i);
+
+ print_fld_uint(FLD_MB_VALUE, mb.m_mtypes[i]);
+ print_fld_bar(FLD_MB_BAR, mb.m_mtypes[i]);
+
+ end_line();
}
+
+
diff --git a/usr.bin/systat/netcmds.c b/usr.bin/systat/netcmds.c
index 527b33f87e3..e69de29bb2d 100644
--- a/usr.bin/systat/netcmds.c
+++ b/usr.bin/systat/netcmds.c
@@ -1,360 +0,0 @@
-/* $OpenBSD: netcmds.c,v 1.19 2007/09/11 15:47:17 gilles Exp $ */
-/* $NetBSD: netcmds.c,v 1.4 1995/05/21 17:14:38 mycroft Exp $ */
-
-/*-
- * Copyright (c) 1980, 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)netcmds.c 8.1 (Berkeley) 6/6/93";
-#endif
-static char rcsid[] = "$OpenBSD: netcmds.c,v 1.19 2007/09/11 15:47:17 gilles Exp $";
-#endif /* not lint */
-
-/*
- * Common network command support routines.
- */
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/mbuf.h>
-#include <sys/protosw.h>
-
-#include <net/route.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_pcb.h>
-
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "systat.h"
-#include "extern.h"
-
-#define streq(a,b) (strcmp(a,b)==0)
-
-static struct hitem {
- struct sockaddr_storage addr;
- int onoff;
-} *hosts;
-
-size_t nports, nhosts;
-int protos;
-
-static void changeitems(char *, int);
-static int selectproto(char *);
-static void showprotos(void);
-static int selectport(long, int);
-static void showports(void);
-static int addrcmp(struct sockaddr *, struct sockaddr *);
-static int selecthost(struct sockaddr *, int);
-static void showhosts(void);
-
-int
-netcmd(char *cmd, char *args)
-{
-
- if (prefix(cmd, "tcp") || prefix(cmd, "udp")) {
- selectproto(cmd);
- return (1);
- }
- if (prefix(cmd, "ignore") || prefix(cmd, "display")) {
- changeitems(args, prefix(cmd, "display"));
- return (1);
- }
- if (prefix(cmd, "reset")) {
- selectproto(0);
- selecthost(0, 0);
- selectport(htons(-1), 0);
- return (1);
- }
- if (prefix(cmd, "show")) {
- move(CMDLINE, 0);
- clrtoeol();
- if (*args == '\0') {
- showprotos();
- showhosts();
- showports();
- return (1);
- }
- if (prefix(args, "protos"))
- showprotos();
- else if (prefix(args, "hosts"))
- showhosts();
- else if (prefix(args, "ports"))
- showports();
- else
- addstr("show what?");
- return (1);
- }
- return (0);
-}
-
-
-static void
-changeitems(char *args, int onoff)
-{
- char *cp;
- struct servent *sp;
- struct addrinfo hints, *res0, *res;
-
- args[strcspn(args, "\n")] = '\0';
-
- for (;;args = cp) {
- for (cp = args; isspace(*cp); cp++)
- ;
- args = cp;
- for (; *cp && !isspace(*cp); cp++)
- ;
- if (*cp)
- *cp++ = '\0';
- if (cp - args == 0)
- break;
- sp = getservbyname(args,
- protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
- if (sp) {
- selectport(sp->s_port, onoff);
- continue;
- }
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM;
- if (getaddrinfo(args, "0", &hints, &res0) != 0) {
- error("%s: unknown host or port", args);
- continue;
- }
- for (res = res0; res; res = res->ai_next)
- selecthost(res->ai_addr, onoff);
- freeaddrinfo(res0);
- }
-}
-
-static int
-selectproto(char *proto)
-{
- int new = protos;
-
- if (proto == 0 || streq(proto, "all"))
- new = TCP|UDP;
- else if (streq(proto, "tcp"))
- new = TCP;
- else if (streq(proto, "udp"))
- new = UDP;
- return (protos = new);
-}
-
-static void
-showprotos(void)
-{
-
- if ((protos&TCP) == 0)
- addch('!');
- addstr("tcp ");
- if ((protos&UDP) == 0)
- addch('!');
- addstr("udp ");
-}
-
-static struct pitem {
- long port;
- int onoff;
-} *ports;
-
-static int
-selectport(long port, int onoff)
-{
- struct pitem *p;
-
- if (ntohs(port) == -1) {
- if (ports == 0)
- return (0);
- free(ports);
- ports = NULL;
- nports = 0;
- return (1);
- }
- for (p = ports; p < ports+nports; p++)
- if (p->port == port) {
- p->onoff = onoff;
- return (0);
- }
- if (nports + 1 > SIZE_MAX / sizeof(*p) ||
- (p = realloc(ports, (nports + 1) * sizeof(*p))) == NULL) {
- error("selectport: %s", strerror(ENOMEM));
- die();
- }
- ports = p;
-
- p = &ports[nports++];
- p->port = port;
- p->onoff = onoff;
- return (1);
-}
-
-int
-checkport(struct inpcb *inp)
-{
- struct pitem *p;
-
- if (ports)
- for (p = ports; p < ports+nports; p++)
- if (p->port == inp->inp_lport || p->port == inp->inp_fport)
- return (p->onoff);
- return (1);
-}
-
-static void
-showports(void)
-{
- struct pitem *p;
- struct servent *sp;
-
- for (p = ports; p < ports+nports; p++) {
- sp = getservbyport(p->port,
- protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
- if (!p->onoff)
- addch('!');
- if (sp)
- printw("%s ", sp->s_name);
- else
- printw("%d ", ntohs(p->port));
- }
-}
-
-static int
-addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
-{
- if (sa1->sa_family != sa2->sa_family)
- return 0;
- if (sa1->sa_len != sa2->sa_len)
- return 0;
- switch (sa1->sa_family) {
- case AF_INET:
- if (((struct sockaddr_in *)sa1)->sin_addr.s_addr ==
- ((struct sockaddr_in *)sa2)->sin_addr.s_addr)
- return 1;
- break;
- case AF_INET6:
- if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)sa1)->sin6_addr,
- &((struct sockaddr_in6 *)sa2)->sin6_addr))
- return 1;
- break;
- default:
- if (memcmp(sa1, sa2, sa1->sa_len) == 0)
- return 1;
- break;
- }
- return 0;
-}
-
-static int
-selecthost(struct sockaddr *sa, int onoff)
-{
- struct hitem *p;
-
- if (sa == 0) {
- if (hosts == 0)
- return (0);
- free(hosts);
- hosts = NULL;
- nhosts = 0;
- return (1);
- }
- for (p = hosts; p < hosts+nhosts; p++)
- if (addrcmp((struct sockaddr *)&p->addr, sa)) {
- p->onoff = onoff;
- return (0);
- }
- if (sa->sa_len > sizeof(struct sockaddr_storage))
- return (-1); /*XXX*/
- if (nhosts + 1 > SIZE_MAX / sizeof(*p) ||
- (p = realloc(hosts, (nhosts + 1) * sizeof(*p))) == NULL) {
- error("selecthost: %s", strerror(ENOMEM));
- die();
- }
- hosts = p;
-
- p = &hosts[nhosts++];
- memcpy(&p->addr, sa, sa->sa_len);
- p->onoff = onoff;
- return (1);
-}
-
-int
-checkhost(struct inpcb *inp)
-{
- struct hitem *p;
-
- if (hosts)
- for (p = hosts; p < hosts+nhosts; p++) {
- if (((struct sockaddr *)&p->addr)->sa_family == AF_INET &&
- !(inp->inp_flags & INP_IPV6)) {
- struct sockaddr_in *sin;
- sin = (struct sockaddr_in *)&p->addr;
- if (sin->sin_addr.s_addr == inp->inp_laddr.s_addr ||
- sin->sin_addr.s_addr == inp->inp_faddr.s_addr)
- return (p->onoff);
- }
- if (((struct sockaddr *)&p->addr)->sa_family == AF_INET6 &&
- (inp->inp_flags & INP_IPV6)) {
- struct sockaddr_in6 *sin6;
- sin6 = (struct sockaddr_in6 *)&p->addr;
- if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_laddr6) ||
- IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_faddr6))
- return (p->onoff);
- }
- }
- return (1);
-}
-
-static void
-showhosts(void)
-{
- struct hitem *p;
- char hbuf[NI_MAXHOST];
- struct sockaddr *sa;
- int flags;
-
- flags = nflag ? NI_NUMERICHOST : 0;
- for (p = hosts; p < hosts+nhosts; p++) {
- sa = (struct sockaddr *)&p->addr;
- if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
- flags) != 0)
- strlcpy(hbuf, "(invalid)", sizeof hbuf);
- if (!p->onoff)
- addch('!');
- printw("%s ", hbuf);
- }
-}
diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c
index b4a29e89f12..62052910532 100644
--- a/usr.bin/systat/netstat.c
+++ b/usr.bin/systat/netstat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: netstat.c,v 1.30 2007/02/25 18:21:24 deraadt Exp $ */
+/* $OpenBSD: netstat.c,v 1.31 2008/06/12 22:26:01 canacar Exp $ */
/* $NetBSD: netstat.c,v 1.3 1995/06/18 23:53:07 cgd Exp $ */
/*-
@@ -30,13 +30,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)netstat.c 8.1 (Berkeley) 6/6/93";
-#endif
-static char rcsid[] = "$OpenBSD: netstat.c,v 1.30 2007/02/25 18:21:24 deraadt Exp $";
-#endif /* not lint */
-
/*
* netstat
*/
@@ -73,139 +66,214 @@ static char rcsid[] = "$OpenBSD: netstat.c,v 1.30 2007/02/25 18:21:24 deraadt Ex
#include <nlist.h>
#include <paths.h>
#include "systat.h"
-#include "extern.h"
+#include "engine.h"
+
+struct netinfo {
+ union {
+ struct in_addr nif_laddr; /* local address */
+ struct in6_addr nif_laddr6; /* local address */
+ } l;
+ union {
+ struct in_addr nif_faddr; /* foreign address */
+ struct in6_addr nif_faddr6; /* foreign address */
+ } f;
+ char *nif_proto; /* protocol */
+ long nif_rcvcc; /* rcv buffer character count */
+ long nif_sndcc; /* snd buffer character count */
+ short nif_lport; /* local port */
+ short nif_fport; /* foreign port */
+ short nif_state; /* tcp state */
+ short nif_family;
+};
+
+#define nif_laddr l.nif_laddr
+#define nif_laddr6 l.nif_laddr6
+#define nif_faddr f.nif_faddr
+#define nif_faddr6 f.nif_faddr6
static void enter(struct inpcb *, struct socket *, int, char *);
static const char *inetname(struct in_addr);
-static void inetprint(struct in_addr *, int, char *);
+static void inetprint(struct in_addr *, int, char *, field_def *);
static const char *inet6name(struct in6_addr *);
-static void inet6print(struct in6_addr *, int, char *);
+static void inet6print(struct in6_addr *, int, char *, field_def *);
+static void shownetstat(struct netinfo *p);
+
+void print_ns(void);
+int read_ns(void);
+int select_ns(void);
+int ns_keyboard_callback(int);
#define streq(a,b) (strcmp(a,b)==0)
-#define YMAX(w) ((w)->_maxy-1)
-WINDOW *
-opennetstat(void)
-{
- sethostent(1);
- setnetent(1);
- return (subwin(stdscr, LINES-1-2, 0, 2, 0));
-}
+static int aflag = 0;
-struct netinfo {
- struct netinfo *nif_forw, *nif_prev;
- int nif_family;
- short nif_line; /* line on screen */
- short nif_seen; /* 0 when not present in list */
- short nif_flags;
-#define NIF_LACHG 0x1 /* local address changed */
-#define NIF_FACHG 0x2 /* foreign address changed */
- short nif_state; /* tcp state */
- char *nif_proto; /* protocol */
- struct in_addr nif_laddr; /* local address */
- struct in6_addr nif_laddr6; /* local address */
- long nif_lport; /* local port */
- struct in_addr nif_faddr; /* foreign address */
- struct in6_addr nif_faddr6; /* foreign address */
- long nif_fport; /* foreign port */
- long nif_rcvcc; /* rcv buffer character count */
- long nif_sndcc; /* snd buffer character count */
+static struct nlist namelist[] = {
+#define X_TCBTABLE 0 /* no sysctl */
+ { "_tcbtable" },
+#define X_UDBTABLE 1 /* no sysctl */
+ { "_udbtable" },
+ { "" },
};
+#define ADD_ALLOC 1000
-static struct {
- struct netinfo *nif_forw, *nif_prev;
-} netcb;
-static int aflag = 0;
-static int lastrow = 1;
+int protos;
-void
-closenetstat(WINDOW *w)
+struct netinfo *netinfos = NULL;
+size_t num_ns = 0;
+static size_t num_alloc = 0;
+
+
+field_def fields_ns[] = {
+ {"LOCAL ADDRESS", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"FOREIGN ADDRESS", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"PROTO", 4, 9, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"RECV-Q", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"SEND-Q", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"STATE", 5, 11, 6, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+};
+
+#define FIELD_ADDR(x) (&fields_ns[x])
+
+#define FLD_NS_LOCAL FIELD_ADDR(0)
+#define FLD_NS_FOREIGN FIELD_ADDR(1)
+#define FLD_NS_PROTO FIELD_ADDR(2)
+#define FLD_NS_RECV_Q FIELD_ADDR(3)
+#define FLD_NS_SEND_Q FIELD_ADDR(4)
+#define FLD_NS_STATE FIELD_ADDR(5)
+
+/* Define views */
+field_def *view_ns_0[] = {
+ FLD_NS_LOCAL, FLD_NS_FOREIGN, FLD_NS_PROTO,
+ FLD_NS_RECV_Q, FLD_NS_SEND_Q, FLD_NS_STATE, NULL
+};
+
+/* Define view managers */
+struct view_manager netstat_mgr = {
+ "Netstat", select_ns, read_ns, NULL, print_header,
+ print_ns, ns_keyboard_callback, NULL, NULL
+};
+
+field_view views_ns[] = {
+ {view_ns_0, "netstat", '0', &netstat_mgr},
+ {NULL, NULL, 0, NULL}
+};
+
+
+
+
+struct netinfo *
+next_ns(void)
+{
+ if (num_alloc <= num_ns) {
+ struct netinfo *ni;
+ size_t a = num_alloc + ADD_ALLOC;
+ if (a < num_alloc)
+ return NULL;
+ ni = realloc(netinfos, a * sizeof(*ni));
+ if (ni == NULL)
+ return NULL;
+ netinfos = ni;
+ num_alloc = a;
+ }
+
+ return &netinfos[num_ns++];
+}
+
+static void
+enter(struct inpcb *inp, struct socket *so, int state, char *proto)
{
struct netinfo *p;
- endhostent();
- endnetent();
- p = (struct netinfo *)netcb.nif_forw;
- while (p != (struct netinfo *)&netcb) {
- if (p->nif_line != -1)
- lastrow--;
- p->nif_line = -1;
- p = p->nif_forw;
+ p = next_ns();
+ if (p == NULL) {
+ error("Out of Memory!");
+ return;
}
- if (w != NULL) {
- wclear(w);
- wrefresh(w);
- delwin(w);
+
+ p->nif_lport = inp->inp_lport;
+ p->nif_fport = inp->inp_fport;
+ p->nif_proto = proto;
+
+ if (inp->inp_flags & INP_IPV6) {
+ p->nif_laddr6 = inp->inp_laddr6;
+ p->nif_faddr6 = inp->inp_faddr6;
+ p->nif_family = AF_INET6;
+ } else {
+ p->nif_laddr = inp->inp_laddr;
+ p->nif_faddr = inp->inp_faddr;
+ p->nif_family = AF_INET;
}
+
+ p->nif_rcvcc = so->so_rcv.sb_cc;
+ p->nif_sndcc = so->so_snd.sb_cc;
+ p->nif_state = state;
}
-static struct nlist namelist[] = {
-#define X_TCBTABLE 0 /* no sysctl */
- { "_tcbtable" },
-#define X_UDBTABLE 1 /* no sysctl */
- { "_udbtable" },
- { "" },
-};
+
+/* netstat callback functions */
int
-initnetstat(void)
+select_ns(void)
{
- int ret;
+ static int init = 0;
+ if (kd == NULL) {
+ num_disp = 1;
+ return (0);
+ }
- if ((ret = kvm_nlist(kd, namelist)) == -1)
- errx(1, "%s", kvm_geterr(kd));
- else if (ret)
- nlisterr(namelist);
- if (namelist[X_TCBTABLE].n_value == 0) {
- error("No symbols in namelist");
- return(0);
+ if (!init) {
+ sethostent(1);
+ setnetent(1);
+ init = 1;
}
- netcb.nif_forw = netcb.nif_prev = (struct netinfo *)&netcb;
- protos = TCP|UDP;
- return(1);
+
+ num_disp = num_ns;
+ return (0);
}
-void
-fetchnetstat(void)
+int
+read_ns(void)
{
struct inpcbtable pcbtable;
struct inpcb *head, *prev, *next;
- struct netinfo *p;
struct inpcb inpcb;
struct socket sockb;
struct tcpcb tcpcb;
void *off;
int istcp;
+ if (kd == NULL) {
+ return (0);
+ }
+
+ num_ns = 0;
+
if (namelist[X_TCBTABLE].n_value == 0)
- return;
- for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw)
- p->nif_seen = 0;
- if (protos&TCP) {
+ return 0;
+
+ if (protos & TCP) {
off = NPTR(X_TCBTABLE);
istcp = 1;
- } else if (protos&UDP) {
+ } else if (protos & UDP) {
off = NPTR(X_UDBTABLE);
istcp = 0;
} else {
error("No protocols to display");
- return;
+ return 0;
}
+
again:
KREAD(off, &pcbtable, sizeof (struct inpcbtable));
+
prev = head = (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue;
next = CIRCLEQ_FIRST(&pcbtable.inpt_queue);
+
while (next != head) {
KREAD(next, &inpcb, sizeof (inpcb));
if (CIRCLEQ_PREV(&inpcb, inp_queue) != prev) {
- printf("prev = %p, head = %p, next = %p, inpcb...prev = %p\n",
- prev, head, next, CIRCLEQ_PREV(&inpcb, inp_queue));
- p = netcb.nif_forw;
- for (; p != (struct netinfo *)&netcb; p = p->nif_forw)
- p->nif_seen = 1;
error("Kernel state in transition");
- return;
+ return 0;
}
prev = next;
next = CIRCLEQ_NEXT(&inpcb, inp_queue);
@@ -218,10 +286,6 @@ again:
IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6))
continue;
}
- if (nhosts && !checkhost(&inpcb))
- continue;
- if (nports && !checkport(&inpcb))
- continue;
KREAD(inpcb.inp_socket, &sockb, sizeof (sockb));
if (istcp) {
KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
@@ -229,198 +293,97 @@ again:
} else
enter(&inpcb, &sockb, 0, "udp");
}
- if (istcp && (protos&UDP)) {
+ if (istcp && (protos & UDP)) {
istcp = 0;
off = NPTR(X_UDBTABLE);
goto again;
}
+
+ num_disp = num_ns;
+ return 0;
}
-static void
-enter(struct inpcb *inp, struct socket *so, int state, char *proto)
+void
+print_ns(void)
{
- struct netinfo *p;
+ int n, count = 0;
- /*
- * Only take exact matches, any sockets with
- * previously unbound addresses will be deleted
- * below in the display routine because they
- * will appear as ``not seen'' in the kernel
- * data structures.
- */
- for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {
- if (p->nif_family == AF_INET && (inp->inp_flags & INP_IPV6))
- continue;
- if (p->nif_family == AF_INET6 && !(inp->inp_flags & INP_IPV6))
- continue;
- if (!streq(proto, p->nif_proto))
- continue;
- if (p->nif_family == AF_INET) {
- if (p->nif_lport != inp->inp_lport ||
- p->nif_laddr.s_addr != inp->inp_laddr.s_addr)
- continue;
- if (p->nif_faddr.s_addr == inp->inp_faddr.s_addr &&
- p->nif_fport == inp->inp_fport)
- break;
-
- } else if (p->nif_family == AF_INET6) {
- if (p->nif_lport != inp->inp_lport ||
- !IN6_ARE_ADDR_EQUAL(&p->nif_laddr6, &inp->inp_laddr6))
- continue;
- if (IN6_ARE_ADDR_EQUAL(&p->nif_faddr6, &inp->inp_faddr6) &&
- p->nif_fport == inp->inp_fport)
- break;
- } else
- continue;
+ if (kd == NULL) {
+ print_fld_str(FLD_NS_LOCAL, "Failed to initialize KVM!");
+ print_fld_str(FLD_NS_FOREIGN, "Failed to initialize KVM!");
+ end_line();
+ return;
}
- if (p == (struct netinfo *)&netcb) {
- if ((p = malloc(sizeof(*p))) == NULL) {
- error("Out of memory");
- return;
- }
- p->nif_prev = (struct netinfo *)&netcb;
- p->nif_forw = netcb.nif_forw;
- netcb.nif_forw->nif_prev = p;
- netcb.nif_forw = p;
- p->nif_line = -1;
- p->nif_lport = inp->inp_lport;
- p->nif_fport = inp->inp_fport;
- p->nif_proto = proto;
- p->nif_flags = NIF_LACHG|NIF_FACHG;
- if (inp->inp_flags & INP_IPV6) {
- p->nif_laddr6 = inp->inp_laddr6;
- p->nif_faddr6 = inp->inp_faddr6;
- p->nif_family = AF_INET6;
- } else {
- p->nif_laddr = inp->inp_laddr;
- p->nif_faddr = inp->inp_faddr;
- p->nif_family = AF_INET;
- }
+
+ for (n = dispstart; n < num_disp; n++) {
+ shownetstat(netinfos + n);
+ count++;
+ if (maxprint > 0 && count >= maxprint)
+ break;
}
- p->nif_rcvcc = so->so_rcv.sb_cc;
- p->nif_sndcc = so->so_snd.sb_cc;
- p->nif_state = state;
- p->nif_seen = 1;
}
-/* column locations */
-#define LADDR 0
-#define FADDR LADDR+23
-#define PROTO FADDR+23
-#define RCVCC PROTO+6
-#define SNDCC RCVCC+7
-#define STATE SNDCC+7
-
-void
-labelnetstat(void)
+int
+initnetstat(void)
{
- if (namelist[X_TCBTABLE].n_type == 0)
- return;
- wmove(wnd, 0, 0);
- wclrtobot(wnd);
- mvwaddstr(wnd, 0, LADDR, "Local Address");
- mvwaddstr(wnd, 0, FADDR, "Foreign Address");
- mvwaddstr(wnd, 0, PROTO, "Proto");
- mvwaddstr(wnd, 0, RCVCC, "Recv-Q");
- mvwaddstr(wnd, 0, SNDCC, "Send-Q");
- mvwaddstr(wnd, 0, STATE, "(state)");
-}
+ field_view *v;
+ int ret;
-void
-shownetstat(void)
-{
- struct netinfo *p, *q;
-
- /*
- * First, delete any connections that have gone
- * away and adjust the position of connections
- * below to reflect the deleted line.
- */
- p = netcb.nif_forw;
- while (p != (struct netinfo *)&netcb) {
- if (p->nif_line == -1 || p->nif_seen) {
- p = p->nif_forw;
- continue;
+ if (kd) {
+ if ((ret = kvm_nlist(kd, namelist)) == -1)
+ errx(1, "%s", kvm_geterr(kd));
+ else if (ret)
+ nlisterr(namelist);
+
+ if (namelist[X_TCBTABLE].n_value == 0) {
+ error("No symbols in namelist");
+ return(0);
}
- wmove(wnd, p->nif_line, 0);
- wdeleteln(wnd);
- q = netcb.nif_forw;
- for (; q != (struct netinfo *)&netcb; q = q->nif_forw)
- if (q != p && q->nif_line > p->nif_line) {
- q->nif_line--;
- /* this shouldn't be necessary */
- q->nif_flags |= NIF_LACHG|NIF_FACHG;
- }
- lastrow--;
- q = p->nif_forw;
- p->nif_prev->nif_forw = p->nif_forw;
- p->nif_forw->nif_prev = p->nif_prev;
- free(p);
- p = q;
}
- /*
- * Update existing connections and add new ones.
- */
- for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {
- if (p->nif_line == -1) {
- /*
- * Add a new entry if possible.
- */
- if (lastrow > YMAX(wnd))
- continue;
- p->nif_line = lastrow++;
- p->nif_flags |= NIF_LACHG|NIF_FACHG;
- }
- if (p->nif_flags & NIF_LACHG) {
- wmove(wnd, p->nif_line, LADDR);
- switch (p->nif_family) {
- case AF_INET:
- inetprint(&p->nif_laddr, p->nif_lport,
- p->nif_proto);
- break;
- case AF_INET6:
- inet6print(&p->nif_laddr6, p->nif_lport,
- p->nif_proto);
- break;
- }
- p->nif_flags &= ~NIF_LACHG;
- }
- if (p->nif_flags & NIF_FACHG) {
- wmove(wnd, p->nif_line, FADDR);
- switch (p->nif_family) {
- case AF_INET:
- inetprint(&p->nif_faddr, p->nif_fport,
- p->nif_proto);
- break;
- case AF_INET6:
- inet6print(&p->nif_faddr6, p->nif_fport,
- p->nif_proto);
- break;
- }
- p->nif_flags &= ~NIF_FACHG;
- }
- mvwaddstr(wnd, p->nif_line, PROTO, p->nif_proto);
- if (p->nif_family == AF_INET6)
- waddstr(wnd, "6");
- mvwprintw(wnd, p->nif_line, RCVCC, "%6d", p->nif_rcvcc);
- mvwprintw(wnd, p->nif_line, SNDCC, "%6d", p->nif_sndcc);
- if (streq(p->nif_proto, "tcp")) {
- if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES)
- mvwprintw(wnd, p->nif_line, STATE, "%d",
- p->nif_state);
- else
- mvwaddstr(wnd, p->nif_line, STATE,
- tcpstates[p->nif_state]);
- }
- wclrtoeol(wnd);
+ protos = TCP|UDP;
+
+ for (v = views_ns; v->name != NULL; v++)
+ add_view(v);
+
+ return(1);
+}
+
+static void
+shownetstat(struct netinfo *p)
+{
+ switch (p->nif_family) {
+ case AF_INET:
+ inetprint(&p->nif_laddr, p->nif_lport,
+ p->nif_proto, FLD_NS_LOCAL);
+ inetprint(&p->nif_faddr, p->nif_fport,
+ p->nif_proto, FLD_NS_FOREIGN);
+ break;
+ case AF_INET6:
+ inet6print(&p->nif_laddr6, p->nif_lport,
+ p->nif_proto, FLD_NS_LOCAL);
+ inet6print(&p->nif_faddr6, p->nif_fport,
+ p->nif_proto, FLD_NS_FOREIGN);
+ break;
}
- if (lastrow < YMAX(wnd)) {
- wmove(wnd, lastrow, 0);
- wclrtobot(wnd);
- wmove(wnd, YMAX(wnd), 0);
- wdeleteln(wnd); /* XXX */
+
+ tb_start();
+ tbprintf("%s", p->nif_proto);
+ if (p->nif_family == AF_INET6)
+ tbprintf("6");
+
+ print_fld_tb(FLD_NS_PROTO);
+
+ print_fld_size(FLD_NS_RECV_Q, p->nif_rcvcc);
+ print_fld_size(FLD_NS_SEND_Q, p->nif_sndcc);
+
+ if (streq(p->nif_proto, "tcp")) {
+ if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES)
+ print_fld_uint(FLD_NS_STATE, p->nif_state);
+ else
+ print_fld_str(FLD_NS_STATE, tcpstates[p->nif_state]);
}
+ end_line();
}
/*
@@ -428,92 +391,39 @@ shownetstat(void)
* If the nflag was specified, use numbers instead of names.
*/
static void
-inetprint(struct in_addr *in, int port, char *proto)
+inetprint(struct in_addr *in, int port, char *proto, field_def *fld)
{
struct servent *sp = 0;
- char line[80], *cp;
- snprintf(line, sizeof line, "%.*s.", 16, inetname(*in));
- cp = strchr(line, '\0');
+ tb_start();
+ tbprintf("%s", inetname(*in));
+
if (!nflag && port)
sp = getservbyport(port, proto);
if (sp || port == 0)
- snprintf(cp, sizeof line - strlen(cp), "%.8s",
- sp ? sp->s_name : "*");
+ tbprintf(":%s", sp ? sp->s_name : "*");
else
- snprintf(cp, sizeof line - strlen(cp), "%d",
- ntohs((u_short)port));
- /* pad to full column to clear any garbage */
- cp = strchr(line, '\0');
- while (cp - line < 22 && cp - line < sizeof line-1)
- *cp++ = ' ';
- *cp = '\0';
- waddstr(wnd, line);
+ tbprintf(":%d", ntohs((u_short)port));
+
+ print_fld_tb(fld);
}
static void
-inet6print(struct in6_addr *in6, int port, char *proto)
+inet6print(struct in6_addr *in6, int port, char *proto, field_def *fld)
{
struct servent *sp = 0;
- char line[80], *cp;
- snprintf(line, sizeof line, "%.*s.", 16, inet6name(in6));
- cp = strchr(line, '\0');
+ tb_start();
+
+ tbprintf("%s", inet6name(in6));
if (!nflag && port)
sp = getservbyport(port, proto);
if (sp || port == 0)
- snprintf(cp, sizeof line - strlen(cp), "%.8s",
- sp ? sp->s_name : "*");
+ tbprintf(":%s", sp ? sp->s_name : "*");
else
- snprintf(cp, sizeof line - strlen(cp), "%d",
- ntohs((u_short)port));
- /* pad to full column to clear any garbage */
- cp = strchr(line, '\0');
- while (cp - line < 22 && cp - line < sizeof line-1)
- *cp++ = ' ';
- *cp = '\0';
- waddstr(wnd, line);
-}
+ tbprintf(":%d", ntohs((u_short)port));
-/*
- * Construct an Internet address representation.
- * If the nflag has been supplied, give
- * numeric value, otherwise try for symbolic name.
- */
-static const char *
-inetname(struct in_addr in)
-{
- char *cp = 0;
- static char line[50];
- struct hostent *hp;
- struct netent *np;
-
- if (!nflag && in.s_addr != INADDR_ANY) {
- int net = inet_netof(in);
- int lna = inet_lnaof(in);
-
- if (lna == INADDR_ANY) {
- np = getnetbyaddr(net, AF_INET);
- if (np)
- cp = np->n_name;
- }
- if (cp == 0) {
- hp = gethostbyaddr(&in, sizeof (in), AF_INET);
- if (hp)
- cp = hp->h_name;
- }
- }
- if (in.s_addr == INADDR_ANY) {
- strlcpy(line, "*", sizeof line);
- } else if (cp) {
- strlcpy(line, cp, sizeof line);
- } else {
- in.s_addr = ntohl(in.s_addr);
-#define C(x) ((x) & 0xff)
- snprintf(line, sizeof line, "%u.%u.%u.%u", C(in.s_addr >> 24),
- C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
- }
- return (line);
+ print_fld_tb(fld);
}
static const char *
@@ -536,38 +446,65 @@ inet6name(struct in6_addr *in6)
return "?";
}
-int
-cmdnetstat(char *cmd, char *args)
+static const char *
+inetname(struct in_addr in)
{
- struct netinfo *p;
+ static char line[NI_MAXHOST];
+ struct sockaddr_in sin;
+ int flags, e;
- if (prefix(cmd, "all")) {
- aflag = !aflag;
- goto fixup;
- }
- if (prefix(cmd, "numbers") || prefix(cmd, "names")) {
- int new;
-
- new = prefix(cmd, "numbers");
- if (new == nflag)
- return (1);
- p = netcb.nif_forw;
- for (; p != (struct netinfo *)&netcb; p = p->nif_forw) {
- if (p->nif_line == -1)
- continue;
- p->nif_flags |= NIF_LACHG|NIF_FACHG;
- }
- nflag = new;
- wclear(wnd);
- labelnetstat();
- goto redisplay;
- }
- if (!netcmd(cmd, args))
+ flags = nflag ? NI_NUMERICHOST : 0;
+ if (in.s_addr == INADDR_ANY)
+ return "*";
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_addr = in;
+
+ e = getnameinfo((struct sockaddr *)&sin, sin.sin_len,
+ line, sizeof(line), NULL, 0, flags);
+
+ if (e == 0)
+ return line;
+
+ error("Lookup: %s", gai_strerror(e));
+
+ return "?";
+}
+
+int
+kvm_ckread(void *a, void *b, size_t l)
+{
+ if (kvm_read(kd, (u_long)a, b, l) != l) {
+ if (verbose)
+ error("error reading kmem at %x\n", a);
return (0);
-fixup:
- fetchnetstat();
-redisplay:
- shownetstat();
- refresh();
- return (1);
+ } else
+ return (1);
+}
+
+
+int
+ns_keyboard_callback(int ch)
+{
+ switch (ch) {
+ case 'n':
+ nflag = !nflag;
+ gotsig_alarm = 1;
+ break;
+ case 't':
+ protos ^= TCP;
+ gotsig_alarm = 1;
+ break;
+ case 'u':
+ protos ^= UDP;
+ gotsig_alarm = 1;
+ break;
+ default:
+ return keyboard_callback(ch);
+ };
+
+ return 1;
}
+
diff --git a/usr.bin/systat/pf.c b/usr.bin/systat/pf.c
new file mode 100644
index 00000000000..1a2e0f9fb9e
--- /dev/null
+++ b/usr.bin/systat/pf.c
@@ -0,0 +1,326 @@
+/* $OpenBSD: pf.c,v 1.1 2008/06/12 22:26:01 canacar Exp $ */
+/*
+ * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
+#include <net/pfvar.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <err.h>
+#include <ifaddrs.h>
+#include <unistd.h>
+#include <net/pfvar.h>
+#include "pfctl_parser.h"
+#include "engine.h"
+#include "systat.h"
+
+void print_pf(void);
+int read_pf(void);
+int select_pf(void);
+
+const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
+const char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
+const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
+const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
+
+static struct pf_status status;
+extern int pf_dev;
+int num_pf = 0;
+
+field_def fields_pf[] = {
+ {"TYPE", 13, 16, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"NAME", 12, 24, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"VALUE", 8, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"RATE", 8, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 60},
+ {"NOTES", 10, 20, 1, FLD_ALIGN_LEFT, -1, 0, 0, 60},
+};
+
+#define FIELD_ADDR(x) (&fields_pf[x])
+
+#define FLD_PF_TYPE FIELD_ADDR(0)
+#define FLD_PF_NAME FIELD_ADDR(1)
+#define FLD_PF_VALUE FIELD_ADDR(2)
+#define FLD_PF_RATE FIELD_ADDR(3)
+#define FLD_PF_DESC FIELD_ADDR(4)
+
+/* Define views */
+field_def *view_pf_0[] = {
+ FLD_PF_TYPE, FLD_PF_NAME, FLD_PF_VALUE, FLD_PF_RATE, FLD_PF_DESC, NULL
+};
+
+
+/* Define view managers */
+struct view_manager pf_mgr = {
+ "PF", select_pf, read_pf, NULL, print_header,
+ print_pf, keyboard_callback, NULL, NULL
+};
+
+field_view views_pf[] = {
+ {view_pf_0, "pf", 'P', &pf_mgr},
+ {NULL, NULL, 0, NULL}
+};
+
+
+
+int
+select_pf(void)
+{
+ return (0);
+}
+
+int
+read_pf(void)
+{
+ if (pf_dev < 0) {
+ num_disp = 0;
+ return 0;
+ }
+
+ if (ioctl(pf_dev, DIOCGETSTATUS, &status)) {
+ error("DIOCGETSTATUS: %s", strerror(errno));
+ return (-1);
+ }
+
+ num_disp = 4;
+
+ if (status.ifname[0] != 0)
+ num_disp += 13;
+
+ num_disp += FCNT_MAX + 2;
+ num_disp += SCNT_MAX + 2;
+ num_disp += PFRES_MAX + 1;
+ num_disp += LCNT_MAX + 1;
+
+ return (0);
+}
+
+int
+initpf(void)
+{
+ field_view *v;
+
+ for (v = views_pf; v->name != NULL; v++)
+ add_view(v);
+
+ return(1);
+}
+
+void
+print_fld_double(field_def *fld, double val)
+{
+ int len;
+
+ if (fld == NULL)
+ return;
+
+ len = fld->width;
+ if (len < 1)
+ return;
+
+ tb_start();
+ if (tbprintf("%.2f", val) > len)
+ print_fld_str(fld, "*");
+ else
+ print_fld_tb(fld);
+ tb_end();
+}
+
+#define ADD_LINE_A(t, n, v) \
+ do { \
+ if (cur >= dispstart && cur < end) { \
+ print_fld_str(FLD_PF_TYPE, (t)); \
+ print_fld_str(FLD_PF_NAME, (n)); \
+ print_fld_age(FLD_PF_VALUE, (v)); \
+ end_line(); \
+ } \
+ if (++cur >= end) \
+ return; \
+ } while (0)
+
+#define ADD_EMPTY_LINE \
+ do { \
+ if (cur >= dispstart && cur < end) \
+ end_line(); \
+ if (++cur >= end) \
+ return; \
+ } while (0)
+
+#define ADD_LINE_S(t, n, v) \
+ do { \
+ if (cur >= dispstart && cur < end) { \
+ print_fld_str(FLD_PF_TYPE, (t)); \
+ print_fld_str(FLD_PF_NAME, (n)); \
+ print_fld_str(FLD_PF_VALUE, (v)); \
+ end_line(); \
+ } \
+ if (++cur >= end) \
+ return; \
+ } while (0)
+
+#define ADD_LINE_V(t, n, v) \
+ do { \
+ if (cur >= dispstart && cur < end) { \
+ print_fld_str(FLD_PF_TYPE, (t)); \
+ print_fld_str(FLD_PF_NAME, (n)); \
+ print_fld_size(FLD_PF_VALUE, (v)); \
+ end_line(); \
+ } \
+ if (++cur >= end) \
+ return; \
+ } while (0)
+
+#define ADD_LINE_VD(t, n, v, d) \
+ do { \
+ if (cur >= dispstart && cur < end) { \
+ print_fld_str(FLD_PF_TYPE, (t)); \
+ print_fld_str(FLD_PF_NAME, (n)); \
+ print_fld_size(FLD_PF_VALUE, (v)); \
+ print_fld_str(FLD_PF_DESC, (d)); \
+ end_line(); \
+ } \
+ if (++cur >= end) \
+ return; \
+ } while (0)
+
+#define ADD_LINE_VR(t, n, v, r) \
+ do { \
+ if (cur >= dispstart && cur < end) { \
+ print_fld_str(FLD_PF_TYPE, (t)); \
+ print_fld_str(FLD_PF_NAME, (n)); \
+ print_fld_size(FLD_PF_VALUE, (v)); \
+ print_fld_double(FLD_PF_RATE, (r)); \
+ end_line(); \
+ } \
+ if (++cur >= end) \
+ return; \
+ } while (0)
+
+
+void
+print_pf(void)
+{
+ char *debug;
+ time_t tm;
+ int i;
+ struct pf_status *s = &status;
+
+ int cur = 0;
+ int end = dispstart + maxprint;
+ if (end > num_disp)
+ end = num_disp;
+
+ tm = time(NULL) - s->since;
+
+ ADD_LINE_S("pf", "Status", s->running ? "Enabled" : "Disabled");
+ ADD_LINE_A("pf", "Since", tm);
+
+ switch (s->debug) {
+ case PF_DEBUG_NONE:
+ debug = "None";
+ break;
+ case PF_DEBUG_URGENT:
+ debug = "Urgent";
+ break;
+ case PF_DEBUG_MISC:
+ debug = "Misc";
+ break;
+ case PF_DEBUG_NOISY:
+ debug = "Loud";
+ break;
+ }
+ ADD_LINE_S("pf", "Debug", debug);
+
+ tb_start();
+ tbprintf("0x%08x\n", ntohl(s->hostid));
+ tb_end();
+
+ ADD_LINE_S("pf", "Hostid", tmp_buf);
+
+ if (s->ifname[0] != 0) {
+ ADD_EMPTY_LINE;
+ ADD_LINE_VD(s->ifname, "Bytes In", s->bcounters[0][0], "IPv4");
+ ADD_LINE_VD(s->ifname, "Bytes In", s->bcounters[1][0], "IPv6");
+ ADD_LINE_VD(s->ifname, "Bytes Out", s->bcounters[0][1], "IPv4");
+ ADD_LINE_VD(s->ifname, "Bytes Out", s->bcounters[1][1], "IPv6");
+ ADD_LINE_VD(s->ifname, "Packets In", s->pcounters[0][0][PF_PASS], "IPv4, Passed");
+ ADD_LINE_VD(s->ifname, "Packets In", s->pcounters[1][0][PF_PASS], "IPv6, Passed");
+ ADD_LINE_VD(s->ifname, "Packets In", s->pcounters[0][0][PF_DROP], "IPv4, Blocked");
+ ADD_LINE_VD(s->ifname, "Packets In", s->pcounters[1][0][PF_DROP], "IPv6, Blocked");
+ ADD_LINE_VD(s->ifname, "Packets Out", s->pcounters[0][1][PF_PASS], "IPv4, Passed");
+ ADD_LINE_VD(s->ifname, "Packets Out", s->pcounters[1][1][PF_PASS], "IPv6, Passed");
+ ADD_LINE_VD(s->ifname, "Packets Out", s->pcounters[0][1][PF_DROP], "IPv4, Blocked");
+ ADD_LINE_VD(s->ifname, "Packets Out", s->pcounters[1][1][PF_DROP], "IPv6, Blocked");
+ }
+
+
+ ADD_EMPTY_LINE;
+ ADD_LINE_V("state", "Count", s->states);
+
+ for (i = 0; i < FCNT_MAX; i++) {
+ if (tm > 0)
+ ADD_LINE_VR("state", pf_fcounters[i], s->fcounters[i],
+ (double)s->fcounters[i] / (double)tm);
+ else
+ ADD_LINE_V("state", pf_fcounters[i], s->fcounters[i]);
+ }
+
+
+ ADD_EMPTY_LINE;
+ ADD_LINE_V("src track", "Count", s->src_nodes);
+
+ for (i = 0; i < SCNT_MAX; i++) {
+ if (tm > 0)
+ ADD_LINE_VR("src track", pf_scounters[i], s->scounters[i],
+ (double)s->scounters[i] / (double)tm);
+ else
+ ADD_LINE_V("src track", pf_scounters[i], s->scounters[i]);
+ }
+
+ ADD_EMPTY_LINE;
+ for (i = 0; i < PFRES_MAX; i++) {
+ if (tm > 0)
+ ADD_LINE_VR("counter", pf_reasons[i], s->counters[i],
+ (double)s->counters[i] / (double)tm);
+ else
+ ADD_LINE_V("counter", pf_reasons[i], s->counters[i]);
+ }
+
+ ADD_EMPTY_LINE;
+ for (i = 0; i < LCNT_MAX; i++) {
+ if (tm > 0)
+ ADD_LINE_VR("limit counter", pf_lcounters[i], s->lcounters[i],
+ (double)s->lcounters[i] / (double)tm);
+ else
+ ADD_LINE_V("limit counter", pf_lcounters[i], s->lcounters[i]);
+ }
+}
diff --git a/usr.bin/systat/pftop.c b/usr.bin/systat/pftop.c
new file mode 100644
index 00000000000..fdad0e540f7
--- /dev/null
+++ b/usr.bin/systat/pftop.c
@@ -0,0 +1,2160 @@
+/* $Id: pftop.c,v 1.1 2008/06/12 22:26:01 canacar Exp $ */
+/*
+ * Copyright (c) 2001, 2007 Can Erkin Acar
+ * Copyright (c) 2001 Daniel Hartmeier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/tcp_fsm.h>
+#include <net/pfvar.h>
+#include <arpa/inet.h>
+
+#ifdef HAVE_ALTQ
+#include <altq/altq.h>
+#include <altq/altq_cbq.h>
+#include <altq/altq_priq.h>
+#include <altq/altq_hfsc.h>
+#endif
+
+#include <ctype.h>
+#include <curses.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "engine.h"
+#include "cache.h"
+
+extern const char *tcpstates[];
+
+#define MIN_NUM_STATES 1024
+#define NUM_STATE_INC 1024
+
+#define DEFAULT_CACHE_SIZE 10000
+
+#ifndef HAVE_PROTO_NAMES
+/* UDP state enumeration */
+#define PFUDPS_NSTATES 3 /* number of state levels */
+
+#define PFUDPS_NAMES { \
+ "NO TRAFFIC", \
+ "SINGLE", \
+ "MULTIPLE", \
+ NULL \
+}
+
+/* Other protocol state enumeration */
+#define PFOTHERS_NSTATES 3 /* number of state levels */
+
+#define PFOTHERS_NAMES { \
+ "NO TRAFFIC", \
+ "SINGLE", \
+ "MULTIPLE", \
+ NULL \
+}
+#endif
+
+#ifdef HAVE_ADDR_WRAP
+#ifdef HAVE_ADDR_TYPE
+/* XXX must also check type before use */
+#define PT_ADDR(x) (&(x)->addr.v.a.addr)
+#else
+#define PT_ADDR(x) (&(x)->addr.addr)
+#endif
+#else
+#define PT_ADDR(x) (&(x)->addr)
+#endif
+
+#ifdef HAVE_ADDR_MASK
+#ifdef HAVE_ADDR_TYPE
+/* XXX must also check type before use */
+#define PT_MASK(x) (&(x)->addr.v.a.mask)
+#else
+#define PT_MASK(x) (&(x)->addr.mask)
+#endif
+#else
+#define PT_MASK(x) (&(x)->mask)
+#endif
+
+#ifdef HAVE_STATE_NOROUTE
+#ifdef HAVE_ADDR_TYPE
+#define PT_NOROUTE(x) ((x)->addr.type == PF_ADDR_NOROUTE)
+#else
+#define PT_NOROUTE(x) ((x)->noroute)
+#endif
+#else
+#define PT_NOROUTE(x) (0)
+#endif
+
+/* view management */
+int select_states(void);
+int read_states(void);
+void sort_states(void);
+void print_states(void);
+
+int select_rules(void);
+int read_rules(void);
+void print_rules(void);
+
+int print_header(void);
+int keyboard_callback(int ch);
+
+#ifdef HAVE_ALTQ
+int select_queues(void);
+int read_queues(void);
+void print_queues(void);
+#endif
+
+/* qsort callbacks */
+int sort_size_callback(const void *s1, const void *s2);
+int sort_exp_callback(const void *s1, const void *s2);
+int sort_pkt_callback(const void *s1, const void *s2);
+int sort_age_callback(const void *s1, const void *s2);
+int sort_sa_callback(const void *s1, const void *s2);
+int sort_sp_callback(const void *s1, const void *s2);
+int sort_da_callback(const void *s1, const void *s2);
+int sort_dp_callback(const void *s1, const void *s2);
+int sort_rate_callback(const void *s1, const void *s2);
+int sort_peak_callback(const void *s1, const void *s2);
+int pf_dev = -1;
+
+struct sc_ent **state_cache = NULL;
+pf_state_t *state_buf = NULL;
+int state_buf_len = 0;
+u_int32_t *state_ord = NULL;
+u_int32_t num_states = 0;
+u_int32_t num_states_all = 0;
+u_int32_t num_rules = 0;
+u_int32_t num_queues = 0;
+int cachestates = 0;
+
+char *filter_string = NULL;
+int dumpfilter = 0;
+
+#ifndef HAVE_RULE_LABELS
+#define PF_RULE_LABEL_SIZE 20
+#endif
+
+#define MIN_LABEL_SIZE 5
+#define ANCHOR_FLD_SIZE 12
+
+/* Define fields */
+field_def fields[] = {
+ {"SRC", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"DEST", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"GW", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"STATE", 5, 23, 18, FLD_ALIGN_COLUMN, -1, 0, 0, 0},
+ {"AGE", 5, 9, 4, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"EXP", 5, 9, 4, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"PR ", 4, 9, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"DIR", 1, 3, 2, FLD_ALIGN_CENTER, -1, 0, 0, 0},
+ {"PKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"BYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"RULE", 2, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"LABEL", MIN_LABEL_SIZE, MIN_LABEL_SIZE, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"STATES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"EVAL", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"ACTION", 1, 8, 4, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"LOG", 1, 3, 2, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"QUICK", 1, 1, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"KS", 1, 1, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"IF", 4, 6, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"INFO", 40, 80, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"MAX", 3, 5, 2, FLD_ALIGN_RIGHT, -1, 0, FLD_FLAG_HIDDEN, 0},
+ {"RATE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"AVG", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"PEAK", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"ANCHOR", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, FLD_FLAG_HIDDEN, 0},
+ {"QUEUE", 15, 30, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"BW", 4, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"SCH", 3, 4, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"PRIO", 1, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"DROP_P", 6, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"DROP_B", 6, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"QLEN", 4, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"BORROW", 4, 6, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"SUSPENDS", 4, 6, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"P/S", 3, 7, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"B/S", 4, 7, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}
+};
+
+
+#define FIELD_ADDR(x) (&fields[x])
+
+/* for states */
+#define FLD_SRC FIELD_ADDR(0)
+#define FLD_DEST FIELD_ADDR(1)
+#define FLD_GW FIELD_ADDR(2)
+#define FLD_STATE FIELD_ADDR(3)
+#define FLD_AGE FIELD_ADDR(4)
+#define FLD_EXP FIELD_ADDR(5)
+/* common */
+#define FLD_PROTO FIELD_ADDR(6)
+#define FLD_DIR FIELD_ADDR(7)
+#define FLD_PKTS FIELD_ADDR(8)
+#define FLD_BYTES FIELD_ADDR(9)
+#define FLD_RULE FIELD_ADDR(10)
+/* for rules */
+#define FLD_LABEL FIELD_ADDR(11)
+#define FLD_STATS FIELD_ADDR(12)
+#define FLD_EVAL FIELD_ADDR(13)
+#define FLD_ACTION FIELD_ADDR(14)
+#define FLD_LOG FIELD_ADDR(15)
+#define FLD_QUICK FIELD_ADDR(16)
+#define FLD_KST FIELD_ADDR(17)
+#define FLD_IF FIELD_ADDR(18)
+#define FLD_RINFO FIELD_ADDR(19)
+#define FLD_STMAX FIELD_ADDR(20)
+/* other */
+#define FLD_SI FIELD_ADDR(21) /* instantaneous speed */
+#define FLD_SA FIELD_ADDR(22) /* average speed */
+#define FLD_SP FIELD_ADDR(23) /* peak speed */
+#define FLD_ANCHOR FIELD_ADDR(24)
+/* for queues */
+#define FLD_QUEUE FIELD_ADDR(25)
+#define FLD_BANDW FIELD_ADDR(26)
+#define FLD_SCHED FIELD_ADDR(27)
+#define FLD_PRIO FIELD_ADDR(28)
+#define FLD_DROPP FIELD_ADDR(29)
+#define FLD_DROPB FIELD_ADDR(30)
+#define FLD_QLEN FIELD_ADDR(31)
+#define FLD_BORR FIELD_ADDR(32)
+#define FLD_SUSP FIELD_ADDR(33)
+#define FLD_PKTSPS FIELD_ADDR(34)
+#define FLD_BYTESPS FIELD_ADDR(35)
+
+/* Define views */
+field_def *view0[] = {
+ FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_STATE,
+ FLD_AGE, FLD_EXP, FLD_PKTS, FLD_BYTES, NULL
+};
+
+field_def *view1[] = {
+ FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_GW, FLD_STATE, FLD_AGE,
+ FLD_EXP, FLD_PKTS, FLD_BYTES, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, NULL
+};
+
+field_def *view2[] = {
+ FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_STATE, FLD_AGE, FLD_EXP,
+ FLD_PKTS, FLD_BYTES, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, FLD_GW, NULL
+};
+
+field_def *view3[] = {
+ FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_AGE, FLD_EXP, FLD_PKTS,
+ FLD_BYTES, FLD_STATE, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, FLD_GW, NULL
+};
+
+field_def *view4[] = {
+ FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_PKTS, FLD_BYTES, FLD_STATE,
+ FLD_AGE, FLD_EXP, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, FLD_GW, NULL
+};
+
+field_def *view5[] = {
+ FLD_RULE, FLD_ANCHOR, FLD_ACTION, FLD_DIR, FLD_LOG, FLD_QUICK, FLD_IF,
+ FLD_PROTO, FLD_KST, FLD_PKTS, FLD_BYTES, FLD_STATS, FLD_STMAX,
+ FLD_RINFO, NULL
+};
+
+field_def *view6[] = {
+ FLD_RULE, FLD_LABEL, FLD_PKTS, FLD_BYTES, FLD_STATS, FLD_STMAX,
+ FLD_ACTION, FLD_DIR, FLD_LOG, FLD_QUICK, FLD_IF, FLD_PROTO,
+ FLD_ANCHOR, FLD_KST, NULL
+};
+
+field_def *view7[] = {
+ FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_SI, FLD_SP, FLD_SA,
+ FLD_BYTES, FLD_STATE, FLD_PKTS, FLD_AGE, FLD_EXP, FLD_RULE, FLD_GW, NULL
+};
+
+field_def *view8[] = {
+ FLD_QUEUE, FLD_BANDW, FLD_SCHED, FLD_PRIO, FLD_PKTS, FLD_BYTES,
+ FLD_DROPP, FLD_DROPB, FLD_QLEN, FLD_BORR, FLD_SUSP, FLD_PKTSPS,
+ FLD_BYTESPS, NULL
+};
+
+/* Define orderings */
+order_type order_list[] = {
+ {"none", "none", 'N', NULL},
+ {"bytes", "bytes", 'B', sort_size_callback},
+ {"expiry", "exp", 'E', sort_exp_callback},
+ {"packets", "pkt", 'P', sort_pkt_callback},
+ {"age", "age", 'A', sort_age_callback},
+ {"source addr", "src", 'F', sort_sa_callback},
+ {"dest. addr", "dest", 'T', sort_da_callback},
+ {"source port", "sport", 'S', sort_sp_callback},
+ {"dest. port", "dport", 'D', sort_dp_callback},
+ {"rate", "rate", 'R', sort_rate_callback},
+ {"peak", "peak", 'K', sort_peak_callback},
+ {NULL, NULL, 0, NULL}
+};
+
+/* Define view managers */
+struct view_manager state_mgr = {
+ "States", select_states, read_states, sort_states, print_header,
+ print_states, keyboard_callback, order_list, NULL
+};
+
+struct view_manager rule_mgr = {
+ "Rules", select_rules, read_rules, NULL, print_header,
+ print_rules, keyboard_callback, NULL, NULL
+};
+
+#ifdef HAVE_ALTQ
+struct view_manager queue_mgr = {
+ "Queues", select_queues, read_queues, NULL, print_header,
+ print_queues, keyboard_callback, NULL, NULL
+};
+#endif
+
+field_view views[] = {
+ {view2, "states", '8', &state_mgr},
+ {view5, "rules", '9', &rule_mgr},
+ {view8, "queues", 'Q', &queue_mgr},
+ {NULL, NULL, 0, NULL}
+};
+
+
+/* altq structures from pfctl */
+
+#ifdef HAVE_ALTQ
+union class_stats {
+ class_stats_t cbq_stats;
+ struct priq_classstats priq_stats;
+ struct hfsc_classstats hfsc_stats;
+};
+
+struct queue_stats {
+ union class_stats data;
+ struct timeval timestamp;
+ u_int8_t valid;
+};
+
+struct pf_altq_node {
+ struct pf_altq altq;
+ struct pf_altq_node *next;
+ struct pf_altq_node *children;
+ struct pf_altq_node *next_flat;
+ struct queue_stats qstats;
+ struct queue_stats qstats_last;
+ u_int8_t depth;
+ u_int8_t visited;
+};
+#endif /* HAVE_ALTQ */
+
+
+/* ordering functions */
+
+int
+sort_size_callback(const void *s1, const void *s2)
+{
+#ifdef HAVE_INOUT_COUNT
+ u_int64_t b1 = COUNTER(state_buf[* (u_int32_t *) s1].bytes[0]) +
+ COUNTER(state_buf[* (u_int32_t *) s1].bytes[1]);
+ u_int64_t b2 = COUNTER(state_buf[* (u_int32_t *) s2].bytes[0]) +
+ COUNTER(state_buf[* (u_int32_t *) s2].bytes[1]);
+#else
+ u_int64_t b1 = COUNTER(state_buf[* (u_int32_t *) s1].bytes);
+ u_int64_t b2 = COUNTER(state_buf[* (u_int32_t *) s2].bytes);
+#endif
+ if (b2 > b1)
+ return sortdir;
+ if (b2 < b1)
+ return -sortdir;
+ return 0;
+}
+
+int
+sort_pkt_callback(const void *s1, const void *s2)
+{
+#ifdef HAVE_INOUT_COUNT
+ u_int64_t p1 = COUNTER(state_buf[* (u_int32_t *) s1].packets[0]) +
+ COUNTER(state_buf[* (u_int32_t *) s1].packets[1]);
+ u_int64_t p2 = COUNTER(state_buf[* (u_int32_t *) s2].packets[0]) +
+ COUNTER(state_buf[* (u_int32_t *) s2].packets[1]);
+#else
+ u_int64_t p1 = COUNTER(state_buf[* (u_int32_t *) s1].packets);
+ u_int64_t p2 = COUNTER(state_buf[* (u_int32_t *) s2].packets);
+#endif
+ if (p2 > p1)
+ return sortdir;
+ if (p2 < p1)
+ return -sortdir;
+ return 0;
+}
+
+int
+sort_age_callback(const void *s1, const void *s2)
+{
+ if (state_buf[* (u_int32_t *) s2].creation >
+ state_buf[* (u_int32_t *) s1].creation)
+ return sortdir;
+ if (state_buf[* (u_int32_t *) s2].creation <
+ state_buf[* (u_int32_t *) s1].creation)
+ return -sortdir;
+ return 0;
+}
+
+int
+sort_exp_callback(const void *s1, const void *s2)
+{
+ if (state_buf[* (u_int32_t *) s2].expire >
+ state_buf[* (u_int32_t *) s1].expire)
+ return sortdir;
+ if (state_buf[* (u_int32_t *) s2].expire <
+ state_buf[* (u_int32_t *) s1].expire)
+ return -sortdir;
+ return 0;
+}
+
+int
+sort_rate_callback(const void *s1, const void *s2)
+{
+ struct sc_ent *e1 = state_cache[* (u_int32_t *) s1];
+ struct sc_ent *e2 = state_cache[* (u_int32_t *) s2];
+
+ if (e1 == NULL)
+ return sortdir;
+ if (e2 == NULL)
+ return -sortdir;
+
+ if (e2->rate > e1 -> rate)
+ return sortdir;
+ if (e2->rate < e1 -> rate)
+ return -sortdir;
+ return 0;
+}
+
+int
+sort_peak_callback(const void *s1, const void *s2)
+{
+ struct sc_ent *e1 = state_cache[* (u_int32_t *) s1];
+ struct sc_ent *e2 = state_cache[* (u_int32_t *) s2];
+
+ if (e2 == NULL)
+ return -sortdir;
+ if (e1 == NULL || e2 == NULL)
+ return 0;
+
+ if (e2->peak > e1 -> peak)
+ return sortdir;
+ if (e2->peak < e1 -> peak)
+ return -sortdir;
+ return 0;
+}
+
+int
+compare_addr(int af, const struct pf_addr *a, const struct pf_addr *b)
+{
+ switch (af) {
+ case AF_INET:
+ if (ntohl(a->addr32[0]) > ntohl(b->addr32[0]))
+ return 1;
+ if (a->addr32[0] != b->addr32[0])
+ return -1;
+ break;
+ case AF_INET6:
+ if (ntohl(a->addr32[0]) > ntohl(b->addr32[0]))
+ return 1;
+ if (a->addr32[0] != b->addr32[0])
+ return -1;
+ if (ntohl(a->addr32[1]) > ntohl(b->addr32[1]))
+ return 1;
+ if (a->addr32[1] != b->addr32[1])
+ return -1;
+ if (ntohl(a->addr32[2]) > ntohl(b->addr32[2]))
+ return 1;
+ if (a->addr32[2] != b->addr32[2])
+ return -1;
+ if (ntohl(a->addr32[3]) > ntohl(b->addr32[3]))
+ return 1;
+ if (a->addr32[3] != b->addr32[3])
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+#ifdef HAVE_PFSYNC_KEY
+
+#ifdef __GNUC__
+__inline__
+#endif
+int
+sort_addr_callback(const pf_state_t *s1,
+ const pf_state_t *s2, int dir)
+{
+ const struct pf_addr *aa, *ab;
+ u_int16_t pa, pb;
+ int af, ret, ii, io;
+
+ af = s1->af;
+
+ if (af > s2->af)
+ return sortdir;
+ if (af < s2->af)
+ return -sortdir;
+
+ ii = io = 0;
+
+ if (dir == PF_OUT) /* looking for source addr */
+ io = 1;
+ else /* looking for dest addr */
+ ii = 1;
+
+ if (s1->direction == PF_IN) {
+ aa = &s1->key[PF_SK_STACK].addr[ii];
+ pa = s1->key[PF_SK_STACK].port[ii];
+ } else {
+ aa = &s1->key[PF_SK_WIRE].addr[io];
+ pa = s1->key[PF_SK_WIRE].port[io];
+ }
+
+ if (s2->direction == PF_IN) {
+ ab = &s2->key[PF_SK_STACK].addr[ii];;
+ pb = s2->key[PF_SK_STACK].port[ii];
+ } else {
+ ab = &s2->key[PF_SK_WIRE].addr[io];;
+ pb = s2->key[PF_SK_WIRE].port[io];
+ }
+
+ ret = compare_addr(af, aa, ab);
+ if (ret)
+ return ret * sortdir;
+
+ if (ntohs(pa) > ntohs(pb))
+ return sortdir;
+ return -sortdir;
+}
+
+#ifdef __GNUC__
+__inline__
+#endif
+int
+sort_port_callback(const pf_state_t *s1,
+ const pf_state_t *s2, int dir)
+{
+ const struct pf_addr *aa, *ab;
+ u_int16_t pa, pb;
+ int af, ret, ii, io;
+
+ af = s1->af;
+
+
+ if (af > s2->af)
+ return sortdir;
+ if (af < s2->af)
+ return -sortdir;
+
+ ii = io = 0;
+
+ if (dir == PF_OUT) /* looking for source addr */
+ io = 1;
+ else /* looking for dest addr */
+ ii = 1;
+
+ if (s1->direction == PF_IN) {
+ aa = &s1->key[PF_SK_STACK].addr[ii];
+ pa = s1->key[PF_SK_STACK].port[ii];
+ } else {
+ aa = &s1->key[PF_SK_WIRE].addr[io];
+ pa = s1->key[PF_SK_WIRE].port[io];
+ }
+
+ if (s2->direction == PF_IN) {
+ ab = &s2->key[PF_SK_STACK].addr[ii];;
+ pb = s2->key[PF_SK_STACK].port[ii];
+ } else {
+ ab = &s2->key[PF_SK_WIRE].addr[io];;
+ pb = s2->key[PF_SK_WIRE].port[io];
+ }
+
+
+ if (ntohs(pa) > ntohs(pb))
+ return sortdir;
+ if (ntohs(pa) < ntohs(pb))
+ return - sortdir;
+
+ ret = compare_addr(af, aa, ab);
+ if (ret)
+ return ret * sortdir;
+ return -sortdir;
+}
+
+#else /* HAVE_PFSYNC_KEY */
+
+#ifdef __GNUC__
+__inline__
+#endif
+int
+sort_addr_callback(const pf_state_t *s1,
+ const pf_state_t *s2, int dir)
+{
+ const pf_state_host_t *a, *b;
+ int af, ret;
+
+ af = s1->af;
+
+ if (af > s2->af)
+ return sortdir;
+ if (af < s2->af)
+ return -sortdir;
+
+ if (s1->direction == dir) {
+ a = &s1->lan;
+ } else {
+ a = &s1->ext;
+ }
+
+ if (s2->direction == dir) {
+ b = &s2->lan;
+ } else {
+ b = &s2->ext;
+ }
+
+ ret = compare_addr(af, &a->addr, &b->addr);
+ if (ret)
+ return ret * sortdir;
+
+ if (ntohs(a->port) > ntohs(b->port))
+ return sortdir;
+ return -sortdir;
+}
+
+#ifdef __GNUC__
+__inline__
+#endif
+int
+sort_port_callback(const pf_state_t *s1,
+ const pf_state_t *s2, int dir)
+{
+ const pf_state_host_t *a, *b;
+ int af;
+
+ af = s1->af;
+
+ if (af > s2->af)
+ return sortdir;
+ if (af < s2->af)
+ return -sortdir;
+
+ if (s1->direction == dir) {
+ a = &s1->lan;
+ } else {
+ a = &s1->ext;
+ }
+
+ if (s2->direction == dir) {
+ b = &s2->lan;
+ } else {
+ b = &s2->ext;
+ }
+
+ if (ntohs(a->port) > ntohs(b->port))
+ return sortdir;
+ if (ntohs(a->port) < ntohs(b->port))
+ return -sortdir;
+
+ if (compare_addr(af, &a->addr, &b->addr) > 0)
+ return sortdir;
+ return -sortdir;
+}
+#endif /* HAVE_PFSYNC_KEY */
+
+int sort_sa_callback(const void *p1, const void *p2)
+{
+ pf_state_t *s1 = state_buf + (* (u_int32_t *) p1);
+ pf_state_t *s2 = state_buf + (* (u_int32_t *) p2);
+ return sort_addr_callback(s1, s2, PF_OUT);
+}
+
+int sort_da_callback(const void *p1, const void *p2)
+{
+ pf_state_t *s1 = state_buf + (* (u_int32_t *) p1);
+ pf_state_t *s2 = state_buf + (* (u_int32_t *) p2);
+ return sort_addr_callback(s1, s2, PF_IN);
+}
+
+int
+sort_sp_callback(const void *p1, const void *p2)
+{
+ pf_state_t *s1 = state_buf + (* (u_int32_t *) p1);
+ pf_state_t *s2 = state_buf + (* (u_int32_t *) p2);
+ return sort_port_callback(s1, s2, PF_OUT);
+}
+
+int
+sort_dp_callback(const void *p1, const void *p2)
+{
+ pf_state_t *s1 = state_buf + (* (u_int32_t *) p1);
+ pf_state_t *s2 = state_buf + (* (u_int32_t *) p2);
+ return sort_port_callback(s1, s2, PF_IN);
+}
+
+void
+sort_states(void)
+{
+ order_type *ordering;
+
+ if (curr_mgr == NULL)
+ return;
+
+ ordering = curr_mgr->order_curr;
+
+ if (ordering == NULL)
+ return;
+ if (ordering->func == NULL)
+ return;
+ if (state_buf == NULL)
+ return;
+ if (num_states <= 0)
+ return;
+
+ mergesort(state_ord, num_states, sizeof(u_int32_t), ordering->func);
+}
+
+/* state management functions */
+
+void
+alloc_buf(int ns)
+{
+ int len;
+
+ if (ns < MIN_NUM_STATES)
+ ns = MIN_NUM_STATES;
+
+ len = ns;
+
+ if (len >= state_buf_len) {
+ len += NUM_STATE_INC;
+ state_buf = realloc(state_buf, len * sizeof(pf_state_t));
+ state_ord = realloc(state_ord, len * sizeof(u_int32_t));
+ state_cache = realloc(state_cache,
+ len * sizeof(struct sc_ent *));
+ if (state_buf == NULL || state_ord == NULL ||
+ state_cache == NULL)
+ err(1, "realloc");
+ state_buf_len = len;
+ }
+}
+
+int
+select_states(void)
+{
+ num_disp = num_states;
+ return (0);
+}
+
+int
+read_states(void)
+{
+ struct pfioc_states ps;
+ int n;
+
+ if (pf_dev == -1)
+ return -1;
+
+ for (;;) {
+ int sbytes = state_buf_len * sizeof(pf_state_t);
+
+ ps.ps_len = sbytes;
+ ps.ps_buf = (char *) state_buf;
+
+ if (ioctl(pf_dev, DIOCGETSTATES, &ps) < 0) {
+ error("DIOCGETSTATES");
+ }
+ num_states_all = ps.ps_len / sizeof(pf_state_t);
+
+ if (ps.ps_len < sbytes)
+ break;
+
+ alloc_buf(num_states_all);
+ }
+
+ if (dumpfilter) {
+ int fd = open("state.dmp", O_WRONLY|O_CREAT|O_EXCL, 0);
+ if (fd > 0) {
+ write(fd, state_buf, ps.ps_len);
+ close(fd);
+ }
+ }
+
+ num_states = num_states_all;
+ for (n = 0; n<num_states_all; n++)
+ state_ord[n] = n;
+
+ if (cachestates) {
+ for (n = 0; n < num_states; n++)
+ state_cache[n] = cache_state(state_buf + n);
+ cache_endupdate();
+ }
+
+ num_disp = num_states;
+ return 0;
+}
+
+int
+unmask(struct pf_addr * m, u_int8_t af)
+{
+ int i = 31, j = 0, b = 0, msize;
+ u_int32_t tmp;
+
+ if (af == AF_INET)
+ msize = 1;
+ else
+ msize = 4;
+ while (j < msize && m->addr32[j] == 0xffffffff) {
+ b += 32;
+ j++;
+ }
+ if (j < msize) {
+ tmp = ntohl(m->addr32[j]);
+ for (i = 31; tmp & (1 << i); --i)
+ b++;
+ }
+ return (b);
+}
+
+/* display functions */
+
+void
+tb_print_addr(struct pf_addr * addr, struct pf_addr * mask, int af)
+{
+ static char buf[48];
+ const char *bf;
+
+ bf = inet_ntop(af, addr, buf, sizeof(buf));
+ tbprintf("%s", bf);
+
+ if (mask != NULL) {
+ if (!PF_AZERO(mask, af))
+ tbprintf("/%u", unmask(mask, af));
+ }
+}
+#ifdef HAVE_PFSYNC_KEY
+void
+print_fld_host2(field_def *fld, struct pfsync_state_key *ks,
+ struct pfsync_state_key *kn, int idx, int af)
+{
+ struct pf_addr *as = &ks->addr[idx];
+ struct pf_addr *an = &kn->addr[idx];
+
+ u_int16_t ps = ntohs(ks->port[idx]);
+ u_int16_t pn = ntohs(kn->port[idx]);
+
+ if (fld == NULL)
+ return;
+
+ if (fld->width < 3) {
+ print_fld_str(fld, "*");
+ return;
+ }
+
+ tb_start();
+ tb_print_addr(as, NULL, af);
+
+ if (af == AF_INET)
+ tbprintf(":%u", ps);
+ else
+ tbprintf("[%u]", ps);
+
+ print_fld_tb(fld);
+
+ if (PF_ANEQ(as, an, af) || ps != pn) {
+ tb_start();
+ tb_print_addr(an, NULL, af);
+
+ if (af == AF_INET)
+ tbprintf(":%u", pn);
+ else
+ tbprintf("[%u]", pn);
+ print_fld_tb(FLD_GW);
+ }
+
+}
+#else
+void
+print_fld_host(field_def *fld, pf_state_host_t * h, int af)
+{
+ u_int16_t p = ntohs(h->port);
+
+ if (fld == NULL)
+ return;
+
+ if (fld->width < 3) {
+ print_fld_str(fld, "*");
+ return;
+ }
+
+ tb_start();
+ tb_print_addr(&h->addr, NULL, af);
+
+ if (af == AF_INET)
+ tbprintf(":%u", p);
+ else
+ tbprintf("[%u]", p);
+
+ print_fld_tb(fld);
+}
+#endif
+
+void
+print_fld_state(field_def *fld, unsigned int proto,
+ unsigned int s1, unsigned int s2)
+{
+ int len;
+
+ if (fld == NULL)
+ return;
+
+ len = fld->width;
+ if (len < 1)
+ return;
+
+ tb_start();
+
+ if (proto == IPPROTO_TCP) {
+ if (s1 <= TCPS_TIME_WAIT && s2 <= TCPS_TIME_WAIT)
+ tbprintf("%s:%s", tcpstates[s1], tcpstates[s2]);
+#ifdef PF_TCPS_PROXY_SRC
+ else if (s1 == PF_TCPS_PROXY_SRC ||
+ s2 == PF_TCPS_PROXY_SRC)
+ tbprintf("PROXY:SRC\n");
+ else if (s1 == PF_TCPS_PROXY_DST ||
+ s2 == PF_TCPS_PROXY_DST)
+ tbprintf("PROXY:DST\n");
+#endif
+ else
+ tbprintf("<BAD STATE LEVELS>");
+ } else if (proto == IPPROTO_UDP && s1 < PFUDPS_NSTATES &&
+ s2 < PFUDPS_NSTATES) {
+ const char *states[] = PFUDPS_NAMES;
+ tbprintf("%s:%s", states[s1], states[s2]);
+ } else if (proto != IPPROTO_ICMP && s1 < PFOTHERS_NSTATES &&
+ s2 < PFOTHERS_NSTATES) {
+ /* XXX ICMP doesn't really have state levels */
+ const char *states[] = PFOTHERS_NAMES;
+ tbprintf("%s:%s", states[s1], states[s2]);
+ } else {
+ tbprintf("%u:%u", s1, s2);
+ }
+
+ if (strlen(tmp_buf) > len) {
+ tb_start();
+ tbprintf("%u:%u", s1, s2);
+ }
+
+ print_fld_tb(fld);
+}
+
+int
+print_state(pf_state_t * s, struct sc_ent * ent)
+{
+ pf_state_peer_t *src, *dst;
+ struct protoent *p;
+
+ if (s->direction == PF_OUT) {
+ src = &s->src;
+ dst = &s->dst;
+ } else {
+ src = &s->dst;
+ dst = &s->src;
+ }
+
+ p = getprotobynumber(s->proto);
+
+ if (p != NULL)
+ print_fld_str(FLD_PROTO, p->p_name);
+ else
+ print_fld_uint(FLD_PROTO, s->proto);
+
+#ifdef HAVE_PFSYNC_KEY
+ if (s->direction == PF_OUT) {
+ print_fld_host2(FLD_SRC, &s->key[PF_SK_WIRE],
+ &s->key[PF_SK_STACK], 1, s->af);
+ print_fld_host2(FLD_DEST, &s->key[PF_SK_WIRE],
+ &s->key[PF_SK_STACK], 0, s->af);
+ } else {
+ print_fld_host2(FLD_SRC, &s->key[PF_SK_STACK],
+ &s->key[PF_SK_WIRE], 0, s->af);
+ print_fld_host2(FLD_DEST, &s->key[PF_SK_STACK],
+ &s->key[PF_SK_WIRE], 1, s->af);
+ }
+#else
+ if (s->direction == PF_OUT) {
+ print_fld_host(FLD_SRC, &s->lan, s->af);
+ print_fld_host(FLD_DEST, &s->ext, s->af);
+ } else {
+ print_fld_host(FLD_SRC, &s->ext, s->af);
+ print_fld_host(FLD_DEST, &s->lan, s->af);
+ }
+
+ if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
+ (s->lan.port != s->gwy.port)) {
+ print_fld_host(FLD_GW, &s->gwy, s->af);
+ }
+#endif
+
+ if (s->direction == PF_OUT)
+ print_fld_str(FLD_DIR, "Out");
+ else
+ print_fld_str(FLD_DIR, "In");
+
+ print_fld_state(FLD_STATE, s->proto, src->state, dst->state);
+ print_fld_age(FLD_AGE, s->creation);
+ print_fld_age(FLD_EXP, s->expire);
+#ifdef HAVE_INOUT_COUNT
+ {
+ u_int64_t sz = COUNTER(s->bytes[0]) + COUNTER(s->bytes[1]);
+
+ print_fld_size(FLD_PKTS, COUNTER(s->packets[0]) +
+ COUNTER(s->packets[1]));
+ print_fld_size(FLD_BYTES, sz);
+ print_fld_rate(FLD_SA, (s->creation > 0) ?
+ ((double)sz/(double)s->creation) : -1);
+ }
+#else
+ print_fld_size(FLD_PKTS, s->packets);
+ print_fld_size(FLD_BYTES, s->bytes);
+ print_fld_rate(FLD_SA, (s->creation > 0) ?
+ ((double)s->bytes/(double)s->creation) : -1);
+
+#endif
+#ifdef HAVE_PFSYNC_STATE
+ print_fld_uint(FLD_RULE, s->rule);
+#else
+#ifdef HAVE_RULE_NUMBER
+ print_fld_uint(FLD_RULE, s->rule.nr);
+#endif
+#endif
+ if (cachestates && ent != NULL) {
+ print_fld_rate(FLD_SI, ent->rate);
+ print_fld_rate(FLD_SP, ent->peak);
+ }
+
+ end_line();
+ return 1;
+}
+
+void
+print_states(void)
+{
+ int n, count = 0;
+
+ for (n = dispstart; n < num_disp; n++) {
+ count += print_state(state_buf + state_ord[n],
+ state_cache[state_ord[n]]);
+ if (maxprint > 0 && count >= maxprint)
+ break;
+ }
+}
+
+/* rule display */
+
+struct pf_rule *rules = NULL;
+u_int32_t alloc_rules = 0;
+
+int
+select_rules(void)
+{
+ num_disp = num_rules;
+ return (0);
+}
+
+
+void
+add_rule_alloc(u_int32_t nr)
+{
+ if (nr == 0)
+ return;
+
+ num_rules += nr;
+
+ if (rules == NULL) {
+ rules = malloc(num_rules * sizeof(struct pf_rule));
+ if (rules == NULL)
+ err(1, "malloc");
+ alloc_rules = num_rules;
+ } else if (num_rules > alloc_rules) {
+ rules = realloc(rules, num_rules * sizeof(struct pf_rule));
+ if (rules == NULL)
+ err(1, "realloc");
+ alloc_rules = num_rules;
+ }
+}
+
+#ifdef HAVE_RULE_LABELS
+int label_length;
+#endif
+
+int
+read_anchor_rules(char *anchor)
+{
+ struct pfioc_rule pr;
+ u_int32_t nr, num, off;
+
+ if (pf_dev < 0)
+ return (-1);
+
+ memset(&pr, 0, sizeof(pr));
+#ifdef HAVE_RULESETS
+ strlcpy(pr.anchor, anchor, sizeof(pr.anchor));
+#endif
+ if (ioctl(pf_dev, DIOCGETRULES, &pr)) {
+ error("anchor %s: %s", anchor, strerror(errno));
+ return (-1);
+ }
+
+ off = num_rules;
+ num = pr.nr;
+ add_rule_alloc(num);
+
+ for (nr = 0; nr < num; ++nr) {
+ pr.nr = nr;
+ if (ioctl(pf_dev, DIOCGETRULE, &pr)) {
+ error("DIOCGETRULE: %s", strerror(errno));
+ return (-1);
+ }
+#ifdef HAVE_RULESETS
+ /* XXX overload pr.anchor, to store a pointer to
+ * anchor name */
+ pr.rule.anchor = (struct pf_anchor *) anchor;
+#endif
+#ifdef HAVE_RULE_LABELS
+ {
+ int len = strlen(pr.rule.label);
+ if (len > label_length)
+ label_length = len;
+ }
+#endif
+ rules[off + nr] = pr.rule;
+ }
+
+ return (num);
+}
+
+#ifdef HAVE_RULESETS
+struct anchor_name {
+ char name[MAXPATHLEN];
+ struct anchor_name *next;
+ u_int32_t ref;
+};
+
+struct anchor_name *anchor_root = NULL;
+struct anchor_name *anchor_end = NULL;
+struct anchor_name *anchor_free = NULL;
+
+struct anchor_name*
+alloc_anchor_name(const char *path)
+{
+ struct anchor_name *a;
+
+ a = anchor_free;
+ if (a == NULL) {
+ a = (struct anchor_name *)malloc(sizeof(struct anchor_name));
+ if (a == NULL)
+ return (NULL);
+ } else
+ anchor_free = a->next;
+
+ if (anchor_root == NULL)
+ anchor_end = a;
+
+ a->next = anchor_root;
+ anchor_root = a;
+
+ a->ref = 0;
+ strlcpy(a->name, path, sizeof(a->name));
+ return (a);
+}
+
+void
+reset_anchor_names(void)
+{
+ if (anchor_end == NULL)
+ return;
+
+ anchor_end->next = anchor_free;
+ anchor_free = anchor_root;
+ anchor_root = anchor_end = NULL;
+}
+
+struct pfioc_ruleset ruleset;
+char *rs_end = NULL;
+
+int
+read_rulesets(const char *path)
+{
+ char *pre;
+ struct anchor_name *a;
+ u_int32_t nr, ns;
+ int len;
+
+ if (path == NULL)
+ ruleset.path[0] = '\0';
+ else if (strlcpy(ruleset.path, path, sizeof(ruleset.path)) >=
+ sizeof(ruleset.path))
+ return (-1);
+
+ /* a persistent storage for anchor names */
+ a = alloc_anchor_name(ruleset.path);
+ if (a == NULL)
+ return (-1);
+
+ len = read_anchor_rules(a->name);
+ if (len < 0)
+ return (-1);
+
+ a->ref += len;
+
+ if (ioctl(pf_dev, DIOCGETRULESETS, &ruleset)) {
+ error("DIOCGETRULESETS: %s", strerror(errno));
+ return (-1);
+ }
+
+ ns = ruleset.nr;
+
+ if (rs_end == NULL)
+ rs_end = ruleset.path + sizeof(ruleset.path);
+
+ /* 'pre' tracks the previous level on the anchor */
+ pre = strchr(ruleset.path, 0);
+ len = rs_end - pre;
+ if (len < 1)
+ return (-1);
+ --len;
+
+ for (nr = 0; nr < ns; ++nr) {
+ ruleset.nr = nr;
+ if (ioctl(pf_dev, DIOCGETRULESET, &ruleset)) {
+ error("DIOCGETRULESET: %s", strerror(errno));
+ return (-1);
+ }
+ *pre = '/';
+ if (strlcpy(pre + 1, ruleset.name, len) < len)
+ read_rulesets(ruleset.path);
+ *pre = '\0';
+ }
+
+ return (0);
+}
+
+void
+compute_anchor_field(void)
+{
+ struct anchor_name *a;
+ int sum, cnt, mx, nx;
+ sum = cnt = mx = 0;
+
+ for (a = anchor_root; a != NULL; a = a->next, cnt++) {
+ int len;
+ if (a->ref == 0)
+ continue;
+ len = strlen(a->name);
+ sum += len;
+ if (len > mx)
+ mx = len;
+ }
+
+ nx = sum/cnt;
+ if (nx < ANCHOR_FLD_SIZE)
+ nx = (mx < ANCHOR_FLD_SIZE) ? mx : ANCHOR_FLD_SIZE;
+
+ if (FLD_ANCHOR->max_width != mx ||
+ FLD_ANCHOR->norm_width != nx) {
+ FLD_ANCHOR->max_width = mx;
+ FLD_ANCHOR->norm_width = nx;
+ field_setup();
+ need_update = 1;
+ }
+}
+#endif
+
+int
+read_rules(void)
+{
+ int ret;
+ num_rules = 0;
+
+ if (pf_dev == -1)
+ return (-1);
+
+#ifdef HAVE_RULE_LABELS
+ label_length = MIN_LABEL_SIZE;
+#endif
+
+#ifdef HAVE_RULESETS
+ reset_anchor_names();
+ ret = read_rulesets(NULL);
+ compute_anchor_field();
+#else
+ ret = read_anchor_rules(NULL);
+#endif
+
+#ifdef HAVE_RULE_LABELS
+ {
+ int nw, mw;
+ nw = mw = label_length;
+ if (nw > 16)
+ nw = 16;
+
+ if (FLD_LABEL->norm_width != nw ||
+ FLD_LABEL->max_width != mw) {
+ FLD_LABEL->norm_width = nw;
+ FLD_LABEL->max_width = mw;
+ field_setup();
+ need_update = 1;
+ }
+ }
+#endif
+
+ num_disp = num_rules;
+ return (ret);
+}
+
+#ifdef HAVE_ADDR_WRAP
+void
+tb_print_addrw(struct pf_addr_wrap *addr, struct pf_addr *mask, u_int8_t af)
+{
+#ifdef HAVE_ADDR_TYPE
+ switch (addr->type) {
+ case PF_ADDR_ADDRMASK:
+ tb_print_addr(&addr->v.a.addr, mask, af);
+ break;
+ case PF_ADDR_NOROUTE:
+ tbprintf("noroute");
+ break;
+ case PF_ADDR_DYNIFTL:
+ tbprintf("(%s)", addr->v.ifname);
+ break;
+ case PF_ADDR_TABLE:
+ tbprintf("<%s>", addr->v.tblname);
+ break;
+ default:
+ tbprintf("UNKNOWN");
+ break;
+ }
+#else
+ if (addr->addr_dyn != NULL)
+ tbprintf("(%s)", addr->addr.pfa.ifname);
+ else
+ tb_print_addr(&addr->addr, mask, af);
+#endif
+}
+#endif
+
+void
+tb_print_op(u_int8_t op, const char *a1, const char *a2)
+{
+ if (op == PF_OP_IRG)
+ tbprintf("%s >< %s ", a1, a2);
+ else if (op == PF_OP_XRG)
+ tbprintf("%s <> %s ", a1, a2);
+#ifdef HAVE_OP_RRG
+ else if (op == PF_OP_RRG)
+ tbprintf("%s:%s ", a1, a2);
+#endif
+ else if (op == PF_OP_EQ)
+ tbprintf("= %s ", a1);
+ else if (op == PF_OP_NE)
+ tbprintf("!= %s ", a1);
+ else if (op == PF_OP_LT)
+ tbprintf("< %s ", a1);
+ else if (op == PF_OP_LE)
+ tbprintf("<= %s ", a1);
+ else if (op == PF_OP_GT)
+ tbprintf("> %s ", a1);
+ else if (op == PF_OP_GE)
+ tbprintf(">= %s ", a1);
+}
+
+void
+tb_print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto)
+{
+ char a1[6], a2[6];
+ struct servent *s = getservbyport(p1, proto);
+
+ p1 = ntohs(p1);
+ p2 = ntohs(p2);
+ snprintf(a1, sizeof(a1), "%u", p1);
+ snprintf(a2, sizeof(a2), "%u", p2);
+ tbprintf("port ");
+ if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
+ tb_print_op(op, s->s_name, a2);
+ else
+ tb_print_op(op, a1, a2);
+}
+
+void
+tb_print_fromto(struct pf_rule_addr *src, struct pf_rule_addr *dst,
+ u_int8_t af, u_int8_t proto)
+{
+ if (
+ PF_AZERO(PT_ADDR(src), AF_INET6) &&
+ PF_AZERO(PT_ADDR(dst), AF_INET6) &&
+ ! PT_NOROUTE(src) && ! PT_NOROUTE(dst) &&
+ PF_AZERO(PT_MASK(src), AF_INET6) &&
+ PF_AZERO(PT_MASK(dst), AF_INET6) &&
+ !src->port_op && !dst->port_op)
+ tbprintf("all ");
+ else {
+ tbprintf("from ");
+ if (PT_NOROUTE(src))
+ tbprintf("no-route ");
+ else if (PF_AZERO(PT_ADDR(src), AF_INET6) &&
+ PF_AZERO(PT_MASK(src), AF_INET6))
+ tbprintf("any ");
+ else {
+#ifdef HAVE_NEG
+ if (src->neg)
+#else
+ if (src->not)
+#endif
+ tbprintf("! ");
+#ifdef HAVE_ADDR_WRAP
+ tb_print_addrw(&src->addr, PT_MASK(src), af);
+#else
+ tb_print_addr(&src->addr, PT_MASK(src), af);
+#endif
+ tbprintf(" ");
+ }
+ if (src->port_op)
+ tb_print_port(src->port_op, src->port[0],
+ src->port[1],
+ proto == IPPROTO_TCP ? "tcp" : "udp");
+
+ tbprintf("to ");
+ if (PT_NOROUTE(dst))
+ tbprintf("no-route ");
+ else if (PF_AZERO(PT_ADDR(dst), AF_INET6) &&
+ PF_AZERO(PT_MASK(dst), AF_INET6))
+ tbprintf("any ");
+ else {
+#ifdef HAVE_NEG
+ if (dst->neg)
+#else
+ if (dst->not)
+#endif
+ tbprintf("! ");
+#ifdef HAVE_ADDR_WRAP
+ tb_print_addrw(&dst->addr, PT_MASK(dst), af);
+#else
+ tb_print_addr(&dst->addr, PT_MASK(dst), af);
+#endif
+ tbprintf(" ");
+ }
+ if (dst->port_op)
+ tb_print_port(dst->port_op, dst->port[0],
+ dst->port[1],
+ proto == IPPROTO_TCP ? "tcp" : "udp");
+ }
+}
+
+#ifdef HAVE_RULE_UGID
+void
+tb_print_ugid(u_int8_t op, unsigned u1, unsigned u2,
+ const char *t, unsigned umax)
+{
+ char a1[11], a2[11];
+
+ snprintf(a1, sizeof(a1), "%u", u1);
+ snprintf(a2, sizeof(a2), "%u", u2);
+
+ tbprintf("%s ", t);
+ if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE))
+ tb_print_op(op, "unknown", a2);
+ else
+ tb_print_op(op, a1, a2);
+}
+#endif
+
+void
+tb_print_flags(u_int8_t f)
+{
+ const char *tcpflags = "FSRPAUEW";
+ int i;
+
+ for (i = 0; tcpflags[i]; ++i)
+ if (f & (1 << i))
+ tbprintf("%c", tcpflags[i]);
+}
+
+void
+print_rule(struct pf_rule *pr)
+{
+ static const char *actiontypes[] = { "Pass", "Block", "Scrub", "Nat",
+ "no Nat", "Binat", "no Binat", "Rdr", "no Rdr" };
+ int numact = sizeof(actiontypes) / sizeof(char *);
+
+#ifdef HAVE_PF_ROUTE
+ static const char *routetypes[] = { "", "fastroute", "route-to",
+ "dup-to", "reply-to" };
+
+ int numroute = sizeof(routetypes) / sizeof(char *);
+#endif
+
+ if (pr == NULL) return;
+
+#ifdef HAVE_RULE_LABELS
+ print_fld_str(FLD_LABEL, pr->label);
+#endif
+#ifdef HAVE_RULE_STATES
+#ifdef HAVE_PFSYNC_KEY
+ print_fld_size(FLD_STATS, pr->states_tot);
+#else
+ print_fld_size(FLD_STATS, pr->states);
+#endif
+#endif
+
+#ifdef HAVE_INOUT_COUNT_RULES
+ print_fld_size(FLD_PKTS, pr->packets[0] + pr->packets[1]);
+ print_fld_size(FLD_BYTES, pr->bytes[0] + pr->bytes[1]);
+#else
+ print_fld_size(FLD_PKTS, pr->packets);
+ print_fld_size(FLD_BYTES, pr->bytes);
+#endif
+ print_fld_uint(FLD_RULE, pr->nr);
+ print_fld_str(FLD_DIR, pr->direction == PF_OUT ? "Out" : "In");
+ if (pr->quick)
+ print_fld_str(FLD_QUICK, "Quick");
+
+ if (pr->keep_state == PF_STATE_NORMAL)
+ print_fld_str(FLD_KST, "Keep");
+ else if (pr->keep_state == PF_STATE_MODULATE)
+ print_fld_str(FLD_KST, "Mod");
+#ifdef PF_STATE_SYNPROXY
+ else if (pr->keep_state == PF_STATE_MODULATE)
+ print_fld_str(FLD_KST, "Syn");
+#endif
+ if (pr->log == 1)
+ print_fld_str(FLD_LOG, "Log");
+ else if (pr->log == 2)
+ print_fld_str(FLD_LOG, "All");
+
+ if (pr->action >= numact)
+ print_fld_uint(FLD_ACTION, pr->action);
+ else print_fld_str(FLD_ACTION, actiontypes[pr->action]);
+
+ if (pr->proto) {
+ struct protoent *p = getprotobynumber(pr->proto);
+
+ if (p != NULL)
+ print_fld_str(FLD_PROTO, p->p_name);
+ else
+ print_fld_uint(FLD_PROTO, pr->proto);
+ }
+
+ if (pr->ifname[0]) {
+ tb_start();
+#ifdef HAVE_RULE_IFNOT
+ if (pr->ifnot)
+ tbprintf("!");
+#endif
+ tbprintf("%s", pr->ifname);
+ print_fld_tb(FLD_IF);
+ }
+#ifdef HAVE_MAX_STATES
+ if (pr->max_states)
+ print_fld_uint(FLD_STMAX, pr->max_states);
+#endif
+ /* print info field */
+
+ tb_start();
+
+#ifdef HAVE_RULE_NATPASS
+ if (pr->natpass)
+ tbprintf("pass ");
+#endif
+ if (pr->action == PF_DROP) {
+ if (pr->rule_flag & PFRULE_RETURNRST)
+ tbprintf("return-rst ");
+#ifdef PFRULE_RETURN
+ else if (pr->rule_flag & PFRULE_RETURN)
+ tbprintf("return ");
+#endif
+#ifdef PFRULE_RETURNICMP
+ else if (pr->rule_flag & PFRULE_RETURNICMP)
+ tbprintf("return-icmp ");
+#endif
+ else
+ tbprintf("drop ");
+ }
+
+#ifdef HAVE_PF_ROUTE
+ if (pr->rt > 0 && pr->rt < numroute) {
+ tbprintf("%s ", routetypes[pr->rt]);
+ if (pr->rt != PF_FASTROUTE)
+ tbprintf("... ");
+ }
+#endif
+ if (pr->af) {
+ if (pr->af == AF_INET)
+ tbprintf("inet ");
+ else
+ tbprintf("inet6 ");
+ }
+
+ tb_print_fromto(&pr->src, &pr->dst, pr->af, pr->proto);
+#ifdef HAVE_RULE_UGID
+ if (pr->uid.op)
+ tb_print_ugid(pr->uid.op, pr->uid.uid[0], pr->uid.uid[1],
+ "user", UID_MAX);
+ if (pr->gid.op)
+ tb_print_ugid(pr->gid.op, pr->gid.gid[0], pr->gid.gid[1],
+ "group", GID_MAX);
+#endif
+
+ if (pr->flags || pr->flagset) {
+ tbprintf(" flags ");
+ tb_print_flags(pr->flags);
+ tbprintf("/");
+ tb_print_flags(pr->flagset);
+ }
+
+ tbprintf(" ");
+
+#ifdef HAVE_RULE_TOS
+ if (pr->tos)
+ tbprintf("tos 0x%2.2x ", pr->tos);
+#endif
+#ifdef PFRULE_FRAGMENT
+ if (pr->rule_flag & PFRULE_FRAGMENT)
+ tbprintf("fragment ");
+#endif
+#ifdef PFRULE_NODF
+ if (pr->rule_flag & PFRULE_NODF)
+ tbprintf("no-df ");
+#endif
+#ifdef PFRULE_RANDOMID
+ if (pr->rule_flag & PFRULE_RANDOMID)
+ tbprintf("random-id ");
+#endif
+ if (pr->min_ttl)
+ tbprintf("min-ttl %d ", pr->min_ttl);
+#ifdef HAVE_MAX_MSS
+ if (pr->max_mss)
+ tbprintf("max-mss %d ", pr->max_mss);
+#endif
+ if (pr->allow_opts)
+ tbprintf("allow-opts ");
+
+ if (pr->action == PF_SCRUB) {
+#ifdef PFRULE_REASSEMBLE_TCP
+ if (pr->rule_flag & PFRULE_REASSEMBLE_TCP)
+ tbprintf("reassemble tcp ");
+#endif
+#ifdef PFRULE_FRAGDROP
+ if (pr->rule_flag & PFRULE_FRAGDROP)
+ tbprintf("fragment drop-ovl ");
+ else
+#endif
+#ifdef PFRULE_FRAGCROP
+ if (pr->rule_flag & PFRULE_FRAGCROP)
+ tbprintf("fragment crop ");
+ else
+#endif
+ tbprintf("fragment reassemble ");
+ }
+
+#ifdef HAVE_ALTQ
+ if (pr->qname[0] && pr->pqname[0])
+ tbprintf("queue(%s, %s) ", pr->qname, pr->pqname);
+ else if (pr->qname[0])
+ tbprintf("queue %s ", pr->qname);
+#endif
+#ifdef HAVE_TAGS
+ if (pr->tagname[0])
+ tbprintf("tag %s ", pr->tagname);
+ if (pr->match_tagname[0]) {
+ if (pr->match_tag_not)
+ tbprintf("! ");
+ tbprintf("tagged %s ", pr->match_tagname);
+ }
+#endif
+ print_fld_tb(FLD_RINFO);
+
+#ifdef HAVE_RULESETS
+ /* XXX anchor field overloaded with anchor name */
+ print_fld_str(FLD_ANCHOR, (char *)pr->anchor);
+#endif
+ tb_end();
+
+ end_line();
+}
+
+void
+print_rules(void)
+{
+ u_int32_t n, count = 0;
+
+ for (n = dispstart; n < num_rules; n++) {
+ print_rule(rules + n);
+ count ++;
+ if (maxprint > 0 && count >= maxprint)
+ break;
+ }
+}
+
+/* queue display */
+
+#ifdef HAVE_ALTQ
+
+struct pf_altq_node *
+pfctl_find_altq_node(struct pf_altq_node *root, const char *qname,
+ const char *ifname)
+{
+ struct pf_altq_node *node, *child;
+
+ for (node = root; node != NULL; node = node->next) {
+ if (!strcmp(node->altq.qname, qname)
+ && !(strcmp(node->altq.ifname, ifname)))
+ return (node);
+ if (node->children != NULL) {
+ child = pfctl_find_altq_node(node->children, qname,
+ ifname);
+ if (child != NULL)
+ return (child);
+ }
+ }
+ return (NULL);
+}
+
+void
+pfctl_insert_altq_node(struct pf_altq_node **root,
+ const struct pf_altq altq, const struct queue_stats qstats)
+{
+ struct pf_altq_node *node;
+
+ node = calloc(1, sizeof(struct pf_altq_node));
+ if (node == NULL)
+ err(1, "pfctl_insert_altq_node: calloc");
+ memcpy(&node->altq, &altq, sizeof(struct pf_altq));
+ memcpy(&node->qstats, &qstats, sizeof(qstats));
+ node->next = node->children = node->next_flat = NULL;
+ node->depth = 0;
+ node->visited = 1;
+
+ if (*root == NULL)
+ *root = node;
+ else if (!altq.parent[0]) {
+ struct pf_altq_node *prev = *root;
+
+ while (prev->next != NULL)
+ prev = prev->next;
+ prev->next = node;
+ } else {
+ struct pf_altq_node *parent;
+
+ parent = pfctl_find_altq_node(*root, altq.parent, altq.ifname);
+ if (parent == NULL)
+ errx(1, "parent %s not found", altq.parent);
+ node->depth = parent->depth+1;
+ if (parent->children == NULL)
+ parent->children = node;
+ else {
+ struct pf_altq_node *prev = parent->children;
+
+ while (prev->next != NULL)
+ prev = prev->next;
+ prev->next = node;
+ }
+ }
+ if (*root != node) {
+ struct pf_altq_node *prev_flat = *root;
+ while (prev_flat->next_flat != NULL) {
+ prev_flat = prev_flat->next_flat;
+ }
+ prev_flat->next_flat = node;
+ }
+}
+
+int
+pfctl_update_qstats(struct pf_altq_node **root, int *inserts)
+{
+ struct pf_altq_node *node;
+ struct pfioc_altq pa;
+ struct pfioc_qstats pq;
+ u_int32_t nr;
+ struct queue_stats qstats;
+ u_int32_t nr_queues;
+
+ *inserts = 0;
+ memset(&pa, 0, sizeof(pa));
+ memset(&pq, 0, sizeof(pq));
+ memset(&qstats, 0, sizeof(qstats));
+
+ if (pf_dev < 0)
+ return (-1);
+
+ if (ioctl(pf_dev, DIOCGETALTQS, &pa)) {
+ error("DIOCGETALTQS: %s", strerror(errno));
+ return (-1);
+ }
+ num_queues = nr_queues = pa.nr;
+ for (nr = 0; nr < nr_queues; ++nr) {
+ pa.nr = nr;
+ if (ioctl(pf_dev, DIOCGETALTQ, &pa)) {
+ error("DIOCGETALTQ: %s", strerror(errno));
+ return (-1);
+ }
+ if (pa.altq.qid > 0) {
+ pq.nr = nr;
+ pq.ticket = pa.ticket;
+ pq.buf = &qstats;
+ pq.nbytes = sizeof(qstats);
+ if (ioctl(pf_dev, DIOCGETQSTATS, &pq)) {
+ error("DIOCGETQSTATS: %s", strerror(errno));
+ return (-1);
+ }
+ qstats.valid = 1;
+ gettimeofday(&qstats.timestamp, NULL);
+ if ((node = pfctl_find_altq_node(*root, pa.altq.qname,
+ pa.altq.ifname)) != NULL) {
+ // update altq data too as bandwidth may have changed
+ memcpy(&node->altq, &pa.altq, sizeof(struct pf_altq));
+ memcpy(&node->qstats_last, &node->qstats,
+ sizeof(struct queue_stats));
+ memcpy(&node->qstats, &qstats,
+ sizeof(qstats));
+ node->visited = 1;
+ } else {
+ pfctl_insert_altq_node(root, pa.altq, qstats);
+ *inserts = 1;
+ }
+ }
+ else
+ --num_queues;
+ }
+ return (0);
+}
+
+void
+pfctl_free_altq_node(struct pf_altq_node *node)
+{
+ while (node != NULL) {
+ struct pf_altq_node *prev;
+
+ if (node->children != NULL)
+ pfctl_free_altq_node(node->children);
+ prev = node;
+ node = node->next;
+ free(prev);
+ }
+}
+
+void
+pfctl_mark_all_unvisited(struct pf_altq_node *root)
+{
+ if (root != NULL) {
+ struct pf_altq_node *node = root;
+ while (node != NULL) {
+ node->visited = 0;
+ node = node->next_flat;
+ }
+ }
+}
+
+int
+pfctl_have_unvisited(struct pf_altq_node *root)
+{
+ if (root == NULL)
+ return(0);
+ else {
+ struct pf_altq_node *node = root;
+ while (node != NULL) {
+ if (node->visited == 0)
+ return(1);
+ node = node->next_flat;
+ }
+ return(0);
+ }
+}
+
+struct pf_altq_node *altq_root = NULL;
+
+int
+select_queues(void)
+{
+ num_disp = num_queues;
+ return (0);
+}
+
+int
+read_queues(void)
+{
+ static int first_read = 1;
+ int inserts;
+ num_disp = num_queues = 0;
+
+ pfctl_mark_all_unvisited(altq_root);
+ if (pfctl_update_qstats(&altq_root, &inserts))
+ return (-1);
+
+ // Allow inserts only on first read;
+ // on subsequent reads clear and reload
+ if (first_read == 0 &&
+ (inserts != 0 || pfctl_have_unvisited(altq_root) != 0)) {
+ pfctl_free_altq_node(altq_root);
+ altq_root = NULL;
+ first_read = 1;
+ if (pfctl_update_qstats(&altq_root, &inserts))
+ return (-1);
+ }
+
+ first_read = 0;
+ num_disp = num_queues;
+
+ return(0);
+}
+
+double
+calc_interval(struct timeval *cur_time, struct timeval *last_time)
+{
+ double sec;
+
+ sec = (double)(cur_time->tv_sec - last_time->tv_sec) +
+ (double)(cur_time->tv_usec - last_time->tv_usec) / 1000000;
+
+ return (sec);
+}
+
+double
+calc_rate(u_int64_t new_bytes, u_int64_t last_bytes, double interval)
+{
+ double rate;
+
+ rate = (double)(new_bytes - last_bytes) / interval;
+ return (rate);
+}
+
+double
+calc_pps(u_int64_t new_pkts, u_int64_t last_pkts, double interval)
+{
+ double pps;
+
+ pps = (double)(new_pkts - last_pkts) / interval;
+ return (pps);
+}
+
+#define DEFAULT_PRIORITY 1
+
+void
+print_queue(struct pf_altq_node *node)
+{
+ u_int8_t d;
+ double interval, pps, bps;
+ pps = bps = 0;
+
+ tb_start();
+ for (d = 0; d < node->depth; d++)
+ tbprintf(" ");
+ tbprintf(node->altq.qname);
+ print_fld_tb(FLD_QUEUE);
+
+ if (node->altq.scheduler == ALTQT_CBQ ||
+ node->altq.scheduler == ALTQT_HFSC
+ )
+ print_fld_bw(FLD_BANDW, (double)node->altq.bandwidth);
+
+ if (node->altq.priority != DEFAULT_PRIORITY)
+ print_fld_uint(FLD_PRIO,
+ node->altq.priority);
+
+ if (node->qstats.valid && node->qstats_last.valid)
+ interval = calc_interval(&node->qstats.timestamp,
+ &node->qstats_last.timestamp);
+ else
+ interval = 0;
+
+ switch (node->altq.scheduler) {
+ case ALTQT_CBQ:
+ print_fld_str(FLD_SCHED, "cbq");
+ print_fld_size(FLD_PKTS,
+ node->qstats.data.cbq_stats.xmit_cnt.packets);
+ print_fld_size(FLD_BYTES,
+ node->qstats.data.cbq_stats.xmit_cnt.bytes);
+ print_fld_size(FLD_DROPP,
+ node->qstats.data.cbq_stats.drop_cnt.packets);
+ print_fld_size(FLD_DROPB,
+ node->qstats.data.cbq_stats.drop_cnt.bytes);
+ print_fld_size(FLD_QLEN, node->qstats.data.cbq_stats.qcnt);
+ print_fld_size(FLD_BORR, node->qstats.data.cbq_stats.borrows);
+ print_fld_size(FLD_SUSP, node->qstats.data.cbq_stats.delays);
+ if (interval > 0) {
+ pps = calc_pps(node->qstats.data.cbq_stats.xmit_cnt.packets,
+ node->qstats_last.data.cbq_stats.xmit_cnt.packets, interval);
+ bps = calc_rate(node->qstats.data.cbq_stats.xmit_cnt.bytes,
+ node->qstats_last.data.cbq_stats.xmit_cnt.bytes, interval);
+ }
+ break;
+ case ALTQT_PRIQ:
+ print_fld_str(FLD_SCHED, "priq");
+ print_fld_size(FLD_PKTS,
+ node->qstats.data.priq_stats.xmitcnt.packets);
+ print_fld_size(FLD_BYTES,
+ node->qstats.data.priq_stats.xmitcnt.bytes);
+ print_fld_size(FLD_DROPP,
+ node->qstats.data.priq_stats.dropcnt.packets);
+ print_fld_size(FLD_DROPB,
+ node->qstats.data.priq_stats.dropcnt.bytes);
+ print_fld_size(FLD_QLEN, node->qstats.data.priq_stats.qlength);
+ if (interval > 0) {
+ pps = calc_pps(node->qstats.data.priq_stats.xmitcnt.packets,
+ node->qstats_last.data.priq_stats.xmitcnt.packets, interval);
+ bps = calc_rate(node->qstats.data.priq_stats.xmitcnt.bytes,
+ node->qstats_last.data.priq_stats.xmitcnt.bytes, interval);
+ }
+ break;
+ case ALTQT_HFSC:
+ print_fld_str(FLD_SCHED, "hfsc");
+ print_fld_size(FLD_PKTS,
+ node->qstats.data.hfsc_stats.xmit_cnt.packets);
+ print_fld_size(FLD_BYTES,
+ node->qstats.data.hfsc_stats.xmit_cnt.bytes);
+ print_fld_size(FLD_DROPP,
+ node->qstats.data.hfsc_stats.drop_cnt.packets);
+ print_fld_size(FLD_DROPB,
+ node->qstats.data.hfsc_stats.drop_cnt.bytes);
+ print_fld_size(FLD_QLEN, node->qstats.data.hfsc_stats.qlength);
+ if (interval > 0) {
+ pps = calc_pps(node->qstats.data.hfsc_stats.xmit_cnt.packets,
+ node->qstats_last.data.hfsc_stats.xmit_cnt.packets, interval);
+ bps = calc_rate(node->qstats.data.hfsc_stats.xmit_cnt.bytes,
+ node->qstats_last.data.hfsc_stats.xmit_cnt.bytes, interval);
+ }
+ break;
+ }
+
+ /* if (node->altq.scheduler != ALTQT_HFSC && interval > 0) { */
+ if (node->altq.scheduler && interval > 0) {
+ tb_start();
+ if (pps > 0 && pps < 1)
+ tbprintf("%-3.1lf", pps);
+ else
+ tbprintf("%u", (unsigned int) pps);
+
+ print_fld_tb(FLD_PKTSPS);
+ print_fld_bw(FLD_BYTESPS, bps);
+ }
+}
+
+void
+print_queues(void)
+{
+ u_int32_t n, count = 0;
+ struct pf_altq_node *node = altq_root;
+
+ for (n = 0; n < dispstart; n++)
+ node = node->next_flat;
+
+ for (; n < num_disp; n++) {
+ print_queue(node);
+ node = node->next_flat;
+ end_line();
+ count ++;
+ if (maxprint > 0 && count >= maxprint)
+ break;
+ }
+}
+
+#endif /* HAVE_ALTQ */
+
+/* main program functions */
+
+void
+update_cache()
+{
+ static int pstate = -1;
+ if (pstate == cachestates)
+ return;
+
+ pstate = cachestates;
+ if (cachestates) {
+ show_field(FLD_SI);
+ show_field(FLD_SP);
+ gotsig_alarm = 1;
+ } else {
+ hide_field(FLD_SI);
+ hide_field(FLD_SP);
+ need_update = 1;
+ }
+ field_setup();
+}
+
+void
+initpftop(void)
+{
+ struct pf_status status;
+ field_view *v;
+ int cachesize = DEFAULT_CACHE_SIZE;
+
+ v = views;
+ while(v->name != NULL)
+ add_view(v++);
+
+ pf_dev = open("/dev/pf", O_RDONLY);
+ if (pf_dev == -1) {
+ alloc_buf(0);
+ warn("open(\"/dev/pf\")");
+ } else if (ioctl(pf_dev, DIOCGETSTATUS, &status)) {
+ warn("DIOCGETSTATUS");
+ alloc_buf(0);
+ } else
+ alloc_buf(status.states);
+
+ /* initialize cache with given size */
+ if (cache_init(cachesize))
+ warnx("Failed to initialize cache.");
+ else if (interactive && cachesize > 0)
+ cachestates = 1;
+
+ update_cache();
+
+#ifdef HAVE_MAX_STATES
+ show_field(FLD_STMAX);
+#endif
+#ifdef HAVE_RULESETS
+ show_field(FLD_ANCHOR);
+#endif
+
+}
diff --git a/usr.bin/systat/pigs.c b/usr.bin/systat/pigs.c
index 46b36311559..0d57af6a476 100644
--- a/usr.bin/systat/pigs.c
+++ b/usr.bin/systat/pigs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pigs.c,v 1.21 2007/09/02 15:19:35 deraadt Exp $ */
+/* $OpenBSD: pigs.c,v 1.22 2008/06/12 22:26:01 canacar Exp $ */
/* $NetBSD: pigs.c,v 1.3 1995/04/29 05:54:50 cgd Exp $ */
/*-
@@ -30,13 +30,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)pigs.c 8.2 (Berkeley) 9/23/93";
-#endif
-static char rcsid[] = "$OpenBSD: pigs.c,v 1.21 2007/09/02 15:19:35 deraadt Exp $";
-#endif /* not lint */
-
/*
* Pigs display from Bill Reeves at Lucasfilm
*/
@@ -56,178 +49,252 @@ static char rcsid[] = "$OpenBSD: pigs.c,v 1.21 2007/09/02 15:19:35 deraadt Exp $
#include <stdlib.h>
#include <string.h>
-#include "extern.h"
#include "systat.h"
int compar(const void *, const void *);
+void print_pg(void);
+int read_pg(void);
+int select_pg(void);
+void showpigs(int k);
-static int nproc;
-static struct p_times {
- float pt_pctcpu;
- struct kinfo_proc2 *pt_kp;
-} *pt;
+static struct kinfo_proc2 *procbase = NULL;
+static int nproc, pigs_cnt, *pb_indices = NULL;
+static int onproc = -1;
static long stime[CPUSTATES];
static double lccpu;
+struct loadavg sysload;
-WINDOW *
-openpigs(void)
-{
- return (subwin(stdscr, LINES-1-2, 0, 2, 0));
-}
-void
-closepigs(WINDOW *w)
-{
- if (w == NULL)
- return;
- wclear(w);
- wrefresh(w);
- delwin(w);
-}
+field_def fields_pg[] = {
+ {"USER", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"NAME", 10, 24, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"PID", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"CPU", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"", 30, 60, 1, FLD_ALIGN_BAR, -1, 0, 0, 100},
+};
-void
-showpigs(void)
-{
- int i, j, y, k;
- struct kinfo_proc2 *kp;
- float total;
- int factor;
- char *uname, *pname, pidname[30];
+#define FIELD_ADDR(x) (&fields_pg[x])
- if (pt == NULL)
- return;
- /* Accumulate the percent of cpu per user. */
- total = 0.0;
- for (i = 0; i <= nproc; i++) {
- /* Accumulate the percentage. */
- total += pt[i].pt_pctcpu;
- }
+#define FLD_PG_USER FIELD_ADDR(0)
+#define FLD_PG_NAME FIELD_ADDR(1)
+#define FLD_PG_PID FIELD_ADDR(2)
+#define FLD_PG_VALUE FIELD_ADDR(3)
+#define FLD_PG_BAR FIELD_ADDR(4)
- if (total < 1.0)
- total = 1.0;
- factor = 50.0/total;
-
- qsort(pt, nproc + 1, sizeof (struct p_times), compar);
- y = 1;
- i = nproc + 1;
- if (i > wnd->_maxy-1)
- i = wnd->_maxy-1;
- for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
- kp = pt[k].pt_kp;
- if (kp == NULL) {
- uname = "";
- pname = "<idle>";
- } else {
- uname = user_from_uid(kp->p_uid, 0);
- pname = kp->p_comm;
- }
- wmove(wnd, y, 0);
- wclrtoeol(wnd);
- mvwaddstr(wnd, y, 0, uname);
- snprintf(pidname, sizeof pidname, "%10.10s", pname);
- mvwaddstr(wnd, y, 9, pidname);
- wmove(wnd, y, 20);
- for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--)
- waddch(wnd, 'X');
- }
- wmove(wnd, y, 0); wclrtobot(wnd);
+/* Define views */
+field_def *view_pg_0[] = {
+ FLD_PG_PID, FLD_PG_USER, FLD_PG_NAME, FLD_PG_VALUE, FLD_PG_BAR, NULL
+};
+
+
+/* Define view managers */
+struct view_manager pigs_mgr = {
+ "Pigs", select_pg, read_pg, NULL, print_header,
+ print_pg, keyboard_callback, NULL, NULL
+};
+
+field_view views_pg[] = {
+ {view_pg_0, "pigs", '5', &pigs_mgr},
+ {NULL, NULL, 0, NULL}
+};
+
+
+#ifdef FSCALE
+# define FIXED_LOADAVG FSCALE
+# define FIXED_PCTCPU FSCALE
+#endif
+
+#ifdef FIXED_PCTCPU
+ typedef long pctcpu;
+# define pctdouble(p) ((double)(p) / FIXED_PCTCPU)
+#else
+typedef double pctcpu;
+# define pctdouble(p) (p)
+#endif
+
+int
+select_pg(void)
+{
+ num_disp = pigs_cnt;
+ return (0);
}
-struct loadavg sysload;
int
-initpigs(void)
+getprocs(void)
{
- static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
- static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
- static int ccpu_mib[] = { CTL_KERN, KERN_CCPU };
size_t size;
- fixpt_t ccpu;
+ int mib[6] = {CTL_KERN, KERN_PROC2, KERN_PROC_KTHREAD, 0, sizeof(struct kinfo_proc2), 0};
+
+ int st;
- size = sizeof(stime);
- (void) sysctl(cp_time_mib, 2, &stime, &size, NULL, 0);
+ free(procbase);
+ procbase = NULL;
- size = sizeof(sysload);
- (void) sysctl(sysload_mib, 2, &sysload, &size, NULL, 0);
+ st = sysctl(mib, 6, NULL, &size, NULL, 0);
+ if (st == -1)
+ return (1);
- size = sizeof(ccpu);
- (void) sysctl(ccpu_mib, 2, &ccpu, &size, NULL, 0);
+ size = 5 * size / 4; /* extra slop */
+ if ((procbase = malloc(size + 1)) == NULL)
+ return (1);
- lccpu = log((double) ccpu / sysload.fscale);
+ mib[5] = (int)(size / sizeof(struct kinfo_proc2));
+ st = sysctl(mib, 6, procbase, &size, NULL, 0);
+ if (st == -1)
+ return (1);
- return(1);
+ nproc = (int)(size / sizeof(struct kinfo_proc2));
+ return (0);
}
-void
-fetchpigs(void)
+
+int
+read_pg(void)
{
static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
- static int lastnproc = 0;
- struct kinfo_proc2 *kpp;
long ctime[CPUSTATES];
double t;
- int i;
+ int i, k;
size_t size;
- float *pctp;
- kpp = kvm_getproc2(kd, KERN_PROC_KTHREAD, 0, sizeof(*kpp), &nproc);
- if (kpp == NULL) {
- error("%s", kvm_geterr(kd));
- if (pt)
- free(pt);
- return;
+ num_disp = pigs_cnt = 0;
+
+ if (getprocs()) {
+ error("Failed to read process info!");
+ return 1;
}
- if (nproc > lastnproc) {
- free(pt);
- if ((pt = calloc(nproc + 1, sizeof(struct p_times))) == NULL) {
- error("Out of memory");
- die();
+
+ if (nproc > onproc) {
+ int *p;
+ p = realloc(pb_indices, (nproc + 1) * sizeof(int));
+ if (p == NULL) {
+ error("Out of Memory!");
+ return 1;
}
+ pb_indices = p;
+ onproc = nproc;
}
- lastnproc = nproc;
- /*
- * calculate %cpu for each proc
- */
- for (i = 0; i < nproc; i++) {
- pt[i].pt_kp = &kpp[i];
- pctp = &pt[i].pt_pctcpu;
- if (kpp->p_swtime == 0)
- *pctp = 0;
- else
- *pctp = ((double) kpp->p_pctcpu / sysload.fscale) /
- (1.0 - exp(kpp->p_swtime * lccpu));
- }
+
+ memset(&procbase[nproc], 0, sizeof(*procbase));
+
+ for (i = 0; i <= nproc; i++)
+ pb_indices[i] = i;
+
/*
* and for the imaginary "idle" process
*/
size = sizeof(ctime);
- (void) sysctl(cp_time_mib, 2, &ctime, &size, NULL, 0);
+ sysctl(cp_time_mib, 2, &ctime, &size, NULL, 0);
t = 0;
for (i = 0; i < CPUSTATES; i++)
t += ctime[i] - stime[i];
if (t == 0.0)
t = 1.0;
- pt[nproc].pt_kp = NULL;
- pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
+
+ procbase[nproc].p_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t / pctdouble(1);
for (i = 0; i < CPUSTATES; i++)
stime[i] = ctime[i];
+
+ qsort(pb_indices, nproc + 1, sizeof (int), compar);
+
+ pigs_cnt = 0;
+ for (k = 0; k < nproc + 1; k++) {
+ int i = pb_indices[k];
+ if (pctdouble(procbase[i].p_pctcpu) < 0.01)
+ break;
+ pigs_cnt++;
+ }
+
+ num_disp = pigs_cnt;
+ return 0;
}
+
void
-labelpigs(void)
+print_pg(void)
{
- wmove(wnd, 0, 0);
- wclrtoeol(wnd);
- mvwaddstr(wnd, 0, 20,
- "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
+ int n, count = 0;
+
+ for (n = dispstart; n < num_disp; n++) {
+ showpigs(pb_indices[n]);
+ count++;
+ if (maxprint > 0 && count >= maxprint)
+ break;
+ }
}
int
+initpigs(void)
+{
+ static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
+ static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
+ static int ccpu_mib[] = { CTL_KERN, KERN_CCPU };
+ field_view *v;
+ size_t size;
+ fixpt_t ccpu;
+
+ size = sizeof(stime);
+ sysctl(cp_time_mib, 2, &stime, &size, NULL, 0);
+
+ size = sizeof(sysload);
+ sysctl(sysload_mib, 2, &sysload, &size, NULL, 0);
+
+ size = sizeof(ccpu);
+ sysctl(ccpu_mib, 2, &ccpu, &size, NULL, 0);
+
+ lccpu = log((double) ccpu / sysload.fscale);
+
+ for (v = views_pg; v->name != NULL; v++)
+ add_view(v);
+
+ return(1);
+}
+
+void
+showpigs(int k)
+{
+ struct kinfo_proc2 *kp;
+ double value;
+ char *uname, *pname;
+
+ if (procbase == NULL)
+ return;
+
+ value = pctdouble(procbase[k].p_pctcpu) * 100;
+
+ kp = &procbase[k];
+ if (kp->p_comm[0] == '\0') {
+ uname = "";
+ pname = "<idle>";
+ } else {
+ uname = user_from_uid(kp->p_uid, 0);
+ pname = kp->p_comm;
+ print_fld_uint(FLD_PG_PID, kp->p_pid);
+ }
+
+ tb_start();
+ tbprintf("%.2f", value);
+ print_fld_tb(FLD_PG_VALUE);
+
+ print_fld_str(FLD_PG_NAME, pname);
+ print_fld_str(FLD_PG_USER, uname);
+ print_fld_bar(FLD_PG_BAR, value);
+
+ end_line();
+}
+
+
+int
compar(const void *a, const void *b)
{
- return (((struct p_times *)a)->pt_pctcpu >
- ((struct p_times *)b)->pt_pctcpu) ? -1 : 1;
+ int i1 = *((int *)a);
+ int i2 = *((int *)b);
+
+ return procbase[i1].p_pctcpu >
+ procbase[i2].p_pctcpu ? -1 : 1;
}
+
diff --git a/usr.bin/systat/sensors.c b/usr.bin/systat/sensors.c
index 98e6c56ecb9..65c0c28f3d4 100644
--- a/usr.bin/systat/sensors.c
+++ b/usr.bin/systat/sensors.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sensors.c,v 1.12 2007/07/29 04:51:59 cnst Exp $ */
+/* $OpenBSD: sensors.c,v 1.13 2008/06/12 22:26:01 canacar Exp $ */
/*
* Copyright (c) 2007 Deanna Phillips <deanna@openbsd.org>
@@ -27,178 +27,261 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-
+#include <string.h>
#include "systat.h"
-#include "extern.h"
struct sensor sensor;
struct sensordev sensordev;
-int row, sensor_cnt;
-void printline(void);
-static char * fmttime(double);
-WINDOW *
-opensensors(void)
-{
- return (subwin(stdscr, LINES-1-1, 0, 1, 0));
-}
+struct sensinfo {
+ int sn_dev;
+ struct sensor sn_sensor;
+};
+#define sn_type sn_sensor.type
+#define sn_numt sn_sensor.numt
+#define sn_desc sn_sensor.desc
+#define sn_status sn_sensor.status
+#define sn_value sn_sensor.value
-void
-closesensors(WINDOW *w)
+char *devnames[MAXSENSORDEVICES];
+
+#define ADD_ALLOC 100
+static size_t sensor_cnt = 0;
+static size_t num_alloc = 0;
+static struct sensinfo *sensors = NULL;
+
+static char *fmttime(double);
+static void showsensor(struct sensinfo *s);
+
+void print_sn(void);
+int read_sn(void);
+int select_sn(void);
+
+const char *drvstat[] = {
+ NULL,
+ "empty", "ready", "powerup", "online", "idle", "active",
+ "rebuild", "powerdown", "fail", "pfail"
+};
+
+
+field_def fields_sn[] = {
+ {"SENSOR", 16, 32, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"VALUE", 16, 20, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"STATUS", 5, 8, 1, FLD_ALIGN_CENTER, -1, 0, 0, 0},
+ {"DESCRIPTION", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}
+};
+
+#define FIELD_ADDR(x) (&fields_sn[x])
+
+#define FLD_SN_SENSOR FIELD_ADDR(0)
+#define FLD_SN_VALUE FIELD_ADDR(1)
+#define FLD_SN_STATUS FIELD_ADDR(2)
+#define FLD_SN_DESCR FIELD_ADDR(3)
+
+/* Define views */
+field_def *view_sn_0[] = {
+ FLD_SN_SENSOR, FLD_SN_VALUE, FLD_SN_STATUS, FLD_SN_DESCR, NULL
+};
+
+
+/* Define view managers */
+struct view_manager sensors_mgr = {
+ "Sensors", select_sn, read_sn, NULL, print_header,
+ print_sn, keyboard_callback, NULL, NULL
+};
+
+field_view views_sn[] = {
+ {view_sn_0, "sensors", '3', &sensors_mgr},
+ {NULL, NULL, 0, NULL}
+};
+
+struct sensinfo *
+next_sn(void)
{
- if (w == NULL)
- return;
- wclear(w);
- wrefresh(w);
- delwin(w);
+ if (num_alloc <= sensor_cnt) {
+ struct sensinfo *s;
+ size_t a = num_alloc + ADD_ALLOC;
+ if (a < num_alloc)
+ return NULL;
+ s = realloc(sensors, a * sizeof(struct sensinfo));
+ if (s == NULL)
+ return NULL;
+ sensors = s;
+ num_alloc = a;
+ }
+
+ return &sensors[sensor_cnt++];
}
-void
-labelsensors(void)
+
+int
+select_sn(void)
{
- wmove(wnd, 0, 0);
- wclrtobot(wnd);
- mvwaddstr(wnd, 1, 0, "Sensor");
- mvwaddstr(wnd, 1, 34, "Value");
- mvwaddstr(wnd, 1, 45, "Status");
- mvwaddstr(wnd, 1, 58, "Description");
+ num_disp = sensor_cnt;
+ return (0);
}
-void
-fetchsensors(void)
+int
+read_sn(void)
{
enum sensor_type type;
size_t slen, sdlen;
int mib[5], dev, numt;
+ struct sensinfo *s;
mib[0] = CTL_HW;
mib[1] = HW_SENSORS;
- slen = sizeof(struct sensor);
- sdlen = sizeof(struct sensordev);
- row = 2;
sensor_cnt = 0;
- wmove(wnd, row, 0);
- wclrtobot(wnd);
-
for (dev = 0; dev < MAXSENSORDEVICES; dev++) {
mib[2] = dev;
+ sdlen = sizeof(struct sensordev);
if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
if (errno != ENOENT)
- warn("sysctl");
+ error("sysctl: %s", strerror(errno));
continue;
}
+
+ if (devnames[dev] && strcmp(devnames[dev], sensordev.xname)) {
+ free(devnames[dev]);
+ devnames[dev] = NULL;
+ }
+ if (devnames[dev] == NULL)
+ devnames[dev] = strdup(sensordev.xname);
+
for (type = 0; type < SENSOR_MAX_TYPES; type++) {
mib[3] = type;
for (numt = 0; numt < sensordev.maxnumt[type]; numt++) {
mib[4] = numt;
+ slen = sizeof(struct sensor);
if (sysctl(mib, 5, &sensor, &slen, NULL, 0)
== -1) {
if (errno != ENOENT)
- warn("sysctl");
+ error("sysctl: %s", strerror(errno));
continue;
}
if (sensor.flags & SENSOR_FINVALID)
continue;
- sensor_cnt++;
- printline();
+
+ s = next_sn();
+ s->sn_sensor = sensor;
+ s->sn_dev = dev;
}
}
}
+
+ num_disp = sensor_cnt;
+ return 0;
}
-const char *drvstat[] = {
- NULL,
- "empty", "ready", "powerup", "online", "idle", "active",
- "rebuild", "powerdown", "fail", "pfail"
-};
void
-showsensors(void)
+print_sn(void)
{
- if (sensor_cnt == 0)
- mvwaddstr(wnd, row, 0, "No sensors found.");
+ int n, count = 0;
+
+ for (n = dispstart; n < num_disp; n++) {
+ showsensor(sensors + n);
+ count++;
+ if (maxprint > 0 && count >= maxprint)
+ break;
+ }
}
int
initsensors(void)
{
- return (1);
+ field_view *v;
+
+ memset(devnames, 0, sizeof(devnames));
+
+ for (v = views_sn; v->name != NULL; v++)
+ add_view(v);
+
+ return(1);
}
-void
-printline(void)
+static void
+showsensor(struct sensinfo *s)
{
- mvwprintw(wnd, row, 0, "%s.%s%d", sensordev.xname,
- sensor_type_s[sensor.type], sensor.numt);
- switch (sensor.type) {
+ tb_start();
+ tbprintf("%s.%s%d", devnames[s->sn_dev],
+ sensor_type_s[s->sn_type], s->sn_numt);
+ print_fld_tb(FLD_SN_SENSOR);
+
+ if (s->sn_desc[0] != '\0')
+ print_fld_str(FLD_SN_DESCR, s->sn_desc);
+
+ tb_start();
+
+ switch (s->sn_type) {
case SENSOR_TEMP:
- mvwprintw(wnd, row, 24, "%10.2f degC",
- (sensor.value - 273150000) / 1000000.0);
+ tbprintf("%10.2f degC",
+ (s->sn_value - 273150000) / 1000000.0);
break;
case SENSOR_FANRPM:
- mvwprintw(wnd, row, 24, "%11lld RPM", sensor.value);
+ tbprintf("%11lld RPM", s->sn_value);
break;
case SENSOR_VOLTS_DC:
- mvwprintw(wnd, row, 24, "%10.2f V DC",
- sensor.value / 1000000.0);
+ tbprintf("%10.2f V DC",
+ s->sn_value / 1000000.0);
break;
case SENSOR_AMPS:
- mvwprintw(wnd, row, 24, "%10.2f A", sensor.value / 1000000.0);
+ tbprintf("%10.2f A", s->sn_value / 1000000.0);
break;
case SENSOR_INDICATOR:
- mvwprintw(wnd, row, 24, "%15s", sensor.value? "On" : "Off");
+ tbprintf("%15s", s->sn_value ? "On" : "Off");
break;
case SENSOR_INTEGER:
- mvwprintw(wnd, row, 24, "%11lld raw", sensor.value);
+ tbprintf("%11lld raw", s->sn_value);
break;
case SENSOR_PERCENT:
- mvwprintw(wnd, row, 24, "%14.2f%%", sensor.value / 1000.0);
+ tbprintf("%14.2f%%", s->sn_value / 1000.0);
break;
case SENSOR_LUX:
- mvwprintw(wnd, row, 24, "%15.2f lx", sensor.value / 1000000.0);
+ tbprintf("%15.2f lx", s->sn_value / 1000000.0);
break;
case SENSOR_DRIVE:
- if (0 < sensor.value &&
- sensor.value < sizeof(drvstat)/sizeof(drvstat[0])) {
- mvwprintw(wnd, row, 24, "%15s", drvstat[sensor.value]);
+ if (0 < s->sn_value &&
+ s->sn_value < sizeof(drvstat)/sizeof(drvstat[0])) {
+ tbprintf("%15s", drvstat[s->sn_value]);
break;
}
break;
case SENSOR_TIMEDELTA:
- mvwprintw(wnd, row, 24, "%15s", fmttime(sensor.value / 1000000000.0));
+ tbprintf("%15s", fmttime(s->sn_value / 1000000000.0));
break;
case SENSOR_WATTHOUR:
- mvwprintw(wnd, row, 24, "%12.2f Wh", sensor.value / 1000000.0);
+ tbprintf("%12.2f Wh", s->sn_value / 1000000.0);
break;
case SENSOR_AMPHOUR:
- mvwprintw(wnd, row, 24, "%10.2f Ah", sensor.value / 1000000.0);
+ tbprintf("%10.2f Ah", s->sn_value / 1000000.0);
break;
default:
- mvwprintw(wnd, row, 24, "%10lld", sensor.value);
+ tbprintf("%10lld", s->sn_value);
break;
}
- if (sensor.desc[0] != '\0')
- mvwprintw(wnd, row, 58, "(%s)", sensor.desc);
- switch (sensor.status) {
+ print_fld_tb(FLD_SN_VALUE);
+
+ switch (s->sn_status) {
case SENSOR_S_UNSPEC:
break;
case SENSOR_S_UNKNOWN:
- mvwaddstr(wnd, row, 45, "unknown");
+ print_fld_str(FLD_SN_STATUS, "unknown");
break;
case SENSOR_S_WARN:
- mvwaddstr(wnd, row, 45, "WARNING");
+ print_fld_str(FLD_SN_STATUS, "WARNING");
break;
case SENSOR_S_CRIT:
- mvwaddstr(wnd, row, 45, "CRITICAL");
+ print_fld_str(FLD_SN_STATUS, "CRITICAL");
break;
case SENSOR_S_OK:
- mvwaddstr(wnd, row, 45, "OK");
+ print_fld_str(FLD_SN_STATUS, "OK");
break;
}
- row++;
+ end_line();
}
#define SECS_PER_DAY 86400
diff --git a/usr.bin/systat/swap.c b/usr.bin/systat/swap.c
index 84e55190b2b..1d8fb80c481 100644
--- a/usr.bin/systat/swap.c
+++ b/usr.bin/systat/swap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: swap.c,v 1.20 2007/09/01 19:32:19 deraadt Exp $ */
+/* $OpenBSD: swap.c,v 1.21 2008/06/12 22:26:01 canacar Exp $ */
/* $NetBSD: swap.c,v 1.9 1998/12/26 07:05:08 marc Exp $ */
/*-
@@ -31,13 +31,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)swap.c 8.3 (Berkeley) 4/29/95";
-#endif
-static char rcsid[] = "$OpenBSD: swap.c,v 1.20 2007/09/01 19:32:19 deraadt Exp $";
-#endif /* not lint */
-
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/buf.h>
@@ -53,123 +46,180 @@ static char rcsid[] = "$OpenBSD: swap.c,v 1.20 2007/09/01 19:32:19 deraadt Exp $
#include <unistd.h>
#include "systat.h"
-#include "extern.h"
+
static long blocksize;
static int hlen, nswap, rnswap;
-static int first = 1;
static struct swapent *swap_devices;
-WINDOW *
-openswap(void)
-{
- return (subwin(stdscr, LINES-1-2, 0, 2, 0));
-}
+void print_sw(void);
+int read_sw(void);
+int select_sw(void);
+static void showswap(int i);
+static void showtotal(void);
+
+
+field_def fields_sw[] = {
+ {"DISK", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
+ {"BLOCKS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"USED", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+ {"", 40, 80, 1, FLD_ALIGN_BAR, -1, 0, 0, 100},
+};
+
+#define FIELD_ADDR(x) (&fields_sw[x])
+
+#define FLD_SW_NAME FIELD_ADDR(0)
+#define FLD_SW_BLOCKS FIELD_ADDR(1)
+#define FLD_SW_USED FIELD_ADDR(2)
+#define FLD_SW_BAR FIELD_ADDR(3)
+
+/* Define views */
+field_def *view_sw_0[] = {
+ FLD_SW_NAME, FLD_SW_BLOCKS, FLD_SW_USED, FLD_SW_BAR, NULL
+};
+
+
+/* Define view managers */
+struct view_manager swap_mgr = {
+ "Swap", select_sw, read_sw, NULL, print_header,
+ print_sw, keyboard_callback, NULL, NULL
+};
+
+field_view views_sw[] = {
+ {view_sw_0, "swap", '6', &swap_mgr},
+ {NULL, NULL, 0, NULL}
+};
-void
-closeswap(WINDOW *w)
-{
- if (w == NULL)
- return;
- wclear(w);
- wrefresh(w);
- delwin(w);
-}
-/* do nothing */
int
-initswap(void)
+select_sw(void)
{
- return (1);
+ if (swap_devices == NULL || nswap == 0)
+ num_disp = 1;
+ else
+ num_disp = nswap;
+ if (nswap > 1)
+ num_disp++;
+ return (0);
}
-void
-fetchswap(void)
+int
+read_sw(void)
{
- int update_label = 0;
+ num_disp = 1;
- first = 0;
nswap = swapctl(SWAP_NSWAP, 0, 0);
+
if (nswap < 0)
error("error: %s", strerror(errno));
if (nswap == 0)
- return;
- update_label = (nswap != rnswap);
+ return 0;
if (swap_devices)
(void)free(swap_devices);
+
swap_devices = (struct swapent *)calloc(nswap, sizeof(*swap_devices));
if (swap_devices == NULL)
- /* XXX */ ; /* XXX systat doesn't do errors! */
+ return 0;
rnswap = swapctl(SWAP_STATS, (void *)swap_devices, nswap);
- if (nswap < 0)
- /* XXX */ ; /* XXX systat doesn't do errors! */
- if (nswap != rnswap)
- /* XXX */ ; /* XXX systat doesn't do errors! */
- if (update_label)
- labelswap();
+ if (rnswap < 0 || nswap != rnswap)
+ return 0;
+
+ num_disp = nswap;
+ if (nswap > 1)
+ num_disp++;
+
+ return 0;
}
+
void
-labelswap(void)
+print_sw(void)
{
- char *header;
- int row;
-
- row = 0;
- wmove(wnd, row, 0);
- wclrtobot(wnd);
- if (first)
- fetchswap();
- if (nswap == 0) {
- mvwprintw(wnd, row++, 0, "No swap");
+ int n, count = 0;
+
+ if (swap_devices == NULL || nswap == 0) {
+ print_fld_str(FLD_SW_BAR, "No swap devices");
return;
}
- header = getbsize(&hlen, &blocksize);
- mvwprintw(wnd, row++, 0, "%-5s%*s%9s %55s",
- "Disk", hlen, header, "Used",
- "/0% /10% /20% /30% /40% /50% /60% /70% /80% /90% /100%");
+
+
+ for (n = dispstart; n < num_disp; n++) {
+ if (n >= nswap)
+ showtotal();
+ else
+ showswap(n);
+ count++;
+ if (maxprint > 0 && count >= maxprint)
+ break;
+ }
+
}
-void
-showswap(void)
+int
+initswap(void)
+{
+ field_view *v;
+
+ char *bs = getbsize(&hlen, &blocksize);
+
+ FLD_SW_BLOCKS->title = strdup(bs);
+
+ for (v = views_sw; v->name != NULL; v++)
+ add_view(v);
+
+ return(1);
+}
+
+
+static void
+showswap(int i)
{
- int col, div, i, j, avail, used, xsize, free;
+ int div, used, xsize;
struct swapent *sep;
char *p;
div = blocksize / 512;
- free = avail = 0;
- for (sep = swap_devices, i = 0; i < nswap; i++, sep++) {
- if (sep == NULL)
- continue;
- p = strrchr(sep->se_path, '/');
- p = p ? p+1 : sep->se_path;
+ sep = &swap_devices[i];
+
+ p = strrchr(sep->se_path, '/');
+ p = p ? p+1 : sep->se_path;
+
+ print_fld_str(FLD_SW_NAME, p);
+
+ xsize = sep->se_nblks;
+ used = sep->se_inuse;
+
+ print_fld_uint(FLD_SW_BLOCKS, xsize / div);
+ print_fld_uint(FLD_SW_USED, used / div);
+ print_fld_bar(FLD_SW_BAR, 100 * used / xsize);
- mvwprintw(wnd, i + 1, 0, "%-5s", p);
+ end_line();
+}
+
+static void
+showtotal(void)
+{
+ struct swapent *sep;
+ int div, i, avail, used, xsize, free;
- col = 5;
- mvwprintw(wnd, i + 1, col, "%*d", hlen, sep->se_nblks / div);
+ div = blocksize / 512;
+ free = avail = 0;
- col += hlen;
+ for (sep = swap_devices, i = 0; i < nswap; i++, sep++) {
xsize = sep->se_nblks;
used = sep->se_inuse;
avail += xsize;
free += xsize - used;
- mvwprintw(wnd, i + 1, col, "%9d ", used / div);
- for (j = (100 * used / xsize + 1) / 2; j > 0; j--)
- waddch(wnd, 'X');
- wclrtoeol(wnd);
- }
- /* do total if necessary */
- if (nswap > 1) {
- used = avail - free;
- mvwprintw(wnd, i + 1, 0, "%-5s%*d%9d ",
- "Total", hlen, avail / div, used / div);
- for (j = (100 * used / avail + 1) / 2; j > 0; j--)
- waddch(wnd, 'X');
- wclrtoeol(wnd);
}
+ used = avail - free;
+
+ print_fld_str(FLD_SW_NAME, "Total");
+ print_fld_uint(FLD_SW_BLOCKS, avail / div);
+ print_fld_uint(FLD_SW_USED, used / div);
+ print_fld_bar(FLD_SW_BAR, 100 * used / avail);
+
+ end_line();
}
diff --git a/usr.bin/systat/systat.h b/usr.bin/systat/systat.h
index 0175357cde4..dfd6742128a 100644
--- a/usr.bin/systat/systat.h
+++ b/usr.bin/systat/systat.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: systat.h,v 1.8 2003/06/03 02:56:17 millert Exp $ */
+/* $OpenBSD: systat.h,v 1.9 2008/06/12 22:26:01 canacar Exp $ */
/* $NetBSD: systat.h,v 1.2 1995/01/20 08:52:14 jtc Exp $ */
/*-
@@ -32,19 +32,14 @@
* @(#)systat.h 8.1 (Berkeley) 6/6/93
*/
-#include <curses.h>
+#ifndef _SYSTAT_H_
+#define _SYSTAT_H_
+
+#include <sys/cdefs.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include "engine.h"
-struct cmdtab {
- char *c_name; /* command name */
- void (*c_refresh)(void); /* display refresh */
- void (*c_fetch)(void); /* sets up data structures */
- void (*c_label)(void); /* label display */
- int (*c_init)(void); /* initialize namelist, etc. */
- WINDOW *(*c_open)(void); /* open display */
- void (*c_close)(WINDOW *); /* close display */
- int (*c_cmd)(char *, char *); /* display command interpreter */
- char c_flags; /* see below */
-};
#define CF_INIT 0x1 /* been initialized */
#define CF_LOADAV 0x2 /* display w/ load average */
@@ -56,3 +51,39 @@ struct cmdtab {
#define NVAL(indx) namelist[(indx)].n_value
#define NPTR(indx) (void *)NVAL((indx))
#define NREAD(indx, buf, len) kvm_ckread(NPTR((indx)), (buf), (len))
+int kvm_ckread(void *, void *, size_t);
+
+extern char **dr_name;
+extern char hostname[];
+extern double avenrun[3];
+extern kvm_t *kd;
+extern long ntext;
+extern int *dk_select;
+extern int dk_ndrive;
+extern int hz, stathz;
+extern double naptime;
+extern size_t nhosts;
+extern size_t nports;
+extern int protos;
+extern int verbose;
+extern int nflag;
+
+struct inpcb;
+
+void die(void);
+int print_header(void);
+int keyboard_callback(int);
+int initnetstat(void);
+int initifstat(void);
+int initiostat(void);
+int initsensors(void);
+int initmembufs(void);
+int initpigs(void);
+int initswap(void);
+int initvmstat(void);
+int initpf(void);
+
+void error(const char *fmt, ...);
+void nlisterr(struct nlist []);
+
+#endif
diff --git a/usr.bin/systat/vmstat.c b/usr.bin/systat/vmstat.c
index c79b7c7f5ac..c8e33e69a0c 100644
--- a/usr.bin/systat/vmstat.c
+++ b/usr.bin/systat/vmstat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmstat.c,v 1.63 2007/09/01 19:32:19 deraadt Exp $ */
+/* $OpenBSD: vmstat.c,v 1.64 2008/06/12 22:26:01 canacar Exp $ */
/* $NetBSD: vmstat.c,v 1.5 1996/05/10 23:16:40 thorpej Exp $ */
/*-
@@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 1/12/94";
#endif
-static char rcsid[] = "$OpenBSD: vmstat.c,v 1.63 2007/09/01 19:32:19 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: vmstat.c,v 1.64 2008/06/12 22:26:01 canacar Exp $";
#endif /* not lint */
/*
@@ -62,7 +62,6 @@ static char rcsid[] = "$OpenBSD: vmstat.c,v 1.63 2007/09/01 19:32:19 deraadt Exp
#include <unistd.h>
#include "systat.h"
-#include "extern.h"
static struct Info {
long time[CPUSTATES];
@@ -71,7 +70,7 @@ static struct Info {
struct nchstats nchstats;
long nchcount;
u_quad_t *intrcnt;
-} s, s1, s2, z;
+} s, s1, s2, s3, z;
#include "dkstats.h"
extern struct _disk cur;
@@ -94,6 +93,11 @@ void putuint64(u_int64_t, int, int, int);
void putfloat(double, int, int, int, int, int);
int ucount(void);
+void print_vm(void);
+int read_vm(void);
+int select_vm(void);
+int vm_keyboard_callback(int);
+
static time_t t;
static double etime;
static float hertz;
@@ -145,10 +149,26 @@ closekre(WINDOW *w)
#define DRIVESPACE 45 /* max space for drives */
+
+field_def *view_vm_0[] = {
+ NULL
+};
+
+/* Define view managers */
+struct view_manager vmstat_mgr = {
+ "VMstat", select_vm, read_vm, NULL, print_header,
+ print_vm, vm_keyboard_callback, NULL, NULL
+};
+
+field_view views_vm[] = {
+ {view_vm_0, "vmstat", '7', &vmstat_mgr},
+ {NULL, NULL, 0, NULL}
+};
+
int ncpu = 1;
int
-initkre(void)
+initvmstat(void)
{
int mib[4], i;
size_t size;
@@ -193,17 +213,24 @@ initkre(void)
allocinfo(&s);
allocinfo(&s1);
allocinfo(&s2);
+ allocinfo(&s3);
allocinfo(&z);
getinfo(&s2);
- copyinfo(&s2, &s1);
+ copyinfo(&z, &s1);
+
+ field_view *v;
+
+ for (v = views_vm; v->name != NULL; v++)
+ add_view(v);
+
return(1);
}
void
fetchkre(void)
{
- getinfo(&s);
+ getinfo(&s3);
}
void
@@ -278,10 +305,9 @@ labelkre(void)
}
}
-#define X(fld) {t=s.fld[i]; s.fld[i]-=s1.fld[i]; if (state==TIME) s1.fld[i]=t;}
-#define Y(fld) {t = s.fld; s.fld -= s1.fld; if (state == TIME) s1.fld = t;}
-#define Z(fld) {t = s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld; \
- if (state == TIME) s1.nchstats.fld = t;}
+#define X(fld) {s.fld[i]; s.fld[i]-=s1.fld[i];}
+#define Y(fld) {s.fld; s.fld -= s1.fld;}
+#define Z(fld) {s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld;}
#define PUTRATE(fld, l, c, w) \
do { \
Y(fld); \
@@ -302,7 +328,6 @@ showkre(void)
static int failcnt = 0, first_run = 0;
if (state == TIME) {
- dkswap();
if (!first_run) {
first_run = 1;
return;
@@ -315,14 +340,8 @@ showkre(void)
}
if (etime < 5.0) { /* < 5 ticks - ignore this trash */
if (failcnt++ >= MAXFAIL) {
- clear();
- mvprintw(2, 10, "The alternate system clock has died!");
- mvprintw(3, 10, "Reverting to ``pigs'' display.");
- move(CMDLINE, 0);
- refresh();
+ error("The alternate system clock has died!");
failcnt = 0;
- sleep(5);
- command("pigs");
}
return;
}
@@ -342,8 +361,6 @@ showkre(void)
}
t = intcnt = s.intrcnt[i];
s.intrcnt[i] -= s1.intrcnt[i];
- if (state == TIME)
- s1.intrcnt[i] = intcnt;
intcnt = (u_int64_t)((float)s.intrcnt[i]/etime + 0.5);
inttotal += intcnt;
putuint64(intcnt, intrloc[i], INTSCOL, 8);
@@ -353,8 +370,6 @@ showkre(void)
Z(ncs_long); Z(ncs_pass2); Z(ncs_2passes);
s.nchcount = nchtotal.ncs_goodhits + nchtotal.ncs_badhits +
nchtotal.ncs_miss + nchtotal.ncs_long;
- if (state == TIME)
- s1.nchcount = s.nchcount;
psiz = 0;
f2 = 0.0;
@@ -453,31 +468,29 @@ showkre(void)
}
int
-cmdkre(char *cmd, char *args)
+vm_keyboard_callback(int ch)
{
-
- if (prefix(cmd, "run")) {
+ switch(ch) {
+ case 'r':
copyinfo(&s2, &s1);
state = RUN;
- return (1);
- }
- if (prefix(cmd, "boot")) {
+ break;
+ case 'b':
state = BOOT;
copyinfo(&z, &s1);
- return (1);
- }
- if (prefix(cmd, "time")) {
+ break;
+ case 't':
state = TIME;
- return (1);
- }
- if (prefix(cmd, "zero")) {
+ break;
+ case 'z':
if (state == RUN)
getinfo(&s1);
- return (1);
+ break;
}
- return (dkcmd(cmd, args));
+ return (keyboard_callback(ch));
}
+
static float
cputime(int indx)
{
@@ -603,7 +616,7 @@ getinfo(struct Info *s)
static void
allocinfo(struct Info *s)
{
-
+ memset(s, 0, sizeof(*s));
s->intrcnt = (u_quad_t *) calloc(nintr, sizeof(u_quad_t));
if (s->intrcnt == NULL)
errx(2, "out of memory");
@@ -639,3 +652,33 @@ dinfo(int dn, int c)
putint((int)(words/etime + 0.5), DISKROW + 3, c, 5);
putfloat(atime/etime, DISKROW + 4, c, 5, 1, 1);
}
+
+
+
+int
+select_vm(void)
+{
+ num_disp = 0;
+ return (0);
+}
+
+int
+read_vm(void)
+{
+ if (state == TIME)
+ copyinfo(&s3, &s1);
+ fetchkre();
+ if (state == TIME)
+ dkswap();
+ num_disp = 0;
+ return 0;
+}
+
+
+void
+print_vm(void)
+{
+ copyinfo(&s3, &s);
+ labelkre();
+ showkre();
+}