📄 pppoem.c
字号:
/*source code components : pppoem.c pppoem.hpurpose : Monitor the DSL connection of a Linux 2.4.4 system (e.g. SuSE 7.2) See also help text in main() and output of: cat /proc/net/pppoe /proc/net/devcompilation : cc -g -DPppoem_use_own_sfilE -DPppoem_use_own_maiN -o pppoem pppoem.cusage : after compilation just start ./pppoem in a terminal window start ./pppoem -help to get the helptext on stderr.license and support address : BSD license, copyright 2001 Thomas Schmitt, stic-source@gmx.net use it as you like*/#ifndef Pppoem_no_system_includeS#include <stdio.h>#include <string.h>#include <errno.h>#include <time.h>#include <wait.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#endif /* ! Pppoem_no_system_includeS *//* ------------------------------------------------------------------------ */#ifdef Pppoem_use_own_maiN#define Pppoem_use_own_cleanuPstatic struct PppoeM *PppoemM= NULL;main(argc,argv)int argc;char **argv;{ char dev_name[80]; int ret; /* Define the default line to watch in /proc/net/dev . dev_name "-" tries to read the name from the second line of /proc/net/pppoe (like "eth0") as soon as it gets available. One could prefer to watch "ppp0" though. Anyway argument -dev_name is able to override the default. loop delay 1.0 second, report intervals 1, 15, 300 standalone | local_time | (only one headline) */ strcpy(dev_name,"-"); ret= Pppoem_new(&PppoemM,dev_name,1.0,1,15,300,1|2); if(ret<=0) exit(1); ret= Pppoem_arg_interpreter(PppoemM,argc,argv,1); if(ret<=0) exit(4); if(argc==2 && (strcmp(argv[1],"-help")==0 || strcmp(argv[1],"-h")==0)) exit(0); /* to get a message on exit */ Cleanup_set_handlers(0); ret= Pppoem_loop(PppoemM,0); if(ret<=0) exit(2); Pppoem_report(PppoemM,"PPPOEM E",!Pppoem_is_open(PppoemM,0)); exit(0);}#endif /* Pppoem_use_own_maiN */#ifdef Pppoem_use_own_cleanuP/* !!! needs a global struct PppoeM *PppoemM */void Cleanup_handler_exit(){ if(PppoemM!=NULL) Pppoem_report(PppoemM,"PPPOEM X",!Pppoem_is_open(PppoemM,0)); exit(3);} int Cleanup_set_handlers(flag)int flag;/* bit0= set to default handlers*/{ if(flag&1) goto set_default; signal(SIGHUP,Cleanup_handler_exit); signal(SIGINT,Cleanup_handler_exit); signal(SIGQUIT,Cleanup_handler_exit); signal(SIGILL,Cleanup_handler_exit); signal(SIGTRAP,Cleanup_handler_exit); signal(SIGFPE,Cleanup_handler_exit); signal(SIGBUS,Cleanup_handler_exit); signal(SIGSEGV,Cleanup_handler_exit); signal(SIGPIPE,Cleanup_handler_exit); signal(SIGALRM,Cleanup_handler_exit); signal(SIGTERM,Cleanup_handler_exit); signal(SIGTERM,Cleanup_handler_exit); signal(SIGUSR1,Cleanup_handler_exit); signal(SIGUSR2,Cleanup_handler_exit); signal(SIGURG,Cleanup_handler_exit); signal(SIGXCPU,Cleanup_handler_exit); signal(SIGXFSZ,Cleanup_handler_exit); signal(SIGVTALRM,Cleanup_handler_exit); signal(SIGPROF,Cleanup_handler_exit); return(1);set_default:; signal(SIGHUP,SIG_DFL); signal(SIGINT,SIG_DFL); signal(SIGQUIT,SIG_DFL); signal(SIGILL,SIG_DFL); signal(SIGTRAP,SIG_DFL); signal(SIGFPE,SIG_DFL); signal(SIGBUS,SIG_DFL); signal(SIGSEGV,SIG_DFL); signal(SIGPIPE,SIG_DFL); signal(SIGALRM,SIG_DFL); signal(SIGTERM,SIG_DFL); signal(SIGUSR1,SIG_DFL); signal(SIGUSR2,SIG_DFL); signal(SIGURG,SIG_DFL); signal(SIGXCPU,SIG_DFL); signal(SIGXFSZ,SIG_DFL); signal(SIGVTALRM,SIG_DFL); signal(SIGPROF,SIG_DFL); return(1);}#endif /* Pppoem_use_own_cleanuP */#ifdef Pppoem_use_smeM#include "../s_tools/smem.h"#else /* Pppoem_use_smeM */#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ));#define Smem_malloC malloc#define Smem_freE free#endif /* ! Pppoem_use_smeM */#ifdef Pppoem_use_own_sfilE/* ---------------------------------- SfilE ---------------------------- */int Sfile_microsleep(microsec,flag)/* sleep very fast by watching no file */unsigned long microsec;int flag;{ struct timeval wt; fd_set rds,wts,exs; int ready; wt.tv_sec= microsec/1000000; wt.tv_usec= microsec%1000000; FD_ZERO(&rds); FD_ZERO(&wts); FD_ZERO(&exs); ready= select(1,&rds,&wts,&exs,&wt); if(ready>0) return(0); /* should never happen */ return(1);}double Sfile_microtime(flag)int flag;{ struct timeval tv; struct timezone tz; gettimeofday(&tv,&tz); return((double) (tv.tv_sec+1.0e-6*tv.tv_usec));}char *Sfile_datestr(tim,flag)time_t tim;short int flag;/* bit0=with hours+minutes bit1=with seconds bit8= local time rather than UTC*/{ static char zeitcode[80]={"000000"}; char puff[80]; struct tm *azt; if(flag&256) azt = localtime(&tim); else azt = gmtime(&tim); if(azt->tm_year>99) sprintf(zeitcode,"%c%01.1d%02.2d%02.2d", 'A'+(azt->tm_year-100)/10,azt->tm_year%10, azt->tm_mon+1,azt->tm_mday); else sprintf(zeitcode,"%02.2d%02.2d%02.2d", azt->tm_year,azt->tm_mon+1,azt->tm_mday); if(flag&1){ sprintf(puff,".%02.2d%02.2d",azt->tm_hour,azt->tm_min); strcat(zeitcode,puff); } if(flag&2){ sprintf(puff,"%02.2d",azt->tm_sec); strcat(zeitcode,puff); } return(zeitcode);}int Sfile_scale(value,result,siz,thresh,flag)double value;char *result;int siz;double thresh;int flag;/* bit0= eventually ommit 'b' bit1= make text as short as possible*/{ char scale_c,scales[6],form[80]; int i; strcpy(scales,"bkmgt"); scale_c= scales[0]; for(i=1;scales[i]!=0;i++) { if(value<thresh) break; value/= 1024; scale_c= scales[i]; } if(scale_c=='b' && (flag&1)) { if(flag&2) sprintf(form,"%%.lf"); else sprintf(form,"%%%ld.lf",siz); sprintf(result,form,value); } else { if(flag&2) sprintf(form,"%%.lf%%c"); else sprintf(form,"%%%ld.lf%%c",siz-1); sprintf(result,form,value,scale_c); } return(1);}int Sfile_fd_is_ready(fd,microsec,flag)int fd;unsigned int microsec;int flag;/* bit0= check for reading bit1= check for writing bit2= check for exceptionreturn-bits are set according to matching flag-bits*/{ struct timeval wt; fd_set rds,wts,exs; int ready,ret; wt.tv_sec= microsec/1000000; wt.tv_usec= microsec%1000000; FD_ZERO(&rds); FD_ZERO(&wts); FD_ZERO(&exs); if(flag&1) FD_SET(fd,&rds); if(flag&2) FD_SET(fd,&wts); if(flag&4) FD_SET(fd,&exs); ready= select(fd+1,&rds,&wts,&exs,&wt); if(ready<=0) return(0); ret= 0; if(flag&1) if(FD_ISSET(fd,&rds)) ret|=1; if(flag&2) if(FD_ISSET(fd,&wts)) ret|=2; if(flag&4) if(FD_ISSET(fd,&exs)) ret|=4; return(ret);}#endif /* Pppoem_use_own_sfilE *//* ---------------------------------- PppoeM ---------------------------- */#include "pppoem.h"int Pppoem_new(mon,dev_name,delay,span1,span2,span3,flag)struct PppoeM **mon;char *dev_name;double delay;int span1,span2,span3;int flag;/* bit0= standalone bit1= use local time for time stamps bit2= print headlines to stderr each time a connection starts*/{ struct PppoeM *m; int i,ret; *mon= m= TSOB_FELD(struct PppoeM,1); if(m==NULL) return(-1); m->standalone= !(flag&1); m->listen_stdin= 0; m->dev_name[0]= 0; m->dev_automatic= 1; m->delay= delay; m->time_spans[0]= span1; m->time_spans[1]= span2; m->time_spans[2]= span3; m->quiet= 0; m->use_local_time= !!(flag&2); m->headlines_on= !!(flag&4); m->poll_count= 0; m->conn_count= 0; m->missing_pppoe_reported= 0; m->is_open= -1; m->start_time= 0; m->start_bytes= 0; m->last_time= 0; m->last_bytes= 0; m->ring_counts= NULL; m->ring_times= NULL; m->ring_size= span1+1; if(span2+1>m->ring_size) m->ring_size= span2+1; if(span3+1>m->ring_size) m->ring_size= span3+1; if(m->ring_size<10) m->ring_size= 10; m->ring_cursor= 0; m->ring_full= 0; if(strlen(dev_name)>=sizeof(m->dev_name)) goto failed; strcpy(m->dev_name,dev_name); if(dev_name[0]!=0 && strcmp(dev_name,"-")!=0) m->dev_automatic= 0; ret= Pppoem_new_ring(m,m->ring_size,0); if(ret<=0) goto failed;/* m->ring_counts= TSOB_FELD(double,m->ring_size); if(m->ring_counts==NULL) goto failed; m->ring_times= TSOB_FELD(double,m->ring_size); if(m->ring_times==NULL) goto failed; for(i=0;i<m->ring_size;i++) m->ring_counts[i]= m->ring_times[i]= 0.0;*/ return(1);failed:; Pppoem_destroy(mon,0); return(-1);}int Pppoem_new_ring(mon,ring_size,flag)struct PppoeM *mon;int ring_size;int flag;{ double *ring_counts= NULL,*ring_times= NULL; int ret,ring_cursor= 0,ring_full= 0,i,idx; if(mon->ring_counts!=NULL && mon->ring_times!=NULL && mon->ring_size==ring_size) return(2); ring_counts= TSOB_FELD(double,ring_size); if(ring_counts==NULL) {ret= -1; goto failed;} ring_times= TSOB_FELD(double,ring_size); if(ring_times==NULL) {ret= -1; goto failed;} for(i=0;i<ring_size;i++) ring_counts[i]= ring_times[i]= 0.0; if(mon->ring_counts!=NULL && mon->ring_times!=NULL) { if(mon->ring_size>ring_size) { if(mon->ring_full || mon->ring_cursor>=ring_size) { for(i= -ring_size;i<0;i++) { Pppoem_ring_index(mon,mon->ring_cursor+i,&idx,0); ring_counts[ring_size+i]= mon->ring_counts[idx]; ring_times[ring_size+i]= mon->ring_times[idx]; } ring_cursor= 0; ring_full= 1; } else {flat_copy:; for(i=0;i<mon->ring_cursor;i++) { ring_counts[i]= mon->ring_counts[i]; ring_times[i]= mon->ring_times[i]; } ring_cursor= mon->ring_cursor; ring_full= 0; } } else { if(mon->ring_full) { for(i=0;i<mon->ring_size;i++) { Pppoem_ring_index(mon,mon->ring_cursor+i,&idx,0); ring_counts[i]= mon->ring_counts[idx]; ring_times[i]= mon->ring_times[idx]; } ring_cursor= mon->ring_size; ring_full= 0; } else { goto flat_copy; } } Smem_freE((char *) mon->ring_counts); mon->ring_counts= NULL; Smem_freE((char *) mon->ring_times); mon->ring_times= NULL; } mon->ring_size= ring_size; mon->ring_counts= ring_counts; mon->ring_times= ring_times; mon->ring_cursor= ring_cursor; mon->ring_full= ring_full; return(1);failed:; if(ring_counts!=NULL) Smem_freE((char *) ring_counts); if(ring_times!=NULL) Smem_freE((char *) ring_times); return(ret);}int Pppoem_destroy(mon,flag)struct PppoeM **mon;int flag;{ struct PppoeM *m; m= *mon; if(m==NULL) return(0); if(m->ring_counts!=NULL) Smem_freE((char *) m->ring_counts); m->ring_counts= NULL; if(m->ring_times!=NULL) Smem_freE((char *) m->ring_times); m->ring_times= NULL; Smem_freE((char *) m); *mon= NULL;}int Pppoem_is_open(mon,flag)struct PppoeM *mon;int flag;{ if(mon==NULL) return(0); return(mon->is_open);}int Pppoem_has_headlines_on(mon,flag)struct PppoeM *mon;int flag;{ if(mon==NULL) return(0); return(mon->headlines_on);}int Pppoem__help_stderr(flag)int flag;/* bit0= also print pppoem options (see Pppoem_arg_interpreter)*/{ fprintf(stderr, "This program monitors the DSL connection of a Linux kernel 2.4.4\n"); fprintf(stderr, "by reading the files /proc/net/pppoe and /proc/net/dev once a second.\n"); fprintf(stderr, "It prints a status report on stderr once per second and a change\n"); fprintf(stderr, "notification on stdout each time the connection changes its state.\n"); fprintf(stderr, "The status report is a text line containing the fields :\n"); fprintf(stderr, "'State' which is either 'DSL OFF' or 'DSL ON' or a device name\n"); fprintf(stderr, "'Time (local)' which is a timestamp like 'YYMMDD.hhmmss'\n"); fprintf(stderr, "'1s' , '15s' , '300s' show the average bytes-per-second for the last\n"); fprintf(stderr, " 1, 15 resp. 300 samples (resp. -1 until valid).\n"); fprintf(stderr, "'total = bytes / uptime' shows a summary since the connection went ON:\n" ); fprintf(stderr, " bytes-per-second = sent plus received bytes / life time in seconds\n"); fprintf(stderr, "Snapshot of Tue Oct 23 16:08:18 CEST 2001 :\n"); fprintf(stderr, " State Time (local) 1s 15s 300s total = bytes / uptime\n" ); fprintf(stderr, "DSL ON A11023.160818 53410 37265 -1 22145 = 5712k / 264s\n" ); fprintf(stderr, "\n"); if(!(flag&1)) return(1); fprintf(stderr, "Options of pppoem :\n"); fprintf(stderr, " -dev_name name\n"); fprintf(stderr, " Set the name of the device line in /proc/net/dev which shall\n"); fprintf(stderr, " be watched to obtain throughput information. If name is given\n"); fprintf(stderr, " as \"-\" then it will be read from /proc/net/pppoe when the\n"); fprintf(stderr, " connection is in state ON (this is the default setting).\n"); fprintf(stderr, " -pretend on|off\n"); fprintf(stderr, " If set to \"on\" ignore /proc/net/pppoe and always watch in\n"); fprintf(stderr, " /proc/net/dev the device given with -dev_name . The state is\n"); fprintf(stderr, " like permanent ON but the -dev_name gets displayed instead.\n"); fprintf(stderr, " One may monitor non-pppoe net devices like \"lo\" this way.\n"); fprintf(stderr, " It might even work with older kernels.\n"); fprintf(stderr, " -listen_stdin on|off\n"); fprintf(stderr, " If set to \"on\" ignore /proc . Listen for messages at stdin:\n"); fprintf(stderr, " \"%%ld %%s %%lf %%lf\" = is_on, dev_name, timestamp, count\n"); fprintf(stderr, " (is_on: 0=OFF,1=ON,2=-pretend, timestamp: seconds since 1970)\n"); fprintf(stderr, " -report on|off|forward\n"); fprintf(stderr, " Control reporting on stdout and stderr. \"off\" disables all\n"); fprintf(stderr, " regular messages. \"on\" is the normal mode. \"forward\"\n"); fprintf(stderr, " prints messages to stdout suitable for -listen_stdin \"on\".\n"); fprintf(stderr, " -show number:number:number\n"); fprintf(stderr, " Set the numbers of samples to be shown for the three gliding\n"); fprintf(stderr, " averages shown in the status line. Default is 1:15:300 .\n"); fprintf(stderr, " -help\n"); fprintf(stderr, " Print this text to stderr.\n"); fprintf(stderr, "\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -