source: rtems-libbsd/freebsd-userspace/commands/usr.bin/netstat/main.c @ 2df6b31

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 2df6b31 was 2df6b31, checked in by Jennifer Averett <jennifer.averett@…>, on 10/23/12 at 19:13:08

netstat: Added exit funtionality.

  • Property mode set to 100644
File size: 31.7 KB
Line 
1#ifdef __rtems__
2#define __need_getopt_newlib
3#include <getopt.h>
4#endif
5/*-
6 * Copyright (c) 1983, 1988, 1993
7 *      Regents of the University of California.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed by the University of
20 *      California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38#ifndef lint
39char const copyright[] =
40"@(#) Copyright (c) 1983, 1988, 1993\n\
41        Regents of the University of California.  All rights reserved.\n";
42#endif /* not lint */
43
44#if 0
45#ifndef lint
46static char sccsid[] = "@(#)main.c      8.4 (Berkeley) 3/1/94";
47#endif /* not lint */
48#endif
49
50#include <sys/cdefs.h>
51__FBSDID("$FreeBSD$");
52
53#include <sys/param.h>
54#include <sys/file.h>
55#ifdef __rtems__
56#include <freebsd/sys/protosw.h>
57#else
58#include <sys/protosw.h>
59#endif
60#include <sys/socket.h>
61#include <sys/socketvar.h>
62
63#include <netinet/in.h>
64
65#ifdef NETGRAPH
66#include <netgraph/ng_socket.h>
67#endif
68
69#include <ctype.h>
70#include <err.h>
71#include <errno.h>
72#include <kvm.h>
73#include <limits.h>
74#include <netdb.h>
75#include <nlist.h>
76#include <paths.h>
77#include <stdint.h>
78#include <stdio.h>
79#include <stdlib.h>
80#include <string.h>
81#include <unistd.h>
82#include "netstat.h"
83
84static struct nlist nl[] = {
85#define N_IFNET         0
86        { .n_name = "_ifnet" },
87#define N_RTSTAT        1
88        { .n_name = "_rtstat" },
89#define N_RTREE         2
90        { .n_name = "_rt_tables"},
91#define N_MRTSTAT       3
92        { .n_name = "_mrtstat" },
93#define N_MFCHASHTBL    4
94        { .n_name = "_mfchashtbl" },
95#define N_VIFTABLE      5
96        { .n_name = "_viftable" },
97#define N_IPX           6
98        { .n_name = "_ipxpcb_list"},
99#define N_IPXSTAT       7
100        { .n_name = "_ipxstat"},
101#define N_SPXSTAT       8
102        { .n_name = "_spx_istat"},
103#define N_DDPSTAT       9
104        { .n_name = "_ddpstat"},
105#define N_DDPCB         10
106        { .n_name = "_ddpcb"},
107#define N_NGSOCKS       11
108        { .n_name = "_ngsocklist"},
109#define N_IP6STAT       12
110        { .n_name = "_ip6stat" },
111#define N_ICMP6STAT     13
112        { .n_name = "_icmp6stat" },
113#define N_IPSECSTAT     14
114        { .n_name = "_ipsec4stat" },
115#define N_IPSEC6STAT    15
116        { .n_name = "_ipsec6stat" },
117#define N_PIM6STAT      16
118        { .n_name = "_pim6stat" },
119#define N_MRT6STAT      17
120        { .n_name = "_mrt6stat" },
121#define N_MF6CTABLE     18
122        { .n_name = "_mf6ctable" },
123#define N_MIF6TABLE     19
124        { .n_name = "_mif6table" },
125#define N_PFKEYSTAT     20
126        { .n_name = "_pfkeystat" },
127#define N_MBSTAT        21
128        { .n_name = "_mbstat" },
129#define N_MBTYPES       22
130        { .n_name = "_mbtypes" },
131#define N_NMBCLUSTERS   23
132        { .n_name = "_nmbclusters" },
133#define N_NMBUFS        24
134        { .n_name = "_nmbufs" },
135#define N_MBHI          25
136        { .n_name = "_mbuf_hiwm" },
137#define N_CLHI          26
138        { .n_name = "_clust_hiwm" },
139#define N_NCPUS         27
140        { .n_name = "_smp_cpus" },
141#define N_PAGESZ        28
142        { .n_name = "_pagesize" },
143#define N_MBPSTAT       29
144        { .n_name = "_mb_statpcpu" },
145#define N_RTTRASH       30
146        { .n_name = "_rttrash" },
147#define N_MBLO          31
148        { .n_name = "_mbuf_lowm" },
149#define N_CLLO          32
150        { .n_name = "_clust_lowm" },
151#define N_CARPSTAT      33
152        { .n_name = "_carpstats" },
153#define N_PFSYNCSTAT    34
154        { .n_name = "_pfsyncstats" },
155#define N_AHSTAT        35
156        { .n_name = "_ahstat" },
157#define N_ESPSTAT       36
158        { .n_name = "_espstat" },
159#define N_IPCOMPSTAT    37
160        { .n_name = "_ipcompstat" },
161#define N_TCPSTAT       38
162        { .n_name = "_tcpstat" },
163#define N_UDPSTAT       39
164        { .n_name = "_udpstat" },
165#define N_IPSTAT        40
166        { .n_name = "_ipstat" },
167#define N_ICMPSTAT      41
168        { .n_name = "_icmpstat" },
169#define N_IGMPSTAT      42
170        { .n_name = "_igmpstat" },
171#define N_PIMSTAT       43
172        { .n_name = "_pimstat" },
173#define N_TCBINFO       44
174        { .n_name = "_tcbinfo" },
175#define N_UDBINFO       45
176        { .n_name = "_udbinfo" },
177#define N_DIVCBINFO     46
178        { .n_name = "_divcbinfo" },
179#define N_RIPCBINFO     47
180        { .n_name = "_ripcbinfo" },
181#define N_UNP_COUNT     48
182        { .n_name = "_unp_count" },
183#define N_UNP_GENCNT    49
184        { .n_name = "_unp_gencnt" },
185#define N_UNP_DHEAD     50
186        { .n_name = "_unp_dhead" },
187#define N_UNP_SHEAD     51
188        { .n_name = "_unp_shead" },
189#define N_RIP6STAT      52
190        { .n_name = "_rip6stat" },
191#define N_SCTPSTAT      53
192        { .n_name = "_sctpstat" },
193#define N_MFCTABLESIZE  54
194        { .n_name = "_mfctablesize" },
195#define N_ARPSTAT       55
196        { .n_name = "_arpstat" },
197        { .n_name = NULL },
198};
199
200struct protox {
201        int     pr_index;               /* index into nlist of cb head */
202        int     pr_sindex;              /* index into nlist of stat block */
203        u_char  pr_wanted;              /* 1 if wanted, 0 otherwise */
204        void    (*pr_cblocks)(u_long, const char *, int, int);
205                                        /* control blocks printing routine */
206        void    (*pr_stats)(u_long, const char *, int, int);
207                                        /* statistics printing routine */
208        void    (*pr_istats)(char *);   /* per/if statistics printing routine */
209        const char      *pr_name;               /* well-known name */
210        int     pr_usesysctl;           /* non-zero if we use sysctl, not kvm */
211        int     pr_protocol;
212} protox[] = {
213        { N_TCBINFO,    N_TCPSTAT,      1,      protopr,
214          tcp_stats,    NULL,           "tcp",  1,      IPPROTO_TCP },
215        { N_UDBINFO,    N_UDPSTAT,      1,      protopr,
216          udp_stats,    NULL,           "udp",  1,      IPPROTO_UDP },
217#ifdef SCTP
218        { -1,           N_SCTPSTAT,     1,      sctp_protopr,
219          sctp_stats,   NULL,           "sctp", 1,      IPPROTO_SCTP },
220#endif
221        { N_DIVCBINFO,  -1,             1,      protopr,
222          NULL,         NULL,           "divert", 1,    IPPROTO_DIVERT },
223        { N_RIPCBINFO,  N_IPSTAT,       1,      protopr,
224          ip_stats,     NULL,           "ip",   1,      IPPROTO_RAW },
225        { N_RIPCBINFO,  N_ICMPSTAT,     1,      protopr,
226          icmp_stats,   NULL,           "icmp", 1,      IPPROTO_ICMP },
227        { N_RIPCBINFO,  N_IGMPSTAT,     1,      protopr,
228          igmp_stats,   NULL,           "igmp", 1,      IPPROTO_IGMP },
229#ifdef IPSEC
230        { -1,           N_IPSECSTAT,    1,      NULL,   /* keep as compat */
231          ipsec_stats,  NULL,           "ipsec", 0,     0},
232        { -1,           N_AHSTAT,       1,      NULL,
233          ah_stats,     NULL,           "ah",   0,      0},
234        { -1,           N_ESPSTAT,      1,      NULL,
235          esp_stats,    NULL,           "esp",  0,      0},
236        { -1,           N_IPCOMPSTAT,   1,      NULL,
237          ipcomp_stats, NULL,           "ipcomp", 0,    0},
238#endif
239        { N_RIPCBINFO,  N_PIMSTAT,      1,      protopr,
240          pim_stats,    NULL,           "pim",  1,      IPPROTO_PIM },
241        { -1,           N_CARPSTAT,     1,      NULL,
242          carp_stats,   NULL,           "carp", 1,      0 },
243        { -1,           N_PFSYNCSTAT,   1,      NULL,
244          pfsync_stats, NULL,           "pfsync", 1,    0 },
245        { -1,           N_ARPSTAT,      1,      NULL,
246          arp_stats,    NULL,           "arp", 1,       0 },
247        { -1,           -1,             0,      NULL,
248          NULL,         NULL,           NULL,   0,      0 }
249};
250
251#ifdef INET6
252struct protox ip6protox[] = {
253        { N_TCBINFO,    N_TCPSTAT,      1,      protopr,
254          tcp_stats,    NULL,           "tcp",  1,      IPPROTO_TCP },
255        { N_UDBINFO,    N_UDPSTAT,      1,      protopr,
256          udp_stats,    NULL,           "udp",  1,      IPPROTO_UDP },
257        { N_RIPCBINFO,  N_IP6STAT,      1,      protopr,
258          ip6_stats,    ip6_ifstats,    "ip6",  1,      IPPROTO_RAW },
259        { N_RIPCBINFO,  N_ICMP6STAT,    1,      protopr,
260          icmp6_stats,  icmp6_ifstats,  "icmp6", 1,     IPPROTO_ICMPV6 },
261#ifdef IPSEC
262        { -1,           N_IPSEC6STAT,   1,      NULL,
263          ipsec_stats,  NULL,           "ipsec6", 0,    0 },
264#endif
265#ifdef notyet
266        { -1,           N_PIM6STAT,     1,      NULL,
267          pim6_stats,   NULL,           "pim6", 1,      0 },
268#endif
269        { -1,           N_RIP6STAT,     1,      NULL,
270          rip6_stats,   NULL,           "rip6", 1,      0 },
271        { -1,           -1,             0,      NULL,
272          NULL,         NULL,           NULL,   0,      0 }
273};
274#endif /*INET6*/
275
276#ifdef IPSEC
277struct protox pfkeyprotox[] = {
278        { -1,           N_PFKEYSTAT,    1,      NULL,
279          pfkey_stats,  NULL,           "pfkey", 0,     0 },
280        { -1,           -1,             0,      NULL,
281          NULL,         NULL,           NULL,   0,      0 }
282};
283#endif
284
285#ifndef __rtems__
286struct protox atalkprotox[] = {
287        { N_DDPCB,      N_DDPSTAT,      1,      atalkprotopr,
288          ddp_stats,    NULL,           "ddp",  0,      0 },
289        { -1,           -1,             0,      NULL,
290          NULL,         NULL,           NULL,   0,      0 }
291};
292#endif
293#ifdef NETGRAPH
294struct protox netgraphprotox[] = {
295        { N_NGSOCKS,    -1,             1,      netgraphprotopr,
296          NULL,         NULL,           "ctrl", 0,      0 },
297        { N_NGSOCKS,    -1,             1,      netgraphprotopr,
298          NULL,         NULL,           "data", 0,      0 },
299        { -1,           -1,             0,      NULL,
300          NULL,         NULL,           NULL,   0,      0 }
301};
302#endif
303#ifdef IPX
304struct protox ipxprotox[] = {
305        { N_IPX,        N_IPXSTAT,      1,      ipxprotopr,
306          ipx_stats,    NULL,           "ipx",  0,      0 },
307        { N_IPX,        N_SPXSTAT,      1,      ipxprotopr,
308          spx_stats,    NULL,           "spx",  0,      0 },
309        { -1,           -1,             0,      NULL,
310          NULL,         NULL,           0,      0,      0 }
311};
312#endif
313
314struct protox *protoprotox[] = {
315                                         protox,
316#ifdef INET6
317                                         ip6protox,
318#endif
319#ifdef IPSEC
320                                         pfkeyprotox,
321#endif
322#ifdef IPX
323                                         ipxprotox,
324#endif
325#ifndef __rtems__
326                                         atalkprotox, NULL };
327#else
328                                };
329#endif
330
331static void printproto(struct protox *, const char *);
332static void usage(void);
333static struct protox *name2protox(const char *);
334static struct protox *knownname(const char *);
335
336static kvm_t *kvmd;
337static char *nlistf = NULL, *memf = NULL;
338
339int     Aflag;          /* show addresses of protocol control block */
340int     aflag;          /* show all sockets (including servers) */
341int     Bflag;          /* show information about bpf consumers */
342int     bflag;          /* show i/f total bytes in/out */
343int     dflag;          /* show i/f dropped packets */
344int     gflag;          /* show group (multicast) routing or stats */
345int     hflag;          /* show counters in human readable format */
346int     iflag;          /* show interfaces */
347int     Lflag;          /* show size of listen queues */
348int     mflag;          /* show memory stats */
349int     noutputs = 0;   /* how much outputs before we exit */
350int     numeric_addr;   /* show addresses numerically */
351int     numeric_port;   /* show ports numerically */
352static int pflag;       /* show given protocol */
353int     rflag;          /* show routing tables (or routing stats) */
354int     sflag;          /* show protocol statistics */
355int     tflag;          /* show i/f watchdog timers */
356int     Wflag;          /* wide display */
357int     xflag;          /* extra information, includes all socket buffer info */
358int     zflag;          /* zero stats */
359
360int     interval;       /* repeat interval for i/f stats */
361
362char    *interface;     /* desired i/f for stats, or NULL for all i/fs */
363int     unit;           /* unit number for above */
364
365int     af;             /* address family */
366int     live;           /* true if we are examining a live system */
367
368
369#ifdef __rtems__
370static int main_netstat(int argc, char *argv[]);
371static int rtems_shell_main_netstat(int argc, char *argv[])
372{
373  int i;
374  rtems_shell_globals_t  netstat_globals;
375  rtems_shell_globals = &netstat_globals;
376  memset (rtems_shell_globals, 0, sizeof (netstat_globals));
377
378  i = 0;
379  protox[i].pr_index     = N_TCBINFO;
380  protox[i].pr_sindex    = N_TCPSTAT;
381  protox[i].pr_wanted    = 1;
382  protox[i].pr_cblocks   = protopr;
383  protox[i].pr_stats     = tcp_stats;
384  protox[i].pr_istats    = NULL;
385  protox[i].pr_name      = "tcp";
386  protox[i].pr_usesysctl = 1;
387  protox[i].pr_protocol  = IPPROTO_TCP;
388  i++;
389  protox[i].pr_index     = N_UDBINFO;
390  protox[i].pr_sindex    = N_UDPSTAT;
391  protox[i].pr_wanted    = 1;
392  protox[i].pr_cblocks   = protopr;
393  protox[i].pr_stats     = udp_stats;
394  protox[i].pr_istats    = NULL;
395  protox[i].pr_name      = "udp";
396  protox[i].pr_usesysctl = 1;
397  protox[i].pr_protocol  = IPPROTO_UDP;
398  i++;
399#ifdef SCTP
400  protox[i].pr_index     = -1;
401  protox[i].pr_sindex    = N_SCTPSTAT;
402  protox[i].pr_wanted    = 1;
403  protox[i].pr_cblocks   = sctp_protopr;
404  protox[i].pr_stats     = sctp_stats;
405  protox[i].pr_istats    = NULL;
406  protox[i].pr_name      = "sctp";
407  protox[i].pr_usesysctl = 1;
408  protox[i].pr_protocol  = IPPROTO_SCTP;
409  i++;
410#endif
411  protox[i].pr_index     = N_DIVCBINFO;
412  protox[i].pr_sindex    = -1;
413  protox[i].pr_wanted    = 1;
414  protox[i].pr_cblocks   = protopr;
415  protox[i].pr_stats     = NULL;
416  protox[i].pr_istats    = NULL;
417  protox[i].pr_name      = "divert";
418  protox[i].pr_usesysctl = 1;
419  protox[i].pr_protocol  = IPPROTO_DIVERT;
420  i++;
421  protox[i].pr_index     = N_RIPCBINFO;
422  protox[i].pr_sindex    = N_IPSTAT;
423  protox[i].pr_wanted    = 1;
424  protox[i].pr_cblocks   = protopr;
425  protox[i].pr_stats     = ip_stats;
426  protox[i].pr_istats    = NULL;
427  protox[i].pr_name      = "ip";
428  protox[i].pr_usesysctl = 1;
429  protox[i].pr_protocol  = IPPROTO_RAW;
430  i++;
431  protox[i].pr_index     = N_RIPCBINFO;
432  protox[i].pr_sindex    = N_ICMPSTAT;
433  protox[i].pr_wanted    = 1;
434  protox[i].pr_cblocks   = protopr;
435  protox[i].pr_stats     = icmp_stats;
436  protox[i].pr_istats    = NULL;
437  protox[i].pr_name      = "icmp";
438  protox[i].pr_usesysctl = 1;
439  protox[i].pr_protocol  = IPPROTO_ICMP;
440  i++;
441  protox[i].pr_index     = N_RIPCBINFO;
442  protox[i].pr_sindex    = N_IGMPSTAT;
443  protox[i].pr_wanted    = 1;
444  protox[i].pr_cblocks   = protopr;
445  protox[i].pr_stats     = igmp_stats;
446  protox[i].pr_istats    = NULL;
447  protox[i].pr_name      = "igmp";
448  protox[i].pr_usesysctl = 1;
449  protox[i].pr_protocol  = IPPROTO_IGMP;
450  i++;
451#ifdef IPSEC
452  protox[i].pr_index     = -1;
453  protox[i].pr_sindex    = N_IPSECSTAT;
454  protox[i].pr_wanted    = 1;
455  protox[i].pr_cblocks   = NULL;
456  protox[i].pr_stats     = ipsec_stats;
457  protox[i].pr_istats    = NULL;
458  protox[i].pr_name      = "ipsec";
459  protox[i].pr_usesysctl = 0;
460  protox[i].pr_protocol  = 0;
461  i++;
462  protox[i].pr_index     = -1;
463  protox[i].pr_sindex    = N_AHSTAT;
464  protox[i].pr_wanted    = 1;
465  protox[i].pr_cblocks   = NULL;
466  protox[i].pr_stats     = ah_stats;
467  protox[i].pr_istats    = NULL;
468  protox[i].pr_name      = "ah";
469  protox[i].pr_usesysctl = 0;
470  protox[i].pr_protocol  = 0;
471  i++;
472  protox[i].pr_index     = -1;
473  protox[i].pr_sindex    = N_ESPSTAT;
474  protox[i].pr_wanted    = 1;
475  protox[i].pr_cblocks   = NULL;
476  protox[i].pr_stats     = esp_stats;
477  protox[i].pr_istats    = NULL;
478  protox[i].pr_name      = "esp";
479  protox[i].pr_usesysctl = 0;
480  protox[i].pr_protocol  = 0;
481  i++;
482  protox[i].pr_index     = -1;
483  protox[i].pr_sindex    = N_IPCOMPSTAT;
484  protox[i].pr_wanted    = 1;
485  protox[i].pr_cblocks   = NULL;
486  protox[i].pr_stats     = ipcomp_stats;
487  protox[i].pr_istats    = NULL;
488  protox[i].pr_name      = "ipcomp";
489  protox[i].pr_usesysctl = 0;
490  protox[i].pr_protocol  = 0;
491  i++;
492#endif
493  protox[i].pr_index     = N_RIPCBINFO;
494  protox[i].pr_sindex    = N_PIMSTAT;
495  protox[i].pr_wanted    = 1;
496  protox[i].pr_cblocks   = protopr;
497  protox[i].pr_stats     = pim_stats;
498  protox[i].pr_istats    = NULL;
499  protox[i].pr_name      = "pim";
500  protox[i].pr_usesysctl = 1;
501  protox[i].pr_protocol  = IPPROTO_PIM;
502  i++;
503  protox[i].pr_index     =  -1;
504  protox[i].pr_sindex    = N_CARPSTAT;
505  protox[i].pr_wanted    = 1;
506  protox[i].pr_cblocks   = NULL;
507  protox[i].pr_stats     = carp_stats;
508  protox[i].pr_istats    = NULL;
509  protox[i].pr_name      = "carp";
510  protox[i].pr_usesysctl = 1;
511  protox[i].pr_protocol  = 0;
512  i++;
513  protox[i].pr_index     =  -1;
514  protox[i].pr_sindex    = N_PFSYNCSTAT;
515  protox[i].pr_wanted    = 1;
516  protox[i].pr_cblocks   = NULL;
517  protox[i].pr_stats     = pfsync_stats;
518  protox[i].pr_istats    = NULL;
519  protox[i].pr_name      = "pfsync";
520  protox[i].pr_usesysctl = 1;
521  protox[i].pr_protocol  = 0;
522  i++;
523  protox[i].pr_index     = -1;
524  protox[i].pr_sindex    = N_ARPSTAT;
525  protox[i].pr_wanted    = 1;
526  protox[i].pr_cblocks   = NULL;
527  protox[i].pr_stats     = arp_stats;
528  protox[i].pr_istats    = NULL;
529  protox[i].pr_name      = "arp";
530  protox[i].pr_usesysctl = 1;
531  protox[i].pr_protocol  = 0;
532  i++;
533  protox[i].pr_index     = -1;
534  protox[i].pr_sindex    = -1;
535  protox[i].pr_wanted    = 0;
536  protox[i].pr_cblocks   = NULL;
537  protox[i].pr_stats     = NULL;
538  protox[i].pr_istats    = NULL;
539  protox[i].pr_name      = NULL;
540  protox[i].pr_usesysctl = 0;
541  protox[i].pr_protocol  = 0;
542
543#ifdef INET6
544  i=0;
545  ip6protox[i].pr_index     = N_TCBINFO;
546  ip6protox[i].pr_sindex    = N_TCPSTAT;
547  ip6protox[i].pr_wanted    = 1;
548  ip6protox[i].pr_cblocks   = protopr;
549  ip6protox[i].pr_stats     = tcp_stats;
550  ip6protox[i].pr_istats    = NULL;
551  ip6protox[i].pr_name      = "tcp";
552  ip6protox[i].pr_usesysctl = 1;
553  ip6protox[i].pr_protocol  = ;
554  i++;
555  ip6protox[i].pr_index     = N_UDBINFO;
556  ip6protox[i].pr_sindex    = N_UDPSTAT;
557  ip6protox[i].pr_wanted    = 1;
558  ip6protox[i].pr_cblocks   = protopr;
559  ip6protox[i].pr_stats     = udp_stats;
560  ip6protox[i].pr_istats    = NULL;
561  ip6protox[i].pr_name      = "udp";
562  ip6protox[i].pr_usesysctl = 1;
563  ip6protox[i].pr_protocol  = IPPROTO_UDP;
564  i++;
565  ip6protox[i].pr_index     = N_RIPCBINFO;
566  ip6protox[i].pr_sindex    = N_IP6STAT;
567  ip6protox[i].pr_wanted    = 1;
568  ip6protox[i].pr_cblocks   = protopr;
569  ip6protox[i].pr_stats     = ip6_stats;
570  ip6protox[i].pr_istats    = ip6_ifstats;
571  ip6protox[i].pr_name      = "ip6";
572  ip6protox[i].pr_usesysctl = 1;
573  ip6protox[i].pr_protocol  = IPPROTO_RAW;
574  i++;
575  ip6protox[i].pr_index     = N_RIPCBINFO;
576  ip6protox[i].pr_sindex    = N_ICMP6STAT;
577  ip6protox[i].pr_wanted    = 1;
578  ip6protox[i].pr_cblocks   = protopr;
579  ip6protox[i].pr_stats     = icmp6_stats;
580  ip6protox[i].pr_istats    = icmp6_ifstats;
581  ip6protox[i].pr_name      = "icmp6";
582  ip6protox[i].pr_usesysctl = 1;
583  ip6protox[i].pr_protocol  = IPPROTO_ICMPV6;
584  i++;
585#ifdef IPSEC
586  ip6protox[i].pr_index     = -1;
587  ip6protox[i].pr_sindex    = N_IPSEC6STAT;
588  ip6protox[i].pr_wanted    = 1;
589  ip6protox[i].pr_cblocks   = NULL;
590  ip6protox[i].pr_stats     = ipsec_stats;
591  ip6protox[i].pr_istats    = NULL;
592  ip6protox[i].pr_name      = "ipsec6";
593  ip6protox[i].pr_usesysctl = 0;
594  ip6protox[i].pr_protocol  = 0;
595  i++;
596#endif
597#ifdef notyet
598  ip6protox[i].pr_index     = -1;
599  ip6protox[i].pr_sindex    = N_PIM6STAT;
600  ip6protox[i].pr_wanted    = 1;
601  ip6protox[i].pr_cblocks   = NULL;
602  ip6protox[i].pr_stats     = pim6_stats;
603  ip6protox[i].pr_istats    = NULL;
604  ip6protox[i].pr_name      = "pim6";
605  ip6protox[i].pr_usesysctl = 1;
606  ip6protox[i].pr_protocol  = 0;
607  i++;
608#endif
609  ip6protox[i].pr_index     = -1;
610  ip6protox[i].pr_sindex    = N_RIP6STAT;
611  ip6protox[i].pr_wanted    = 1;
612  ip6protox[i].pr_cblocks   = NULL;
613  ip6protox[i].pr_stats     = rip6_stats;
614  ip6protox[i].pr_istats    = NULL;
615  ip6protox[i].pr_name      = "rip6";
616  ip6protox[i].pr_usesysctl = 1;
617  ip6protox[i].pr_protocol  = 0;
618  i++;
619  ip6protox[i].pr_index     = -1;
620  ip6protox[i].pr_sindex    = -1;
621  ip6protox[i].pr_wanted    = 0;
622  ip6protox[i].pr_cblocks   = NULL;
623  ip6protox[i].pr_stats     = NULL;
624  ip6protox[i].pr_istats    = NULL;
625  ip6protox[i].pr_name      = NULL;
626  ip6protox[i].pr_usesysctl = 0;
627  ip6protox[i].pr_protocol  = 0;
628  i++;
629#endif /*INET6*/
630
631#ifdef IPSEC
632  i=0;
633  pfkeyprotox[i].pr_index     = -1;
634  pfkeyprotox[i].pr_sindex    = N_PFKEYSTAT;
635  pfkeyprotox[i].pr_wanted    = 1;
636  pfkeyprotox[i].pr_cblocks   = NULL;
637  pfkeyprotox[i].pr_stats     = pfkey_stats;
638  pfkeyprotox[i].pr_istats    = NULL;
639  pfkeyprotox[i].pr_name      = "pfkey";
640  pfkeyprotox[i].pr_usesysctl = 0;
641  pfkeyprotox[i].pr_protocol  = 0;
642  i++;
643  pfkeyprotox[i].pr_index     = -1;
644  pfkeyprotox[i].pr_sindex    = -1;
645  pfkeyprotox[i].pr_wanted    = 0;
646  pfkeyprotox[i].pr_cblocks   = NULL;
647  pfkeyprotox[i].pr_stats     = NULL;
648  pfkeyprotox[i].pr_istats    = NULL;
649  pfkeyprotox[i].pr_name      = NULL;
650  pfkeyprotox[i].pr_usesysctl = 0;
651  pfkeyprotox[i].pr_protocol  = 0;
652#endif
653
654#ifdef NETGRAPH
655  netgraphprotox[i].pr_index     = N_NGSOCKS;
656  netgraphprotox[i].pr_sindex    = -1;
657  netgraphprotox[i].pr_wanted    = 1;
658  netgraphprotox[i].pr_cblocks   = netgraphprotopr;
659  netgraphprotox[i].pr_stats     = NULL;
660  netgraphprotox[i].pr_istats    = NULL;
661  netgraphprotox[i].pr_name      = "ctrl";
662  netgraphprotox[i].pr_usesysctl = 0;
663  netgraphprotox[i].pr_protocol  = 0;
664  i++;
665  netgraphprotox[i].pr_index     = N_NGSOCKS;
666  netgraphprotox[i].pr_sindex    = -1;
667  netgraphprotox[i].pr_wanted    = 1;
668  netgraphprotox[i].pr_cblocks   = netgraphprotopr;
669  netgraphprotox[i].pr_stats     = NULL;
670  netgraphprotox[i].pr_istats    = NULL;
671  netgraphprotox[i].pr_name      = "data";
672  netgraphprotox[i].pr_usesysctl = 0;
673  netgraphprotox[i].pr_protocol  = 0;
674  i++;
675  netgraphprotox[i].pr_index     = -1;
676  netgraphprotox[i].pr_sindex    = -1;
677  netgraphprotox[i].pr_wanted    = 0;
678  netgraphprotox[i].pr_cblocks   = NULL;
679  netgraphprotox[i].pr_stats     = NULL;
680  netgraphprotox[i].pr_istats    = NULL;
681  netgraphprotox[i].pr_name      = NULL;
682  netgraphprotox[i].pr_usesysctl = 0;
683  netgraphprotox[i].pr_protocol  = 0;
684#endif
685#ifdef IPX
686  i=0;
687  ipxprotox[i].pr_index     = N_IPX;
688  ipxprotox[i].pr_sindex    = N_IPXSTAT;
689  ipxprotox[i].pr_wanted    = 1;
690  ipxprotox[i].pr_cblocks   = ipxprotopr;
691  ipxprotox[i].pr_stats     = ipx_stats;
692  ipxprotox[i].pr_istats    = NULL;
693  ipxprotox[i].pr_name      = "ipx";
694  ipxprotox[i].pr_usesysctl = 0;
695  ipxprotox[i].pr_protocol  = 0;
696  i++;
697  ipxprotox[i].pr_index     = N_IPX;
698  ipxprotox[i].pr_sindex    = N_SPXSTAT;
699  ipxprotox[i].pr_wanted    = 1;
700  ipxprotox[i].pr_cblocks   = ipxprotopr;
701  ipxprotox[i].pr_stats     = spx_stats;
702  ipxprotox[i].pr_istats    = NULL;
703  ipxprotox[i].pr_name      = "spx";
704  ipxprotox[i].pr_usesysctl = 0;
705  ipxprotox[i].pr_protocol  = 0;
706  i++;
707  ipxprotox[i].pr_index     = -1;
708  ipxprotox[i].pr_sindex    = -1;
709  ipxprotox[i].pr_wanted    = 0;
710  ipxprotox[i].pr_cblocks   = NULL;
711  ipxprotox[i].pr_stats     = NULL;
712  ipxprotox[i].pr_istats    = NULL;
713  ipxprotox[i].pr_name      = 0;
714  ipxprotox[i].pr_usesysctl = 0;
715  ipxprotox[i].pr_protocol  = 0;
716  i++;
717#endif
718
719  i=0;
720  protoprotox[i] = protox;
721  i++;
722#ifdef INET6
723  protoprotox[i] = ip6protox,
724  i++;
725#endif
726#ifdef IPSEC
727  protoprotox[i] = pfkeyprotox,
728  i++;
729#endif
730#ifdef IPX
731  protoprotox[i] = ipxprotox,
732#endif
733  noutputs = 0;
734
735  netstat_globals.exit_code = 1;
736  if (setjmp (netstat_globals.exit_jmp) == 0)
737    return main_netstat (argc, argv);
738  return netstat_globals.exit_code;
739}
740#endif
741
742int
743#ifdef __rtems__
744main_netstat(int argc, char *argv[])
745#else
746main(int argc, char *argv[])
747#endif
748{
749        struct protox *tp = NULL;  /* for printing cblocks & stats */
750        int ch;
751#ifdef __rtems__
752        struct getopt_data getopt_reent;
753#endif
754
755        af = AF_UNSPEC;
756
757#ifdef __rtems__
758        memset(&getopt_reent, 0, sizeof(getopt_data));
759        while ((ch = getopt_r(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSstuWw:xz", &getopt_reent)) != -1)
760#else
761        while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSstuWw:xz")) != -1)
762#endif
763                switch(ch) {
764                case 'A':
765                        Aflag = 1;
766                        break;
767                case 'a':
768                        aflag = 1;
769                        break;
770                case 'B':
771                        Bflag = 1;
772                        break;
773                case 'b':
774                        bflag = 1;
775                        break;
776                case 'd':
777                        dflag = 1;
778                        break;
779                case 'f':
780                        if (strcmp(optarg, "ipx") == 0)
781                                af = AF_IPX;
782                        else if (strcmp(optarg, "inet") == 0)
783                                af = AF_INET;
784#ifdef INET6
785                        else if (strcmp(optarg, "inet6") == 0)
786                                af = AF_INET6;
787#endif
788#ifdef IPSEC
789                        else if (strcmp(optarg, "pfkey") == 0)
790                                af = PF_KEY;
791#endif
792                        else if (strcmp(optarg, "unix") == 0)
793                                af = AF_UNIX;
794                        else if (strcmp(optarg, "atalk") == 0)
795                                af = AF_APPLETALK;
796#ifdef NETGRAPH
797                        else if (strcmp(optarg, "ng") == 0
798                            || strcmp(optarg, "netgraph") == 0)
799                                af = AF_NETGRAPH;
800#endif
801                        else if (strcmp(optarg, "link") == 0)
802                                af = AF_LINK;
803                        else {
804                                errx(1, "%s: unknown address family", optarg);
805                        }
806                        break;
807                case 'g':
808                        gflag = 1;
809                        break;
810                case 'h':
811                        hflag = 1;
812                        break;
813                case 'I': {
814                        char *cp;
815
816                        iflag = 1;
817                        for (cp = interface = optarg; isalpha(*cp); cp++)
818                                continue;
819                        unit = atoi(cp);
820                        break;
821                }
822                case 'i':
823                        iflag = 1;
824                        break;
825                case 'L':
826                        Lflag = 1;
827                        break;
828                case 'M':
829                        memf = optarg;
830                        break;
831                case 'm':
832                        mflag = 1;
833                        break;
834                case 'N':
835                        nlistf = optarg;
836                        break;
837                case 'n':
838                        numeric_addr = numeric_port = 1;
839                        break;
840                case 'p':
841                        if ((tp = name2protox(optarg)) == NULL) {
842                                errx(1,
843                                     "%s: unknown or uninstrumented protocol",
844                                     optarg);
845                        }
846                        pflag = 1;
847                        break;
848                case 'q':
849                        noutputs = atoi(optarg);
850                        if (noutputs != 0)
851                                noutputs++;
852                        break;
853                case 'r':
854                        rflag = 1;
855                        break;
856                case 's':
857                        ++sflag;
858                        break;
859                case 'S':
860                        numeric_addr = 1;
861                        break;
862                case 't':
863                        tflag = 1;
864                        break;
865                case 'u':
866                        af = AF_UNIX;
867                        break;
868                case 'W':
869                case 'l':
870                        Wflag = 1;
871                        break;
872                case 'w':
873                        interval = atoi(optarg);
874                        iflag = 1;
875                        break;
876                case 'x':
877                        xflag = 1;
878                        break;
879                case 'z':
880                        zflag = 1;
881                        break;
882                case '?':
883                default:
884                        usage();
885                }
886        argv += optind;
887        argc -= optind;
888
889#define BACKWARD_COMPATIBILITY
890#ifdef  BACKWARD_COMPATIBILITY
891        if (*argv) {
892                if (isdigit(**argv)) {
893                        interval = atoi(*argv);
894                        if (interval <= 0)
895                                usage();
896                        ++argv;
897                        iflag = 1;
898                }
899                if (*argv) {
900                        nlistf = *argv;
901                        if (*++argv)
902                                memf = *argv;
903                }
904        }
905#endif
906
907        /*
908         * Discard setgid privileges if not the running kernel so that bad
909         * guys can't print interesting stuff from kernel memory.
910         */
911        live = (nlistf == NULL && memf == NULL);
912        if (!live)
913                setgid(getgid());
914
915        if (Bflag) {
916                if (!live)
917                        usage();
918                bpf_stats(interface);
919                exit(0);
920        }
921        if (mflag) {
922                if (!live) {
923                        if (kread(0, NULL, 0) == 0)
924                                mbpr(kvmd, nl[N_MBSTAT].n_value);
925                } else
926                        mbpr(NULL, 0);
927                exit(0);
928        }
929#if 0
930        /*
931         * Keep file descriptors open to avoid overhead
932         * of open/close on each call to get* routines.
933         */
934        sethostent(1);
935        setnetent(1);
936#else
937        /*
938         * This does not make sense any more with DNS being default over
939         * the files.  Doing a setXXXXent(1) causes a tcp connection to be
940         * used for the queries, which is slower.
941         */
942#endif
943        kread(0, NULL, 0);
944        if (iflag && !sflag) {
945                intpr(interval, nl[N_IFNET].n_value, NULL);
946                exit(0);
947        }
948        if (rflag) {
949                if (sflag)
950                        rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
951                else
952                        routepr(nl[N_RTREE].n_value);
953                exit(0);
954        }
955        if (gflag) {
956                if (sflag) {
957                        if (af == AF_INET || af == AF_UNSPEC)
958                                mrt_stats(nl[N_MRTSTAT].n_value);
959#ifdef INET6
960                        if (af == AF_INET6 || af == AF_UNSPEC)
961                                mrt6_stats(nl[N_MRT6STAT].n_value);
962#endif
963                } else {
964                        if (af == AF_INET || af == AF_UNSPEC)
965                                mroutepr(nl[N_MFCHASHTBL].n_value,
966                                         nl[N_MFCTABLESIZE].n_value,
967                                         nl[N_VIFTABLE].n_value);
968#ifdef INET6
969                        if (af == AF_INET6 || af == AF_UNSPEC)
970                                mroute6pr(nl[N_MF6CTABLE].n_value,
971                                          nl[N_MIF6TABLE].n_value);
972#endif
973                }
974                exit(0);
975        }
976
977        if (tp) {
978                printproto(tp, tp->pr_name);
979                exit(0);
980        }
981        if (af == AF_INET || af == AF_UNSPEC)
982                for (tp = protox; tp->pr_name; tp++)
983                        printproto(tp, tp->pr_name);
984#ifdef INET6
985        if (af == AF_INET6 || af == AF_UNSPEC)
986                for (tp = ip6protox; tp->pr_name; tp++)
987                        printproto(tp, tp->pr_name);
988#endif /*INET6*/
989#ifdef IPSEC
990        if (af == PF_KEY || af == AF_UNSPEC)
991                for (tp = pfkeyprotox; tp->pr_name; tp++)
992                        printproto(tp, tp->pr_name);
993#endif /*IPSEC*/
994#ifdef IPX
995        if (af == AF_IPX || af == AF_UNSPEC) {
996                for (tp = ipxprotox; tp->pr_name; tp++)
997                        printproto(tp, tp->pr_name);
998        }
999#endif /* IPX */
1000#ifndef __rtems__
1001        if (af == AF_APPLETALK || af == AF_UNSPEC)
1002                for (tp = atalkprotox; tp->pr_name; tp++)
1003                        printproto(tp, tp->pr_name);
1004#endif
1005#ifdef NETGRAPH
1006        if (af == AF_NETGRAPH || af == AF_UNSPEC)
1007                for (tp = netgraphprotox; tp->pr_name; tp++)
1008                        printproto(tp, tp->pr_name);
1009#endif /* NETGRAPH */
1010#ifndef __rtems__
1011        if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
1012                unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
1013                    nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value);
1014#endif
1015        exit(0);
1016}
1017
1018/*
1019 * Print out protocol statistics or control blocks (per sflag).
1020 * If the interface was not specifically requested, and the symbol
1021 * is not in the namelist, ignore this one.
1022 */
1023static void
1024printproto(tp, name)
1025        struct protox *tp;
1026        const char *name;
1027{
1028        void (*pr)(u_long, const char *, int, int);
1029        u_long off;
1030
1031        if (sflag) {
1032                if (iflag) {
1033                        if (tp->pr_istats)
1034                                intpr(interval, nl[N_IFNET].n_value,
1035                                      tp->pr_istats);
1036                        else if (pflag)
1037                                printf("%s: no per-interface stats routine\n",
1038                                    tp->pr_name);
1039                        return;
1040                } else {
1041                        pr = tp->pr_stats;
1042                        if (!pr) {
1043                                if (pflag)
1044                                        printf("%s: no stats routine\n",
1045                                            tp->pr_name);
1046                                return;
1047                        }
1048                        if (tp->pr_usesysctl && live)
1049                                off = 0;
1050                        else if (tp->pr_sindex < 0) {
1051                                if (pflag)
1052                                        printf(
1053                                    "%s: stats routine doesn't work on cores\n",
1054                                            tp->pr_name);
1055                                return;
1056                        } else
1057                                off = nl[tp->pr_sindex].n_value;
1058                }
1059        } else {
1060                pr = tp->pr_cblocks;
1061                if (!pr) {
1062                        if (pflag)
1063                                printf("%s: no PCB routine\n", tp->pr_name);
1064                        return;
1065                }
1066                if (tp->pr_usesysctl && live)
1067                        off = 0;
1068                else if (tp->pr_index < 0) {
1069                        if (pflag)
1070                                printf(
1071                                    "%s: PCB routine doesn't work on cores\n",
1072                                    tp->pr_name);
1073                        return;
1074                } else
1075                        off = nl[tp->pr_index].n_value;
1076        }
1077        if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
1078            af != AF_UNSPEC))
1079                (*pr)(off, name, af, tp->pr_protocol);
1080}
1081
1082#ifdef __rtems__
1083#define _POSIX2_LINE_MAX 128
1084#endif
1085
1086#ifndef __rtems__
1087/*
1088 * Read kernel memory, return 0 on success.
1089 */
1090int
1091kread(u_long addr, void *buf, size_t size)
1092{
1093        char errbuf[_POSIX2_LINE_MAX];
1094
1095        if (kvmd == NULL) {
1096                kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
1097                setgid(getgid());
1098                if (kvmd != NULL) {
1099                        if (kvm_nlist(kvmd, nl) < 0) {
1100                                if (nlistf)
1101                                        errx(1, "%s: kvm_nlist: %s", nlistf,
1102                                             kvm_geterr(kvmd));
1103                                else
1104                                        errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
1105                        }
1106
1107                        if (nl[0].n_type == 0) {
1108                                if (nlistf)
1109                                        errx(1, "%s: no namelist", nlistf);
1110                                else
1111                                        errx(1, "no namelist");
1112                        }
1113                } else {
1114                        warnx("kvm not available: %s", errbuf);
1115                        return(-1);
1116                }
1117        }
1118        if (!buf)
1119                return (0);
1120        if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
1121                warnx("%s", kvm_geterr(kvmd));
1122                return (-1);
1123        }
1124        return (0);
1125}
1126#endif
1127
1128const char *
1129plural(uintmax_t n)
1130{
1131        return (n != 1 ? "s" : "");
1132}
1133
1134const char *
1135plurales(uintmax_t n)
1136{
1137        return (n != 1 ? "es" : "");
1138}
1139
1140const char *
1141pluralies(uintmax_t n)
1142{
1143        return (n != 1 ? "ies" : "y");
1144}
1145
1146/*
1147 * Find the protox for the given "well-known" name.
1148 */
1149static struct protox *
1150knownname(const char *name)
1151{
1152        struct protox **tpp, *tp;
1153
1154        for (tpp = protoprotox; *tpp; tpp++)
1155                for (tp = *tpp; tp->pr_name; tp++)
1156                        if (strcmp(tp->pr_name, name) == 0)
1157                                return (tp);
1158        return (NULL);
1159}
1160
1161/*
1162 * Find the protox corresponding to name.
1163 */
1164static struct protox *
1165name2protox(const char *name)
1166{
1167        struct protox *tp;
1168        char **alias;                   /* alias from p->aliases */
1169        struct protoent *p;
1170
1171        /*
1172         * Try to find the name in the list of "well-known" names. If that
1173         * fails, check if name is an alias for an Internet protocol.
1174         */
1175        if ((tp = knownname(name)) != NULL)
1176                return (tp);
1177
1178        setprotoent(1);                 /* make protocol lookup cheaper */
1179        while ((p = getprotoent()) != NULL) {
1180                /* assert: name not same as p->name */
1181                for (alias = p->p_aliases; *alias; alias++)
1182                        if (strcmp(name, *alias) == 0) {
1183                                endprotoent();
1184                                return (knownname(p->p_name));
1185                        }
1186        }
1187        endprotoent();
1188        return (NULL);
1189}
1190
1191static void
1192usage(void)
1193{
1194        (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
1195"usage: netstat [-AaLnSWx] [-f protocol_family | -p protocol]\n"
1196"               [-M core] [-N system]",
1197"       netstat -i | -I interface [-abdhntW] [-f address_family]\n"
1198"               [-M core] [-N system]",
1199"       netstat -w wait [-I interface] [-d] [-M core] [-N system] [-q howmany]",
1200"       netstat -s [-s] [-z] [-f protocol_family | -p protocol]\n"
1201"               [-M core] [-N system]",
1202"       netstat -i | -I interface -s [-f protocol_family | -p protocol]\n"
1203"               [-M core] [-N system]",
1204"       netstat -m [-M core] [-N system]",
1205"       netstat -B [-I interface]",
1206"       netstat -r [-AanW] [-f address_family] [-M core] [-N system]",
1207"       netstat -rs [-s] [-M core] [-N system]",
1208"       netstat -g [-W] [-f address_family] [-M core] [-N system]",
1209"       netstat -gs [-s] [-f address_family] [-M core] [-N system]");
1210        exit(1);
1211}
1212
1213#ifdef __rtems__
1214  #include <rtems/shell.h>
1215
1216  rtems_shell_cmd_t rtems_shell_NETSTAT_Command = {
1217    "netstat",                     /* name */
1218    "netstat [args]",              /* usage */
1219    "net",                         /* topic */
1220    rtems_shell_main_netstat,      /* command */
1221    NULL,                          /* alias */
1222    NULL                           /* next */
1223  };
1224#endif
Note: See TracBrowser for help on using the repository browser.