]> mj.ucw.cz Git - nwho.git/blob - nwho.c
b7c932c3b3487c6d9f4684a4b3d7e206eb5652af
[nwho.git] / nwho.c
1 /*
2  *      The Remote User Information Lister
3  *
4  *      (c) 1997--2010 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <dirent.h>
13 #include <time.h>
14 #include <netinet/in.h>
15
16 #include "nwho.h"
17
18 static int is_uptime;
19 static time_t now;
20
21 struct out_host {
22   char name[32];
23   struct nwho_pkt *pkt;
24 };
25
26 struct out_user {
27   struct userinfo *user;
28   struct out_host *host;
29 };
30
31 static struct out_host **host_array;
32 static int num_hosts;
33 static int max_hosts = 16;
34
35 static struct out_user *user_array;
36 static int num_users;
37 static int max_users = 16;
38
39 static void *
40 xmalloc(size_t size)
41 {
42   void *p = malloc(size);
43   if (!p)
44     die("Out of memory");
45   return p;
46 }
47
48 static struct out_host *
49 new_host(struct nwho_pkt *orig_pkt, char *name)
50 {
51   int len = nwho_pkt_size(orig_pkt);
52   struct nwho_pkt *pkt = xmalloc(len);
53   memcpy(pkt, orig_pkt, len);
54
55   struct out_host *host = xmalloc(sizeof(*host));
56   snprintf(host->name, sizeof(host->name), "%s", name);
57   host->pkt = pkt;
58
59   if (!host_array || num_hosts >= max_hosts)
60     {
61       max_hosts *= 2;
62       host_array = realloc(host_array, max_hosts * sizeof(struct out_host));
63     }
64   host_array[num_hosts++] = host;
65
66   return host;
67 }
68
69 static void
70 new_user(struct out_host *host, struct userinfo *ui)
71 {
72   if (!user_array || num_users >= max_users)
73     {
74       max_users *= 2;
75       user_array = realloc(user_array, max_users * sizeof(struct out_user));
76     }
77   user_array[num_users++] = (struct out_user) {
78     .user = ui,
79     .host = host
80   };
81 }
82
83 static void
84 puttime(int s)
85 {
86   int d, h, m;
87   if (s < 100)
88     printf("%4ds", s);
89   else
90     {
91       m = s/60;
92       s %= 60;
93       h = m/60;
94       m %= 60;
95       if (h < 100)
96         printf("%02d.%02d", h, m);
97       else
98         {
99           d = h/24;
100           h %= 24;
101           if (d < 100)
102             printf("%2dd%02d", d, h);
103           else
104             printf("%4dd", d);
105         }
106     }
107 }
108
109 static void
110 show_uptime(void)
111 {
112   for (int i=0; i<num_hosts; i++)
113     {
114       struct out_host *h = host_array[i];
115       struct nwho_pkt *p = h->pkt;
116
117       if (now - ntohl(p->server_time) >= DEFAULT_DOWN_TIME)
118         {
119           printf("%-16s down\n", h->name);
120           continue;
121         }
122       printf("%-16s up ", h->name);
123       puttime(ntohl(p->uptime));
124       printf("  load");
125       for(int j=0; j<3; j++)
126         {
127           int l = ntohl(p->avl[j]);
128           printf(" %2d.%02d", l/100, l%100);
129         }
130       printf(" %3d users\n", (int) ntohl(p->num_users));
131     }
132 }
133
134 static void
135 show_users(void)
136 {
137   puts("Name     Li      M Where            LogT  IdleT");
138
139   for (int i=0; i<num_users; i++)
140     {
141       struct out_host *h = user_array[i].host;
142       struct userinfo *u = user_array[i].user;
143
144       if (now - ntohl(h->pkt->server_time) >= DEFAULT_DOWN_TIME)
145         continue;
146       printf("%-8.8s %-7s %c %-16s ", u->name, u->con, (u->mesg_y ? ' ' : '-'), h->name);
147       puttime(ntohl(u->login_time));
148       putchar(' ');
149       puttime(ntohl(u->idle_time));
150       putchar('\n');
151     }
152
153   for (int i=0; i<num_hosts; i++)
154     {
155       struct out_host *h = host_array[i];
156       if (ntohl(h->pkt->num_users) >= MAX_USERS)
157         printf("%s: MAX_USERS reached!\n", h->name);
158     }
159 }
160
161 static void
162 scan(void)
163 {
164   DIR *d;
165   struct dirent *e;
166   struct nwho_pkt pkt;
167   int fd, r;
168
169   if (chdir(NWHO_SPOOL_DIR) < 0)
170     {
171       fprintf(stderr, "chdir(" NWHO_SPOOL_DIR "): %m\n");
172       exit(1);
173     }
174   d = opendir(".");
175   if (!d)
176     {
177       perror("opendir");
178       exit(1);
179     }
180   while (e = readdir(d))
181     if (e->d_name[0] != '.')
182       {
183         fd = open(e->d_name, O_RDONLY);
184         if (fd < 0)
185           {
186             fprintf(stderr, "%s: %m\n", e->d_name);
187             continue;
188           }
189         r = read(fd, &pkt, sizeof(pkt));
190         close(fd);
191         if (r < sizeof(struct nwho_pkt) - MAX_USERS*sizeof(struct userinfo)
192             || pkt.magic != htonl(NWHO_MAGIC)
193             || r != sizeof(struct nwho_pkt) - (MAX_USERS - ntohl(pkt.num_users))*sizeof(struct userinfo))
194           {
195             fprintf(stderr, "%s: Malformed record\n", e->d_name);
196             continue;
197           }
198         struct out_host *host = new_host(&pkt, e->d_name);
199         for (int i=0; i < ntohl(pkt.num_users); i++)
200           new_user(host, &host->pkt->users[i]);
201       }
202   closedir(d);
203 }
204
205 int
206 main(int argc, char **argv)
207 {
208   if (argc == 2 && !strcmp(argv[1], "--version"))
209     {
210       printf("nwho " STRINGIFY(VERSION) "\n");
211       return 0;
212     }
213
214   if (strstr(argv[0], "uptime"))
215     is_uptime = 1;
216   if (argc != 1)
217     {
218       fprintf(stderr, "Usage: %s\n", argv[0]);
219       return 1;
220     }
221
222   now = time(NULL);
223   scan();
224   if (!num_hosts)
225     {
226       puts("No data available.");
227       return 0;
228     }
229
230   if (!is_uptime)
231     show_users();
232   else
233     show_uptime();
234   return 0;
235 }