Merge from vendor branch OPENSSH:
[games.git] / usr.bin / ncplist / ncplist.c
1 /*
2  * Copyright (c) 1999, Boris Popov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *    This product includes software developed by Boris Popov.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD: src/usr.bin/ncplist/ncplist.c,v 1.1 1999/10/20 11:31:02 bp Exp $
33  * $DragonFly: src/usr.bin/ncplist/ncplist.c,v 1.2 2003/06/17 04:29:30 dillon Exp $
34  */
35 #include <sys/param.h>
36 #include <sys/time.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41
42 #include <netncp/ncp_lib.h>
43
44 extern char *__progname;
45
46 static struct ncp_conn_stat conndesc;
47
48 static void help(void);
49 static void show_connlist(void);
50 static void show_serverlist(char *server);
51 static void show_userlist(char *server);
52 static void list_volumes(char *server);
53 static void str_trim_right(char *s, char c);
54
55
56 int
57 ncp_get_connid(char *server, int justattach) {
58         int connid, error;
59         struct ncp_conn_loginfo li;
60
61         connid = ncp_conn_find(server, NULL);
62         if (connid > 0) {
63                 ncp_conn_getinfo(connid, &conndesc);
64                 return connid;
65         }
66         if (!justattach) {
67                 if (connid == -1) {
68                         printf("You are not attached to server %s\n",server);
69                         return -1;
70                 }
71                 printf("You are not attached to any server\n");
72                 return -1;
73         }
74         ncp_li_init(&li, 0, NULL);
75         if (server) {
76                 ncp_li_setserver(&li, server);
77                 error = ncp_find_fileserver(&li, AF_IPX, NULL);
78                 if (error) {
79                         printf("Could not find server %s\n", li.server);
80                         return -1;
81                 }
82         } else {
83                 error = ncp_find_fileserver(&li, AF_IPX, NULL);
84                 if (error) {
85                         printf("Can't find any file server\n");
86                         return -1;
87                 }
88         }
89         error = ncp_connect(&li, &connid);
90         if (error) {
91                 printf("Can't attach to a nearest server\n");
92                 return -1;
93         }
94         ncp_conn_getinfo(connid, &conndesc);
95         return connid;
96 }
97
98 static struct ncp_bitname conn_statenames [] = {
99         {NCPFL_INVALID, "invalid"},
100         {NCPFL_LOGGED,  "active"},
101         {NCPFL_PERMANENT, "permanent"},
102         {NCPFL_PRIMARY, "primary"},
103         {0, NULL}
104 };
105
106 static void
107 str_trim_right(char *s, char c) {
108         int len;
109
110         for(len = strlen(s) - 1; len > 0 && s[len] == c; len--)
111                 s[len] = '\0';
112 }
113
114 void
115 show_connlist(void) {
116         void *p;
117         int cnt;
118         char buf[200];
119         struct ncp_conn_stat *ncsp;
120
121         printf("Active NCP connections:\n");
122         p = ncp_conn_list();
123         if (p == NULL) {
124                 printf("None\n");
125                 return;
126         }
127         printf(" refid server:user(connid), owner:group(mode), refs, <state>\n");
128         cnt = *(int*)p;
129         ncsp = (struct ncp_conn_stat*)(((int*)p)+1);
130         while(cnt--) {
131                 printf("%6d %s:%s(%d), %s:%s(%o), %d, %s",
132                     ncsp->connRef, ncsp->li.server,ncsp->user,ncsp->connid,
133                     user_from_uid(ncsp->owner, 0), 
134                     group_from_gid(ncsp->group, 0), 
135                     ncsp->li.access_mode,
136                     ncsp->ref_cnt,
137                     ncp_printb(buf, ncsp->flags, conn_statenames));
138                 printf("\n");
139                 ncsp++;
140         }
141         free(p);
142         printf("\n");
143 }
144
145 void
146 show_serverlist(char *server) {
147         int found = 0, connid;
148         struct ncp_bindery_object obj;
149         char *pattern = "*";
150
151         connid = ncp_get_connid(server, 1);
152         if (connid < 0)
153                 return;
154         printf("Visible servers (from %s):\n", conndesc.li.server);
155         printf("Name                                            Network    Node       Port\n");
156         printf("----------------------------------------------- -------- ------------ ----\n");
157         obj.object_id = 0xffffffff;
158
159         while (ncp_scan_bindery_object(connid, obj.object_id, NCP_BINDERY_FSERVER, 
160             pattern, &obj) == 0) {
161                 struct nw_property prop;
162                 struct ipx_addr *naddr = (struct ipx_addr *) &prop;
163
164                 found = 1;
165                 printf("%-48s", obj.object_name);
166
167                 if (ncp_read_property_value(connid, NCP_BINDERY_FSERVER,
168                                             obj.object_name, 1, "NET_ADDRESS",
169                                             &prop) == 0) {
170                         ipx_print_addr(naddr);
171                 }
172                 printf("\n");
173         }
174
175         if (!found) {
176                 printf("No servers found\n");
177         }
178         printf("\n");
179 }
180
181
182 void
183 show_userlist(char *server) {
184         int connid, error, i;
185         struct ncp_file_server_info info;
186         struct ncp_bindery_object user;
187         time_t login_time;
188         struct ipx_addr addr;
189         u_int8_t conn_type;
190
191         connid = ncp_get_connid(server, 0);
192         if (connid < 0) return;
193         if (ncp_get_file_server_information(connid, &info) != 0) {
194                 perror("Could not get server information");
195                 return;
196         }
197         printf("User information for server %s\n",info.ServerName);
198         printf("\n%-6s%-21s%-27s%-12s\n"
199                "---------------------------------------------"
200                "---------------------------------\n",
201                "Conn",
202                "User name",
203                "Station Address",
204                "Login time");
205         for (i = 1; i <= info.MaximumServiceConnections; i++) {
206                 char name[49];
207                 name[48] = '\0';
208                 error = ncp_get_stations_logged_info(connid, i, &user, &login_time);
209                 if (error) continue;
210                 memset(&addr, 0, sizeof(addr));
211                 error = ncp_get_internet_address(connid, i, &addr, &conn_type);
212                 if (error) continue;
213                 memcpy(name, user.object_name, 48);
214                 str_trim_right(name, ' ');
215                 printf("%4d: %-20s ", i, name);
216                 ipx_print_addr(&addr);
217                 printf(" ");
218                 printf("%s", ctime(&login_time));
219         }
220
221         return;
222 }
223
224 void
225 show_queuelist(char *server, char *patt) {
226         struct ncp_bindery_object q;
227         int found = 0, connid;
228         char default_pattern[] = "*";
229         char *pattern = default_pattern;
230
231         connid = ncp_get_connid(server, 1);
232         if (connid < 0) return;
233         if (patt != NULL)
234                 pattern = patt;
235         ncp_str_upper(pattern);
236
237         printf("\nServer: %s\n", server);
238         printf("%-52s%-10s\n"
239                "-----------------------------------------------"
240                "-------------\n",
241                "Print queue name",
242                "Queue ID");
243         q.object_id = 0xffffffff;
244
245         while (ncp_scan_bindery_object(connid, q.object_id,
246                                        NCP_BINDERY_PQUEUE, pattern, &q) == 0)
247         {
248                 found = 1;
249                 printf("%-52s", q.object_name);
250                 printf("%08X\n", (unsigned int) q.object_id);
251         }
252
253         if (!found) {
254                 printf("No queues found\n");
255         }
256         return;
257 }
258
259 void
260 list_volumes(char *server) {
261         int found = 0, connid, i, error;
262         struct ncp_file_server_info si;
263         char volname[NCP_VOLNAME_LEN+1];
264
265         connid = ncp_get_connid(server, 1);
266         if (connid < 0) return;
267         
268         error = ncp_get_file_server_information(connid, &si);
269         if (error) {
270                 ncp_error("Can't get information for server %s", error, server);
271                 return;
272         }
273
274         printf("\nMounted volumes on server %s:\n", server);
275         printf("Number Name\n");
276         printf("------ -----------------------------------------------\n");
277
278         for(i = 0; i < si.NumberMountedVolumes; i++) {
279                 if (NWGetVolumeName(connid, i, volname))
280                         continue;
281                 found = 1;
282                 printf("%6d %s\n", i, volname);
283         }
284
285         if (!found)
286                 printf("No volumes found ?\n");
287         return;
288 }
289
290 struct ncp_bind_type {
291         u_long  type;
292         char    *name;
293 };
294
295 static struct ncp_bind_type btypes[] = {
296         {NCP_BINDERY_USER,      "USER"},
297         {NCP_BINDERY_UGROUP,    "GROUP"},
298         {NCP_BINDERY_PSERVER,   "PSERVER"},
299         {0x278,                 "TREE"},
300         {0, NULL}
301 };
302
303 void
304 list_bindery(char *server, char *type, char *patt) {
305         struct ncp_bindery_object q;
306         int i, found = 0, connid;
307         char default_pattern[] = "*";
308         char *pattern = default_pattern;
309         u_long objtype;
310
311         ncp_str_upper(type);
312         objtype = 0;
313
314         for(i = 0; btypes[i].type; i++) {
315                 if (strcmp(btypes[i].name, type) == 0) {
316                         objtype = btypes[i].type;
317                         break;
318                 }
319         }
320         if (!objtype) {
321                 printf("Bindery object of type %s is unknown\n", type);
322                 return;
323         }
324         if (patt != NULL)
325                 pattern = patt;
326         ncp_str_upper(pattern);
327         connid = ncp_get_connid(server, 1);
328         if (connid < 0) return;
329
330         connid = ncp_get_connid(server, 1);
331         if (connid < 0) return;
332
333
334         printf("\nServer: %s\n", server);
335         printf("%-52s%-10s\n"
336                "-----------------------------------------------"
337                "-------------\n",
338                "Object name",
339                "Object ID");
340
341         q.object_id = 0xffffffff;
342         while (ncp_scan_bindery_object(connid, q.object_id,
343                                        objtype, pattern, &q) == 0)
344         {
345                 found = 1;
346                 printf("%-52s", q.object_name);
347                 printf("%08X\n", (unsigned int) q.object_id);
348         }
349
350         if (!found) {
351                 printf("No bindery objects found\n");
352         }
353         return;
354 }
355
356 enum listop {
357         LO_NONE, LO_SERVERS, LO_QUEUES, LO_BINDERY, LO_USERS, LO_VOLUMES
358 };
359
360 #define MAX_ARGS        10
361
362 int
363 main(int argc, char *argv[]) {
364         int opt, wdone = 0, nargs = 0, i;
365         enum listop what;
366         char *args[MAX_ARGS];
367
368         bzero(args, sizeof(args));
369
370         what = LO_NONE;
371         while ((opt = getopt(argc, argv, "h")) != EOF) {
372                 switch (opt) {
373                     case 'h': case '?':
374                         help();
375                         /*NOTREACHED */
376                     default:
377                         help();
378                         return 1;
379                 }
380         }
381         if (optind >= argc)
382                 help();
383
384         if(ncp_initlib())
385                 exit(1);
386
387         switch(argv[optind++][0]) {
388             case 'b':
389                 what = LO_BINDERY;
390                 nargs = 2;
391                 break;
392             case 'c':
393                 show_connlist();
394                 return 0;
395             case 's':
396                 what = LO_SERVERS;
397                 break;
398             case 'u':
399                 what = LO_USERS;
400                 nargs = 1;
401                 break;
402             case 'q':
403                 what = LO_QUEUES;
404                 nargs = 1;
405                 break;
406             case 'v':
407                 what = LO_VOLUMES;
408                 nargs = 1;
409                 break;
410             default:
411                 printf("Unknown command %s\n", argv[optind-1]);
412                 help();
413         }
414         for (i = 0; i < MAX_ARGS; i++) {
415                 if (optind < argc) {
416                         args[i] = argv[optind++];
417                 } else if (i < nargs) {
418                         printf("Not enough arguments\n");
419                         help();
420                         return 1;
421                 } else
422                         break;
423         }
424         switch(what) {
425             case LO_SERVERS:
426                 show_serverlist(args[0]);
427                 wdone = 1;
428                 break;
429             case LO_USERS:
430                 show_userlist(args[0]);
431                 wdone = 1;
432                 break;
433             case LO_QUEUES:
434                 show_queuelist(args[0], args[1]);
435                 wdone = 1;
436                 break;
437             case LO_VOLUMES:
438                 list_volumes(args[0]);
439                 wdone = 1;
440                 break;
441             case LO_BINDERY:
442                 list_bindery(args[0], args[1], args[2]);
443                 wdone = 1;
444                 break;
445             default:
446                 help();
447         }
448         return 0;
449 }
450
451 static void
452 help(void) {
453         printf("\n");
454         printf("usage: %s command [args]\n", __progname);
455         printf("where commands are:\n"
456         " b server user|group [pattern] list bindery objects on server\n"
457         " c                             display opened connections\n"
458         " s [server]                    display known servers\n"
459         " u server                      list logged-in users on server\n"
460         " q server [pattern]            list print queues on server\n"
461         " v server                      list mounted volumes on a specified server\n"
462         "\n");
463         exit(1);
464 }