-/* $OpenBSD: route.c,v 1.12 1996/11/25 03:57:56 deraadt Exp $ */
+/* $OpenBSD: route.c,v 1.13 1996/12/14 17:23:54 deraadt Exp $ */
/* $NetBSD: route.c,v 1.16 1996/04/15 18:27:05 cgd Exp $ */
/*
#if 0
static char sccsid[] = "@(#)route.c 8.3 (Berkeley) 3/19/94";
#else
-static char rcsid[] = "$OpenBSD: route.c,v 1.12 1996/11/25 03:57:56 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: route.c,v 1.13 1996/12/14 17:23:54 deraadt Exp $";
#endif
#endif /* not lint */
#include <string.h>
#include <paths.h>
-struct keytab {
- char *kt_cp;
- int kt_i;
-} keywords[] = {
#include "keywords.h"
- {0, 0}
-};
struct ortentry route;
union sockunion {
u_long rtm_inits;
struct in_addr inet_makeaddr();
char *routename(), *netname();
-void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();
-void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();
+void flushroutes(), newroute(), monitor(), sockaddr(), sodump();
+void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs();
+void bprintf(), mask_addr();
int getaddr(), rtmsg(), x25_makemask();
extern char *inet_ntoa(), *iso_ntoa(), *link_ntoa();
+extern void show();
__dead void
usage(cp)
setuid(uid);
if (s < 0)
quit("socket");
- if (*argv)
- switch (keyword(*argv)) {
- case K_GET:
- uid = 0;
- /* FALLTHROUGH */
-
- case K_CHANGE:
- case K_ADD:
- case K_DELETE:
- newroute(argc, argv);
- exit(0);
- /* NOTREACHED */
-
- case K_MONITOR:
- monitor();
- /* NOTREACHED */
-
- case K_FLUSH:
- flushroutes(argc, argv);
- exit(0);
- /* NOTREACHED */
- }
- usage(*argv);
- /* NOTREACHED */
+ if (*argv == NULL)
+ goto no_cmd;
+ switch (keyword(*argv)) {
+ case K_GET:
+ uid = 0;
+ /* FALLTHROUGH */
+ case K_CHANGE:
+ case K_ADD:
+ case K_DELETE:
+ newroute(argc, argv);
+ break;
+ case K_SHOW:
+ uid = 0;
+ show(argc, argv);
+ break;
+ case K_MONITOR:
+ monitor();
+ break;
+ case K_FLUSH:
+ flushroutes(argc, argv);
+ break;
+ no_cmd:
+ default:
+ usage(*argv);
+ return 1;
+ }
+ return 0;
}
/*
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
quit("actual retrieval of routing table");
lim = buf + needed;
- if (verbose)
+ if (verbose) {
(void) printf("Examining routing table from sysctl\n");
+ if (af)
+ printf("(address family %s)\n", (*argv + 1));
+ }
seqno = 0; /* ??? */
for (next = buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next;
}
}
+static char hexlist[] = "0123456789abcdef";
+
+char *
+any_ntoa(sa)
+ const struct sockaddr *sa;
+{
+ static char obuf[240];
+ const char *in = sa->sa_data;
+ char *out = obuf;
+ int len = sa->sa_len;
+
+ *out++ = 'Q';
+ do {
+ *out++ = hexlist[(*in >> 4) & 15];
+ *out++ = hexlist[(*in++) & 15];
+ *out++ = '.';
+ } while (--len > 0 && (out + 3) < &obuf[sizeof obuf-1]);
+ out[-1] = '\0';
+ return (obuf);
+}
+
char *
routename(sa)
struct sockaddr *sa;
{
- register char *cp;
+ register char *cp = NULL;
static char line[MAXHOSTNAMELEN];
struct hostent *hp;
- static char domain[MAXHOSTNAMELEN + 1];
+ static char domain[MAXHOSTNAMELEN];
static int first = 1;
char *ns_print();
char *ipx_print();
if (first) {
first = 0;
- if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+ if (gethostname(domain, sizeof domain) == 0 &&
(cp = strchr(domain, '.')))
(void) strcpy(domain, cp + 1);
else
domain[0] = 0;
+ cp = NULL;
}
if (sa->sa_len == 0)
{ struct in_addr in;
in = ((struct sockaddr_in *)sa)->sin_addr;
- cp = 0;
if (in.s_addr == INADDR_ANY || sa->sa_len < 4)
cp = "default";
- if (cp == 0 && !nflag) {
- hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
- AF_INET);
- if (hp) {
+ if (!cp && !nflag) {
+ if ((hp = gethostbyaddr((char *)&in,
+ sizeof (struct in_addr), AF_INET))) {
if ((cp = strchr(hp->h_name, '.')) &&
!strcmp(cp + 1, domain))
*cp = 0;
cp = hp->h_name;
}
}
- if (cp)
- strcpy(line, cp);
- else {
-#define C(x) ((x) & 0xff)
- in.s_addr = ntohl(in.s_addr);
- (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
- C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
- }
+ strncpy(line, cp ? cp : inet_ntoa(in), sizeof line-1);
+ line[sizeof line-1] = '\0';
break;
}
break;
default:
- { u_short *s = (u_short *)sa;
- u_short *slim = s + ((sa->sa_len + 1) >> 1);
- char *cp = line + sprintf(line, "(%d)", sa->sa_family);
-
- while (++s < slim) /* start with sa->sa_data */
- cp += sprintf(cp, " %x", *s);
+ (void) snprintf(line, sizeof line, "(%d) %s",
+ sa->sa_family, any_ntoa(sa));
break;
- }
}
return (line);
}
netname(sa)
struct sockaddr *sa;
{
- char *cp = 0;
+ char *cp = NULL;
static char line[MAXHOSTNAMELEN];
struct netent *np = 0;
- u_long net, mask;
- register u_long i;
+ u_int32_t net, mask;
int subnetshift;
char *ns_print();
char *ipx_print();
{ struct in_addr in;
in = ((struct sockaddr_in *)sa)->sin_addr;
- i = in.s_addr = ntohl(in.s_addr);
+ in.s_addr = ntohl(in.s_addr);
if (in.s_addr == 0)
cp = "default";
else if (!nflag) {
- if (IN_CLASSA(i)) {
+ if (IN_CLASSA(in.s_addr)) {
mask = IN_CLASSA_NET;
subnetshift = 8;
- } else if (IN_CLASSB(i)) {
+ } else if (IN_CLASSB(in.s_addr)) {
mask = IN_CLASSB_NET;
subnetshift = 8;
} else {
* width subnet fields.
*/
while (in.s_addr &~ mask)
- mask = (long)mask >> subnetshift;
+ mask = (u_int32_t)mask >> subnetshift;
net = in.s_addr & mask;
while ((mask & 1) == 0)
mask >>= 1, net >>= 1;
if (np)
cp = np->n_name;
}
- if (cp) {
- strncpy(line, cp, sizeof line-1);
- line[sizeof line-1] = '\0';
- } else if ((in.s_addr & 0xffffff) == 0)
- (void) sprintf(line, "%u", C(in.s_addr >> 24));
- else if ((in.s_addr & 0xffff) == 0)
- (void) sprintf(line, "%u.%u", C(in.s_addr >> 24),
- C(in.s_addr >> 16));
- else if ((in.s_addr & 0xff) == 0)
- (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
- C(in.s_addr >> 16), C(in.s_addr >> 8));
- else
- (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
- C(in.s_addr >> 16), C(in.s_addr >> 8),
- C(in.s_addr));
+ in = ((struct sockaddr_in *)sa)->sin_addr;
+ strncpy(line, cp ? cp : inet_ntoa(in), sizeof line-1);
+ line[sizeof line-1] = '\0';
break;
}
return (link_ntoa((struct sockaddr_dl *)sa));
case AF_ISO:
- (void) sprintf(line, "iso %s",
+ (void) snprintf(line, sizeof line, "iso %s",
iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr));
break;
default:
- { u_short *s = (u_short *)sa->sa_data;
- u_short *slim = s + ((sa->sa_len + 1)>>1);
- char *cp = line + sprintf(line, "af %d:", sa->sa_family);
-
- while (s < slim)
- cp += sprintf(cp, " %x", *s++);
+ snprintf(line, sizeof line, "af %d: %s",
+ sa->sa_family, any_ntoa(sa));
break;
- }
}
return (line);
}
if (ret == 0) {
if (!qflag && strcmp(*argv, "0") == 0)
- printf("%s,%s",
+ printf("%s,%s",
"old usage of trailing 0",
"assuming route to if\n");
else
continue;
} else if (ret > 0 && ret < 10) {
if (!qflag) {
- printf("old usage of trailing digit, ");
- printf("assuming route via gateway\n");
+ printf("old usage of trailing digit, ");
+ printf("assuming route via gateway\n");
}
iflag = 0;
continue;
void
inet_makenetandmask(net, sin)
- u_long net;
+ u_int32_t net;
register struct sockaddr_in *sin;
{
- u_long addr, mask = 0;
+ u_int32_t addr, mask = 0;
register char *cp;
rtm_addrs |= RTA_NETMASK;
struct ns_addr ns_addr();
struct ipx_addr ipx_addr();
struct iso_addr *iso_addr();
+ struct ccitt_addr *ccitt_addr();
struct hostent *hp;
struct netent *np;
u_long val;
if (which == RTA_NETMASK || which == RTA_GENMASK) {
register char *cp = (char *)TSEL(&su->siso);
su->siso.siso_nlen = 0;
- do {--cp ;} while ((cp > (char *)su) && (*cp == 0));
+ do {
+ --cp;
+ } while ((cp > (char *)su) && (*cp == 0));
su->siso.siso_len = 1 + cp - (char *)su;
}
return (1);
struct sockaddr_ns *sns;
{
struct ns_addr work;
- union { union ns_net net_e; u_long long_e; } net;
+ union { union ns_net net_e; u_int32_t long_e; } net;
u_short port;
static char mybuf[50+MAXHOSTNAMELEN];
char cport[10], chost[25];
char *host = "";
- register char *p;
register u_char *q;
work = sns->sns_addr;
*cport = '\0';
(void) snprintf(mybuf, sizeof mybuf, "0x%x.%s%s",
- ntohl(net.long_e), host, cport);
+ (u_int32_t)ntohl(net.long_e), host, cport);
return (mybuf);
}
struct sockaddr_ipx *sipx;
{
struct ipx_addr work;
- union { union ipx_net net_e; u_long long_e; } net;
+ union { union ipx_net net_e; u_int32_t long_e; } net;
u_short port;
- static char mybuf[50], cport[10], chost[25];
+ static char mybuf[50+MAXHOSTNAMELEN], cport[10], chost[25];
char *host = "";
register char *p;
register u_char *q;
if (ipx_nullhost(work) && net.long_e == 0) {
if (!port)
return ("*.*");
- (void) sprintf(mybuf, "*.%XH", port);
+ (void) sprintf(mybuf, "*.0x%XH", port);
return (mybuf);
}
else
*cport = 0;
- (void) sprintf(mybuf,"%XH.%s%s", ntohl(net.long_e), host, cport);
+ (void) snprintf(mybuf, sizeof mybuf, "%XH.%s%s",
+ (u_int32_t)ntohl(net.long_e), host, cport);
return (mybuf);
}
(void) printf("\n%s\n", "\
recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire");
- printf("%8d%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE));
- printf("%8d%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE));
- printf("%8d%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH));
- printf("%8d%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT));
- printf("%8d%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR));
- printf("%8d%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT));
- printf("%8d%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU));
+ printf("%8d%c ", (int)rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE));
+ printf("%8d%c ", (int)rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE));
+ printf("%8d%c ", (int)rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH));
+ printf("%8d%c ", (int)msec(rtm->rtm_rmx.rmx_rtt), lock(RTT));
+ printf("%8d%c ", (int)msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR));
+ printf("%8d%c ", (int)rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT));
+ printf("%8d%c ", (int)rtm->rtm_rmx.rmx_mtu, lock(MTU));
if (rtm->rtm_rmx.rmx_expire)
rtm->rtm_rmx.rmx_expire -= time(0);
- printf("%8d%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
+ printf("%8d%c\n", (int)rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
#undef lock
#undef msec
#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD)
if (b == 0)
return;
- while (i = *s++) {
- if (b & (1 << (i-1))) {
+ while ((i = *s++)) {
+ if ((b & (1 << (i-1)))) {
if (gotsome == 0)
i = '<';
else
register char *cp = (char *)sa;
int size = sa->sa_len;
char *cplim = cp + size;
- register int byte = 0, state = VIRGIN, new;
+ register int byte = 0, state = VIRGIN, new = 0;
memset(cp, 0, size);
cp++;
--- /dev/null
+/* $NetBSD: show.c,v 1.1 1996/11/15 18:01:41 gwr Exp $ */
+
+/*
+ * Copyright (c) 1983, 1988, 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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[] = "from: @(#)route.c 8.3 (Berkeley) 3/9/94";
+#else
+static char *rcsid = "$NetBSD: show.c,v 1.1 1996/11/15 18:01:41 gwr Exp $";
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netns/ns.h>
+
+#include <sys/sysctl.h>
+
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* XXX: things from route.c */
+extern char *routename __P((struct sockaddr *));
+extern char *netname __P((struct sockaddr *));
+extern char *ns_print __P((struct sockaddr_ns *));
+extern int nflag;
+
+/*
+ * Definitions for showing gateway flags.
+ */
+struct bits {
+ short b_mask;
+ char b_val;
+};
+static const struct bits bits[] = {
+ { RTF_UP, 'U' },
+ { RTF_GATEWAY, 'G' },
+ { RTF_HOST, 'H' },
+ { RTF_REJECT, 'R' },
+ { RTF_DYNAMIC, 'D' },
+ { RTF_MODIFIED, 'M' },
+ { RTF_DONE, 'd' }, /* Completed -- for routing messages only */
+ { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */
+ { RTF_CLONING, 'C' },
+ { RTF_XRESOLVE, 'X' },
+ { RTF_LLINFO, 'L' },
+ { RTF_STATIC, 'S' },
+ { RTF_PROTO1, '1' },
+ { RTF_PROTO2, '2' },
+ { 0 }
+};
+
+static void p_rtentry __P((struct rt_msghdr *));
+static void p_sockaddr __P((struct sockaddr *, int, int));
+static void p_flags __P((int, char *));
+static void pr_rthdr __P((void));
+static void pr_family __P((int));
+
+/*
+ * Print routing tables.
+ */
+void
+show(argc, argv)
+ int argc;
+ char **argv;
+{
+ register struct rt_msghdr *rtm;
+ char *buf, *next, *lim;
+ size_t needed;
+ int mib[6];
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = 0;
+ mib[4] = NET_RT_DUMP;
+ mib[5] = 0;
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
+ perror("route-sysctl-estimate");
+ exit(1);
+ }
+ if ((buf = malloc(needed)) == 0) {
+ printf("out of space\n");
+ exit(1);
+ }
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+ perror("sysctl of routing table");
+ exit(1);
+ }
+ lim = buf + needed;
+
+ printf("Routing tables\n");
+
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ p_rtentry(rtm);
+ }
+}
+
+/* column widths; each followed by one space */
+#define WID_DST 16 /* width of destination column */
+#define WID_GW 18 /* width of gateway column */
+
+/*
+ * Print header for routing table columns.
+ */
+static void
+pr_rthdr()
+{
+ printf("%-*.*s %-*.*s %-6.6s\n",
+ WID_DST, WID_DST, "Destination",
+ WID_GW, WID_GW, "Gateway",
+ "Flags");
+}
+
+/*
+ * Print a routing table entry.
+ */
+static void
+p_rtentry(rtm)
+ register struct rt_msghdr *rtm;
+{
+ register struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
+#ifdef notdef
+ static int masks_done, banner_printed;
+#endif
+ static int old_af;
+ int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
+
+#ifdef notdef
+ /* for the moment, netmasks are skipped over */
+ if (!banner_printed) {
+ printf("Netmasks:\n");
+ banner_printed = 1;
+ }
+ if (masks_done == 0) {
+ if (rtm->rtm_addrs != RTA_DST ) {
+ masks_done = 1;
+ af = sa->sa_family;
+ }
+ } else
+#endif
+ af = sa->sa_family;
+ if (old_af != af) {
+ old_af = af;
+ pr_family(af);
+ pr_rthdr();
+ }
+ if (rtm->rtm_addrs == RTA_DST)
+ p_sockaddr(sa, 0, 36);
+ else {
+ p_sockaddr(sa, rtm->rtm_flags, 16);
+ if (sa->sa_len == 0)
+ sa->sa_len = sizeof(long);
+ sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
+ p_sockaddr(sa, 0, 18);
+ }
+ p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
+ putchar('\n');
+}
+
+
+/*
+ * Print address family header before a section of the routing table.
+ */
+static void
+pr_family(af)
+ int af;
+{
+ char *afname;
+
+ switch (af) {
+ case AF_INET:
+ afname = "Internet";
+ break;
+ case AF_NS:
+ afname = "XNS";
+ break;
+ case AF_IPX:
+ afname = "IPX";
+ break;
+ case AF_ISO:
+ afname = "ISO";
+ break;
+ case AF_CCITT:
+ afname = "X.25";
+ break;
+ default:
+ afname = NULL;
+ break;
+ }
+ if (afname)
+ printf("\n%s:\n", afname);
+ else
+ printf("\nProtocol Family %d:\n", af);
+}
+
+
+static void
+p_sockaddr(sa, flags, width)
+ struct sockaddr *sa;
+ int flags, width;
+{
+ char workbuf[128], *cplim;
+ register char *cp = workbuf;
+
+ switch(sa->sa_family) {
+
+ case AF_LINK:
+ {
+ register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
+
+ if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
+ sdl->sdl_slen == 0)
+ (void) sprintf(workbuf, "link#%d", sdl->sdl_index);
+ else switch (sdl->sdl_type) {
+ case IFT_ETHER:
+ {
+ register int i;
+ register u_char *lla = (u_char *)sdl->sdl_data +
+ sdl->sdl_nlen;
+
+ cplim = "";
+ for (i = 0; i < sdl->sdl_alen; i++, lla++) {
+ cp += sprintf(cp, "%s%x", cplim, *lla);
+ cplim = ":";
+ }
+ cp = workbuf;
+ break;
+ }
+ default:
+ cp = link_ntoa(sdl);
+ break;
+ }
+ break;
+ }
+
+ case AF_INET:
+ {
+ register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+ if (sin->sin_addr.s_addr == 0)
+ cp = "default";
+ else
+ cp = (flags & RTF_HOST) ? routename(sa) : netname(sa);
+ break;
+ }
+
+ case AF_NS:
+ cp = ns_print((struct sockaddr_ns *)sa);
+ break;
+
+ default:
+ {
+ register u_char *s = (u_char *)sa->sa_data, *slim;
+
+ slim = sa->sa_len + (u_char *) sa;
+ cplim = cp + sizeof(workbuf) - 6;
+ cp += sprintf(cp, "(%d)", sa->sa_family);
+ while (s < slim && cp < cplim) {
+ cp += sprintf(cp, " %02x", *s++);
+ if (s < slim)
+ cp += sprintf(cp, "%02x", *s++);
+ }
+ cp = workbuf;
+ }
+ }
+ if (width < 0 )
+ printf("%s ", cp);
+ else {
+ if (nflag)
+ printf("%-*s ", width, cp);
+ else
+ printf("%-*.*s ", width, width, cp);
+ }
+}
+
+static void
+p_flags(f, format)
+ register int f;
+ char *format;
+{
+ char name[33], *flags;
+ register const struct bits *p = bits;
+
+ for (flags = name; p->b_mask && flags < &name[sizeof name-2]; p++)
+ if (p->b_mask & f)
+ *flags++ = p->b_val;
+ *flags = '\0';
+ printf(format, name);
+}
+