diff --git a/.downloads/ncpfs-2.0.6.tgz b/.downloads/ncpfs-2.0.6.tgz new file mode 100644 index 0000000..44b8600 Binary files /dev/null and b/.downloads/ncpfs-2.0.6.tgz differ diff --git a/BUGS b/BUGS index 57790a4..c0d8116 100644 --- a/BUGS +++ b/BUGS @@ -5,6 +5,20 @@ But there are really problems that might be fixed in the future. ------------------------------------------------------------------------------- +You might experience lockups of ncpfs volumes. It happens especially +under high network traffic, not necessarily only IPX traffic. I am not +able to reproduce this problem on my machine, so I'm sorry I can not +do anything about that. When such a lockup happens, you have to shut +down the complete ipx subsystem by deleting all ipx interfaces, +unmounting all ncpfs volumes (in this order!) and restarting all +again. + +For the kernel hackers who want to look at the problem: The routine +ipx_sendmsg in net/ipx/af_ipx.c sometimes locks forever if called with +nonblock=0. I DO NOT KNOW WHY!!! HELP ME, PLEASE! + +------------------------------------------------------------------------------- + 'df' returns 0: Free disk space is distributed among the volumes in NetWare. df is only able to report one number per mounted filesystem. As connections are quite expensive for NetWare (with diff --git a/Changes b/Changes index e06311e..823a054 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,16 @@ I only began this file with ncpfs-0.12. If you're interested in older versions, you can find them on ftp.gwdg.de:/pub/linux/misc/ncpfs/old. +ncpfs-2.0.5 -> ncpfs-2.0.6 +- Added a short description of a problem that I need help with to the + file BUGS. If you know a bit of the linux networking code, please + take a look at it. Thanks a lot. +- Added canonic output format to nwpbvalues and the command nwbpset. I + would like to invite you to help building capable bindery management + utilities. For little examples, look at the manual page of nwbpset. +- Added some values to ipxparse. Those interested in NDS should take a + look at it. It's really not much, but maybe it's a beginning. + ncpfs-2.0.4 -> ncpfs-2.0.5 - Removed another bug in nwbpvalues. - Cleaned up man/Makefile diff --git a/Makefile b/Makefile index 2e15187..ab8fba4 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux ncp-filesystem routines. # -VERSION = 2.0.5 +VERSION = 2.0.6 # If you are using kerneld to autoload ncp support, # uncomment this (kerneld is in linux since about 1.3.57): diff --git a/ipxdump/ipxparse.c b/ipxdump/ipxparse.c index 6b42828..2fb8d1c 100644 --- a/ipxdump/ipxparse.c +++ b/ipxdump/ipxparse.c @@ -329,9 +329,10 @@ int handle_burst(struct sockaddr_ipx *source, return 1; } -void handle_ncp (struct sockaddr_ipx *source, - struct sockaddr_ipx *target, - unsigned char *buf, int length, int no) +void +handle_ncp(struct sockaddr_ipx *source, + struct sockaddr_ipx *target, + unsigned char *buf, int length, int no) { struct ncp_request_header *rq = (struct ncp_request_header *)buf; struct ncp_reply_header *rs = (struct ncp_reply_header *)buf; @@ -339,6 +340,10 @@ void handle_ncp (struct sockaddr_ipx *source, int data_length = 0; int i; + static struct sockaddr_ipx request_source; + static struct ncp_request_header request_header; + static char request_data[5]; + if (ntohs(rq->type) == NCP_REQUEST) { /* Request */ @@ -346,6 +351,10 @@ void handle_ncp (struct sockaddr_ipx *source, rq->conn_low + 256 * rq->conn_high, rq->sequence, rq->task); + memcpy(&request_source, source, sizeof(request_source)); + memcpy(&request_header, rq, sizeof(request_header)); + memcpy(request_data, rq+1, sizeof(request_data)); + data = buf + sizeof(struct ncp_request_header); data_length = length - sizeof(struct ncp_request_header); @@ -583,13 +592,343 @@ void handle_ncp (struct sockaddr_ipx *source, data_length -= 1; break; case 97: + { + struct INPUT + { + __u16 proposed_max_size; + __u8 security_flag; + } *i = (struct INPUT *)data; + printf("fn: %-3d\n", rq->function); printf("Get Big Packet NCP Max Packet Size\n"); + printf("proposed_max_size: %x\n", + ntohs(i->proposed_max_size)); + printf("security_flag: %x\n", + i->security_flag); break; + } case 101: + { + struct INPUT + { + __u32 local_conn_id; + __u32 local_max_packet_size; + __u16 local_target_socket; + __u32 local_max_send_size; + __u32 local_max_recv_size; + } *i = (struct INPUT *)data; + printf("fn: %-3d\n", rq->function); printf("Packet Burst Connection Request\n"); + printf("local_conn_id: %lx\n", + ntohl(i->local_conn_id)); + printf("local_max_packet_size: %lx\n", + ntohl(i->local_max_packet_size)); + printf("local_target_socket: %lx\n", + ntohl(i->local_target_socket)); + printf("local_max_send_size: %lx\n", + ntohl(i->local_max_send_size)); + printf("local_max_recv_size: %lx\n", + ntohl(i->local_max_recv_size)); + } break; + case 104: + { + printf("fn: %-3d, subfn: %-3d, NDS call\n", + rq->function, data[0]); + + /* I took this information from the (german!!) + book 'Einf"uhrung in die NetWare LAN + Analyse', Laura A. Chappell, Dan E. Hakes, + Novell Press, Markt & Technik, ISBN + 3-8272-5084-6, and from the book mentioned + in the ncpfs README. I'm not sure it is + correct, because I do not have NW 4.x. If + you have the time, could you watch a NW4 + workstation, and tell me whether anything + of this makes sense at all. */ + + switch(data[0]) + { + case 1: + printf("Ping for NDS\n"); + break; + case 2: + { + struct INPUT + { + __u8 subfunction_code; + __u32 fragger_handle; + __u32 max_fragment_size; + __u32 message_size; + __u32 fragment_flag; + __u32 verb; + } *i = (struct INPUT *)data; + printf("Send NDS Fragment Request/Reply\n"); + printf("fragger_handle: %lx\n", + (unsigned long)i->fragger_handle); + printf("max_fragment_size: %lx\n", + (unsigned long)i->max_fragment_size); + printf("message_size: %lx\n", + (unsigned long)i->message_size); + printf("fragment_flag: %lx\n", + (unsigned long)i->fragment_flag); + printf("verb: %d\n", i->verb); + + switch (i->verb) + { + case 1: + printf("Resolve Name\n"); + break; + case 2: + printf("Read Entry Information\n"); + break; + case 3: + printf("Read\n"); + break; + case 4: + printf("Compare\n"); + break; + case 5: + printf("List\n"); + break; + case 6: + printf("Search Entries\n"); + break; + case 7: + printf("Add Entry\n"); + break; + case 8: + printf("Remove Entry\n"); + break; + case 9: + printf("Modify Entry\n"); + break; + case 10: + printf("Modify RDN\n"); + break; + case 11: + printf("Create Attribute\n"); + break; + case 12: + printf("Read Attribute Definition\n"); + break; + case 13: + printf("Remove Attribute Definition\n"); + break; + case 14: + printf("Define Class\n"); + break; + case 15: + printf("Read Class Definition\n"); + break; + case 16: + printf("Modify Class Definition\n"); + break; + case 17: + printf("Remove Class Definition\n"); + break; + case 18: + printf("List Containable Classes\n"); + break; + case 19: + printf("Get Effective Rights\n"); + break; + case 20: + printf("Add Partition\n"); + break; + case 21: + printf("Remove Partition\n"); + break; + case 22: + printf("List Partitions\n"); + break; + case 23: + printf("Split Partition\n"); + break; + case 24: + printf("Join Partitions\n"); + break; + case 25: + printf("Add Replica\n"); + break; + case 26: + printf("Remove Replica\n"); + break; + case 27: + printf("Open Stream\n"); + break; + case 28: + printf("Search Filter\n"); + break; + case 29: + printf("Create Subordinate Reference\n"); + break; + case 30: + printf("Link Replica\n"); + break; + case 31: + printf("Change Replica Type\n"); + break; + case 32: + printf("Start Update Schema\n"); + break; + case 33: + printf("End Update Schema\n"); + break; + case 34: + printf("Update Schema\n"); + break; + case 35: + printf("Start Update Replica\n"); + break; + case 36: + printf("End Update Replica\n"); + break; + case 37: + printf("Update Replica\n"); + break; + case 38: + printf("Synchronize Partition\n"); + break; + case 39: + printf("Synchronize Schema\n"); + break; + case 40: + printf("Read Syntaxes\n"); + break; + case 41: + printf("Get Replica Root ID\n"); + break; + case 42: + printf("Begin Move Entry\n"); + break; + case 43: + printf("Finish Move Entry\n"); + break; + case 44: + printf("Release Moved Entry\n"); + break; + case 45: + printf("Backup Entry\n"); + break; + case 46: + printf("Restore Entry\n"); + break; + case 47: + printf("Save DIB\n"); + break; + case 48: + case 49: + printf("Unused\n"); + break; + case 50: + printf("Close Iteration\n"); + break; + case 51: + printf("Unused\n"); + break; + case 52: + printf("Audit Skulking\n"); + break; + case 53: + printf("Get Server Address\n"); + break; + case 54: + printf("Set Keys\n"); + break; + case 55: + printf("Change Password\n"); + break; + case 56: + printf("Verify Password\n"); + break; + case 57: + printf("Begin Login\n"); + break; + case 58: + printf("Finish Login\n"); + break; + case 59: + printf("Begin Authentication\n"); + break; + case 60: + printf("Finish Authentication\n"); + break; + case 61: + printf("Logout\n"); + break; + case 62: + printf("Repair Ring\n"); + break; + case 63: + printf("Repair Timestamps\n"); + break; + case 64: + printf("Create Back Link\n"); + break; + case 65: + printf("Delete External Reference\n"); + break; + case 66: + printf("Rename External Reference\n"); + break; + case 67: + printf("Create Directory Entry\n"); + break; + case 68: + printf("Remove Directory Entry\n"); + break; + case 69: + printf("Designate New Master\n"); + break; + case 70: + printf("Change Tree Name\n"); + break; + case 71: + printf("Partition Entry Count\n"); + break; + case 72: + printf("Check Login Restrictions\n"); + break; + case 73: + printf("Start Join\n"); + break; + case 74: + printf("Low Level Split\n"); + break; + case 75: + printf("Low Level Join\n"); + break; + case 76: + printf("Abort Low Level Join\n"); + break; + case 77: + printf("Get All Servers\n"); + break; + default: + printf("Unknown Verb: %d\n", + data[0]); + break; + } + break; + } + case 3: + printf("Close NDS Fragment\n"); + break; + case 4: + printf("Return Bindery Context\n"); + break; + case 5: + printf("Monitor NDS connection\n"); + break; + case 200: + printf("NDS Auditing\n"); + break; + default: + break; + } + } default: printf("fn: %-3d\n", rq->function); } @@ -605,6 +944,70 @@ void handle_ncp (struct sockaddr_ipx *source, data = buf + sizeof(struct ncp_reply_header); data_length = length - sizeof(struct ncp_reply_header); + + if ( (memcmp(&request_source, target, + sizeof(request_source)) == 0) + && (request_header.sequence == rs->sequence)) + { + switch (request_header.function) + { + case 22: + switch (request_data[2]) + { + case 18: + { + struct XDATA + { + __u8 new_directory_handle; + __u8 access_rights_mask; + } *x = (struct XDATA *)data; + printf("new_directory_handle: %x\n", + x->new_directory_handle); + printf("access_rights_mask: %x\n", + x->access_rights_mask); + } + break; + } + break; + case 72: + printf("Read data\n"); + data_length = 0; + break; + case 97: + { + struct XDATA + { + __u16 accepted_max_size; + __u16 echo_socket; + __u8 security_flag; + } *x = (struct XDATA *)data; + printf("accepted_max_size: %x\n", + ntohs(x->accepted_max_size)); + printf("echo_socket: %x\n", + ntohs(x->echo_socket)); + printf("security_flag: %x\n", + (x->security_flag)); + } + break; + case 101: + { + struct XDATA + { + __u8 completion_code; + __u32 remote_target_id; + __u32 remote_max_packet_size; + } *x = (struct XDATA *)data; + printf("completion_code: %x\n", + x->completion_code); + printf("remote_target_id: %lx\n", + ntohl(x->remote_target_id)); + printf("remote_max_packet_size: %lx\n", + ntohl(x->remote_max_packet_size)); + } + break; + } + } + } if (data == NULL) diff --git a/man/nwbols.1 b/man/nwbols.1 index 8ead31a..53d6c66 100644 --- a/man/nwbols.1 +++ b/man/nwbols.1 @@ -22,9 +22,10 @@ nwbols \- List NetWare Bindery Objects .B -t .I type ] [ -.B -v +.B -o +.I pattern ] [ -.B pattern +.B -v ] .SH DESCRIPTION @@ -95,7 +96,8 @@ objects to be listed. must be given as a decimal number. .RE -.B pattern +.B -o +.I pattern .RS 3 Specifying a pattern is another way to restrict the objects listed. Please note that this pattern is evaluated by the NetWare diff --git a/man/nwbpset.1 b/man/nwbpset.1 new file mode 100644 index 0000000..257abc3 --- /dev/null +++ b/man/nwbpset.1 @@ -0,0 +1,107 @@ +.TH NWBPSET 1 8/7/1996 nwbpset nwbpset +.SH NAME +nwbpset \- Create a bindery property or set its value +.SH SYNOPSIS +.B nwbpset +[ +.B -h +] [ +.B -S +.I server +] [ +.B -U +.I user name +] [ +.B -P +.I password + | +.B -n +] [ +.B -C +] + +.SH DESCRIPTION +.B nwbpset +Reads a property specification from the standard input and creates and +sets the corresponding property. The format is determined by the +output of 'nwbpvalues -c'. nwbpset will hopefully become an important +part of the bindery management suite of ncpfs, together with +'nwbpvalues -c'. See util/nwbpsecurity for an example. + +As another example, look at the following command line: + + nwbpvalues -t 1 -o supervisor -p user_defaults -c |\\ + sed '2s/.*/ME/'|\\ + sed '3s/.*/LOGIN_CONTROL/'|\\ + nwbpset + +With this command, the property user_defaults of the user object +\'supervisor\' is copied into the property login_control of the user +object \'me\'. + + nwbpvalues -t 1 -o me -p login_control -c |\\ + sed '9s/.*/ff/'|\\ + nwbpset + +This command disables the user object me. + +Feel free to contribute other examples! + +.B nwbpset +looks up the file +.I $HOME/.nwclient +to find a file server, a user name and possibly a password. See +nwclient(5) for more information. Please note that the access +permissions of $HOME/.nwclient MUST be 600 for security reasons. + +.SH OPTIONS + +.B -h +.RS 3 +.B -h +is used to print out a short help text. +.RE + +.B -S +.I server +.RS 3 +.B server +is the name of the server you want to use. +.RE + +.B -U +.I user +.RS 3 +.B user +is the user name to use for login. +.RE + +.B -P +.I password +.RS 3 +.B password +is the password to use for login. If neither +.B -n +nor +.B -P +are given, and the user has no open connection to the server, nwbpset +prompts for a password. +.RE + +.B -n +.RS 3 +.B -n +should be given if no password is required for the login. +.RE + +.B -C +.RS 3 +By default, passwords are converted to uppercase before they are sent +to the server, because most servers require this. You can turn off +this conversion by +.B -C. +.RE + +.SH AUTHORS +nwbpset was written by Volker Lendecke. See the Changes file of ncpfs +for other contributors. diff --git a/man/nwbpvalues.1 b/man/nwbpvalues.1 index 96f8afe..74d2c2a 100644 --- a/man/nwbpvalues.1 +++ b/man/nwbpvalues.1 @@ -29,6 +29,8 @@ nwbpvalues \- Print a NetWare Bindery Propery's contents .I property ] [ .B -v +] [ +.B -c ] .SH DESCRIPTION @@ -122,6 +124,11 @@ the object flags, its security byte and the properties flag is also listed. .RE +.B -c +.RS 3 +Use canonical output, to be used with nwbpset. +.RE + .SH AUTHORS nwbpvalues was written by Volker Lendecke with the corresponding Caldera utility in mind. See the Changes file of ncpfs for other diff --git a/ncpfs-2.0.5.lsm b/ncpfs-2.0.6.lsm similarity index 84% rename from ncpfs-2.0.5.lsm rename to ncpfs-2.0.6.lsm index 96361cd..d930a5a 100644 --- a/ncpfs-2.0.5.lsm +++ b/ncpfs-2.0.6.lsm @@ -1,7 +1,7 @@ Begin3 Title: ncpfs -Version: 2.0.5 -Entered-date: 01. August 1996 +Version: 2.0.6 +Entered-date: 08. August 1996 Description: With ncpfs you can mount volumes of your netware server under Linux. You can also print to netware print queues and spool netware print queues to the @@ -13,7 +13,7 @@ Author: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke) Maintained-by: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke) Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs Alternate-site: sunsite.unc.edu:/pub/Linux/system/Filesystems/ncpfs - ~132k ncpfs-2.0.5.tgz - ~ 1k ncpfs-2.0.5.lsm + ~136k ncpfs-2.0.6.tgz + ~ 1k ncpfs-2.0.6.lsm Copying-policy: GPL End diff --git a/util/Makefile b/util/Makefile index 0d58bc5..1b02dec 100644 --- a/util/Makefile +++ b/util/Makefile @@ -4,7 +4,7 @@ USERUTILS = slist pqlist nwfsinfo pserver nprint nsend ncopy nwpasswd USERUTILS += nwbols nwbocreate nwborm nwboprops -USERUTILS += nwbpcreate nwbprm nwbpvalues nwbpadd +USERUTILS += nwbpcreate nwbprm nwbpvalues nwbpadd nwbpset USERUTILS += nwgrant nwrevoke nwuserlist nwrights UIDUTILS = ncpmount ncpumount SBINUTILS = nwmsg diff --git a/util/nwbols.c b/util/nwbols.c index f55d759..7d54580 100644 --- a/util/nwbols.c +++ b/util/nwbols.c @@ -36,6 +36,7 @@ help(void) "-C Don't convert password to uppercase\n" "\n" "-t type Object type to be listed (decimal)\n" + "-o object Object pattern\n" "-v Verbose listing\n" "\n"); } @@ -63,7 +64,7 @@ main(int argc, char **argv) return 1; } - while ((opt = getopt(argc, argv, "h?vt:")) != EOF) + while ((opt = getopt(argc, argv, "h?vt:o:")) != EOF) { switch(opt) { case 'h': @@ -73,6 +74,9 @@ main(int argc, char **argv) case 't': type = atoi(optarg); break; + case 'o': + pattern = optarg; + break; case 'v': verbose = 1; break; @@ -82,17 +86,12 @@ main(int argc, char **argv) } } - if (optind < argc-1) + if (optind < argc) { usage(); exit(1); } - if (optind == argc-1) - { - pattern = argv[optind]; - } - for (p = pattern; *p != '\0'; p++) { *p = toupper(*p); diff --git a/util/nwbpsecurity b/util/nwbpsecurity new file mode 100755 index 0000000..35c8b97 --- /dev/null +++ b/util/nwbpsecurity @@ -0,0 +1,24 @@ +#!/bin/sh +SECURITY=`nwbpvalues $* -c | head -3 | tail -1` +WRITE=`echo $SECURITY | cut -b1` +READ=`echo $SECURITY | cut -b2` + +function print_sec () { + case "$1" in + 0 ) echo "Everyone" + ;; + 1 ) echo "Logged in" + ;; + 2 ) echo "Object" + ;; + 3 ) echo "Supervisor" + ;; + * ) echo "Bindery" + ;; + esac +} + +echo -n "Write security: " +print_sec $WRITE +echo -n "Read security : " +print_sec $READ diff --git a/util/nwbpset.c b/util/nwbpset.c new file mode 100644 index 0000000..20886dc --- /dev/null +++ b/util/nwbpset.c @@ -0,0 +1,238 @@ +/* + * nwbpset.c + * + * Create a property and set its values + * + * Copyright (C) 1996 by Volker Lendecke + * + */ + +#include "ncplib.h" +#include +#include + +static char *progname; + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [options]\n", progname); +} + +static void +help(void) +{ + printf("\n"); + printf("usage: %s [options] [values]\n", progname); + printf("\n" + "-h Print this help text\n" + "-S server Server name to be used\n" + "-U username Username sent to server\n" + "-P password Use this password\n" + "-n Do not use any password\n" + "-C Don't convert password to uppercase\n" + "\n"); +} + +static char * +get_line(char *buf, int len, FILE *stream) +{ + char *result = fgets(buf, len, stream); + if (result != NULL) + { + buf[strlen(buf)-1] = '\0'; /* remove newline */ + } + return result; +} + +int +main(int argc, char *argv[]) +{ + struct ncp_conn *conn; + char object_name[49]; + int object_type = -1; + char property_name[17]; + int property_flag, property_security; + struct ncp_property_info info; + long err; + int result = 1; + char buf[512]; + int opt; + + progname = argv[0]; + + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { + com_err(argv[0], err, "when initializing"); + goto finished; + } + + while ((opt = getopt(argc, argv, "h?")) != EOF) + { + switch(opt) { + case 'h': + case '?': + help(); + goto finished; + default: + usage(); + goto finished; + } + } + + memset(buf, 0, sizeof(buf)); + if (get_line(buf, sizeof(buf), stdin) == NULL) + { + fprintf(stderr, "Illegal format on stdin\n"); + goto finished; + } + object_type = strtoul(buf, NULL, 16); + + memset(object_name, 0, sizeof(object_name)); + if (get_line(object_name, sizeof(object_name), stdin) == NULL) + { + fprintf(stderr, "Illegal format on stdin\n"); + goto finished; + } + memset(property_name, 0, sizeof(property_name)); + if (get_line(property_name, sizeof(property_name), stdin) == NULL) + { + fprintf(stderr, "Illegal format on stdin\n"); + goto finished; + } + + memset(buf, 0, sizeof(buf)); + if (get_line(buf, sizeof(buf), stdin) == NULL) + { + fprintf(stderr, "Illegal format on stdin\n"); + goto finished; + } + property_flag = (atoi(buf) & 3); + + memset(buf, 0, sizeof(buf)); + if (get_line(buf, sizeof(buf), stdin) == NULL) + { + fprintf(stderr, "Illegal format on stdin\n"); + goto finished; + } + property_security = (strtoul(buf, NULL, 16) & 0xff); + + if (ncp_scan_property(conn, object_type, object_name, + 0xffffffff, property_name, &info) == 0) + { + /* Property already exists */ + + if ((property_flag & 2) != (info.property_flags & 2)) + { + fprintf(stderr, "Tried to write %s property\n", + (property_flag & 2) != 0 ? + "SET over existing ITEM" : + "ITEM over existing SET"); + goto finished; + } + + if (info.property_security != property_security) + { + if (ncp_change_property_security(conn, object_type, + object_name, + property_name, + property_security)!=0) + { + fprintf(stderr, "Could not change " + "property security\n"); + goto finished; + } + } + } + else + { + if (ncp_create_property(conn, object_type, object_name, + property_name, property_flag, + property_security) != 0) + { + fprintf(stderr, "Could not create property\n"); + goto finished; + } + } + + if ((property_flag & 2) == 0) + { + /* ITEM property */ + int i; + int length; + int segno; + char property_value[255*128]; + + memset(property_value, 0, sizeof(property_value)); + + for (i = 0; i < sizeof(property_value); i++) + { + if (get_line(buf, sizeof(buf), stdin) == NULL) + { + break; + } + property_value[i] = strtoul(buf, NULL, 16); + } + length = i-1; + + for (segno = 1; segno <= 255; segno++) + { + struct nw_property segment; + int offset = (segno-1)*128; + + if ( offset > length ) + { + /* everything written */ + break; + } + memcpy(segment.value, &(property_value[offset]), 128); + segment.more_flag = segno*128 < length; + if (ncp_write_property_value(conn, object_type, + object_name, + property_name, + segno, &segment) != 0) + { + fprintf(stderr, "Could not write property\n"); + goto finished; + } + } + } + else + { + /* SET property */ + + while (get_line(buf, sizeof(buf), stdin) != NULL) + { + int element_type = strtoul(buf, NULL, 16); + char element_name[49]; + + memset(element_name, 0, sizeof(element_name)); + if (get_line(element_name, sizeof(element_name), + stdin) == NULL) + { + fprintf(stderr, "Illegal format on stdin\n"); + goto finished; + } + + if (ncp_add_object_to_set(conn, object_type, + object_name, property_name, + element_type, + element_name) != 0) + { + if (conn->completion != 0xE9) /* object already + in set */ + { + fprintf(stderr, "Could not add object " + "to set\n"); + goto finished; + } + } + } + } + + result = 0; + + finished: + ncp_close(conn); + return result; +} diff --git a/util/nwbpvalues.c b/util/nwbpvalues.c index 66dfedb..aaa5e92 100644 --- a/util/nwbpvalues.c +++ b/util/nwbpvalues.c @@ -40,6 +40,7 @@ help(void) "-t type Object type (decimal value)\n" "-p property Name of property to be listed\n" "-v Verbose object listing\n" + "-c Canonical output, for use with nwbpadd\n" "\n"); } @@ -53,6 +54,7 @@ main(int argc, char *argv[]) __u8 property_value[255*128]; int segno; int verbose = 0; + int canonical = 0; struct nw_property segment; struct ncp_property_info info; long err; @@ -69,7 +71,7 @@ main(int argc, char *argv[]) goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:p:v")) != EOF) + while ((opt = getopt(argc, argv, "h?o:t:p:vc")) != EOF) { switch(opt) { case 'o': @@ -92,6 +94,9 @@ main(int argc, char *argv[]) case 'v': verbose = 1; break; + case 'c': + canonical = 1; + break; case 'h': case '?': help(); @@ -141,11 +146,30 @@ main(int argc, char *argv[]) } segno += 1; } - + + if (canonical != 0) + { + printf("%-4.4x\n%s\n", object_type, object_name); + printf("%s\n%d\n%x\n", + info.property_name, info.property_flags, info.property_security); + + } if ((info.property_flags & 2) == 0) { - print_property(property_name, property_value, segno); + /* ITEM property */ + if (canonical != 0) + { + int i; + for (i = 0; i < segno*128; i++) + { + printf("%-2.2x\n", property_value[i]); + } + } + else + { + print_property(property_name, property_value, segno); + } } else { @@ -166,7 +190,13 @@ main(int argc, char *argv[]) if (ncp_get_bindery_object_name(conn, ntohl(value[i]), &o) == 0) { - if (verbose != 0) + if (canonical != 0) + { + printf("%-4.4x\n%s\n", + (unsigned int) o.object_type, + o.object_name); + } + else if (verbose != 0) { printf("%s %08X %04X\n", o.object_name,