xref: /original-bsd/contrib/usr.x25/x25sa.c (revision 210ce081)
1 /*
2  * Print the kernel X.25 accounting file, in the following format:
3  *  month
4  *  day
5  *  hour:min	- call start time
6  *  duration	- call duration in seconds
7  *  user	- name of user who placed the call
8  *  in/out	- incoming or outgoing call flag
9  *  address	- X.121 address
10  *  host	- host name associated with address, if known
11  *  rev/---	- reverse charge flag
12  *  packet size	- packet size in bytes
13  *  user data	- 4 bytes of user data (protocol),
14  * 		  ITI calls appear as x29d, EAN 1&2 as ean1/ean2,
15  * 		  others as 4 hex digits.
16  *  packets sent
17  *  packets received - number of packets sent and received.
18  *
19  * Not the nicest format for people, but it is assumed that the
20  * output will be further processed before people see it.
21  * The idea here is to convert the raw data to a form
22  * convenient for shell or awk scripts.
23  */
24 #include <stdio.h>
25 #include <sys/file.h>
26 #include <sys/types.h>
27 #include <sys/time.h>
28 #include <pwd.h>
29 #include <netccitt/x25.h>
30 #include <netccitt/x25acct.h>
31 #include <netdb.h>
32 
33 main(argc, argv)
34 	char	**argv;
35 {
36 	struct passwd *pw;
37 	char *user, ubuf[20], *dayt, *filename;
38 	FILE *fp;
39 	struct x25acct ac;
40 	char addr[16+1];
41 	char *format_udata();
42 	struct hostent *hp, *getx25hostbyaddr();
43 
44 	if (argc > 2) {
45 		fprintf(stderr, "usage: %s [file]\n", argv[0]);
46 		exit(1);
47 	}
48 	filename = argc == 2 ? argv[1] : X25ACCTF;
49 	if ((fp = fopen(filename, "r")) == NULL) {
50 		fprintf(stderr, "%s: ", argv[0]);
51 		perror(filename);
52 		exit(1);
53 	}
54 	setx25hostent(1);	/* don't close after each call */
55 	while (fread((char *)&ac, sizeof ac, 1, fp) == 1) {
56 		if (ac.x25acct_txcnt == 0 && ac.x25acct_rxcnt == 0)
57 			continue;
58 		if ((pw = getpwuid(ac.x25acct_uid)) == NULL) {
59 			fprintf(stderr, "%s: unknown uid: %d\n",
60 				argv[0], ac.x25acct_uid);
61 			sprintf(ubuf, "#%d", ac.x25acct_uid);
62 			user = ubuf;
63 		}
64 		else
65 			user = pw->pw_name;
66 		dayt = ctime(&ac.x25acct_stime);
67 		dayt[16] = '\0'; /* we probably know what year it is */
68 		dayt += 4;	/* skip the day */
69 
70 		if (ac.x25acct_addrlen > 16) {
71 			fprintf(stderr, "%s: Invalid addrlen %d\n",
72 				argv[0], ac.x25acct_addrlen);
73 			continue;
74 		}
75 		/*
76 		 * Convert bcd address to ascii.
77 		 */
78 		bzero(addr, sizeof addr);
79 		from_bcd(addr, (u_char *)ac.x25acct_addr,
80 			(int)ac.x25acct_addrlen);
81 		hp = getx25hostbyaddr(addr);
82 
83 		printf("%s %4d %-8s %s %-14s %-9s %s %3d %-4s %3ld %3ld\n",
84 			dayt,
85 			ac.x25acct_etime,
86 			user,
87 			ac.x25acct_callin ? "in " : "out",
88 			addr,
89 			hp ? hp->h_name : addr,
90 			/* REVERSE means collect (by default caller pays) */
91 			ac.x25acct_revcharge ? "rev" : "---",
92 			1 << ac.x25acct_psize,
93 			format_udata(ac.x25acct_udata),
94 			ac.x25acct_txcnt,
95 			ac.x25acct_rxcnt);
96 	}
97 	exit(0);
98 }
99 
100 	char *
101 format_udata(udata)
102 	char *udata;
103 {
104 	static char buf[15];
105 
106 	if (bcmp(udata, "\1\0\0\0", 4) == 0)
107 		return "x29d";
108 	if (bcmp(udata, "ean", 3) == 0)
109 		return udata;
110 	sprintf(buf, "%x.%x.%x.%x",
111 		udata[0], udata[1], udata[2], udata[3]);
112 	return buf;
113 }
114 
115 from_bcd (a, x, len)
116 	register char *a;
117 	register u_char *x;
118 	register int len;
119 {
120 	register int posn = 0;
121 
122 	while (--len >= 0) {
123 		if (posn++ & 0x01)
124 			*a = *x++ & 0x0f;
125 		else
126 			*a = (*x >> 4) & 0x0f;
127 		*a++ |= 0x30;
128 	}
129 }
130