Update to upstream util-linux 2.20.1
[framework/base/util-linux-ng.git] / sys-utils / cytune.c
1 /* cytune.c -- Tune Cyclades driver
2  *
3  * Copyright 1995 Nick Simicich (njs@scifi.emi.net)
4  *
5  * Modifications by Rik Faith (faith@cs.unc.edu)
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by the Nick Simicich
18  * 4. Neither the name of the Nick Simicich nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY NICK SIMICICH AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL NICK SIMICICH OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  */
35
36  /*
37   * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
38   * - added Native Language Support
39   * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
40   * - fixed strerr(errno) in gettext calls
41   */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <sys/types.h>
46 #include <sys/time.h>
47 #include <sys/ioctl.h>
48 #include <unistd.h>
49 #include <string.h>
50 #include <fcntl.h>
51 #include <errno.h>
52 #include <signal.h>
53 #include <termios.h>
54
55 #include "cyclades.h"
56
57 #if 0
58 #ifndef XMIT
59 # include <linux/version.h>
60 # if LINUX_VERSION_CODE > 66056
61 #  define XMIT
62 # endif
63 #endif
64 #endif
65
66 #include "xalloc.h"
67 #include "nls.h"
68                                 /* Until it gets put in the kernel,
69                                    toggle by hand. */
70 #undef XMIT
71
72 struct cyclades_control {
73   struct cyclades_monitor c;
74   int cfile;
75   int maxmax;
76   double maxtran;
77   double maxxmit;
78   unsigned long threshold_value;
79   unsigned long timeout_value;
80 };
81 struct cyclades_control *cmon;
82 int cmon_index;
83
84 #define mvtime(tvpto, tvpfrom)  (((tvpto)->tv_sec = (tvpfrom)->tv_sec),(tvpto)->tv_usec = (tvpfrom)->tv_usec)
85
86
87 static inline double
88 dtime(struct timeval * tvpnew, struct timeval * tvpold) {
89   double diff;
90   diff = (double)tvpnew->tv_sec - (double)tvpold->tv_sec;
91   diff += ((double)tvpnew->tv_usec - (double)tvpold->tv_usec)/1000000;
92   return diff;
93 }
94
95 static int global_argc, global_optind;
96 static char ***global_argv;
97
98 static void
99 summary(int sig) {
100   struct cyclades_control *cc;
101   int argc, local_optind;
102   char **argv;
103   int i;
104
105   argc = global_argc;
106   argv = *global_argv;
107   local_optind = global_optind;
108
109   if (sig > 0) {
110     for(i = local_optind; i < argc; i ++) {
111       cc = &cmon[cmon_index];
112       fprintf(stderr, _("File %s, For threshold value %lu, Maximum characters in fifo were %d,\nand the maximum transfer rate in characters/second was %f\n"), 
113               argv[i],
114               cc->threshold_value,
115               cc->maxmax,
116               cc->maxtran);
117     }
118     
119     exit(0);
120   }
121   cc = &cmon[cmon_index];
122   if (cc->threshold_value > 0 && sig != -1) {
123     fprintf(stderr, _("File %s, For threshold value %lu and timrout value %lu, Maximum characters in fifo were %d,\nand the maximum transfer rate in characters/second was %f\n"),
124             argv[cmon_index+local_optind],
125             cc->threshold_value,
126             cc->timeout_value,
127             cc->maxmax,
128             cc->maxtran);
129   }
130   cc->maxmax = 0;
131   cc->maxtran = 0.0;
132   cc->threshold_value = 0;
133   cc->timeout_value = 0;
134 }
135
136 static int query   = 0;
137 static int interval = 1;
138
139 static int set     = 0;
140 static int set_val = -1;
141 static int get     = 0;
142
143 static int set_def     = 0;
144 static int set_def_val = -1;
145 static int get_def     = 0;
146
147 static int set_time = 0;
148 static int set_time_val = -1;
149
150 static int set_def_time = 0;
151 static int set_def_time_val = -1;
152
153
154 int main(int argc, char *argv[]) {
155
156   struct timeval lasttime, thistime;
157   struct timezone tz = {0,0};
158   double diff;
159   int errflg = 0;
160   int file;
161   int numfiles;
162   struct cyclades_monitor cywork;
163   
164   int i;
165   unsigned long threshold_value;
166   unsigned long timeout_value;
167   double xfer_rate;
168 #ifdef XMIT
169   double xmit_rate;
170 #endif
171   
172   global_argc = argc;           /* For signal routine. */
173   global_argv = &argv;          /* For signal routine. */
174
175   setlocale(LC_ALL, "");
176   bindtextdomain(PACKAGE, LOCALEDIR);
177   textdomain(PACKAGE);
178
179   while ((i = getopt(argc, argv, "qs:S:t:T:gGi:")) != -1) {
180     switch (i) {
181     case 'q':
182       query = 1;
183       break;
184     case 'i':
185       interval = atoi(optarg);
186       if(interval <= 0) {
187         fprintf(stderr, _("Invalid interval value: %s\n"),optarg);
188         errflg ++;
189       }
190       break;
191     case 's':
192       ++set;
193       set_val = atoi(optarg);
194       if(set_val <= 0 || set_val > 12) {
195         fprintf(stderr, _("Invalid set value: %s\n"),optarg);
196         errflg ++;
197       }
198       break;
199     case 'S':
200        ++set_def;
201       set_def_val = atoi(optarg);
202       if(set_def_val < 0 || set_def_val > 12) {
203         fprintf(stderr, _("Invalid default value: %s\n"),optarg);
204         errflg ++;
205       }
206       break;
207     case 't':
208       ++set_time;
209       set_time_val = atoi(optarg);
210       if(set_time_val <= 0 || set_time_val > 255) {
211         fprintf(stderr, _("Invalid set time value: %s\n"),optarg);
212         errflg ++;
213       }
214       break;
215     case 'T':
216        ++set_def_time;
217       set_def_time_val = atoi(optarg);
218       if(set_def_time_val < 0 || set_def_time_val > 255) {
219         fprintf(stderr, _("Invalid default time value: %s\n"),optarg);
220         errflg ++;
221       }
222       break;
223     case 'g': ++get;     break;
224     case 'G': ++get_def; break;
225     default:
226       errflg ++;
227     }
228   }
229   numfiles = argc - optind;
230   if(errflg || (numfiles == 0)
231      || (!query && !set && !set_def && 
232          !get && !get_def && !set_time && !set_def_time) || 
233      (set && set_def) || (set_time && set_def_time) || 
234      (get && get_def)) {
235     fprintf(stderr, 
236             _("Usage: %s [-q [-i interval]] ([-s value]|[-S value]) ([-t value]|[-T value]) [-g|-G] file [file...]\n"),
237             argv[0]);
238     exit(1);
239   }
240
241   global_optind = optind;       /* For signal routine. */
242
243   if (set || set_def) {
244     for(i = optind; i < argc; i++) {
245       file = open(argv[i],O_RDONLY);
246       if(file == -1) {
247         int errsv = errno;
248         fprintf(stderr, _("Can't open %s: %s\n"),argv[i],strerror(errsv));
249         exit(1);
250       }
251       if(ioctl(file,
252                set ? CYSETTHRESH : CYSETDEFTHRESH,
253                set ? set_val : set_def_val)) {
254         int errsv = errno;
255         fprintf(stderr, _("Can't set %s to threshold %d: %s\n"),
256                 argv[i],set?set_val:set_def_val,strerror(errsv));
257         exit(1);
258       }
259       close(file);
260     }
261   }
262   if (set_time || set_def_time) {
263     for(i = optind; i < argc; i++) {
264       file = open(argv[i],O_RDONLY);
265       if(file == -1) {
266         int errsv = errno;
267         fprintf(stderr, _("Can't open %s: %s\n"),argv[i],strerror(errsv));
268         exit(1);
269       }
270       if(ioctl(file,
271                set_time ? CYSETTIMEOUT : CYSETDEFTIMEOUT,
272                set_time ? set_time_val : set_def_time_val)) {
273         int errsv = errno;
274         fprintf(stderr, _("Can't set %s to time threshold %d: %s\n"),
275                 argv[i],set_time?set_time_val:set_def_time_val,strerror(errsv));
276         exit(1);
277       }
278       close(file);
279     }
280   }
281
282   if (get || get_def) {
283     for(i = optind; i < argc; i++) {
284       file = open(argv[i],O_RDONLY);
285       if(file == -1) {
286         int errsv = errno;
287         fprintf(stderr, _("Can't open %s: %s\n"),argv[i],strerror(errsv));
288         exit(1);
289       }
290       if(ioctl(file, get ? CYGETTHRESH : CYGETDEFTHRESH, &threshold_value)) {
291         int errsv = errno;
292         fprintf(stderr, _("Can't get threshold for %s: %s\n"),
293                 argv[i],strerror(errsv));
294         exit(1);
295       }
296       if(ioctl(file, get ? CYGETTIMEOUT : CYGETDEFTIMEOUT, &timeout_value)) {
297         int errsv = errno;
298         fprintf(stderr, _("Can't get timeout for %s: %s\n"),
299                 argv[i],strerror(errsv));
300         exit(1);
301       }
302       close(file);
303       if (get)
304               printf(_("%s: %ld current threshold and %ld current timeout\n"),
305                      argv[i], threshold_value, timeout_value);
306       else
307               printf(_("%s: %ld default threshold and %ld default timeout\n"),
308                      argv[i], threshold_value, timeout_value);
309     }
310   }
311
312   if(!query) return 0;          /* must have been something earlier */
313
314   /* query stuff after this line */
315   
316   cmon = xmalloc(sizeof(struct cyclades_control) * numfiles);
317
318   if(signal(SIGINT, summary)||
319      signal(SIGQUIT, summary)||
320      signal(SIGTERM, summary)) {
321     perror(_("Can't set signal handler"));
322     exit(1);
323   }
324   if(gettimeofday(&lasttime,&tz)) {
325     perror(_("gettimeofday failed"));
326     exit(1);
327   }
328   for(i = optind; i < argc; i ++) {
329     cmon_index = i - optind;
330     cmon[cmon_index].cfile = open(argv[i], O_RDONLY);
331     if(-1 == cmon[cmon_index].cfile) {
332       int errsv = errno;
333       fprintf(stderr, _("Can't open %s: %s\n"),argv[i],strerror(errsv));
334       exit(1);
335     }
336     if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cmon[cmon_index].c)) {
337       int errsv = errno;
338       fprintf(stderr, _("Can't issue CYGETMON on %s: %s\n"),
339               argv[i],strerror(errsv));
340       exit(1);
341     }
342     summary(-1);
343     if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) {
344       int errsv = errno;
345       fprintf(stderr, _("Can't get threshold for %s: %s\n"),
346               argv[i],strerror(errsv));
347       exit(1);
348     }
349     if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) {
350       int errsv = errno;
351       fprintf(stderr, _("Can't get timeout for %s: %s\n"),
352               argv[i],strerror(errsv));
353       exit(1);
354     }
355   }
356   while(1) {
357     sleep(interval);
358     
359     if(gettimeofday(&thistime,&tz)) {
360       perror(_("gettimeofday failed"));
361       exit(1);
362     }
363     diff = dtime(&thistime, &lasttime);
364     mvtime(&lasttime, &thistime);
365
366     for(i = optind; i < argc; i ++) {
367       cmon_index = i - optind;
368       if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cywork)) {
369         int errsv = errno;
370         fprintf(stderr, _("Can't issue CYGETMON on %s: %s\n"),
371                 argv[i],strerror(errsv));
372         exit(1);
373       }
374       if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) {
375         int errsv = errno;
376         fprintf(stderr, _("Can't get threshold for %s: %s\n"),
377                 argv[i],strerror(errsv));
378         exit(1);
379       }
380       if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) {
381         int errsv = errno;
382         fprintf(stderr, _("Can't get timeout for %s: %s\n"),
383                 argv[i],strerror(errsv));
384         exit(1);
385       }
386
387       xfer_rate = cywork.char_count/diff;
388 #ifdef XMIT
389       xmit_rate = cywork.send_count/diff;
390 #endif
391
392       if(threshold_value != cmon[cmon_index].threshold_value ||
393          timeout_value != cmon[cmon_index].timeout_value) {
394         summary(-2);
395         /* Note that the summary must come before the setting of */
396         /* threshold_value */
397         cmon[cmon_index].threshold_value = threshold_value;      
398         cmon[cmon_index].timeout_value = timeout_value;  
399       } else {
400         /* Don't record this first cycle after change */
401         if(xfer_rate > cmon[cmon_index].maxtran) 
402           cmon[cmon_index].maxtran = xfer_rate;
403 #ifdef XMIT
404         if(xmit_rate > cmon[cmon_index].maxxmit)
405           cmon[cmon_index].maxxmit = xmit_rate;
406 #endif
407         if(cmon[cmon_index].maxmax < 0 ||
408            cywork.char_max > (unsigned long) cmon[cmon_index].maxmax)
409           cmon[cmon_index].maxmax = cywork.char_max;
410       }
411
412 #ifdef XMIT
413       printf(_("%s: %lu ints, %lu/%lu chars; fifo: %lu thresh, %lu tmout, "
414                "%lu max, %lu now\n"),
415              argv[i],
416              cywork.int_count,cywork.char_count,cywork.send_count,
417              threshold_value,timeout_value,
418              cywork.char_max,cywork.char_last);
419       printf(_("   %f int/sec; %f rec, %f send (char/sec)\n"),
420              cywork.int_count/diff,
421              xfer_rate,
422              xmit_rate);
423 #else
424       printf(_("%s: %lu ints, %lu chars; fifo: %lu thresh, %lu tmout, "
425                "%lu max, %lu now\n"),
426              argv[i],
427              cywork.int_count,cywork.char_count,
428              threshold_value,timeout_value,
429              cywork.char_max,cywork.char_last);
430       printf(_("   %f int/sec; %f rec (char/sec)\n"),
431              cywork.int_count/diff,
432              xfer_rate);
433 #endif
434       memcpy(&cmon[cmon_index].c, &cywork, sizeof (struct cyclades_monitor));
435     }
436   }
437
438   return 0;
439 }