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