ncplist.c revision 52406
1219820Sjeff/*
2219820Sjeff * Copyright (c) 1999, Boris Popov
3219820Sjeff * All rights reserved.
4219820Sjeff *
5270710Shselasky * Redistribution and use in source and binary forms, with or without
6328653Shselasky * modification, are permitted provided that the following conditions
7219820Sjeff * are met:
8219820Sjeff * 1. Redistributions of source code must retain the above copyright
9219820Sjeff *    notice, this list of conditions and the following disclaimer.
10219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright
11219820Sjeff *    notice, this list of conditions and the following disclaimer in the
12219820Sjeff *    documentation and/or other materials provided with the distribution.
13219820Sjeff * 3. All advertising materials mentioning features or use of this software
14219820Sjeff *    must display the following acknowledgement:
15219820Sjeff *    This product includes software developed by Boris Popov.
16219820Sjeff * 4. Neither the name of the author nor the names of any co-contributors
17219820Sjeff *    may be used to endorse or promote products derived from this software
18219820Sjeff *    without specific prior written permission.
19219820Sjeff *
20219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21219820Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23219820Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24219820Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25219820Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26219820Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28219820Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29289644Shselasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30289644Shselasky * SUCH DAMAGE.
31219820Sjeff *
32328653Shselasky * $FreeBSD: head/usr.bin/ncplist/ncplist.c 52406 1999-10-20 11:31:02Z bp $
33328653Shselasky */
34219820Sjeff#include <sys/param.h>
35219820Sjeff#include <sys/time.h>
36300671Shselasky#include <stdio.h>
37328653Shselasky#include <string.h>
38219820Sjeff#include <unistd.h>
39219820Sjeff#include <stdlib.h>
40328653Shselasky
41328653Shselasky#include <netncp/ncp_lib.h>
42219820Sjeff
43219820Sjeffextern char *__progname;
44219820Sjeff
45328653Shselaskystatic struct ncp_conn_stat conndesc;
46289564Shselasky
47328653Shselaskystatic void help(void);
48328653Shselaskystatic void show_connlist(void);
49219820Sjeffstatic void show_serverlist(char *server);
50335425Shselaskystatic void show_userlist(char *server);
51335425Shselaskystatic void list_volumes(char *server);
52335425Shselaskystatic void str_trim_right(char *s, char c);
53335425Shselasky
54328653Shselasky
55328653Shselaskyint
56219820Sjeffncp_get_connid(char *server, int justattach) {
57328653Shselasky	int connid, error;
58328653Shselasky	struct ncp_conn_loginfo li;
59219820Sjeff
60328653Shselasky	connid = ncp_conn_find(server, NULL);
61219820Sjeff	if (connid > 0) {
62328653Shselasky		ncp_conn_getinfo(connid, &conndesc);
63328653Shselasky		return connid;
64328653Shselasky	}
65328653Shselasky	if (!justattach) {
66328653Shselasky		if (connid == -1) {
67328653Shselasky			printf("You are not attached to server %s\n",server);
68328653Shselasky			return -1;
69328653Shselasky		}
70335424Shselasky		printf("You are not attached to any server\n");
71335424Shselasky		return -1;
72335424Shselasky	}
73335424Shselasky	ncp_li_init(&li, 0, NULL);
74328653Shselasky	if (server) {
75219820Sjeff		ncp_li_setserver(&li, server);
76328653Shselasky		error = ncp_find_fileserver(&li, AF_IPX, NULL);
77328653Shselasky		if (error) {
78335424Shselasky			printf("Could not find server %s\n", li.server);
79335424Shselasky			return -1;
80335424Shselasky		}
81335424Shselasky	} else {
82328653Shselasky		error = ncp_find_fileserver(&li, AF_IPX, NULL);
83328653Shselasky		if (error) {
84328653Shselasky			printf("Can't find any file server\n");
85328653Shselasky			return -1;
86328653Shselasky		}
87328653Shselasky	}
88328653Shselasky	error = ncp_connect(&li, &connid);
89330861Shselasky	if (error) {
90328653Shselasky		printf("Can't attach to a nearest server\n");
91330861Shselasky		return -1;
92328653Shselasky	}
93328653Shselasky	ncp_conn_getinfo(connid, &conndesc);
94330861Shselasky	return connid;
95328653Shselasky}
96328653Shselasky
97328653Shselaskystatic struct ncp_bitname conn_statenames [] = {
98330861Shselasky	{NCPFL_INVALID, "invalid"},
99330861Shselasky	{NCPFL_LOGGED,	"active"},
100330861Shselasky	{NCPFL_PERMANENT, "permanent"},
101328653Shselasky	{NCPFL_PRIMARY,	"primary"},
102328653Shselasky	{0, NULL}
103328653Shselasky};
104328653Shselasky
105328653Shselaskystatic void
106328653Shselaskystr_trim_right(char *s, char c) {
107328653Shselasky	int len;
108328653Shselasky
109328653Shselasky	for(len = strlen(s) - 1; len > 0 && s[len] == c; len--)
110328653Shselasky		s[len] = '\0';
111328653Shselasky}
112328653Shselasky
113328653Shselaskyvoid
114328653Shselaskyshow_connlist(void) {
115328653Shselasky	void *p;
116328653Shselasky	int cnt;
117219820Sjeff	char buf[200];
118219820Sjeff	struct ncp_conn_stat *ncsp;
119335423Shselasky
120328653Shselasky	printf("Active NCP connections:\n");
121328653Shselasky	p = ncp_conn_list();
122335423Shselasky	if (p == NULL) {
123335423Shselasky		printf("None\n");
124328653Shselasky		return;
125328653Shselasky	}
126328653Shselasky	printf(" refid server:user(connid), owner:group(mode), refs, <state>\n");
127328653Shselasky	cnt = *(int*)p;
128328653Shselasky	ncsp = (struct ncp_conn_stat*)(((int*)p)+1);
129328653Shselasky	while(cnt--) {
130328653Shselasky		printf("%6d %s:%s(%d), %s:%s(%o), %d, %s",
131328653Shselasky		    ncsp->connRef, ncsp->li.server,ncsp->user,ncsp->connid,
132328653Shselasky		    user_from_uid(ncsp->owner, 0),
133328653Shselasky		    group_from_gid(ncsp->group, 0),
134328653Shselasky		    ncsp->li.access_mode,
135328653Shselasky		    ncsp->ref_cnt,
136328653Shselasky		    ncp_printb(buf, ncsp->flags, conn_statenames));
137328653Shselasky		printf("\n");
138328653Shselasky		ncsp++;
139328653Shselasky	}
140328653Shselasky	free(p);
141328653Shselasky	printf("\n");
142328653Shselasky}
143328653Shselasky
144328653Shselaskyvoid
145328653Shselaskyshow_serverlist(char *server) {
146328653Shselasky	int found = 0, connid;
147328653Shselasky	struct ncp_bindery_object obj;
148328653Shselasky	char *pattern = "*";
149328653Shselasky
150328653Shselasky	connid = ncp_get_connid(server, 1);
151328653Shselasky	if (connid < 0)
152328653Shselasky		return;
153328653Shselasky	printf("Visible servers (from %s):\n", conndesc.li.server);
154328653Shselasky	printf("Name                                            Network    Node       Port\n");
155328653Shselasky	printf("----------------------------------------------- -------- ------------ ----\n");
156328653Shselasky	obj.object_id = 0xffffffff;
157328653Shselasky
158328653Shselasky	while (ncp_scan_bindery_object(connid, obj.object_id, NCP_BINDERY_FSERVER,
159328653Shselasky	    pattern, &obj) == 0) {
160328653Shselasky		struct nw_property prop;
161328653Shselasky		struct ipx_addr *naddr = (struct ipx_addr *) &prop;
162328653Shselasky
163328653Shselasky		found = 1;
164328653Shselasky		printf("%-48s", obj.object_name);
165328653Shselasky
166328653Shselasky		if (ncp_read_property_value(connid, NCP_BINDERY_FSERVER,
167328653Shselasky					    obj.object_name, 1, "NET_ADDRESS",
168328653Shselasky					    &prop) == 0) {
169328653Shselasky			ipx_print_addr(naddr);
170328653Shselasky		}
171328653Shselasky		printf("\n");
172328653Shselasky	}
173328653Shselasky
174219820Sjeff	if (!found) {
175219820Sjeff		printf("No servers found\n");
176328653Shselasky	}
177328653Shselasky	printf("\n");
178328653Shselasky}
179328653Shselasky
180328653Shselasky
181328653Shselaskyvoid
182328653Shselaskyshow_userlist(char *server) {
183328653Shselasky	int connid, error, i;
184328653Shselasky	struct ncp_file_server_info info;
185328653Shselasky	struct ncp_bindery_object user;
186334760Shselasky	time_t login_time;
187334760Shselasky	struct ipx_addr addr;
188334760Shselasky	u_int8_t conn_type;
189334760Shselasky
190334760Shselasky	connid = ncp_get_connid(server, 0);
191328653Shselasky	if (connid < 0) return;
192328653Shselasky	if (ncp_get_file_server_information(connid, &info) != 0) {
193328653Shselasky		perror("Could not get server information");
194328653Shselasky		return;
195328653Shselasky	}
196328653Shselasky	printf("User information for server %s\n",info.ServerName);
197328653Shselasky	printf("\n%-6s%-21s%-27s%-12s\n"
198328653Shselasky	       "---------------------------------------------"
199328653Shselasky	       "---------------------------------\n",
200328653Shselasky	       "Conn",
201328653Shselasky	       "User name",
202328653Shselasky	       "Station Address",
203328653Shselasky	       "Login time");
204328653Shselasky	for (i = 1; i <= info.MaximumServiceConnections; i++) {
205328653Shselasky		char name[49];
206297459Snp		name[48] = '\0';
207328653Shselasky		error = ncp_get_stations_logged_info(connid, i, &user, &login_time);
208328653Shselasky		if (error) continue;
209328653Shselasky		memset(&addr, 0, sizeof(addr));
210328653Shselasky		error = ncp_get_internet_address(connid, i, &addr, &conn_type);
211297459Snp		if (error) continue;
212297459Snp		memcpy(name, user.object_name, 48);
213297459Snp		str_trim_right(name, ' ');
214328653Shselasky		printf("%4d: %-20s ", i, name);
215330862Shselasky		ipx_print_addr(&addr);
216328653Shselasky		printf(" ");
217328653Shselasky		printf("%s", ctime(&login_time));
218328653Shselasky	}
219328653Shselasky
220328653Shselasky	return;
221297459Snp}
222330862Shselasky
223330862Shselaskyvoid
224330862Shselaskyshow_queuelist(char *server, char *patt) {
225330862Shselasky	struct ncp_bindery_object q;
226330862Shselasky	int found = 0, connid;
227330862Shselasky	char default_pattern[] = "*";
228330862Shselasky	char *pattern = default_pattern;
229330862Shselasky
230328653Shselasky	connid = ncp_get_connid(server, 1);
231328653Shselasky	if (connid < 0) return;
232289564Shselasky	if (patt != NULL)
233328653Shselasky		pattern = patt;
234289564Shselasky	ncp_str_upper(pattern);
235219820Sjeff
236328653Shselasky	printf("\nServer: %s\n", server);
237328653Shselasky	printf("%-52s%-10s\n"
238328653Shselasky	       "-----------------------------------------------"
239289564Shselasky	       "-------------\n",
240328653Shselasky	       "Print queue name",
241328653Shselasky	       "Queue ID");
242328653Shselasky	q.object_id = 0xffffffff;
243328653Shselasky
244328653Shselasky	while (ncp_scan_bindery_object(connid, q.object_id,
245289564Shselasky				       NCP_BINDERY_PQUEUE, pattern, &q) == 0)
246328653Shselasky	{
247289564Shselasky		found = 1;
248328653Shselasky		printf("%-52s", q.object_name);
249289564Shselasky		printf("%08X\n", (unsigned int) q.object_id);
250289564Shselasky	}
251289564Shselasky
252328653Shselasky	if (!found) {
253289564Shselasky		printf("No queues found\n");
254328653Shselasky	}
255289564Shselasky	return;
256289564Shselasky}
257328653Shselasky
258328653Shselaskyvoid
259328653Shselaskylist_volumes(char *server) {
260328653Shselasky	int found = 0, connid, i, error;
261328653Shselasky	struct ncp_file_server_info si;
262328653Shselasky	char volname[NCP_VOLNAME_LEN+1];
263328653Shselasky
264328653Shselasky	connid = ncp_get_connid(server, 1);
265328653Shselasky	if (connid < 0) return;
266328653Shselasky
267328653Shselasky	error = ncp_get_file_server_information(connid, &si);
268328653Shselasky	if (error) {
269328653Shselasky		ncp_error("Can't get information for server %s", error, server);
270328653Shselasky		return;
271328653Shselasky	}
272328653Shselasky
273328653Shselasky	printf("\nMounted volumes on server %s:\n", server);
274328653Shselasky	printf("Number Name\n");
275328653Shselasky	printf("------ -----------------------------------------------\n");
276328653Shselasky
277328653Shselasky	for(i = 0; i < si.NumberMountedVolumes; i++) {
278328653Shselasky		if (NWGetVolumeName(connid, i, volname))
279328653Shselasky			continue;
280328653Shselasky		found = 1;
281328653Shselasky		printf("%6d %s\n", i, volname);
282330847Shselasky	}
283330847Shselasky
284328653Shselasky	if (!found)
285328653Shselasky		printf("No volumes found ?\n");
286328653Shselasky	return;
287328653Shselasky}
288328653Shselasky
289328653Shselaskystruct ncp_bind_type {
290328653Shselasky	u_long	type;
291328653Shselasky	char	*name;
292328653Shselasky};
293328653Shselasky
294328653Shselaskystatic struct ncp_bind_type btypes[] = {
295328653Shselasky	{NCP_BINDERY_USER,	"USER"},
296328653Shselasky	{NCP_BINDERY_UGROUP,	"GROUP"},
297328653Shselasky	{NCP_BINDERY_PSERVER,	"PSERVER"},
298328653Shselasky	{0x278,			"TREE"},
299328653Shselasky	{0, NULL}
300328653Shselasky};
301328653Shselasky
302void
303list_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
355enum listop {
356	LO_NONE, LO_SERVERS, LO_QUEUES, LO_BINDERY, LO_USERS, LO_VOLUMES
357};
358
359#define MAX_ARGS	10
360
361int
362main(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
450static void
451help(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}
464