PATCH rpcclient

Nigel Williams nigel at veritas.com
Mon Jan 21 17:38:01 GMT 2002


This patch contains adds share management functionality to rpcclient

nigel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smbcacl_lib.h
Type: application/octet-stream
Size: 1145 bytes
Desc: not available
Url : http://lists.samba.org/archive/samba-technical/attachments/20020121/ee9f3d20/smbcacl_lib.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smbcacl_lib.c
Type: application/octet-stream
Size: 16416 bytes
Desc: not available
Url : http://lists.samba.org/archive/samba-technical/attachments/20020121/ee9f3d20/smbcacl_lib-0001.obj
-------------- next part --------------
Index: include/includes.h
===================================================================
RCS file: /cvsroot/samba/source/include/includes.h,v
retrieving revision 1.257
diff -u -r1.257 includes.h
--- include/includes.h	20 Jan 2002 14:30:53 -0000	1.257
+++ include/includes.h	22 Jan 2002 01:22:51 -0000
@@ -743,6 +743,8 @@
 
 #include "popt.h"
 
+#include "smbcacl_lib.h"
+
 #ifndef MAXCODEPAGELINES
 #define MAXCODEPAGELINES 256
 #endif
Index: rpcclient/cmd_srvsvc.c
===================================================================
RCS file: /cvsroot/samba/source/rpcclient/cmd_srvsvc.c,v
retrieving revision 1.30
diff -u -r1.30 cmd_srvsvc.c
--- rpcclient/cmd_srvsvc.c	12 Oct 2001 05:56:23 -0000	1.30
+++ rpcclient/cmd_srvsvc.c	22 Jan 2002 01:22:55 -0000
@@ -6,6 +6,7 @@
    Copyright (C) Andrew Tridgell 1992-1999
    Copyright (C) Luke Kenneth Casson Leighton 1996 - 1999
    Copyright (C) Tim Potter 2000
+   Copyright (C) Nigel Williams 2001
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -222,13 +223,1645 @@
 	return result;
 }
 
+static void unistr3_to_ascii(char *dest, const UNISTR3 *str, size_t maxlen) 
+{
+	UNISTR2 desc;
+
+	desc.uni_max_len = str->uni_str_len;
+	desc.uni_str_len = str->uni_str_len;
+	desc.buffer      = str->str.buffer;
+
+	return unistr2_to_ascii(dest, &desc, maxlen);
+}
+
+static void display_srv_disk_info_0(DISK_INFO *disk_info) 
+{
+	fstring disk_name;
+
+	unistr3_to_ascii(disk_name, &disk_info->disk_name, sizeof(disk_name)-1);
+
+	printf("\t%s\n", disk_name);
+}
+
+static NTSTATUS cmd_srvsvc_srv_disk_enum(struct cli_state *cli, 
+					 TALLOC_CTX *mem_ctx,
+					 int argc, char **argv) 
+{
+
+	int i;
+	uint32 preferred_len = 0xffffffff;
+	ENUM_HND enum_hnd;
+	uint32 er, entries_read;
+	uint32 total_entries;
+	DISK_INFO *disk_info;
+
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	if (argc != 1) {
+		printf("Usage: %s\n", argv[0]);
+		return NT_STATUS_OK;
+	}
+
+	ZERO_STRUCT(enum_hnd);
+
+	er = 0;
+
+	do {
+
+		result = cli_srvsvc_net_srv_disk_enum(cli, 
+						      mem_ctx,
+						      cli->desthost,
+						      preferred_len,
+						      &enum_hnd,
+						      &entries_read,
+						      &total_entries,
+						      &disk_info
+			);
+
+    
+		if (!NT_STATUS_IS_OK(result)) {
+			goto done;
+		}
+
+		/* Display results */
+
+		for(i = 0; i < entries_read; i++) {
+
+			display_srv_disk_info_0(disk_info+i);
+		}
+
+		er += entries_read;
+    
+	} while(er < total_entries);
+
+
+ done:
+	return result;
+}
+
+static NTSTATUS cmd_srvsvc_name_validate(struct cli_state *cli, 
+					 TALLOC_CTX *mem_ctx,
+					 int argc, char **argv) 
+{
+
+	fstring name;
+
+	typedef enum  _NETSETUP_NAME_TYPE {
+
+		NetSetupUnknown = 0,
+		NetSetupMachine,
+		NetSetupWorkgroup,
+		NetSetupDomain,
+		NetSetupNonExistentDomain,
+#if(_WIN32_WINNT >= 0x0500)
+		NetSetupDnsMachine,
+#endif
+		NetSetupShare = 9  /* not documented in msdn under NetValidateName */
+
+	} NETSETUP_NAME_TYPE, *PNETSETUP_NAME_TYPE;
+
+	NETSETUP_NAME_TYPE type = NetSetupShare;
+
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	if (argc > 3 || argc < 2) {
+		printf("Usage: %s [netname] [type]\n", argv[0]);
+		return NT_STATUS_OK;
+	}
+
+	fstrcpy(name, argv[1]);
+  
+	if(argc == 3)
+		type = atoi(argv[2]);
+
+	result = cli_srvsvc_net_name_validate(cli, 
+					      mem_ctx,
+					      cli->desthost,
+					      name,
+					      type
+		);
+
+    
+	if (!NT_STATUS_IS_OK(result)) {
+		goto done;
+	}
+
+ done:
+	return result;
+}
+
+#define CONST_STR(A) ((char *)(A))
+#define ELEMS(A) (sizeof(A)/sizeof((A)[0]))
+
+/* 
+ * Some defs that will move in the future
+ *
+ */
+
+#define SHARE_NETNAME_PARMNUM         1
+#define SHARE_TYPE_PARMNUM            3
+#define SHARE_REMARK_PARMNUM          4
+#define SHARE_PERMISSIONS_PARMNUM     5
+#define SHARE_MAX_USES_PARMNUM        6
+#define SHARE_CURRENT_USES_PARMNUM    7
+#define SHARE_PATH_PARMNUM            8
+#define SHARE_PASSWD_PARMNUM          9
+#define SHARE_FILE_SD_PARMNUM       501
+
+typedef struct {
+
+	const char *name;
+	uint32 value;
+} assoc;
+
+static assoc share_info_fields [] = {
+
+	"SHARE_NETNAME_PARMNUM",      SHARE_NETNAME_PARMNUM,
+	"SHARE_TYPE_PARMNUM",         SHARE_TYPE_PARMNUM,
+	"SHARE_REMARK_PARMNUM",       SHARE_REMARK_PARMNUM,
+	"SHARE_PERMISSIONS_PARMNUM",  SHARE_PERMISSIONS_PARMNUM,
+	"SHARE_MAX_USES_PARMNUM",     SHARE_MAX_USES_PARMNUM,
+	"SHARE_CURRENT_USES_PARMNUM", SHARE_CURRENT_USES_PARMNUM,
+	"SHARE_PATH_PARMNUM",         SHARE_PATH_PARMNUM,
+	"SHARE_PASSWD_PARMNUM",       SHARE_PASSWD_PARMNUM,
+	"SHARE_FILE_SD_PARMNUM",      SHARE_FILE_SD_PARMNUM,
+	{NULL}
+};
+
+#define SHARE_REMARK_INFOLEVEL          \
+            (PARMNUM_BASE_INFOLEVEL + SHARE_REMARK_PARMNUM)
+#define SHARE_MAX_USES_INFOLEVEL        \
+            (PARMNUM_BASE_INFOLEVEL + SHARE_MAX_USES_PARMNUM)
+#define SHARE_FILE_SD_INFOLEVEL         \
+            (PARMNUM_BASE_INFOLEVEL + SHARE_FILE_SD_PARMNUM)
+
+#define SHI1_NUM_ELEMENTS       4
+#define SHI2_NUM_ELEMENTS       10
+
+#define SHI_USES_UNLIMITED      (DWORD)-1
+
+#define SHI1005_FLAGS_DFS       0x01    // Share is in the DFS
+#define SHI1005_FLAGS_DFS_ROOT  0x02    // Share is root of DFS
+
+#define COW_PERMACHINE          0x04    // Share data is per-machine data
+#define COW_PERUSER             0x08    // Share data is per-user data
+
+#define CSC_CACHEABLE           0x10    // Client can cache files for off-line access
+#define CSC_NOFLOWOPS           0x20    // Client need not flow operations to the server
+#define CSC_AUTO_INWARD         0x40    // Auto inward propagation (server->client) w/o UI
+#define CSC_AUTO_OUTWARD        0x80    // Auto outward propagation(client->server) w/o UI
+
+#define SHI1005_VALID_FLAGS_SET (   CSC_CACHEABLE   | \
+                                    CSC_NOFLOWOPS   | \
+                                    CSC_AUTO_INWARD | \
+                                    CSC_AUTO_OUTWARD| \
+                                    COW_PERMACHINE  | \
+                                    COW_PERUSER    )
+
+#define SHI1007_VALID_FLAGS_SET SHI1005_VALID_FLAGS_SET
+
+static assoc flag_names[] = {
+
+	"SHI1005_FLAGS_DFS",      SHI1005_FLAGS_DFS,
+	"SHI1005_FLAGS_DFS_ROOT", SHI1005_FLAGS_DFS_ROOT,
+	"COW_PERMACHINE",         COW_PERMACHINE,
+	"COW_PERUSER",            COW_PERUSER,
+	"CSC_CACHEABLE",          CSC_CACHEABLE,
+	"CSC_NOFLOWOPS",          CSC_NOFLOWOPS,
+	"CSC_AUTO_INWARD",        CSC_AUTO_INWARD,
+	"CSC_AUTO_OUTWARD",       CSC_AUTO_OUTWARD,
+	{NULL}
+};
+
+#define ACCESS_NONE         0
+#define ACCESS_ALL          ( ACCESS_READ | \
+                              ACCESS_WRITE | \
+                              ACCESS_CREATE | \
+                              ACCESS_EXEC | \
+                              ACCESS_DELETE | \
+                              ACCESS_ATRIB | \
+                              ACCESS_PERM \
+                            )
+
+#define ACCESS_READ         0x01
+#define ACCESS_WRITE        0x02
+#define ACCESS_CREATE       0x04
+#define ACCESS_EXEC         0x08
+#define ACCESS_DELETE       0x10
+#define ACCESS_ATRIB        0x20
+#define ACCESS_PERM         0x40
+
+#define SHARE_ACCESS_READ   ACCESS_READ
+#define SHARE_ACCESS_WRITE  ACCESS_WRITE
+#define SHARE_ACCESS_CREATE ACCESS_CREATE
+#define SHARE_ACCESS_EXEC   ACCESS_EXEC
+#define SHARE_ACCESS_DELETE ACCESS_DELETE
+#define SHARE_ACCESS_ATRIB  ACCESS_ATRIB
+#define SHARE_ACCESS_PERM   ACCESS_PERM
+#define SHARE_ACCESS_NONE   ACCESS_NONE
+#define SHARE_ACCESS_ALL    ACCESS_ALL
+
+static assoc share_types[] = {
+
+	{"Admin",   STYPE_HIDDEN},
+	{"Disk",    STYPE_DISKTREE},
+	{"Printer", STYPE_PRINTQ},
+	{"Device",  STYPE_DEVICE},
+	{"IPC",     STYPE_IPC},
+	{NULL}
+};
+
+static assoc perm_types[] = {
+  
+	{"ACCESS_READ",   SHARE_ACCESS_READ},
+	{"ACCESS_WRITE",  SHARE_ACCESS_WRITE},
+	{"ACCESS_CREATE", SHARE_ACCESS_CREATE},
+	{"ACCESS_EXEC",   SHARE_ACCESS_EXEC},
+	{"ACCESS_DELETE", SHARE_ACCESS_DELETE},
+	{"ACCESS_ATRIB",  SHARE_ACCESS_ATRIB},
+	{"ACCESS_PERM",   SHARE_ACCESS_PERM},
+	{"ACCESS_NONE",   SHARE_ACCESS_NONE},
+	{"ACCESS_ALL",    SHARE_ACCESS_ALL},
+	{NULL}
+};
+
+static const char *admin_share = "admin_";
+
+static BOOL find_assoc(const assoc *a, char *name, size_t name_len, uint32 *value) 
+{
+
+	int i;
+
+	if(*name) {
+
+		for(i = 0; a[i].name; i++) {
+      
+			if(strncmp(name, a[i].name, name_len) == 0) {
+
+				*value = a[i].value;
+				return True;
+			}
+		}
+	} else {
+
+		for(i = 0; a[i].name; i++) {
+
+			if(a[i].value == *value) {
+
+				strncpy(name, a[i].name, name_len);
+				return True;
+			}
+		}
+	}
+
+	return False;
+}
+
+static BOOL find_assoc_all(const assoc *a, char *name, size_t name_len, uint32 *value, const char *separator) 
+{
+
+	BOOL ret = False;
+
+	int i;
+  
+	if(*name) {
+
+		fstring tok;
+
+		char *p = name;
+
+		ret = True;
+
+		while(next_token((char **)&p, tok, (char *)separator, sizeof(tok))) {
+
+			BOOL loc_ret = False;
+      
+			for(i = 0; !loc_ret && a[i].name; i++) {
+	
+				if(strcmp(name, a[i].name) == 0) {
+	  
+					*value |= a[i].value;
+					loc_ret = True;
+				}
+			}
+      
+			if(!loc_ret) {
+	
+				ret = False;
+				break;
+			}
+		}
+      
+	} else {
+      
+		int offset = 0;
+
+		const char *loc_separator = "";
+
+		for(i = 0; a[i].name; i++) {
+
+			if(a[i].value == *value && (a[i].value & *value) == *value) {
+
+				offset += snprintf(&name[offset], name_len - offset, "%s%s", loc_separator, a[i].name);
+				loc_separator = separator;
+			}
+		}
+
+		if(offset == 0 || offset >= name_len) 
+			ret = False;
+	}
+  
+	return ret;
+}
+
+static BOOL parse_share_get_share_type_str(uint32 type, char *typestr, size_t size)
+{
+	BOOL ret = True;
+
+	*typestr = '\0';
+
+	if(type & STYPE_HIDDEN) {
+
+		strncat(typestr, admin_share, size);
+		size -= strlen(admin_share);
+
+		type &= ~STYPE_HIDDEN;
+	}
+
+	switch (type)
+	{
+	case STYPE_DISKTREE: strncat(typestr, "Disk"   , size); break;
+	case STYPE_PRINTQ  : strncat(typestr, "Printer", size); break;	      
+	case STYPE_DEVICE  : strncat(typestr, "Device" , size); break;
+	case STYPE_IPC     : strncat(typestr, "IPC"    , size); break;      
+	default            : 
+		strncat(typestr, "????", size); 
+		ret = False;
+		break;      
+	}
+
+	return ret;
+}
+
+static BOOL parse_share_get_share_type_from_str(const char *type_str, uint32 *type)
+{
+	int i;
+	int t = 0;
+
+	static int admin_share_len = -1;
+
+	if(!type_str)
+	  return False;
+
+	if(admin_share_len < 0)
+		admin_share_len = strlen(admin_share);
+
+	*type = 0;
+
+	if(strncmp(type_str, admin_share, admin_share_len) == 0) {
+    
+		*type |= STYPE_HIDDEN;
+
+		type_str += admin_share_len;
+	}
+
+	if(!find_assoc(share_types, (char *)type_str, strlen(type_str), &t))
+		return False;
+
+	*type |= t;
+
+	return True;
+}
+
+static BOOL parse_share_get_share_perms_str(uint32 perms, char *permsstr, size_t size) 
+{
+	*permsstr = '\0';
+
+	return find_assoc_all(perm_types, permsstr, size, &perms, "|");
+}
+
+static BOOL parse_share_get_share_perms_from_str(const char *perms_str, uint32 *perms) 
+{
+	*perms = 0;
+
+	if(!perms_str)
+	  return False;
+
+	return find_assoc_all(perm_types, (char *)perms_str, strlen(perms_str), perms, "|");
+}
+
+static int parse_share_get_share_flags_str(uint32 flags, char *flagsstr, size_t size) 
+{
+	*flagsstr = 0;
+
+	return find_assoc_all(flag_names, flagsstr, size, &flags, "|");
+}
+
+static BOOL parse_share_get_share_flags_from_str(const char *flagsstr, uint32 *flags) 
+{
+	*flags = 0;
+
+	if(!flagsstr)
+	  return False;
+
+	return find_assoc_all(flag_names, (char *)flagsstr, strlen(flagsstr), flags, "|");
+}
+
+typedef struct {
+
+	char locator;
+	const char *desc;
+	char *default_val;
+	char *val_ptr;
+	pstring val;
+	int found;
+} cmd_arg;
+
+static cmd_arg share_arg_type     = {'t', "type",                     "Disk"};
+static cmd_arg share_arg_remark   = {'r', "remark",                   NULL};
+static cmd_arg share_arg_perms    = {'p', "permissions",              "ACCESS_NONE"};
+static cmd_arg share_arg_max_uses = {'u', "max uses",                 "-1"};
+static cmd_arg share_arg_path     = {'P', "path",                     NULL};
+static cmd_arg share_arg_passwd   = {'w', "passwd",                   NULL};
+static cmd_arg share_arg_flags    = {'f', "flags",                    "0"};
+static cmd_arg share_arg_sd       = {'s', "security descriptor",      NULL};
+static cmd_arg share_arg_adn      = {'a', "alternate directory name", NULL};
+
+typedef struct {
+
+	cmd_arg *cmd_arg_p;
+	BOOL required;
+} cmd_arg_option;
+
+static cmd_arg_option options_level_0[] = {
+	{NULL}
+};
+
+static cmd_arg_option options_level_1[] = {
+	{&share_arg_type,   False},
+	{&share_arg_remark, False},
+	{NULL}
+};
+
+static cmd_arg_option options_level_2[] = {
+	{&share_arg_type,     False},
+	{&share_arg_remark,   False},
+	{&share_arg_perms,    False},
+	{&share_arg_max_uses, False},
+	{&share_arg_path,     True},
+	{&share_arg_passwd,   False},
+	{NULL}
+};
+
+static cmd_arg_option options_level_501[] = {
+	{&share_arg_type,   False},
+	{&share_arg_remark, False},
+	{&share_arg_flags,  True},
+	{NULL}
+};
+
+static cmd_arg_option options_level_502[] = {
+	{&share_arg_type,     False},
+	{&share_arg_remark,   False},
+	{&share_arg_perms,    False},
+	{&share_arg_max_uses, False},
+	{&share_arg_path,     True},
+	{&share_arg_passwd,   False},
+	{&share_arg_sd,       True},
+	{NULL}
+};
+
+static cmd_arg_option options_level_1004[] = {
+	{&share_arg_remark, True},
+	{NULL}
+};
+
+static cmd_arg_option options_level_1005[] = {
+	{&share_arg_flags, True},
+	{NULL}
+};
+
+static cmd_arg_option options_level_1006[] = {
+	{&share_arg_max_uses, True},
+	{NULL}
+};
+
+static cmd_arg_option options_level_1007[] = {
+	{&share_arg_flags, True},
+	{&share_arg_adn,   True},
+	{NULL}
+};
+
+static cmd_arg_option options_level_1501[] = {
+	{&share_arg_sd, True},
+	{NULL}
+};
+
+typedef struct args_avalable_at_level {
+  
+	int level;
+	cmd_arg_option *poss;
+} args_available_at_level;
+
+static args_available_at_level parse_share_args[] = {
+	{0,    options_level_0},
+	{1,    options_level_1},
+	{2,    options_level_2},
+	{501,  options_level_501},
+	{502,  options_level_502},
+	{1004, options_level_1004},
+	{1005, options_level_1005},
+	{1006, options_level_1006},
+	{1007, options_level_1007},
+	{1501, options_level_1501},
+	{-1}
+};
+
+static const char *cmd_arg_val(cmd_arg_option *sao, char c) 
+{
+	for(; sao->cmd_arg_p; sao++)
+		if(c == sao->cmd_arg_p->locator)
+			return sao->cmd_arg_p->val_ptr;
+  
+	return NULL;
+}
+
+static void cmd_arg_show_usage_for_info_level(int level, cmd_arg_option *sao) 
+{  
+	printf("Usage for info level %d:\n", level);
+
+	for(; sao->cmd_arg_p; sao++)
+		printf("\t-%c:\tdefault:%s\tdesc: %s\n", 
+		       sao->cmd_arg_p->locator, 
+		       (sao->cmd_arg_p->default_val)?sao->cmd_arg_p->default_val:"<none>",
+		       sao->cmd_arg_p->desc);
+}
+
+static BOOL cmd_arg_process(int level, args_available_at_level *aaal, int argc, char *argv[], cmd_arg_option **saop) 
+{
+	extern char *optarg;
+	extern int optind;
+	int opt;
+	int i;
+	BOOL found = False;
+	fstring arg_control;
+
+	cmd_arg_option *sao = NULL;
+
+	for(; aaal->level >= 0; aaal++) {
+    
+		if(aaal->level == level) {
+
+			found = True;
+			break;
+		}
+	}
+
+	if(!found) {
+
+		return False;
+	}
+
+	*saop = sao = aaal->poss;
+
+	*arg_control = 0;
+
+	for(; sao->cmd_arg_p; sao++) {
+    
+		strncat(arg_control, &sao->cmd_arg_p->locator, 1);
+		strncat(arg_control, ":", 1);
+
+		sao->cmd_arg_p->found = 0;
+	}
+
+	optind = 0;
+
+	while((opt = getopt(argc, argv, arg_control)) != EOF) {
+
+		sao = aaal->poss;
+
+		for( ; sao->cmd_arg_p; sao++) {
+			if(opt == sao->cmd_arg_p->locator) {
+	
+				sao->cmd_arg_p->found = 1;
+				sao->cmd_arg_p->val_ptr = sao->cmd_arg_p->val;
+				pstrcpy(sao->cmd_arg_p->val_ptr, optarg);
+				break;
+			}
+		}
+	}
+  
+	sao = aaal->poss;
+
+	for(; sao->cmd_arg_p; sao++) {
+		if(!sao->cmd_arg_p->found) {
+
+			if(sao->required)
+				return False;
+
+			sao->cmd_arg_p->val_ptr = sao->cmd_arg_p->default_val;
+		}
+	}
+  
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_0(SRV_SHARE_INFO_0 *si, const char *netname, 
+					       TALLOC_CTX *mem_ctx, 
+					       cmd_arg_option *sao) 
+{
+	init_srv_share_info0(&si->info_0, CONST_STR(netname));
+	init_srv_share_info0_str(&si->info_0_str, CONST_STR(netname));
+  
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_1(SRV_SHARE_INFO_1 *si, const char *netname, 
+					       TALLOC_CTX *mem_ctx, 
+					       cmd_arg_option *sao) 
+{
+	int type;
+	const char *remark;
+
+	if(!parse_share_get_share_type_from_str(cmd_arg_val(sao, 't'), &type))
+		return False;
+
+	remark = cmd_arg_val(sao, 'r');
+
+	init_srv_share_info1(&si->info_1, CONST_STR(netname), type, CONST_STR(remark));
+	init_srv_share_info1_str(&si->info_1_str, CONST_STR(netname), CONST_STR(remark));
+  
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_2(SRV_SHARE_INFO_2 *si, const char *netname, 
+					       TALLOC_CTX *mem_ctx, 
+					       cmd_arg_option *sao) 
+{
+	int type;
+	const char *remark;
+	int perms;
+	int max_uses;
+	int num_uses;
+	const char *path;
+	const char *password;
+
+	if(!parse_share_get_share_type_from_str(cmd_arg_val(sao, 't'), &type))
+		return False;
+
+	remark = cmd_arg_val(sao, 'r');
+
+	if(!parse_share_get_share_perms_from_str(cmd_arg_val(sao, 'p'), &perms))
+		return False;
+
+	max_uses = atoi(cmd_arg_val(sao, 'u'));
+
+	num_uses = 0;
+
+	path     = cmd_arg_val(sao, 'P');
+	password = cmd_arg_val(sao, 'w');
+
+	init_srv_share_info2(&si->info_2, CONST_STR(netname), type, CONST_STR(remark), 
+			     perms, max_uses, num_uses, 
+			     CONST_STR(path), CONST_STR(password));
+
+	init_srv_share_info2_str(&si->info_2_str, CONST_STR(netname), CONST_STR(remark), 
+				 CONST_STR(path), CONST_STR(password));
+  
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_501(SRV_SHARE_INFO_501 *si, const char *netname, 
+						 TALLOC_CTX *mem_ctx, 
+						 cmd_arg_option *sao) 
+{
+	int type;
+	const char *remark;
+	uint32 flags = 0;
+
+	if(!parse_share_get_share_type_from_str(cmd_arg_val(sao, 't'), &type))
+		return False;
+
+	remark = cmd_arg_val(sao, 'r');
+
+	if(!parse_share_get_share_flags_from_str(cmd_arg_val(sao, 'f'), &flags))
+		return False;
+
+	init_srv_share_info501(&si->info_501, CONST_STR(netname), type, CONST_STR(remark), flags);
+	init_srv_share_info501_str(&si->info_501_str, CONST_STR(netname), CONST_STR(remark));
+  
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_502(SRV_SHARE_INFO_502 *si, const char *netname, 
+						 TALLOC_CTX *mem_ctx, 
+						 cmd_arg_option *sao) 
+{
+	int type;
+	const char *remark;
+	int perms;
+	int max_uses;
+	int num_uses;
+	const char *path;
+	const char *password;
+	const char *sec_desc_str;
+	SEC_DESC *sec_desc = NULL;
+
+	if(!parse_share_get_share_type_from_str(cmd_arg_val(sao, 't'), &type))
+		return False;
+
+	remark = cmd_arg_val(sao, 'r');
+
+	if(!parse_share_get_share_perms_from_str(cmd_arg_val(sao, 'p'), &perms))
+		return False;
+
+	max_uses = atoi(cmd_arg_val(sao, 'u'));
+
+	num_uses = 0;
+
+	path         = cmd_arg_val(sao, 'P');
+	password     = cmd_arg_val(sao, 'w');
+	sec_desc_str = cmd_arg_val(sao, 's');
+
+	if(sec_desc_str)
+		if(!smbcacl_lib_sec_desc_parse(mem_ctx, sec_desc_str, &sec_desc))
+			return False;
+
+	{
+		int sd_size = sec_desc?sec_desc_size(sec_desc):0;
+
+		init_srv_share_info502(&si->info_502, 
+				       CONST_STR(netname), type, CONST_STR(remark), 
+				       perms, max_uses, num_uses, 
+				       CONST_STR(path), CONST_STR(password), 
+				       sec_desc, sd_size);
+		
+		init_srv_share_info502_str(&si->info_502_str, 
+					   CONST_STR(netname), CONST_STR(remark), 
+					   CONST_STR(path), CONST_STR(password), 
+					   sec_desc, sd_size);
+	}
+
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_1004(SRV_SHARE_INFO_1004 *si, const char *netname, 
+						  TALLOC_CTX *mem_ctx, 
+						  cmd_arg_option *sao) 
+{
+
+	const char *remark;
+
+	remark = cmd_arg_val(sao, 'r');
+
+	init_srv_share_info1004(&si->info_1004, CONST_STR(remark));
+	init_srv_share_info1004_str(&si->info_1004_str, CONST_STR(remark));
+  
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_1005(SRV_SHARE_INFO_1005 *si, const char *netname, 
+						  TALLOC_CTX *mem_ctx, 
+						  cmd_arg_option *sao) 
+{
+	uint32 flags;
+
+	if(!parse_share_get_share_flags_from_str(cmd_arg_val(sao, 'f'), &flags))
+		return False;
+
+	si->dfs_root_flag = flags;
+  
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_1006(SRV_SHARE_INFO_1006 *si, const char *netname, 
+						  TALLOC_CTX *mem_ctx, 
+						  cmd_arg_option *sao) 
+{
+	si->max_uses = atoi(cmd_arg_val(sao, 'u'));
+  
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_1007(SRV_SHARE_INFO_1007 *si, const char *netname, 
+						  TALLOC_CTX *mem_ctx, 
+						  cmd_arg_option *sao) 
+{
+	uint32 flags;
+	const char *alternate_directory_name;
+
+	if(!parse_share_get_share_flags_from_str(cmd_arg_val(sao, 'f'), &flags))
+		return False;
+
+	alternate_directory_name = cmd_arg_val(sao, 'a');
+
+	init_srv_share_info1007(&si->info_1007, flags, alternate_directory_name);
+	init_srv_share_info1007_str(&si->info_1007_str, alternate_directory_name);
+  
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args_1501(SRV_SHARE_INFO_1501 *si, const char *netname, 
+						  TALLOC_CTX *mem_ctx, 
+						  cmd_arg_option *sao)
+{
+	const char *sec_desc_str;
+	SEC_DESC *sec_desc = NULL;
+	int sd_size;
+
+	sec_desc_str = cmd_arg_val(sao, 's');
+
+	if(sec_desc_str)
+		if(!smbcacl_lib_sec_desc_parse(mem_ctx, sec_desc_str, &sec_desc))
+			return False;
+
+	sd_size = sec_desc?sec_desc_size(sec_desc):0;
+
+	si->sdb = make_sec_desc_buf(mem_ctx, sd_size, sec_desc);
+
+	return True;
+}
+
+static BOOL parse_share_share_info_from_args(SRV_SHARE_INFO *si, char *netname, 
+					     TALLOC_CTX *mem_ctx, 
+					     int argc, char *argv[]) 
+{
+	cmd_arg_option *sao = NULL;
+
+	if(argc < 2) 
+		return False;
+
+	si->switch_value = atoi(argv[1]);
+
+	if(!cmd_arg_process(si->switch_value, parse_share_args, argc-2, argv+2, &sao)) {
+
+		if(sao) 
+			cmd_arg_show_usage_for_info_level(si->switch_value, sao);
+
+		return False;
+	}
+
+	si->ptr_share_ctr = 1;
+
+	fstrcpy(netname, argv[0]);
+
+	switch(si->switch_value) {
+
+	case 0:
+		return parse_share_share_info_from_args_0(   &si->share.info0,    netname, mem_ctx, sao);
+		break;
+	case 1:
+		return parse_share_share_info_from_args_1(   &si->share.info1,    netname, mem_ctx, sao);
+		break;
+	case 2:
+		return parse_share_share_info_from_args_2(   &si->share.info2,    netname, mem_ctx, sao);
+		break;
+	case 501:
+		return parse_share_share_info_from_args_501( &si->share.info501,  netname, mem_ctx, sao);
+		break;
+	case 502:
+		return parse_share_share_info_from_args_502( &si->share.info502,  netname, mem_ctx, sao);
+		break;
+	case 1004:
+		return parse_share_share_info_from_args_1004(&si->share.info1004, netname, mem_ctx, sao);
+		break;
+	case 1005:
+		return parse_share_share_info_from_args_1005(&si->share.info1005, netname, mem_ctx, sao);
+		break;
+	case 1006:
+		return parse_share_share_info_from_args_1006(&si->share.info1006, netname, mem_ctx, sao);
+		break;
+	case 1007:
+		return parse_share_share_info_from_args_1007(&si->share.info1007, netname, mem_ctx, sao);
+		break;
+	case 1501:
+		return parse_share_share_info_from_args_1501(&si->share.info1501, netname, mem_ctx, sao);
+		break;
+	default:
+	}
+
+	return False;
+}
+
+void display_share_info_0(SRV_SHARE_INFO_0 *info0) 
+{
+  
+	fstring netname = "";
+
+	if(info0->info_0.ptr_netname) {
+		unistr2_to_ascii(netname, &info0->info_0_str.uni_netname, sizeof(netname)-1);
+	}
+
+	printf("level 0\tshare %s:\n", 
+	       netname);
+}
+
+void display_share_info_1(SRV_SHARE_INFO_1 *info1) 
+{
+	fstring netname = "";
+	fstring comment = "";
+	fstring typestr = "";
+
+	if(info1->info_1.ptr_netname) {
+		unistr2_to_ascii(netname, &info1->info_1_str.uni_netname, sizeof(netname)-1);
+	}
+
+	parse_share_get_share_type_str(info1->info_1.type, typestr, sizeof(typestr));
+
+	if(info1->info_1.ptr_remark) {
+		unistr2_to_ascii(comment, &info1->info_1_str.uni_remark, sizeof(comment)-1);
+	}
+  
+	printf("level 1\tshare %s:\n"
+	       "\ttype\t:%s(0x%x)\n"
+	       "\tcomment\t:%s.\n", 
+	       netname, 
+	       typestr, info1->info_1.type, 
+	       comment);
+}
+
+void display_share_info_2(SRV_SHARE_INFO_2 *info2) 
+{
+	fstring netname  = "";
+	fstring comment  = "";
+	fstring path     = "";
+	fstring passwd   = "";
+	fstring typestr  = "";
+	fstring permsstr = "";
+
+	int max_uses;
+	int num_uses;
+
+	if(info2->info_2.ptr_netname) {
+		unistr2_to_ascii(netname, &info2->info_2_str.uni_netname, sizeof(netname)-1);
+	}
+
+	parse_share_get_share_type_str(info2->info_2.type, typestr, sizeof(typestr));
+
+	if(info2->info_2.ptr_remark) {
+		unistr2_to_ascii(comment, &info2->info_2_str.uni_remark, sizeof(comment)-1);
+	}
+
+	parse_share_get_share_perms_str(info2->info_2.perms, permsstr, sizeof(permsstr));
+
+	max_uses = info2->info_2.max_uses;
+	num_uses = info2->info_2.num_uses;
+
+	if(info2->info_2.ptr_path) {
+		unistr2_to_ascii(path, &info2->info_2_str.uni_path, sizeof(path)-1);
+	}
+
+	if(info2->info_2.ptr_passwd) {
+		unistr2_to_ascii(passwd, &info2->info_2_str.uni_passwd, sizeof(passwd)-1);
+	}
+  
+	printf("level 2\tshare %s:\n"
+	       "\ttype\t:%s(0x%x)\n"
+	       "\tcomment\t:%s\n"
+	       "\tperms\t:%s(0x%x)\n"
+	       "\tmax_uses\t:%d\n"
+	       "\tnum_uses\t:%d\n"
+	       "\tpath\t:%s\n"
+	       "\tpasswd\t:%s.\n", 
+	       netname, 
+	       typestr, info2->info_2.type,
+	       comment, 
+	       permsstr, info2->info_2.perms,
+	       max_uses, 
+	       num_uses, 
+	       path, 
+	       passwd);
+
+}
+
+void display_share_info_501(SRV_SHARE_INFO_501 *info501) 
+{
+	fstring netname  = "";
+	fstring comment  = "";
+	fstring typestr  = "";
+	fstring flagsstr = "";
+
+	if(info501->info_501.ptr_netname) {
+    
+		unistr2_to_ascii(netname, &info501->info_501_str.uni_netname, sizeof(netname)-1);
+	}
+
+	parse_share_get_share_type_str(info501->info_501.type, typestr, sizeof(typestr));
+
+	if(info501->info_501.ptr_remark) {
+    
+		unistr2_to_ascii(comment, &info501->info_501_str.uni_remark, sizeof(comment)-1);
+	}
+
+	printf("level 501\tshare %s:\n"
+	       "\ttype\t:%s(0x%x)\n"
+	       "\tcomment\t:%s\n"
+	       "\tflags\t:%s(0x%x).\n", 
+	       netname, 
+	       typestr, info501->info_501.type,
+	       comment, 
+	       flagsstr, info501->info_501.flags);
+}
+
+void display_share_info_502(SRV_SHARE_INFO_502 *info502) 
+{
+	fstring netname  = "";
+	fstring comment  = "";
+	fstring path     = "";
+	fstring passwd   = "";
+	fstring typestr  = "";
+	fstring permsstr = "";
+	pstring sdstr    = "";
+
+	int sd_size = -1;
+
+	int max_uses;
+	int num_uses;
+
+	if(info502->info_502.ptr_netname) {
+		unistr2_to_ascii(netname, &info502->info_502_str.uni_netname, sizeof(netname)-1);
+	}
+
+	parse_share_get_share_type_str(info502->info_502.type, typestr, sizeof(typestr));
+
+	if(info502->info_502.ptr_remark) {
+		unistr2_to_ascii(comment, &info502->info_502_str.uni_remark, sizeof(comment)-1);
+	}
+
+	parse_share_get_share_perms_str(info502->info_502.perms, permsstr, sizeof(permsstr));
+
+	max_uses = info502->info_502.max_uses;
+	num_uses = info502->info_502.num_uses;
+
+	if(info502->info_502.ptr_path) {
+		unistr2_to_ascii(path, &info502->info_502_str.uni_path, sizeof(path)-1);
+	}
+
+	if(info502->info_502.ptr_passwd) {
+		unistr2_to_ascii(passwd, &info502->info_502_str.uni_passwd, sizeof(passwd)-1);
+	}
+
+	if(info502->info_502.ptr_sd) {
+		sd_size = info502->info_502.sd_size;
+
+		if(smbcacl_lib_sec_desc_str(info502->info_502_str.sd, sdstr, sizeof(sdstr)) >= sizeof(sdstr)) {
+  
+			strncpy(&sdstr[sizeof(sdstr)-5-1], "...\n", 5);
+		}
+	}
+
+	printf("level 502\tshare %s:\n"
+	       "\ttype\t:%s(0x%x)\n"
+	       "\tcomment\t:%s\n"
+	       "\tperms\t:%s(0x%x)\n"
+	       "\tmax_uses\t:%d\n"
+	       "\tnum_uses\t:%d\n"
+	       "\tpath\t:%s\n"
+	       "\tpasswd\t:%s\n"
+	       "\tsd_size\t:%d\n"
+	       "%s\n",
+	       netname, 
+	       typestr, info502->info_502.type,
+	       comment, 
+	       permsstr, info502->info_502.perms,
+	       max_uses, 
+	       num_uses, 
+	       path, 
+	       passwd,
+	       sd_size, 
+	       sdstr);
+}
+
+void display_share_info_1004(SRV_SHARE_INFO_1004 *info1004) 
+{
+	fstring comment  = "";
+
+	if(info1004->info_1004.ptr_remark) {
+		unistr2_to_ascii(comment, &info1004->info_1004_str.uni_remark, sizeof(comment)-1);
+	}
+
+	printf("level 1004:\n"
+	       "\tcomment\t:%s.\n", 
+	       comment);
+}
+
+void display_share_info_1005(SRV_SHARE_INFO_1005 *info1005) 
+{
+	fstring flagsstr  = "";
+	uint32 flags      = info1005->dfs_root_flag;
+
+	parse_share_get_share_flags_str(flags, flagsstr, sizeof(flagsstr));
+
+	printf("level 1005:\n"
+	       "\tflags\t:%s(0x%x).\n", 
+	       flagsstr, flags);
+}
+
+void display_share_info_1006(SRV_SHARE_INFO_1006 *info1006) 
+{
+	int max_uses = info1006->max_uses;
+
+	printf("level 1006:\n"
+	       "\tmax uses\t:%d.\n", 
+	       max_uses);
+}
+
+void display_share_info_1007(SRV_SHARE_INFO_1007 *info1007) 
+{
+	fstring alternate_directory_name = "";
+	fstring flagsstr                 = "";
+	uint32 flags                     = info1007->info_1007.flags;
+
+	if(info1007->info_1007.ptr_AlternateDirectoryName) {
+
+		unistr2_to_ascii(alternate_directory_name, 
+				 &info1007->info_1007_str.uni_AlternateDirectoryName, 
+				 sizeof(alternate_directory_name)-1);
+	}
+
+	parse_share_get_share_flags_str(flags, flagsstr, sizeof(flagsstr));
+
+	printf("level 1007:\n"
+	       "\tflags\t:%s(0x%x)\n"
+	       "\talt dir\t:%s.\n", 
+	       flagsstr, flags, 
+	       alternate_directory_name);
+}
+
+void display_share_info_1501(SRV_SHARE_INFO_1501 *info1501) 
+{
+	pstring sdstr = "";
+
+	int sd_size = -1;
+
+	if(info1501->sdb->ptr) {
+		sd_size = info1501->sdb->len;
+
+		if(smbcacl_lib_sec_desc_str(info1501->sdb->sec, sdstr, sizeof(sdstr)) >= sizeof(sdstr)) {
+  
+			strncpy(&sdstr[sizeof(sdstr)-5-1], "...\n", 5);
+		}
+	}
+
+	printf("level 1501:\n"
+	       "\tsd size\t:%d\n"
+	       "%s.\n", 
+	       sd_size, 
+	       sdstr);
+}
+
+static NTSTATUS cmd_srvsvc_share_enum_sticky(struct cli_state *cli, 
+					     TALLOC_CTX *mem_ctx,
+					     int argc, char **argv) 
+{
+	int i;
+	int er;
+	uint32 preferred_len = 0xffffffff;
+	ENUM_HND enum_hnd;
+	uint32 total_entries;
+	SRV_SHARE_INFO_CTR share_info_ctr;
+	uint32 info_level = 502;
+  
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	if (argc > 2) {
+		printf("Usage: %s [info_level 0,1,2,502]\n", argv[0]);
+		return NT_STATUS_OK;
+	}
+
+	if(argc == 2)
+		info_level = atoi(argv[1]);
+
+	/* this call includes the enum handle even when zero */
+
+	enum_hnd.ptr_hnd = 1;
+	enum_hnd.handle  = 0;
+
+	ZERO_STRUCT(share_info_ctr);
+	total_entries = 0;
+
+	share_info_ctr.info_level = info_level;
+
+	er = 0;
+
+	do {
+
+		result = cli_srvsvc_net_share_enum_sticky(cli, 
+							  mem_ctx,
+							  cli->desthost,
+							  preferred_len,
+							  &enum_hnd,
+							  &total_entries,
+							  &share_info_ctr
+			);
+
+    
+		if (!NT_STATUS_IS_OK(result)) {
+			goto done;
+		}
+
+		switch(share_info_ctr.switch_value) {
+		case 0:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_0(&share_info_ctr.share.info0[i]);
+			}
+			break;
+		case 1:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1(&share_info_ctr.share.info1[i]);
+			}
+			break;
+		case 2:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_2(&share_info_ctr.share.info2[i]);
+			}
+			break;
+		case 501:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_501(&share_info_ctr.share.info501[i]);
+			}
+			break;
+		case 502:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_502(&share_info_ctr.share.info502[i]);
+			}
+			break;
+		case 1004:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1004(&share_info_ctr.share.info1004[i]);
+			}
+			break;
+		case 1005:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1005(&share_info_ctr.share.info1005[i]);
+			}
+			break;
+		case 1006:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1006(&share_info_ctr.share.info1006[i]);
+			}
+			break;
+		case 1007:
+
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1007(&share_info_ctr.share.info1007[i]);
+			}
+			break;
+		case 1501:
+
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1501(&share_info_ctr.share.info1501[i]);
+			}
+			break;
+		default:
+			printf("unknown share info type %d.\n", share_info_ctr.switch_value);
+		}
+
+		er += share_info_ctr.num_entries;
+    
+	} while(er < total_entries);
+
+ done:
+	return result;
+}
+
+static NTSTATUS cmd_srvsvc_share_enum(struct cli_state *cli, 
+				      TALLOC_CTX *mem_ctx,
+				      int argc, char **argv) 
+{
+	int i;
+	int er;
+	uint32 preferred_len = 0xffffffff;
+	ENUM_HND enum_hnd;
+	uint32 total_entries;
+	SRV_SHARE_INFO_CTR share_info_ctr;
+	uint32 info_level = 502;
+  
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	if (argc > 2) {
+		printf("Usage: %s [info_level 0,1,2,501,502]\n", argv[0]);
+		return NT_STATUS_OK;
+	}
+
+	if(argc == 2)
+		info_level = atoi(argv[1]);
+
+	/* this call includes the enum handle even when zero */
+
+	enum_hnd.ptr_hnd = 1;
+	enum_hnd.handle  = 0;
+
+	ZERO_STRUCT(share_info_ctr);
+	total_entries = 0;
+
+	share_info_ctr.info_level = info_level;
+
+	er = 0;
+
+	do {
+
+		result = cli_srvsvc_net_share_enum(cli, 
+						   mem_ctx,
+						   cli->desthost,
+						   preferred_len,
+						   &enum_hnd,
+						   &total_entries,
+						   &share_info_ctr
+			);
+
+    
+		if (!NT_STATUS_IS_OK(result)) {
+			goto done;
+		}
+
+		switch(share_info_ctr.switch_value) {
+		case 0:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_0(&share_info_ctr.share.info0[i]);
+			}
+			break;
+		case 1:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1(&share_info_ctr.share.info1[i]);
+			}
+			break;
+		case 2:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_2(&share_info_ctr.share.info2[i]);
+			}
+			break;
+		case 501:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_501(&share_info_ctr.share.info501[i]);
+			}
+			break;
+		case 502:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_502(&share_info_ctr.share.info502[i]);
+			}
+			break;
+		case 1004:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1004(&share_info_ctr.share.info1004[i]);
+			}
+			break;
+		case 1005:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1005(&share_info_ctr.share.info1005[i]);
+			}
+			break;
+		case 1006:
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1006(&share_info_ctr.share.info1006[i]);
+			}
+			break;
+		case 1007:
+
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1007(&share_info_ctr.share.info1007[i]);
+			}
+			break;
+		case 1501:
+
+			for(i = 0; i < share_info_ctr.num_entries; i++) {
+				display_share_info_1501(&share_info_ctr.share.info1501[i]);
+			}
+			break;
+		default:
+			printf("unknown share info type %d.\n", share_info_ctr.switch_value);
+		}
+
+		er += share_info_ctr.num_entries;
+    
+	} while(er < total_entries);
+
+ done:
+	return result;
+}
+
+static NTSTATUS cmd_srvsvc_share_get_info(struct cli_state *cli, 
+					  TALLOC_CTX *mem_ctx,
+					  int argc, char **argv) 
+{
+	fstring netname;
+	SRV_SHARE_INFO share_info;
+  
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	if (argc > 3 || argc < 2) {
+		printf("Usage: %s [netname] [info_level 0,1,2,501,502,1005]\n", argv[0]);
+		return NT_STATUS_OK;
+	}
+
+	ZERO_STRUCT(share_info);
+
+	share_info.switch_value = 502;
+
+	fstrcpy(netname, argv[1]);
+
+	if(argc == 3)
+		share_info.switch_value = atoi(argv[2]);
+
+	result = cli_srvsvc_net_share_get_info(cli, 
+					       mem_ctx,
+					       cli->desthost,
+					       netname,
+					       &share_info
+		);
+  
+    
+	if (!NT_STATUS_IS_OK(result)) {
+		goto done;
+	}
+
+	switch(share_info.switch_value) {
+	case 0:
+		display_share_info_0(&share_info.share.info0);
+		break;
+	case 1:
+		display_share_info_1(&share_info.share.info1);
+		break;
+	case 2:
+		display_share_info_2(&share_info.share.info2);
+		break;
+	case 501:
+		display_share_info_501(&share_info.share.info501);
+		break;
+	case 502:
+		display_share_info_502(&share_info.share.info502);
+		break;
+	case 1004:
+		display_share_info_1004(&share_info.share.info1004);
+		break;
+	case 1005:
+		display_share_info_1005(&share_info.share.info1005);
+		break;
+	case 1006:
+		display_share_info_1006(&share_info.share.info1006);
+		break;
+	case 1007:
+		display_share_info_1007(&share_info.share.info1007);
+		break;
+	case 1501:
+		display_share_info_1501(&share_info.share.info1501);
+		break;
+	default:
+		printf("unknown share info type %d.\n", share_info.switch_value);
+	}
+
+ done:
+	return result;
+}
+
+static NTSTATUS cmd_srvsvc_share_set_info(struct cli_state *cli, 
+					  TALLOC_CTX *mem_ctx,
+					  int argc, char **argv) 
+{
+	fstring netname;
+
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	SRV_SHARE_INFO share_info;
+
+	uint32 parm_error = 0;
+
+	ZERO_STRUCT(share_info);
+
+	if(!parse_share_share_info_from_args(&share_info, netname, mem_ctx, argc-1, argv+1)) {
+    
+		printf("Usage: %s [netname] [info_level 1,2,502,1004,1006,1501]\n", argv[0]);
+		return NT_STATUS_OK;
+	}
+
+	result = cli_srvsvc_net_share_set_info(cli, 
+					       mem_ctx,
+					       cli->desthost,
+					       netname,
+					       &share_info,
+					       &parm_error
+		);
+  
+    
+	if (!NT_STATUS_IS_OK(result)) {
+		goto done;
+	}
+
+ done:
+	return result;
+}
+
+static NTSTATUS cmd_srvsvc_share_add(struct cli_state *cli, 
+				     TALLOC_CTX *mem_ctx,
+				     int argc, char **argv) 
+{
+	fstring netname;
+	SRV_SHARE_INFO share_info;
+	uint32 parm_error = 0;
+  
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	ZERO_STRUCT(share_info);
+
+	if(!parse_share_share_info_from_args(&share_info, netname, mem_ctx, argc-1, argv+1)) {
+    
+		printf("Usage: %s [netname] [info_level 2,502] [share info...]\n", argv[0]);
+		return NT_STATUS_OK;
+	}
+
+	result = cli_srvsvc_net_share_add(cli, 
+					  mem_ctx,
+					  cli->desthost,
+					  &share_info,
+					  &parm_error
+		);
+    
+	if (!NT_STATUS_IS_OK(result)) {
+		goto done;
+	}
+  
+ done:
+	return result;
+}
+
+static NTSTATUS cmd_srvsvc_share_del(struct cli_state *cli, 
+				     TALLOC_CTX *mem_ctx,
+				     int argc, char **argv) 
+{  
+	fstring netname;
+	SRV_SHARE_INFO share_info;
+  
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	if (argc != 2) {
+		printf("Usage: %s [netname]\n", argv[0]);
+		return NT_STATUS_OK;
+	}
+
+	fstrcpy(netname, argv[1]);
+
+	result = cli_srvsvc_net_share_del(cli, 
+					  mem_ctx,
+					  cli->desthost,
+					  netname
+		);
+    
+	if (!NT_STATUS_IS_OK(result)) {
+		goto done;
+	}
+  
+ done:
+	return result;
+}
+
+static NTSTATUS cmd_srvsvc_share_del_sticky(struct cli_state *cli, 
+					    TALLOC_CTX *mem_ctx,
+					    int argc, char **argv) 
+{  
+	fstring netname;
+	SRV_SHARE_INFO share_info;
+  
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	if (argc != 2) {
+		printf("Usage: %s [netname]\n", argv[0]);
+		return NT_STATUS_OK;
+	}
+
+	fstrcpy(netname, argv[1]);
+
+	result = cli_srvsvc_net_share_del_sticky(cli, 
+						 mem_ctx,
+						 cli->desthost,
+						 netname
+		);
+    
+	if (!NT_STATUS_IS_OK(result)) {
+		goto done;
+	}
+
+	/* do something */
+  
+ done:
+	return result;
+}
+
 /* List of commands exported by this module */
 
 struct cmd_set srvsvc_commands[] = {
 
 	{ "SRVSVC" },
 
-	{ "srvinfo",    cmd_srvsvc_srv_query_info,  PIPE_SRVSVC, "Server query info", "" },
+	{ "srvinfo",     cmd_srvsvc_srv_query_info,   PIPE_SRVSVC, "Server query info",        "" },
+	{ "srvdskenum",  cmd_srvsvc_srv_disk_enum,    PIPE_SRVSVC, "Server disk enum",         "" },
+	{ "namevalidate",cmd_srvsvc_name_validate,    PIPE_SRVSVC, "Name validate",            "" },
+	{ "shareenum",   cmd_srvsvc_share_enum,       PIPE_SRVSVC, "Enumerate shares",         "" },
+	{ "shareenums",  cmd_srvsvc_share_enum_sticky,PIPE_SRVSVC, "Enumerate shares (sticky)","" },
+	{ "sharegetinfo",cmd_srvsvc_share_get_info,   PIPE_SRVSVC, "Get share info",           "" },
+	{ "sharesetinfo",cmd_srvsvc_share_set_info,   PIPE_SRVSVC, "Set share info",           "" },
+	{ "shareadd",    cmd_srvsvc_share_add,        PIPE_SRVSVC, "Add share",                "" },
+	{ "sharedel",    cmd_srvsvc_share_del,        PIPE_SRVSVC, "Delete share",             "" },
+	{ "sharedels",   cmd_srvsvc_share_del_sticky, PIPE_SRVSVC, "Delete share (sticky)",    "" },
 
 	{ NULL }
 };
Index: rpcclient/rpcclient.c
===================================================================
RCS file: /cvsroot/samba/source/rpcclient/rpcclient.c,v
retrieving revision 1.172
diff -u -r1.172 rpcclient.c
--- rpcclient/rpcclient.c	6 Jan 2002 03:24:51 -0000	1.172
+++ rpcclient/rpcclient.c	22 Jan 2002 01:22:55 -0000
@@ -386,6 +386,169 @@
 	DLIST_ADD(cmd_list, entry);
 }
 
+static BOOL parse_command_line(const char *cmd, int *argc, char ***argv) {
+
+	BOOL ret = True;
+	BOOL in,esc,q;
+
+	int c;
+	const char *p;
+
+	int argl = 0;
+	char *arg = NULL, *narg = NULL, *s = NULL;
+
+#undef RESIZEARG
+#define RESIZEARG      ((argl = (argl == 0)?sizeof(pstring):argl*2), \
+                        (s -= (uint32)arg), \
+                        (arg = (narg = realloc(arg, argl))?narg:arg), \
+                        (s += (uint32)arg), \
+                        narg)
+#undef NEXTARGCHAR
+#define NEXTARGCHAR(C) (((s - arg == argl)?RESIZEARG:arg)?(*s++ = (C), True):False)
+
+	*argc = 0;
+	*argv = NULL;
+
+	while(True) {
+
+		in = esc = q = False;
+
+		p = cmd;
+
+		while((c = *p++)) {
+
+			if(in && !esc && (c == '"' || (isspace(c) && !q))) {
+
+				/* terminate token on unquoted space or quote */
+
+				if(!(ret = NEXTARGCHAR(0)))
+					break;
+
+				if(*argv)
+					(*argv)[*argc] = strdup(arg);
+
+				(*argc)++;
+
+				*arg = 0;
+
+				in = False;
+
+				if(q && c == '"') {/* don't store the closing quote of a quoted token */
+					q = False;
+					continue;
+				}
+			}
+
+			if(!in) {
+
+				if(isspace(c))
+					continue;
+
+				/* start a new token */
+
+				in = True; 
+
+				s = arg;
+
+				if(c == '"') {
+
+					/* discard the initial quote of a quoted token */
+
+					q = True;
+					continue;
+				}
+			}
+
+			if(!esc) {
+
+				/* check for the escape character */
+
+				if(c == '\\') {
+					esc = True;
+					continue;
+				}
+
+			} else {
+
+				/* allow a set of escape characters */
+
+				switch(c) {
+
+				case '\\':
+					c = '\\';
+					break;
+				case '"':
+					c = '"';
+					break;
+				case 'n':
+					c = '\n';
+					break;
+				case 'r':
+					c = '\r';
+				case 't':
+					c = '\t';
+					break;
+				case 's':
+					c = ' ';
+					break;
+				default:
+					*s++ = '\\';
+				}
+
+				esc = False;
+			}
+
+			if(!(ret = NEXTARGCHAR(c)))
+				break;
+		}
+
+		if(!ret)
+			break;
+
+		/* add a trailing escape character ? */
+
+		if(esc && !(ret = NEXTARGCHAR('\\')))
+			break;
+
+		if(!(ret = NEXTARGCHAR(0)))
+			break;
+
+		if(*arg) {  /* this will lose a trailing quote */
+
+			/* a token was terminated by eol */
+
+			if(*argv)
+				(*argv)[*argc] = strdup(arg);
+
+			(*argc)++;
+
+			*arg = 0;
+		}
+    
+		if(*argv)
+			break;
+
+		if(*argc)
+			*argv = (char **)malloc(*argc * sizeof(**argv));
+
+		*argc = 0;
+	}
+
+	SAFE_FREE(arg);
+
+	if(!ret && *argv) {
+
+		while((*argc)--)
+			SAFE_FREE((*argv)[*argc]);
+
+		SAFE_FREE(*argv);
+
+		*argv = NULL;
+	}
+
+	return ret;
+}
+
 static NTSTATUS do_cmd(struct cli_state *cli, struct cmd_set *cmd_entry, 
                        char *cmd)
 {
@@ -394,9 +557,9 @@
 	pstring buf;
 	int argc = 0, i;
 
+#if 0
 	/* Count number of arguments first time through the loop then
 	   allocate memory and strdup them. */
-
  again:
 	while(next_token(&p, buf, " ", sizeof(buf))) {
 		if (argv) {
@@ -424,7 +587,28 @@
 					
 		goto again;
 	}
+#else
+
+	/* hopefully using this won't break any existing code */
+
+	if(!parse_command_line(cmd, &argc, &argv)) {
+
+	  goto done;
+	}
+
+	{
+	  int i;
+	  DEBUG(4, ("command <%s> => (%d) ", cmd, argc));
 
+	  for(i = 0; i < argc; i++) {
+
+	    DEBUG(4, ("<%s>", argv[i]));
+	  }
+
+	  DEBUG(4, (".\n"));
+	}
+
+#endif
 	/* Call the function */
 
 	if (cmd_entry->fn) {
@@ -467,8 +651,8 @@
 	/* Cleanup */
 
         if (argv) {
-                for (i = 0; i < argc; i++)
-                        SAFE_FREE(argv[i]);
+	  while(argc--)
+	    SAFE_FREE(argv[argc]);
 	
                 SAFE_FREE(argv);
         }
@@ -543,6 +727,8 @@
 	printf("\t-s configfile         specify an alternative config file\n");
 	printf("\t-U username           set the network username\n");
 	printf("\t-W domain             set the domain name for user account\n");
+	printf("\t-D DC                 set a DC for non-local lsa lookups\n");
+	printf("\t-n                    set for numeric acl representation\n");
 	printf("\n");
 }
 
@@ -572,7 +758,7 @@
 
 	DEBUGLEVEL = 1;
 
-	while ((opt = getopt(argc, argv, "A:s:Nd:U:W:c:l:h")) != EOF) {
+	while ((opt = getopt(argc, argv, "A:s:Nd:U:W:c:l:D:nh")) != EOF) {
 		switch (opt) {
 		case 'A':
 			/* only get the username, password, and domain from the file */
@@ -618,6 +804,13 @@
 		case 'W':
 			pstrcpy(domain, optarg);
 			break;
+
+		case 'D':
+			smbcacl_lib_DC_set(optarg);
+			break;
+		case 'n':
+			smbcacl_lib_numeric_set(1);
+			break;
 			
 		case 'h':
 		default:
@@ -639,6 +832,10 @@
 		argv[0] += 2;
 
 	pstrcpy(server, argv[0]);
+
+	/* tell acl lib where to go for local name translations */
+
+	smbcacl_lib_server_set(server);
 
 	/* the following functions are part of the Samba debugging
 	   facilities.  See lib/debug.c */


More information about the samba-technical mailing list