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