route.8: Remove NS remains.
[dragonfly.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  */
34 #include <sys/param.h>
35 #include <sys/time.h>
36 #include <grp.h>
37 #include <pwd.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42
43 #include <netncp/ncp_lib.h>
44
45 extern char *__progname;
46
47 static struct ncp_conn_stat conndesc;
48
49 static void help(void);
50 static void show_connlist(void);
51 static void show_queuelist(char *, char *);
52 static void show_serverlist(char *);
53 static void show_userlist(char *);
54 static void list_bindery(char *, char *, char*);
55 static void list_volumes(char *);
56 static int ncp_get_connid(char *, int);
57 static void str_trim_right(char *, char);
58
59
60 static int
61 ncp_get_connid(char *server, int justattach) {
62         int connid, error;
63         struct ncp_conn_loginfo li;
64
65         connid = ncp_conn_find(server, NULL);
66         if (connid > 0) {
67                 ncp_conn_getinfo(connid, &conndesc);
68                 return connid;
69         }
70         if (!justattach) {
71                 if (connid == -1) {
72                         printf("You are not attached to server %s\n",server);
73                         return -1;
74                 }
75                 printf("You are not attached to any server\n");
76                 return -1;
77         }
78         ncp_li_init(&li, 0, NULL);
79         if (server) {
80                 ncp_li_setserver(&li, server);
81                 error = ncp_find_fileserver(&li, AF_IPX, NULL);
82                 if (error) {
83                         printf("Could not find server %s\n", li.server);
84                         return -1;
85                 }
86         } else {
87                 error = ncp_find_fileserver(&li, AF_IPX, NULL);
88                 if (error) {
89                         printf("Can't find any file server\n");
90                         return -1;
91                 }
92         }
93         error = ncp_connect(&li, &connid);
94         if (error) {
95                 printf("Can't attach to a nearest server\n");
96                 return -1;
97         }
98         ncp_conn_getinfo(connid, &conndesc);
99         return connid;
100 }
101
102 static struct ncp_bitname conn_statenames [] = {
103         {NCPFL_INVALID, "invalid"},
104         {NCPFL_LOGGED,  "active"},
105         {NCPFL_PERMANENT, "permanent"},
106         {NCPFL_PRIMARY, "primary"},
107         {0, NULL}
108 };
109
110 static void
111 str_trim_right(char *s, char c) {
112         int len;
113
114         for(len = strlen(s) - 1; len > 0 && s[len] == c; len--)
115                 s[len] = '\0';
116 }
117
118 static void
119 show_connlist(void) {
120         void *p;
121         int cnt;
122         char buf[200];
123         struct ncp_conn_stat *ncsp;
124
125         printf("Active NCP connections:\n");
126         p = ncp_conn_list();
127         if (p == NULL) {
128                 printf("None\n");
129                 return;
130         }
131         printf(" refid server:user(connid), owner:group(mode), refs, <state>\n");
132         cnt = *(int*)p;
133         ncsp = (struct ncp_conn_stat*)(((int*)p)+1);
134         while(cnt--) {
135                 printf("%6d %s:%s(%d), %s:%s(%o), %d, %s",
136                     ncsp->connRef, ncsp->li.server,ncsp->user,ncsp->connid,
137                     user_from_uid(ncsp->owner, 0), 
138                     group_from_gid(ncsp->group, 0), 
139                     ncsp->li.access_mode,
140                     ncsp->ref_cnt,
141                     ncp_printb(buf, ncsp->flags, conn_statenames));
142                 printf("\n");
143                 ncsp++;
144         }
145         free(p);
146         printf("\n");
147 }
148
149 void
150 show_serverlist(char *server) {
151         int found = 0, connid;
152         struct ncp_bindery_object obj;
153         char *pattern = "*";
154
155         connid = ncp_get_connid(server, 1);
156         if (connid < 0)
157                 return;
158         printf("Visible servers (from %s):\n", conndesc.li.server);
159         printf("Name                                            Network    Node       Port\n");
160         printf("----------------------------------------------- -------- ------------ ----\n");
161         obj.object_id = 0xffffffff;
162
163         while (ncp_scan_bindery_object(connid, obj.object_id, NCP_BINDERY_FSERVER, 
164             pattern, &obj) == 0) {
165                 struct nw_property prop;
166                 struct ipx_addr *naddr = (struct ipx_addr *) &prop;
167
168                 found = 1;
169                 printf("%-48s", obj.object_name);
170
171                 if (ncp_read_property_value(connid, NCP_BINDERY_FSERVER,
172                                             obj.object_name, 1, "NET_ADDRESS",
173                                             &prop) == 0) {
174                         ipx_print_addr(naddr);
175                 }
176                 printf("\n");
177         }
178
179         if (!found) {
180                 printf("No servers found\n");
181         }
182         printf("\n");
183 }
184
185
186 void
187 show_userlist(char *server) {
188         int connid, error, i;
189         struct ncp_file_server_info info;
190         struct ncp_bindery_object user;
191         time_t login_time;
192         struct ipx_addr addr;
193         u_int8_t conn_type;
194
195         connid = ncp_get_connid(server, 0);
196         if (connid < 0) return;
197         if (ncp_get_file_server_information(connid, &info) != 0) {
198                 perror("Could not get server information");
199                 return;
200         }
201         printf("User information for server %s\n",info.ServerName);
202         printf("\n%-6s%-21s%-27s%-12s\n"
203                "---------------------------------------------"
204                "---------------------------------\n",
205                "Conn",
206                "User name",
207                "Station Address",
208                "Login time");
209         for (i = 1; i <= info.MaximumServiceConnections; i++) {
210                 char name[49];
211                 name[48] = '\0';
212                 error = ncp_get_stations_logged_info(connid, i, &user, &login_time);
213                 if (error) continue;
214                 memset(&addr, 0, sizeof(addr));
215                 error = ncp_get_internet_address(connid, i, &addr, &conn_type);
216                 if (error) continue;
217                 memcpy(name, user.object_name, 48);
218                 str_trim_right(name, ' ');
219                 printf("%4d: %-20s ", i, name);
220                 ipx_print_addr(&addr);
221                 printf(" ");
222                 printf("%s", ctime(&login_time));
223         }
224
225         return;
226 }
227
228 static void
229 show_queuelist(char *server, char *patt) {
230         struct ncp_bindery_object q;
231         int found = 0, connid;
232         char default_pattern[] = "*";
233         char *pattern = default_pattern;
234
235         connid = ncp_get_connid(server, 1);
236         if (connid < 0) return;
237         if (patt != NULL)
238                 pattern = patt;
239         ncp_str_upper(pattern);
240
241         printf("\nServer: %s\n", server);
242         printf("%-52s%-10s\n"
243                "-----------------------------------------------"
244                "-------------\n",
245                "Print queue name",
246                "Queue ID");
247         q.object_id = 0xffffffff;
248
249         while (ncp_scan_bindery_object(connid, q.object_id,
250                                        NCP_BINDERY_PQUEUE, pattern, &q) == 0)
251         {
252                 found = 1;
253                 printf("%-52s", q.object_name);
254                 printf("%08X\n", (unsigned int) q.object_id);
255         }
256
257         if (!found) {
258                 printf("No queues found\n");
259         }
260         return;
261 }
262
263 void
264 list_volumes(char *server) {
265         int found = 0, connid, i, error;
266         struct ncp_file_server_info si;
267         char volname[NCP_VOLNAME_LEN+1];
268
269         connid = ncp_get_connid(server, 1);
270         if (connid < 0) return;
271         
272         error = ncp_get_file_server_information(connid, &si);
273         if (error) {
274                 ncp_error("Can't get information for server %s", error, server);
275                 return;
276         }
277
278         printf("\nMounted volumes on server %s:\n", server);
279         printf("Number Name\n");
280         printf("------ -----------------------------------------------\n");
281
282         for(i = 0; i < si.NumberMountedVolumes; i++) {
283                 if (NWGetVolumeName(connid, i, volname))
284                         continue;
285                 found = 1;
286                 printf("%6d %s\n", i, volname);
287         }
288
289         if (!found)
290                 printf("No volumes found ?\n");
291         return;
292 }
293
294 struct ncp_bind_type {
295         u_long  type;
296         char    *name;
297 };
298
299 static struct ncp_bind_type btypes[] = {
300         {NCP_BINDERY_USER,      "USER"},
301         {NCP_BINDERY_UGROUP,    "GROUP"},
302         {NCP_BINDERY_PSERVER,   "PSERVER"},
303         {0x278,                 "TREE"},
304         {0, NULL}
305 };
306
307 static void
308 list_bindery(char *server, char *type, char *patt) {
309         struct ncp_bindery_object q;
310         int i, found = 0, connid;
311         char default_pattern[] = "*";
312         char *pattern = default_pattern;
313         u_long objtype;
314
315         ncp_str_upper(type);
316         objtype = 0;
317
318         for(i = 0; btypes[i].type; i++) {
319                 if (strcmp(btypes[i].name, type) == 0) {
320                         objtype = btypes[i].type;
321                         break;
322                 }
323         }
324         if (!objtype) {
325                 printf("Bindery object of type %s is unknown\n", type);
326                 return;
327         }
328         if (patt != NULL)
329                 pattern = patt;
330         ncp_str_upper(pattern);
331         connid = ncp_get_connid(server, 1);
332         if (connid < 0) return;
333
334         connid = ncp_get_connid(server, 1);
335         if (connid < 0) return;
336
337
338         printf("\nServer: %s\n", server);
339         printf("%-52s%-10s\n"
340                "-----------------------------------------------"
341                "-------------\n",
342                "Object name",
343                "Object ID");
344
345         q.object_id = 0xffffffff;
346         while (ncp_scan_bindery_object(connid, q.object_id,
347                                        objtype, pattern, &q) == 0)
348         {
349                 found = 1;
350                 printf("%-52s", q.object_name);
351                 printf("%08X\n", (unsigned int) q.object_id);
352         }
353
354         if (!found) {
355                 printf("No bindery objects found\n");
356         }
357         return;
358 }
359
360 enum listop {
361         LO_NONE, LO_SERVERS, LO_QUEUES, LO_BINDERY, LO_USERS, LO_VOLUMES
362 };
363
364 #define MAX_ARGS        10
365
366 int
367 main(int argc, char *argv[]) {
368         int opt, wdone = 0, nargs = 0, i;
369         enum listop what;
370         char *args[MAX_ARGS];
371
372         bzero(args, sizeof(args));
373
374         what = LO_NONE;
375         while ((opt = getopt(argc, argv, "h")) != -1) {
376                 switch (opt) {
377                     case 'h': case '?':
378                         help();
379                         /*NOTREACHED */
380                     default:
381                         help();
382                         return 1;
383                 }
384         }
385         if (optind >= argc)
386                 help();
387
388         if(ncp_initlib())
389                 exit(1);
390
391         switch(argv[optind++][0]) {
392             case 'b':
393                 what = LO_BINDERY;
394                 nargs = 2;
395                 break;
396             case 'c':
397                 show_connlist();
398                 return 0;
399             case 's':
400                 what = LO_SERVERS;
401                 break;
402             case 'u':
403                 what = LO_USERS;
404                 nargs = 1;
405                 break;
406             case 'q':
407                 what = LO_QUEUES;
408                 nargs = 1;
409                 break;
410             case 'v':
411                 what = LO_VOLUMES;
412                 nargs = 1;
413                 break;
414             default:
415                 printf("Unknown command %s\n", argv[optind-1]);
416                 help();
417         }
418         for (i = 0; i < MAX_ARGS; i++) {
419                 if (optind < argc) {
420                         args[i] = argv[optind++];
421                 } else if (i < nargs) {
422                         printf("Not enough arguments\n");
423                         help();
424                         return 1;
425                 } else
426                         break;
427         }
428         switch(what) {
429             case LO_SERVERS:
430                 show_serverlist(args[0]);
431                 wdone = 1;
432                 break;
433             case LO_USERS:
434                 show_userlist(args[0]);
435                 wdone = 1;
436                 break;
437             case LO_QUEUES:
438                 show_queuelist(args[0], args[1]);
439                 wdone = 1;
440                 break;
441             case LO_VOLUMES:
442                 list_volumes(args[0]);
443                 wdone = 1;
444                 break;
445             case LO_BINDERY:
446                 list_bindery(args[0], args[1], args[2]);
447                 wdone = 1;
448                 break;
449             default:
450                 help();
451         }
452         return 0;
453 }
454
455 static void
456 help(void) {
457         printf("\n");
458         printf("usage: %s command [args]\n", __progname);
459         printf("where commands are:\n"
460         " b server user|group [pattern] list bindery objects on server\n"
461         " c                             display opened connections\n"
462         " s [server]                    display known servers\n"
463         " u server                      list logged-in users on server\n"
464         " q server [pattern]            list print queues on server\n"
465         " v server                      list mounted volumes on a specified server\n"
466         "\n");
467         exit(1);
468 }