Replace outdated NLS support with GNU gettext (patch from
[platform/upstream/net-tools.git] / statistics.c
1 /* Copyright '97 by Andi Kleen. Subject to the GPL. */
2 /* 19980630 - i18n - Arnaldo Carvalho de Melo <acme@conectiva.com.br> */
3
4 #include <ctype.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "config.h"
9 #include "intl.h"
10
11 /* #define WARN 1 */
12
13 #ifdef WARN
14 #define UFWARN(x) x
15 #else
16 #define UFWARN(x) 
17 #endif
18
19 int print_static; 
20
21 enum State { number = 0, i_forward, i_inp_icmp, i_outp_icmp, i_rto_alg };
22 #define normal number
23
24 struct entry {
25         char *title;
26         char *out; 
27         enum State type;
28 }; 
29
30 static enum State state;
31 static int indent[] = { 4, 4, 8, 8, 4 };       /* for each state */
32
33 #define I_STATIC (1<<16) /* static configuration option. */
34 #define I_TITLE  (1<<17)
35
36 char *titles[] = { /* for each state */
37         NULL, NULL, 
38         N_("ICMP input histogram:"),
39         N_("ICMP output histogram:"),
40         NULL
41 };
42
43 /* XXX check against the snmp mib rfc.
44  */
45 struct entry Iptab[] = {
46         { N_("Forwarding"), N_("Forwarding is %s"), i_forward|I_STATIC },
47         { N_("DefaultTTL"), N_("Default TTL is %d"), number|I_STATIC },
48         { N_("InReceives"), N_("%d total packets received"), number },
49         { N_("InHdrErrors"), N_("%d with invalid headers"), number },
50         { N_("InAddrErrors"), N_("%d with invalid addresses"), number },
51         { N_("ForwDatagrams"), N_("%d forwarded"), number },
52         { N_("InUnknownProtos"), N_("%d with unknown protocol"), number },
53         { N_("InDiscards"), N_("%d incoming packets discarded"), number },
54         { N_("InDelivers"), N_("%d incoming packets delivered"), number },
55         { N_("OutRequests"), N_("%d requests sent out"), number }, /*?*/
56         { N_("OutDiscards"), N_("%d outgoing packets dropped"), number }, 
57         { N_("OutNoRoutes"), N_("%d dropped because of missing route"), number },
58         { N_("ReasmTimeout"), N_("%d fragments dropped after timeout"), number },
59         { N_("ReasmReqds"), N_("%d reassemblies required"), number }, /* ? */
60         { N_("ReasmOKs"), N_("%d packets reassembled ok"), number }, 
61         { N_("ReasmFails"), N_("%d packet reassembles failed"), number }, 
62         { N_("FragOKs"), N_("%d fragments received ok"), number },
63         { N_("FragFails"), N_("%d fragments failed"), number },
64         { N_("FragCreates"), N_("%d fragments created"), number }
65 };
66
67 struct entry Icmptab[] = {
68         { N_("InMsgs"), N_("%d ICMP messages received"), number },
69         { N_("InErrors"), N_("%d input ICMP message failed."), number },
70         { N_("InDestUnreachs"), N_("destination unreachable: %d"), i_inp_icmp|I_TITLE },
71         { N_("InTimeExcds"), N_("timeout in transit: %d"), i_inp_icmp|I_TITLE },
72         { N_("InParmProbs"), N_("wrong parameters: %d"), i_inp_icmp|I_TITLE },  /*?*/
73         { N_("InSrcQuenchs"), N_("source quenchs: %d"), i_inp_icmp|I_TITLE },
74         { N_("InRedirects"), N_("redirects: %d"), i_inp_icmp|I_TITLE },
75         { N_("InEchos"), N_("echo requests: %d"), i_inp_icmp|I_TITLE },
76         { N_("InEchoReps"), N_("echo replies: %d"), i_inp_icmp|I_TITLE },
77         { N_("InTimestamps"), N_("timestamp request: %d"), i_inp_icmp|I_TITLE },
78         { N_("InTimestampReps"), N_("timestamp reply: %d"), i_inp_icmp|I_TITLE },
79         { N_("InAddrMasks"), N_("address mask request: %d"), i_inp_icmp|I_TITLE }, /*?*/
80         { N_("InAddrMaskReps"), N_("address mask replies"), i_inp_icmp|I_TITLE }, /*?*/
81         { N_("OutMsgs"), N_("%d ICMP messages sent"), number },
82         { N_("OutErrors"), N_("%d ICMP messages failed"), number },
83         { N_("OutDestUnreachs"), N_("destination unreachable: %d"), i_outp_icmp|I_TITLE },
84         { N_("OutTimeExcds"), N_("time exceeded: %d"), i_outp_icmp|I_TITLE },
85         { N_("OutParmProbs"), N_("wrong parameters: %d"), i_outp_icmp|I_TITLE }, /*?*/
86         { N_("OutSrcQuenchs"), N_("source quench: %d"), i_outp_icmp|I_TITLE },
87         { N_("OutRedirects"), N_("redirect: %d"), i_outp_icmp|I_TITLE },
88         { N_("OutEchos"), N_("echo request: %d"), i_outp_icmp|I_TITLE },
89         { N_("OutEchoReps"), N_("echo replies: %d"), i_outp_icmp|I_TITLE },
90         { N_("OutTimestamps"), N_("timestamp requests: %d"), i_outp_icmp|I_TITLE },
91         { N_("OutTimestampReps"), N_("timestamp replies: %d"), i_outp_icmp|I_TITLE },
92         { N_("OutAddrMasks"), N_("address mask requests: %d"), i_outp_icmp|I_TITLE },
93         { N_("OutAddrMaskReps"), N_("address mask replies: %d"), i_outp_icmp|I_TITLE },
94 };
95
96 struct entry Tcptab[] = {
97         { N_("RtoAlgorithm"), N_("RTO algorithm is %s"), i_rto_alg|I_STATIC },
98         { N_("RtoMin"), "", number },
99         { N_("RtoMax"), "", number },
100         { N_("MaxConn"), "", number },
101         { N_("ActiveOpens"), N_("%d active opens"), number },
102         { N_("PassiveOpens"), N_("%d passive opens"), number },
103         { N_("AttemptFails"), N_("%d failed connection attempts"), number },
104         { N_("EstabResets"), N_("%d connection resets received"), number },
105         { N_("CurrEstab"), N_("%d connections established"), number },
106         { N_("InSegs"), N_("%d segments received"), number },
107         { N_("OutSegs"), N_("%d segments send out"), number },
108         { N_("RetransSegs"), N_("%d segments retransmited"), number },
109         { N_("InErrs"), N_("%d bad segments received."), number },
110         { N_("OutRsts"), N_("%d resets sent"), number },
111 };
112
113 struct entry Udptab[] = {
114         { N_("InDatagrams"), N_("%d packets received"), number },
115         { N_("NoPorts"), N_("%d packets to unknown port received."), number },
116         { N_("InErrors"), N_("%d packet receive errors"), number },
117         { N_("OutDatagrams"), N_("%d packets send"), number },
118 };
119
120 struct tabtab {
121         char *title; 
122         struct entry *tab; 
123         size_t size; 
124 }; 
125
126 struct tabtab snmptabs[] = { 
127         { "Ip", Iptab, sizeof(Iptab) },
128         { "Icmp", Icmptab, sizeof(Icmptab) },
129         { "Tcp", Tcptab, sizeof(Tcptab) },
130         { "Udp", Udptab, sizeof(Udptab) },
131         { NULL }
132 }; 
133
134 static char *skiptok(char *s)
135 {
136         while (!isspace(*s) && *s != '\0')
137                 s++; 
138         return s;
139 }
140
141
142 /* XXX IGMP */ 
143
144 int cmpentries(const void *a, const void *b)
145 {
146         return strcmp( ((struct entry*)a)->title, ((struct entry*)b)->title);
147 }
148
149 void printval(struct tabtab *tab, char *title, int val) 
150 {
151         struct entry *ent, key; 
152         int type; 
153         char buf[512];
154
155         key.title = title; 
156         ent = bsearch(&key, tab->tab, tab->size/sizeof(struct entry),
157                                   sizeof(struct entry), cmpentries); 
158         if (!ent)  { /* try our best */ 
159                 printf("%*s%s: %d\n", indent[state], "", _(title), val);
160                 return;
161         }
162         type = ent->type; 
163         if (type & I_STATIC) {
164                 type &= ~I_STATIC; 
165                 if (!print_static) 
166                         return; 
167         }
168         if (*ent->out == '\0') 
169                 return; 
170
171         if (type & I_TITLE) {
172                 type &= ~I_TITLE;
173                 if (state != type)
174                         printf("%*s%s\n", indent[state], "", _(titles[type]));
175         }
176
177         buf[0] = '\0';
178         switch (type) {
179         case number:
180                 sprintf(buf, _(ent->out), val);
181                 break; 
182         case i_forward:
183                 type = normal;
184                 sprintf(buf, _(ent->out), val == 2 ? _("enabled") : _("disabled"));
185                 break; 
186         case i_outp_icmp:
187         case i_inp_icmp: 
188                 if (val > 0) {
189                         sprintf(buf,_(ent->out), val); 
190                 }
191                 break; 
192         case i_rto_alg: /* XXXX */
193                 break; 
194         default:
195                 abort(); 
196         }
197         if (buf[0]) 
198                 printf("%*s%s\n",indent[type],"", buf);
199         
200         state = type;
201 }
202
203 struct tabtab *newtable(struct tabtab *tabs, char *title) 
204 {
205         struct tabtab *t; 
206
207         for (t = tabs; t->title; t++) 
208                 if (!strcmp(title, t->title)) {
209                         printf("%s:\n", _(title)); 
210                         state = normal; 
211                         return t; 
212                 }
213         return NULL; 
214 }
215
216 void parsesnmp()
217 {
218         FILE *f; 
219         char buf1[512], buf2[512]; 
220         char *sp, *np, *p; 
221
222         f = fopen("/proc/net/snmp", "r"); 
223         if (!f) {
224                 perror(_("cannot open /proc/net/snmp"));
225                 return;
226         }
227         while (fgets(buf1,sizeof buf1,f)) {
228                 int endflag; 
229                 struct tabtab *tab; 
230
231                 if (!fgets(buf2,sizeof buf2,f)) break; 
232                 sp = strchr(buf1, ':');
233                 np = strchr(buf2, ':'); 
234                 if (!np || !sp) 
235                         goto formaterr; 
236                 *sp = '\0'; 
237                 tab = newtable(snmptabs, buf1); 
238                 if (tab == NULL)  {
239                         UFWARN((printf(_("unknown title %s\n"), buf1)));
240                         continue; 
241                 }
242                 np++; sp++; 
243                 
244                 endflag = 0; 
245                 while (!endflag) {
246                         while(isspace(*sp)) sp++; 
247                         while(isspace(*np)) np++; 
248                         /*if (*np == '\0') goto formaterr;*/ 
249
250                         p = skiptok(sp); 
251                         if (*p == '\0') endflag=1; 
252                         *p = '\0'; 
253
254                         if (*sp != '\0') /* XXX */ 
255                                 printval(tab, sp, strtoul(np,&np,10)); 
256                         sp = p+1; 
257                 }
258         }
259         if (ferror(f)) 
260                 perror("/proc/net/snmp"); 
261         fclose(f); 
262         return; 
263
264 formaterr: 
265         perror(_("error parsing /proc/net/snmp")); 
266         return; 
267 }
268
269 void inittab()
270 {
271         struct tabtab *t;
272  
273         /* we sort at runtime because I'm lazy ;) */ 
274         for (t = snmptabs; t->title; t++)  
275                 qsort(t->tab, t->size/sizeof(struct entry), 
276                           sizeof(struct entry), cmpentries); 
277 }