1/* uusnap.c
2   (c) 1992 Heiko W.Rupp hwr@pilhuhn.ka.sub.org
3   uusnap is a tool to display the activities of the connected
4   systems.
5
6   Put a file uusnap.systems in NEWCONFIGDIR (see Makefile), in which
7   the systems, you want to monitor are listed, one on a single line.
8   The sequence of the files there determine the sequence of the
9   listing.
10
11   At the moment it only works with taylor config and taylor dirs
12
13   compile it form the Makefile or:
14   cc -c -g -pipe -O  -I. -I. -DNEWCONFIGLIB=\"/usr/local/lib/uucp\" uusnap.c
15   cc  -o uusnap uusnap.o
16   For this, uusnap.[ch] must be in the same directory as uucp.h and so.
17
18   uusnap must have read access to SPOOLDIR/.Status in order to work.
19*/
20
21#define MAXSYS 30		/* maximum number of systems */
22#define WAIT_NORMAL 10		/* wait period if noone is talking */
23#define WAIT_TALKING 2		/* refresh display every second if */
24				/* someone is talking with us */
25
26#include "uucp.h"
27#if USE_RCS_ID
28char uusnap_rcsid[] = "$Id: uusnap.c,v 1.9 92/05/05 22:51:50 hwr Exp Locker: hwr $";
29#endif
30
31#include <ctype.h>
32#include <time.h>
33#include <sys/types.h>
34#include <sys/dir.h>
35
36extern char *ctime(time_t*);
37
38struct sysInfo  {
39    char sysname[10];		/* name of the system to watch */
40    char *statfile;		/* name of its status file */
41    char *spooldir;		/* root of its spooldir */
42    int in;			/* number of unprocessed in-files */
43    int out;			/* number of files to send them */
44    time_t last;		/* last poll time */
45    time_t next;		/* time of next poll */
46    time_t lastidir;		/* time of last in-spooldir access */
47    time_t lastodir;		/* time of last outgoing spd acc */
48    time_t laststat;		/* time of last status file access */
49    int status;			/* status of the system */
50    int num_retries;		/* number of retries */
51};
52
53struct sysInfo Systems[MAXSYS];
54
55
56/*  I have extend the system status. If time for the specified system
57    is Never, I say so. To get this to work, one also should extend
58    uucico.c. It is not important to do this. With the normal uucico,
59    one only gets no status.
60*/
61
62const char *azStatus[] =        /* Status codes as defined by uucico  */
63{   			        /* listing them here instead of       */
64  "Conversation complete",      /* including the appropriate file     */
65  "Port unavailable",           /* reduces the size of the executable */
66  "Dial failed",
67  "Login failed",
68  "Handshake failed",
69  "Call failed",
70  "Talking",
71  "Wrong time to call",
72  "Time to call = Never !"
73};
74
75main()
76{
77    int i;
78    i=get_systems();
79    display_info(i);
80
81    exit(0);
82}
83
84int
85get_systems()
86{
87    char filename[1024];
88    char fn[1024];
89    char line[80];
90    FILE *fp;
91    int i=0;
92    int j;
93    struct stat stbuf;
94    struct sysInfo sys;
95
96    strcpy(filename,NEWCONFIGLIB);
97    strcat(filename,"/uusnap.systems");
98    if ((fp=fopen(filename,"r"))!=NULL) {
99	while (fgets(line,80,fp)!=NULL) {
100	    *(rindex(line,'\n'))='\0';
101	    strcpy(sys.sysname,line); /* get the name of the system */
102	    strcpy(fn,SPOOLDIR); /* get the name of the statusfile */
103	    strcat(fn,"/.Status/");
104	    strcat(fn,line);
105	    sys.statfile=malloc(strlen(fn)+1);
106	    strcpy(sys.statfile,fn);
107	    strcpy(fn,SPOOLDIR); /* get the name of the spooldir */
108	    strcat(fn,"/");
109	    strcat(fn,line);
110	    sys.spooldir=malloc(strlen(fn)+1);
111	    strcpy(sys.spooldir,fn);
112	    sys.laststat=0;
113	    sys.lastidir=sys.lastodir=0;
114	    Systems[i]=sys;		/* get_stat_for_system needs it */
115	    get_stat_for_system(i);    	/* now get the system status */
116	    get_inq_num(i,TRUE);	/* number of unprocessed files */
117	    get_outq_num(i,TRUE);       /* number of files to send */
118	    i++;
119	}
120	fclose(fp);
121    }
122    else {
123	fprintf(stderr,"Can't open %s \n",filename);
124	exit(1);
125    }
126    return i;
127}
128
129
130
131display_info(int numSys)
132{
133    char *filename;
134    int sysnum;
135    FILE *fp;
136    char contentline[80];
137    char isTalking=FALSE;
138    struct stat stbuf;
139    struct sysInfo sys;
140    time_t time;
141
142    filename = (char*)malloc(1024);
143    if (filename == NULL) {
144	fprintf(stderr, "Can't malloc 1024 bytes");
145	exit(1);
146    }
147
148    while(TRUE) {
149	display_headline();
150	for (sysnum=0;sysnum<numSys;sysnum++) {
151	    sys = Systems[sysnum];
152	    stat(sys.statfile,&stbuf);
153	    if ((time=stbuf.st_atime) > sys.laststat) {
154		get_stat_for_system(sysnum);
155	    }
156	    if(display_status_line(sysnum)==1)
157		isTalking=TRUE;
158	}
159	if (isTalking) {
160	    sleep(WAIT_TALKING);
161	    isTalking = FALSE;
162	}
163	else
164	    sleep(WAIT_NORMAL);            /* wait a bit */
165    }
166    return 0;
167}
168
169int
170display_status_line(int sn)
171{
172    char *time_s;
173
174    int sys_stat,num_retries,wait;
175    int i;
176    time_t last_time;
177    time_t next_time;
178
179    struct sysInfo sys;
180
181    sys = Systems[sn];
182
183    printf("%10s  ",sys.sysname);
184    get_inq_num(sn);
185    if (sys.in==0)
186	printf("     ");
187    else
188	printf("%3d  ",sys.in);
189    get_outq_num(sn);
190    if (sys.out==0)
191	printf("     ");
192    else
193	printf("%3d  ",sys.out);
194    time_s = ctime(&sys.last);
195    time_s = time_s + 11;
196    *(time_s+8)='\0';
197    printf("%8s ",time_s);	/* time of last poll */
198    time_s = ctime(&sys.next);
199    time_s = time_s + 11;
200    *(time_s+8)='\0';
201    if (sys.last == sys.next)
202	printf("           ");
203    else
204	printf("%8s   ",time_s);	/* time of next poll */
205    if (sys.num_retries==0)
206	printf("   ");
207    else
208	printf("%2d ",sys.num_retries);
209    if (sys_stat==6) 		/* system is talking */
210	printf("\E[7m");	/* reverse video on */
211    printf("%s",azStatus[sys.status]);
212    if (sys.status==6) {
213	printf("\E[m\n");	/* reverse video off */
214	return 1;
215    }
216    else {
217	printf("\n");
218	return 0;
219    }
220}
221
222
223display_headline()
224{
225    printf("\E[;H\E[2J");	/* clear screen */
226    printf("\E[7muusnap (press CTRL-C to escape)\E[m \n\n");
227    printf("  System     #in #out   last     next   #ret    Status\n");
228    return 0;
229}
230
231get_inq_num(int num,char firstTime)
232{
233    int i=0;
234    char filename[1024];
235    struct stat stbuf;
236    DIR *dirp;
237
238    strcpy(filename,Systems[num].spooldir);
239    strcat(filename,"/X./.");
240    stat(filename,&stbuf);
241    if ((stbuf.st_mtime > Systems[num].lastidir) || (firstTime)) {
242	if ((dirp=opendir(filename))!=NULL) {
243	    while(readdir(dirp))
244		i++;
245	    closedir(dirp);
246	    stat(filename,&stbuf);
247	    Systems[num].lastidir=stbuf.st_mtime;
248	}
249	else {
250	    fprintf(stderr,"Can't open %s \n",filename);
251	    exit(1);
252	}
253	if (i>=2)
254	    i-=2;			/* correct . and .. */
255	Systems[num].in=i;
256    }
257    return 0;
258}
259
260get_outq_num(int sys,char firstTime)
261{
262    int i=0;
263    char filename[1024];
264    struct stat stbuf;
265    DIR *dirp;
266
267    strcpy(filename,Systems[sys].spooldir);
268    strcat(filename,"/C./.");
269    stat(filename,&stbuf);
270    if ((stbuf.st_mtime > Systems[sys].lastodir) || (firstTime)) {
271	if ((dirp=opendir(filename))!=NULL) {
272	    while(readdir(dirp))
273		i++;
274	    closedir(dirp);
275	    stat(filename,&stbuf);
276	    Systems[sys].lastodir=stbuf.st_mtime;
277	}
278	else {
279	    fprintf(stderr,"Can't open %s \n",filename);
280	    exit(1);
281	}
282	if (i>=2)
283	    i-=2;			/* correct . and .. */
284	Systems[sys].out=i;
285    }
286    return 0;
287}
288
289get_stat_for_system(int i)
290{
291    char fn[80];
292    struct sysInfo sys;
293    struct stat stbuf;
294    FILE *fp;
295    time_t wait;
296
297    sys = Systems[i];
298    stat(sys.statfile,&stbuf);
299    if (stbuf.st_atime > sys.laststat) {
300	if ((fp=fopen(sys.statfile,"r"))!=NULL) {
301	    fgets(fn,80,fp);
302	    fclose(fp);
303	    sscanf(fn,"%d %d %ld %d",
304		   &sys.status,
305		   &sys.num_retries,
306		   &sys.last,
307		   &wait);
308	    sys.next=sys.last+wait;
309	}
310	else {
311	    sys.status=0;
312	    sys.num_retries=0;
313	    sys.last=0;
314	    sys.next=0;
315	}
316	stat(sys.statfile,&stbuf);
317	sys.laststat=stbuf.st_atime;
318    }
319    Systems[i] = sys;
320    return 0;
321}
322