2 * The Remote User Information Lister
4 * (c) 1997--2010 Martin Mares <mj@ucw.cz>
14 #include <netinet/in.h>
27 struct userinfo *user;
28 struct out_host *host;
31 static struct out_host **host_array;
33 static int max_hosts = 16;
35 static struct out_user *user_array;
37 static int max_users = 16;
42 void *p = malloc(size);
48 static struct out_host *
49 new_host(struct nwho_pkt *orig_pkt, char *name)
51 int len = nwho_pkt_size(orig_pkt);
52 struct nwho_pkt *pkt = xmalloc(len);
53 memcpy(pkt, orig_pkt, len);
55 struct out_host *host = xmalloc(sizeof(*host));
56 snprintf(host->name, sizeof(host->name), "%s", name);
59 if (!host_array || num_hosts >= max_hosts)
62 host_array = realloc(host_array, max_hosts * sizeof(struct out_host));
64 host_array[num_hosts++] = host;
70 new_user(struct out_host *host, struct userinfo *ui)
72 if (!user_array || num_users >= max_users)
75 user_array = realloc(user_array, max_users * sizeof(struct out_user));
77 user_array[num_users++] = (struct out_user) {
84 cmp_users_by_hosts(const void *va, const void *vb)
86 const struct out_user *a = va;
87 const struct out_user *b = vb;
88 return strcmp(a->host->name, b->host->name);
92 cmp_users_by_names(const void *va, const void *vb)
94 const struct out_user *a = va;
95 const struct out_user *b = vb;
96 return strcmp(a->user->name, b->user->name);
100 sort_users(int by_hosts)
102 qsort(user_array, num_users, sizeof(user_array[0]),
103 (by_hosts ? cmp_users_by_hosts : cmp_users_by_names));
107 cmp_hosts(const void *va, const void *vb)
109 const struct out_host * const *a = va;
110 const struct out_host * const *b = vb;
111 return strcmp((*a)->name, (*b)->name);
117 qsort(host_array, num_hosts, sizeof(host_array[0]), cmp_hosts);
133 printf("%02d.%02d", h, m);
139 printf("%2dd%02d", d, h);
149 for (int i=0; i<num_hosts; i++)
151 struct out_host *h = host_array[i];
152 struct nwho_pkt *p = h->pkt;
154 if (now - ntohl(p->server_time) >= DEFAULT_DOWN_TIME)
156 printf("%-16s down\n", h->name);
159 printf("%-16s up ", h->name);
160 puttime(ntohl(p->uptime));
162 for(int j=0; j<3; j++)
164 int l = ntohl(p->avl[j]);
165 printf(" %2d.%02d", l/100, l%100);
167 printf(" %3d users\n", (int) ntohl(p->num_users));
174 puts("Name Li M Where LogT IdleT");
176 for (int i=0; i<num_users; i++)
178 struct out_host *h = user_array[i].host;
179 struct userinfo *u = user_array[i].user;
181 if (now - ntohl(h->pkt->server_time) >= DEFAULT_DOWN_TIME)
183 printf("%-8.8s %-7s %c %-16s ", u->name, u->con, (u->mesg_y ? ' ' : '-'), h->name);
184 puttime(ntohl(u->login_time));
186 puttime(ntohl(u->idle_time));
190 for (int i=0; i<num_hosts; i++)
192 struct out_host *h = host_array[i];
193 if (ntohl(h->pkt->num_users) >= MAX_USERS)
194 printf("%s: MAX_USERS reached!\n", h->name);
206 if (chdir(NWHO_SPOOL_DIR) < 0)
208 fprintf(stderr, "chdir(" NWHO_SPOOL_DIR "): %m\n");
217 while (e = readdir(d))
218 if (e->d_name[0] != '.')
220 fd = open(e->d_name, O_RDONLY);
223 fprintf(stderr, "%s: %m\n", e->d_name);
226 r = read(fd, &pkt, sizeof(pkt));
228 if (r < sizeof(struct nwho_pkt) - MAX_USERS*sizeof(struct userinfo)
229 || pkt.magic != htonl(NWHO_MAGIC)
230 || r != sizeof(struct nwho_pkt) - (MAX_USERS - ntohl(pkt.num_users))*sizeof(struct userinfo))
232 fprintf(stderr, "%s: Malformed record\n", e->d_name);
235 struct out_host *host = new_host(&pkt, e->d_name);
236 for (int i=0; i < ntohl(pkt.num_users); i++)
237 new_user(host, &host->pkt->users[i]);
246 Usage: nwho <options>\n\
247 or: nuptime <options>\n\
250 -h Sort user list by hosts (default: by users)\n\
251 -u Display host uptimes (default if called as `nuptime')\n\
257 main(int argc, char **argv)
259 if (argc == 2 && !strcmp(argv[1], "--version"))
261 printf("nwho " STRINGIFY(VERSION) "\n");
264 if (argc == 2 && !strcmp(argv[1], "--help"))
268 int uptime_mode = !!strstr(argv[0], "uptime");
269 int want_sort_by_hosts = 0;
271 while ((opt = getopt(argc, argv, "hu")) >= 0)
275 want_sort_by_hosts = 1;
281 fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
286 fprintf(stderr, "This program does not need any arguments. Try `%s --help' for more information.\n", argv[0]);
294 puts("No data available.");
300 sort_users(want_sort_by_hosts);