summaryrefslogtreecommitdiff
path: root/source3/utils
diff options
context:
space:
mode:
Diffstat (limited to 'source3/utils')
-rw-r--r--source3/utils/editreg.c2056
-rw-r--r--source3/utils/net.c23
-rw-r--r--source3/utils/net_ads.c11
-rw-r--r--source3/utils/net_help.c5
-rw-r--r--source3/utils/net_rpc.c8
-rw-r--r--source3/utils/net_rpc_samsync.c2
-rw-r--r--source3/utils/nmblookup.c224
-rw-r--r--source3/utils/ntlm_auth.c3
-rw-r--r--source3/utils/pdbedit.c9
-rw-r--r--source3/utils/profiles.c126
-rw-r--r--source3/utils/smbcacls.c166
-rw-r--r--source3/utils/smbcontrol.c1121
-rw-r--r--source3/utils/smbtree.c191
-rw-r--r--source3/utils/status.c6
-rw-r--r--source3/utils/testparm.c17
15 files changed, 1059 insertions, 2909 deletions
diff --git a/source3/utils/editreg.c b/source3/utils/editreg.c
deleted file mode 100644
index 6b3b4516bb..0000000000
--- a/source3/utils/editreg.c
+++ /dev/null
@@ -1,2056 +0,0 @@
-/*
- Samba Unix/Linux SMB client utility editreg.c
- Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com
- Copyright (C) 2003 Jelmer Vernooij (conversion to popt)
-
- 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/*************************************************************************
-
- A utility to edit a Windows NT/2K etc registry file.
-
- Many of the ideas in here come from other people and software.
- I first looked in Wine in misc/registry.c and was also influenced by
- http://www.wednesday.demon.co.uk/dosreg.html
-
- Which seems to contain comments from someone else. I reproduce them here
- incase the site above disappears. It actually comes from
- http://home.eunet.no/~pnordahl/ntpasswd/WinReg.txt.
-
- The goal here is to read the registry into memory, manipulate it, and then
- write it out if it was changed by any actions of the user.
-
-The windows NT registry has 2 different blocks, where one can occur many
-times...
-
-the "regf"-Block
-================
-
-"regf" is obviosly the abbreviation for "Registry file". "regf" is the
-signature of the header-block which is always 4kb in size, although only
-the first 64 bytes seem to be used and a checksum is calculated over
-the first 0x200 bytes only!
-
-Offset Size Contents
-0x00000000 D-Word ID: ASCII-"regf" = 0x66676572
-0x00000004 D-Word ???? //see struct REGF
-0x00000008 D-Word ???? Always the same value as at 0x00000004
-0x0000000C Q-Word last modify date in WinNT date-format
-0x00000014 D-Word 1
-0x00000018 D-Word 3
-0x0000001C D-Word 0
-0x00000020 D-Word 1
-0x00000024 D-Word Offset of 1st key record
-0x00000028 D-Word Size of the data-blocks (Filesize-4kb)
-0x0000002C D-Word 1
-0x000001FC D-Word Sum of all D-Words from 0x00000000 to
-0x000001FB //XOR of all words. Nigel
-
-I have analyzed more registry files (from multiple machines running
-NT 4.0 german version) and could not find an explanation for the values
-marked with ???? the rest of the first 4kb page is not important...
-
-the "hbin"-Block
-================
-I don't know what "hbin" stands for, but this block is always a multiple
-of 4kb in size.
-
-Inside these hbin-blocks the different records are placed. The memory-
-management looks like a C-compiler heap management to me...
-
-hbin-Header
-===========
-Offset Size Contents
-0x0000 D-Word ID: ASCII-"hbin" = 0x6E696268
-0x0004 D-Word Offset from the 1st hbin-Block
-0x0008 D-Word Offset to the next hbin-Block
-0x001C D-Word Block-size
-
-The values in 0x0008 and 0x001C should be the same, so I don't know
-if they are correct or swapped...
-
-From offset 0x0020 inside a hbin-block data is stored with the following
-format:
-
-Offset Size Contents
-0x0000 D-Word Data-block size //this size must be a
-multiple of 8. Nigel
-0x0004 ???? Data
-
-If the size field is negative (bit 31 set), the corresponding block
-is free and has a size of -blocksize!
-
-That does not seem to be true. All block lengths seem to be negative! (Richard Sharpe)
-
-The data is stored as one record per block. Block size is a multiple
-of 4 and the last block reaches the next hbin-block, leaving no room.
-
-Records in the hbin-blocks
-==========================
-
-nk-Record
-
- The nk-record can be treated as a kombination of tree-record and
- key-record of the win 95 registry.
-
-lf-Record
-
- The lf-record is the counterpart to the RGKN-record (the
- hash-function)
-
-vk-Record
-
- The vk-record consists information to a single value.
-
-sk-Record
-
- sk (? Security Key ?) is the ACL of the registry.
-
-Value-Lists
-
- The value-lists contain information about which values are inside a
- sub-key and don't have a header.
-
-Datas
-
- The datas of the registry are (like the value-list) stored without a
- header.
-
-All offset-values are relative to the first hbin-block and point to the
-block-size field of the record-entry. to get the file offset, you have to add
-the header size (4kb) and the size field (4 bytes)...
-
-the nk-Record
-=============
-Offset Size Contents
-0x0000 Word ID: ASCII-"nk" = 0x6B6E
-0x0002 Word for the root-key: 0x2C, otherwise 0x20 //key symbolic links 0x10. Nigel
-0x0004 Q-Word write-date/time in windows nt notation
-0x0010 D-Word Offset of Owner/Parent key
-0x0014 D-Word number of sub-Keys
-0x001C D-Word Offset of the sub-key lf-Records
-0x0024 D-Word number of values
-0x0028 D-Word Offset of the Value-List
-0x002C D-Word Offset of the sk-Record
-
-0x0030 D-Word Offset of the Class-Name //see NK structure for the use of these fields. Nigel
-0x0044 D-Word Unused (data-trash) //some kind of run time index. Does not appear to be important. Nigel
-0x0048 Word name-length
-0x004A Word class-name length
-0x004C ???? key-name
-
-the Value-List
-==============
-Offset Size Contents
-0x0000 D-Word Offset 1st Value
-0x0004 D-Word Offset 2nd Value
-0x???? D-Word Offset nth Value
-
-To determine the number of values, you have to look at the owner-nk-record!
-
-Der vk-Record
-=============
-Offset Size Contents
-0x0000 Word ID: ASCII-"vk" = 0x6B76
-0x0002 Word name length
-0x0004 D-Word length of the data //if top bit is set when offset contains data. Nigel
-0x0008 D-Word Offset of Data
-0x000C D-Word Type of value
-0x0010 Word Flag
-0x0012 Word Unused (data-trash)
-0x0014 ???? Name
-
-If bit 0 of the flag-word is set, a name is present, otherwise the value has no name (=default)
-
-If the data-size is lower 5, the data-offset value is used to store the data itself!
-
-The data-types
-==============
-Wert Beteutung
-0x0001 RegSZ: character string (in UNICODE!)
-0x0002 ExpandSZ: string with "%var%" expanding (UNICODE!)
-0x0003 RegBin: raw-binary value
-0x0004 RegDWord: Dword
-0x0007 RegMultiSZ: multiple strings, seperated with 0
- (UNICODE!)
-
-The "lf"-record
-===============
-Offset Size Contents
-0x0000 Word ID: ASCII-"lf" = 0x666C
-0x0002 Word number of keys
-0x0004 ???? Hash-Records
-
-Hash-Record
-===========
-Offset Size Contents
-0x0000 D-Word Offset of corresponding "nk"-Record
-0x0004 D-Word ASCII: the first 4 characters of the key-name, padded with 0's. Case sensitiv!
-
-Keep in mind, that the value at 0x0004 is used for checking the data-consistency! If you change the
-key-name you have to change the hash-value too!
-
-//These hashrecords must be sorted low to high within the lf record. Nigel.
-
-The "sk"-block
-==============
-(due to the complexity of the SAM-info, not clear jet)
-(This is just a security descriptor in the data. R Sharpe.)
-
-
-Offset Size Contents
-0x0000 Word ID: ASCII-"sk" = 0x6B73
-0x0002 Word Unused
-0x0004 D-Word Offset of previous "sk"-Record
-0x0008 D-Word Offset of next "sk"-Record
-0x000C D-Word usage-counter
-0x0010 D-Word Size of "sk"-record in bytes
-???? //standard self
-relative security desciptor. Nigel
-???? ???? Security and auditing settings...
-????
-
-The usage counter counts the number of references to this
-"sk"-record. You can use one "sk"-record for the entire registry!
-
-Windows nt date/time format
-===========================
-The time-format is a 64-bit integer which is incremented every
-0,0000001 seconds by 1 (I don't know how accurate it realy is!)
-It starts with 0 at the 1st of january 1601 0:00! All values are
-stored in GMT time! The time-zone is important to get the real
-time!
-
-Common values for win95 and win-nt
-==================================
-Offset values marking an "end of list", are either 0 or -1 (0xFFFFFFFF).
-If a value has no name (length=0, flag(bit 0)=0), it is treated as the
-"Default" entry...
-If a value has no data (length=0), it is displayed as empty.
-
-simplyfied win-3.?? registry:
-=============================
-
-+-----------+
-| next rec. |---+ +----->+------------+
-| first sub | | | | Usage cnt. |
-| name | | +-->+------------+ | | length |
-| value | | | | next rec. | | | text |------->+-------+
-+-----------+ | | | name rec. |--+ +------------+ | xxxxx |
- +------------+ | | value rec. |-------->+------------+ +-------+
- v | +------------+ | Usage cnt. |
-+-----------+ | | length |
-| next rec. | | | text |------->+-------+
-| first sub |------+ +------------+ | xxxxx |
-| name | +-------+
-| value |
-+-----------+
-
-Greatly simplyfied structure of the nt-registry:
-================================================
-
-+---------------------------------------------------------------+
-| |
-v |
-+---------+ +---------->+-----------+ +----->+---------+ |
-| "nk" | | | lf-rec. | | | nk-rec. | |
-| ID | | | # of keys | | | parent |---+
-| Date | | | 1st key |--+ | .... |
-| parent | | +-----------+ +---------+
-| suk-keys|-----+
-| values |--------------------->+----------+
-| SK-rec. |---------------+ | 1. value |--> +----------+
-| class |--+ | +----------+ | vk-rec. |
-+---------+ | | | .... |
- v | | data |--> +-------+
- +------------+ | +----------+ | xxxxx |
- | Class name | | +-------+
- +------------+ |
- v
- +---------+ +---------+
- +----->| next sk |--->| Next sk |--+
- | +---| prev sk |<---| prev sk | |
- | | | .... | | ... | |
- | | +---------+ +---------+ |
- | | ^ |
- | | | |
- | +--------------------+ |
- +----------------------------------+
-
----------------------------------------------------------------------------
-
-Hope this helps.... (Although it was "fun" for me to uncover this things,
- it took me several sleepless nights ;)
-
- B.D.
-
-*************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <fcntl.h>
-#include "popt.h"
-
-static int verbose = 0;
-
-/*
- * These definitions are for the in-memory registry structure.
- * It is a tree structure that mimics what you see with tools like regedit
- */
-
-/*
- * DateTime struct for Windows
- */
-
-typedef struct date_time_s {
- unsigned int low, high;
-} NTTIME;
-
-/*
- * Definition of a Key. It has a name, classname, date/time last modified,
- * sub-keys, values, and a security descriptor
- */
-
-#define REG_ROOT_KEY 1
-#define REG_SUB_KEY 2
-#define REG_SYM_LINK 3
-
-typedef struct reg_key_s {
- char *name; /* Name of the key */
- char *class_name;
- int type; /* One of REG_ROOT_KEY or REG_SUB_KEY */
- NTTIME last_mod; /* Time last modified */
- struct reg_key_s *owner;
- struct key_list_s *sub_keys;
- struct val_list_s *values;
- struct key_sec_desc_s *security;
-} REG_KEY;
-
-/*
- * The KEY_LIST struct lists sub-keys.
- */
-
-typedef struct key_list_s {
- int key_count;
- REG_KEY *keys[1];
-} KEY_LIST;
-
-typedef struct val_key_s {
- char *name;
- int has_name;
- int data_type;
- int data_len;
- void *data_blk; /* Might want a separate block */
-} VAL_KEY;
-
-typedef struct val_list_s {
- int val_count;
- VAL_KEY *vals[1];
-} VAL_LIST;
-
-#ifndef MAXSUBAUTHS
-#define MAXSUBAUTHS 15
-#endif
-
-typedef struct dom_sid_s {
- unsigned char ver, auths;
- unsigned char auth[6];
- unsigned int sub_auths[MAXSUBAUTHS];
-} DOM_SID;
-
-typedef struct ace_struct_s {
- unsigned char type, flags;
- unsigned int perms; /* Perhaps a better def is in order */
- DOM_SID *trustee;
-} ACE;
-
-typedef struct acl_struct_s {
- unsigned short rev, refcnt;
- unsigned short num_aces;
- ACE *aces[1];
-} ACL;
-
-typedef struct sec_desc_s {
- unsigned int rev, type;
- DOM_SID *owner, *group;
- ACL *sacl, *dacl;
-} SEC_DESC;
-
-#define SEC_DESC_NON 0
-#define SEC_DESC_RES 1
-#define SEC_DESC_OCU 2
-
-typedef struct key_sec_desc_s {
- struct key_sec_desc_s *prev, *next;
- int ref_cnt;
- int state;
- SEC_DESC *sec_desc;
-} KEY_SEC_DESC;
-
-
-/*
- * An API for accessing/creating/destroying items above
- */
-
-/*
- * Iterate over the keys, depth first, calling a function for each key
- * and indicating if it is terminal or non-terminal and if it has values.
- *
- * In addition, for each value in the list, call a value list function
- */
-
-/*
- * There should eventually be one to deal with security keys as well
- */
-
-typedef int (*key_print_f)(const char *path, char *key_name, char *class_name,
- int root, int terminal, int values);
-
-typedef int (*val_print_f)(const char *path, char *val_name, int val_type,
- int data_len, void *data_blk, int terminal,
- int first, int last);
-
-typedef int (*sec_print_f)(SEC_DESC *sec_desc);
-
-typedef struct regf_struct_s REGF;
-
-int nt_key_iterator(REGF *regf, REG_KEY *key_tree, int bf, const char *path,
- key_print_f key_print, sec_print_f sec_print,
- val_print_f val_print);
-
-int nt_val_list_iterator(REGF *regf, VAL_LIST *val_list, int bf, char *path,
- int terminal, val_print_f val_print)
-{
- int i;
-
- if (!val_list) return 1;
-
- if (!val_print) return 1;
-
- for (i=0; i<val_list->val_count; i++) {
- if (!val_print(path, val_list->vals[i]->name, val_list->vals[i]->data_type,
- val_list->vals[i]->data_len, val_list->vals[i]->data_blk,
- terminal,
- (i == 0),
- (i == val_list->val_count))) {
-
- return 0;
-
- }
- }
-
- return 1;
-}
-
-int nt_key_list_iterator(REGF *regf, KEY_LIST *key_list, int bf,
- const char *path,
- key_print_f key_print, sec_print_f sec_print,
- val_print_f val_print)
-{
- int i;
-
- if (!key_list) return 1;
-
- for (i=0; i< key_list->key_count; i++) {
- if (!nt_key_iterator(regf, key_list->keys[i], bf, path, key_print,
- sec_print, val_print)) {
- return 0;
- }
- }
- return 1;
-}
-
-int nt_key_iterator(REGF *regf, REG_KEY *key_tree, int bf, const char *path,
- key_print_f key_print, sec_print_f sec_print,
- val_print_f val_print)
-{
- int path_len = strlen(path);
- char *new_path;
-
- if (!regf || !key_tree)
- return -1;
-
- /* List the key first, then the values, then the sub-keys */
-
- if (key_print) {
-
- if (!(*key_print)(path, key_tree->name,
- key_tree->class_name,
- (key_tree->type == REG_ROOT_KEY),
- (key_tree->sub_keys == NULL),
- (key_tree->values?(key_tree->values->val_count):0)))
- return 0;
- }
-
- /*
- * If we have a security print routine, call it
- * If the security print routine returns false, stop.
- */
- if (sec_print) {
- if (key_tree->security && !(*sec_print)(key_tree->security->sec_desc))
- return 0;
- }
-
- new_path = (char *)malloc(path_len + 1 + strlen(key_tree->name) + 1);
- if (!new_path) return 0; /* Errors? */
- new_path[0] = '\0';
- strcat(new_path, path);
- strcat(new_path, "\\");
- strcat(new_path, key_tree->name);
-
- /*
- * Now, iterate through the values in the val_list
- */
-
- if (key_tree->values &&
- !nt_val_list_iterator(regf, key_tree->values, bf, new_path,
- (key_tree->values!=NULL),
- val_print)) {
-
- free(new_path);
- return 0;
- }
-
- /*
- * Now, iterate through the keys in the key list
- */
-
- if (key_tree->sub_keys &&
- !nt_key_list_iterator(regf, key_tree->sub_keys, bf, new_path, key_print,
- sec_print, val_print)) {
- free(new_path);
- return 0;
- }
-
- free(new_path);
- return 1;
-}
-
-/* Make, delete keys */
-
-int nt_delete_val_key(VAL_KEY *val_key)
-{
-
- if (val_key) {
- if (val_key->data_blk) free(val_key->data_blk);
- free(val_key);
- };
- return 1;
-}
-
-int nt_delete_val_list(VAL_LIST *vl)
-{
- int i;
-
- if (vl) {
- for (i=0; i<vl->val_count; i++)
- nt_delete_val_key(vl->vals[i]);
- free(vl);
- }
- return 1;
-}
-
-int nt_delete_reg_key(REG_KEY *key);
-int nt_delete_key_list(KEY_LIST *key_list)
-{
- int i;
-
- if (key_list) {
- for (i=0; i<key_list->key_count; i++)
- nt_delete_reg_key(key_list->keys[i]);
- free(key_list);
- }
- return 1;
-}
-
-int nt_delete_sid(DOM_SID *sid)
-{
-
- if (sid) free(sid);
- return 1;
-
-}
-
-int nt_delete_ace(ACE *ace)
-{
-
- if (ace) {
- nt_delete_sid(ace->trustee);
- free(ace);
- }
- return 1;
-
-}
-
-int nt_delete_acl(ACL *acl)
-{
-
- if (acl) {
- int i;
-
- for (i=0; i<acl->num_aces; i++)
- nt_delete_ace(acl->aces[i]);
-
- free(acl);
- }
- return 1;
-}
-
-int nt_delete_sec_desc(SEC_DESC *sec_desc)
-{
-
- if (sec_desc) {
-
- nt_delete_sid(sec_desc->owner);
- nt_delete_sid(sec_desc->group);
- nt_delete_acl(sec_desc->sacl);
- nt_delete_acl(sec_desc->dacl);
- free(sec_desc);
-
- }
- return 1;
-}
-
-int nt_delete_key_sec_desc(KEY_SEC_DESC *key_sec_desc)
-{
-
- if (key_sec_desc) {
- key_sec_desc->ref_cnt--;
- if (key_sec_desc->ref_cnt<=0) {
- /*
- * There should always be a next and prev, even if they point to us
- */
- key_sec_desc->next->prev = key_sec_desc->prev;
- key_sec_desc->prev->next = key_sec_desc->next;
- nt_delete_sec_desc(key_sec_desc->sec_desc);
- }
- }
- return 1;
-}
-
-int nt_delete_reg_key(REG_KEY *key)
-{
-
- if (key) {
- if (key->name) free(key->name);
- if (key->class_name) free(key->class_name);
-
- /*
- * Do not delete the owner ...
- */
-
- if (key->sub_keys) nt_delete_key_list(key->sub_keys);
- if (key->values) nt_delete_val_list(key->values);
- if (key->security) nt_delete_key_sec_desc(key->security);
- free(key);
- }
- return 1;
-}
-
-/*
- * Create/delete key lists and add delete keys to/from a list, count the keys
- */
-
-
-/*
- * Create/delete value lists, add/delete values, count them
- */
-
-
-/*
- * Create/delete security descriptors, add/delete SIDS, count SIDS, etc.
- * We reference count the security descriptors. Any new reference increments
- * the ref count. If we modify an SD, we copy the old one, dec the ref count
- * and make the change. We also want to be able to check for equality so
- * we can reduce the number of SDs in use.
- */
-
-/*
- * Code to parse registry specification from command line or files
- *
- * Format:
- * [cmd:]key:type:value
- *
- * cmd = a|d|c|add|delete|change|as|ds|cs
- *
- */
-
-
-/*
- * Load and unload a registry file.
- *
- * Load, loads it into memory as a tree, while unload sealizes/flattens it
- */
-
-/*
- * Get the starting record for NT Registry file
- */
-
-/* A map of sk offsets in the regf to KEY_SEC_DESCs for quick lookup etc */
-typedef struct sk_map_s {
- int sk_off;
- KEY_SEC_DESC *key_sec_desc;
-} SK_MAP;
-
-/*
- * Where we keep all the regf stuff for one registry.
- * This is the structure that we use to tie the in memory tree etc
- * together. By keeping separate structs, we can operate on different
- * registries at the same time.
- * Currently, the SK_MAP is an array of mapping structure.
- * Since we only need this on input and output, we fill in the structure
- * as we go on input. On output, we know how many SK items we have, so
- * we can allocate the structure as we need to.
- * If you add stuff here that is dynamically allocated, add the
- * appropriate free statements below.
- */
-
-#define REGF_REGTYPE_NONE 0
-#define REGF_REGTYPE_NT 1
-#define REGF_REGTYPE_W9X 2
-
-#define TTTONTTIME(r, t1, t2) (r)->last_mod_time.low = (t1); \
- (r)->last_mod_time.high = (t2);
-
-#define REGF_HDR_BLKSIZ 0x1000
-
-struct regf_struct_s {
- int reg_type;
- char *regfile_name, *outfile_name;
- int fd;
- struct stat sbuf;
- char *base;
- int modified;
- NTTIME last_mod_time;
- REG_KEY *root; /* Root of the tree for this file */
- int sk_count, sk_map_size;
- SK_MAP *sk_map;
-};
-
-/*
- * Structures for dealing with the on-disk format of the registry
- */
-
-#define IVAL(buf) ((unsigned int) \
- (unsigned int)*((unsigned char *)(buf)+3)<<24| \
- (unsigned int)*((unsigned char *)(buf)+2)<<16| \
- (unsigned int)*((unsigned char *)(buf)+1)<<8| \
- (unsigned int)*((unsigned char *)(buf)+0))
-
-#define SVAL(buf) ((unsigned short) \
- (unsigned short)*((unsigned char *)(buf)+1)<<8| \
- (unsigned short)*((unsigned char *)(buf)+0))
-
-#define CVAL(buf) ((unsigned char)*((unsigned char *)(buf)))
-
-#define OFF(f) ((f) + REGF_HDR_BLKSIZ + 4)
-#define LOCN(base, f) ((base) + OFF(f))
-
-/*
- * All of the structures below actually have a four-byte lenght before them
- * which always seems to be negative. The following macro retrieves that
- * size as an integer
- */
-
-#define BLK_SIZE(b) ((int)*(int *)(((int *)b)-1))
-
-typedef unsigned int DWORD;
-typedef unsigned short WORD;
-
-#define REG_REGF_ID 0x66676572
-
-typedef struct regf_block {
- DWORD REGF_ID; /* regf */
- DWORD uk1;
- DWORD uk2;
- DWORD tim1, tim2;
- DWORD uk3; /* 1 */
- DWORD uk4; /* 3 */
- DWORD uk5; /* 0 */
- DWORD uk6; /* 1 */
- DWORD first_key; /* offset */
- unsigned int dblk_size;
- DWORD uk7[116]; /* 1 */
- DWORD chksum;
-} REGF_HDR;
-
-typedef struct hbin_sub_struct {
- DWORD dblocksize;
- char data[1];
-} HBIN_SUB_HDR;
-
-#define REG_HBIN_ID 0x6E696268
-
-typedef struct hbin_struct {
- DWORD HBIN_ID; /* hbin */
- DWORD next_off;
- DWORD prev_off;
- DWORD uk1;
- DWORD uk2;
- DWORD uk3;
- DWORD uk4;
- DWORD blk_size;
- HBIN_SUB_HDR hbin_sub_hdr;
-} HBIN_HDR;
-
-#define REG_NK_ID 0x6B6E
-
-typedef struct nk_struct {
- WORD NK_ID;
- WORD type;
- DWORD t1, t2;
- DWORD uk1;
- DWORD own_off;
- DWORD subk_num;
- DWORD uk2;
- DWORD lf_off;
- DWORD uk3;
- DWORD val_cnt;
- DWORD val_off;
- DWORD sk_off;
- DWORD clsnam_off;
- DWORD unk4[4];
- DWORD unk5;
- WORD nam_len;
- WORD clsnam_len;
- char key_nam[1]; /* Actual length determined by nam_len */
-} NK_HDR;
-
-#define REG_SK_ID 0x6B73
-
-typedef struct sk_struct {
- WORD SK_ID;
- WORD uk1;
- DWORD prev_off;
- DWORD next_off;
- DWORD ref_cnt;
- DWORD rec_size;
- char sec_desc[1];
-} SK_HDR;
-
-typedef struct ace_struct {
- unsigned char type;
- unsigned char flags;
- unsigned short length;
- unsigned int perms;
- DOM_SID trustee;
-} REG_ACE;
-
-typedef struct acl_struct {
- WORD rev;
- WORD size;
- DWORD num_aces;
- REG_ACE *aces; /* One or more ACEs */
-} REG_ACL;
-
-typedef struct sec_desc_rec {
- WORD rev;
- WORD type;
- DWORD owner_off;
- DWORD group_off;
- DWORD sacl_off;
- DWORD dacl_off;
-} REG_SEC_DESC;
-
-typedef struct hash_struct {
- DWORD nk_off;
- char hash[4];
-} HASH_REC;
-
-#define REG_LF_ID 0x666C
-
-typedef struct lf_struct {
- WORD LF_ID;
- WORD key_count;
- struct hash_struct hr[1]; /* Array of hash records, depending on key_count */
-} LF_HDR;
-
-typedef DWORD VL_TYPE[1]; /* Value list is an array of vk rec offsets */
-
-#define REG_VK_ID 0x6B76
-
-typedef struct vk_struct {
- WORD VK_ID;
- WORD nam_len;
- DWORD dat_len; /* If top-bit set, offset contains the data */
- DWORD dat_off;
- DWORD dat_type;
- WORD flag; /* =1, has name, else no name (=Default). */
- WORD unk1;
- char dat_name[1]; /* Name starts here ... */
-} VK_HDR;
-
-#define REG_TYPE_REGSZ 1
-#define REG_TYPE_EXPANDSZ 2
-#define REG_TYPE_BIN 3
-#define REG_TYPE_DWORD 4
-#define REG_TYPE_MULTISZ 7
-
-typedef struct _val_str {
- unsigned int val;
- const char * str;
-} VAL_STR;
-
-const VAL_STR reg_type_names[] = {
- { 1, "REG_SZ" },
- { 2, "REG_EXPAND_SZ" },
- { 3, "REG_BIN" },
- { 4, "REG_DWORD" },
- { 7, "REG_MULTI_SZ" },
- { 0, NULL },
-};
-
-const char *val_to_str(unsigned int val, const VAL_STR *val_array)
-{
- int i = 0;
-
- if (!val_array) return NULL;
-
- while (val_array[i].val && val_array[i].str) {
-
- if (val_array[i].val == val) return val_array[i].str;
- i++;
-
- }
-
- return NULL;
-
-}
-
-/*
- * Convert from UniCode to Ascii ... Does not take into account other lang
- * Restrict by ascii_max if > 0
- */
-int uni_to_ascii(unsigned char *uni, unsigned char *ascii, int ascii_max,
- int uni_max)
-{
- int i = 0;
-
- while (i < ascii_max && !(!uni[i*2] && !uni[i*2+1])) {
- if (uni_max > 0 && (i*2) >= uni_max) break;
- ascii[i] = uni[i*2];
- i++;
-
- }
-
- ascii[i] = '\0';
-
- return i;
-}
-
-/*
- * Convert a data value to a string for display
- */
-int data_to_ascii(unsigned char *datap, int len, int type, char *ascii, int ascii_max)
-{
- unsigned char *asciip;
- int i;
-
- switch (type) {
- case REG_TYPE_REGSZ:
- fprintf(stderr, "Len: %d\n", len);
- return uni_to_ascii(datap, ascii, len, ascii_max);
- break;
-
- case REG_TYPE_EXPANDSZ:
- return uni_to_ascii(datap, ascii, len, ascii_max);
- break;
-
- case REG_TYPE_BIN:
- asciip = ascii;
- for (i=0; (i<len)&&(i+1)*3<ascii_max; i++) {
- int str_rem = ascii_max - ((int)asciip - (int)ascii);
- asciip += snprintf(asciip, str_rem, "%02x", *(unsigned char *)(datap+i));
- if (i < len && str_rem > 0)
- *asciip = ' '; asciip++;
- }
- *asciip = '\0';
- return ((int)asciip - (int)ascii);
- break;
-
- case REG_TYPE_DWORD:
- if (*(int *)datap == 0)
- return snprintf(ascii, ascii_max, "0");
- else
- return snprintf(ascii, ascii_max, "0x%x", *(int *)datap);
- break;
-
- case REG_TYPE_MULTISZ:
-
- break;
-
- default:
- return 0;
- break;
- }
-
- return len;
-
-}
-
-REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size);
-
-int nt_set_regf_input_file(REGF *regf, char *filename)
-{
- return ((regf->regfile_name = strdup(filename)) != NULL);
-}
-
-int nt_set_regf_output_file(REGF *regf, char *filename)
-{
- return ((regf->outfile_name = strdup(filename)) != NULL);
-}
-
-/* Create a regf structure and init it */
-
-REGF *nt_create_regf(void)
-{
- REGF *tmp = (REGF *)malloc(sizeof(REGF));
- if (!tmp) return tmp;
- bzero(tmp, sizeof(REGF));
- return tmp;
-}
-
-/* Free all the bits and pieces ... Assumes regf was malloc'd */
-/* If you add stuff to REGF, add the relevant free bits here */
-int nt_free_regf(REGF *regf)
-{
- if (!regf) return 0;
-
- if (regf->regfile_name) free(regf->regfile_name);
- if (regf->outfile_name) free(regf->outfile_name);
-
- /* Free the mmap'd area */
-
- if (regf->base) munmap(regf->base, regf->sbuf.st_size);
- regf->base = NULL;
- close(regf->fd); /* Ignore the error :-) */
-
- nt_delete_reg_key(regf->root); /* Free the tree */
- free(regf->sk_map);
- regf->sk_count = regf->sk_map_size = 0;
-
- free(regf);
-
- return 1;
-}
-
-/* Get the header of the registry. Return a pointer to the structure
- * If the mmap'd area has not been allocated, then mmap the input file
- */
-REGF_HDR *nt_get_regf_hdr(REGF *regf)
-{
- if (!regf)
- return NULL; /* What about errors */
-
- if (!regf->regfile_name)
- return NULL; /* What about errors */
-
- if (!regf->base) { /* Try to mmap etc the file */
-
- if ((regf->fd = open(regf->regfile_name, O_RDONLY, 0000)) <0) {
- return NULL; /* What about errors? */
- }
-
- if (fstat(regf->fd, &regf->sbuf) < 0) {
- return NULL;
- }
-
- regf->base = mmap(0, regf->sbuf.st_size, PROT_READ, MAP_SHARED, regf->fd, 0);
-
- if ((int)regf->base == 1) {
- fprintf(stderr, "Could not mmap file: %s, %s\n", regf->regfile_name,
- strerror(errno));
- return NULL;
- }
- }
-
- /*
- * At this point, regf->base != NULL, and we should be able to read the
- * header
- */
-
- assert(regf->base != NULL);
-
- return (REGF_HDR *)regf->base;
-}
-
-/*
- * Validate a regf header
- * For now, do nothing, but we should check the checksum
- */
-int valid_regf_hdr(REGF_HDR *regf_hdr)
-{
- if (!regf_hdr) return 0;
-
- return 1;
-}
-
-/*
- * Process an SK header ...
- * Every time we see a new one, add it to the map. Otherwise, just look it up.
- * We will do a simple linear search for the moment, since many KEYs have the
- * same security descriptor.
- * We allocate the map in increments of 10 entries.
- */
-
-/*
- * Create a new entry in the map, and increase the size of the map if needed
- */
-
-SK_MAP *alloc_sk_map_entry(REGF *regf, KEY_SEC_DESC *tmp, int sk_off)
-{
- if (!regf->sk_map) { /* Allocate a block of 10 */
- regf->sk_map = (SK_MAP *)malloc(sizeof(SK_MAP) * 10);
- if (!regf->sk_map) {
- free(tmp);
- return NULL;
- }
- regf->sk_map_size = 10;
- regf->sk_count = 1;
- (regf->sk_map)[0].sk_off = sk_off;
- (regf->sk_map)[0].key_sec_desc = tmp;
- }
- else { /* Simply allocate a new slot, unless we have to expand the list */
- int ndx = regf->sk_count;
- if (regf->sk_count >= regf->sk_map_size) {
- regf->sk_map = (SK_MAP *)realloc(regf->sk_map,
- (regf->sk_map_size + 10)*sizeof(SK_MAP));
- if (!regf->sk_map) {
- free(tmp);
- return NULL;
- }
- /*
- * ndx already points at the first entry of the new block
- */
- regf->sk_map_size += 10;
- }
- (regf->sk_map)[ndx].sk_off = sk_off;
- (regf->sk_map)[ndx].key_sec_desc = tmp;
- regf->sk_count++;
- }
- return regf->sk_map;
-}
-
-/*
- * Search for a KEY_SEC_DESC in the sk_map, but dont create one if not
- * found
- */
-
-KEY_SEC_DESC *lookup_sec_key(SK_MAP *sk_map, int count, int sk_off)
-{
- int i;
-
- if (!sk_map) return NULL;
-
- for (i = 0; i < count; i++) {
-
- if (sk_map[i].sk_off == sk_off)
- return sk_map[i].key_sec_desc;
-
- }
-
- return NULL;
-
-}
-
-/*
- * Allocate a KEY_SEC_DESC if we can't find one in the map
- */
-
-KEY_SEC_DESC *lookup_create_sec_key(REGF *regf, SK_MAP *sk_map, int sk_off)
-{
- KEY_SEC_DESC *tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off);
-
- if (tmp) {
- return tmp;
- }
- else { /* Allocate a new one */
- tmp = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC));
- if (!tmp) {
- return NULL;
- }
- tmp->state = SEC_DESC_RES;
- if (!alloc_sk_map_entry(regf, tmp, sk_off)) {
- return NULL;
- }
- return tmp;
- }
-}
-
-/*
- * Allocate storage and duplicate a SID
- * We could allocate the SID to be only the size needed, but I am too lazy.
- */
-DOM_SID *dup_sid(DOM_SID *sid)
-{
- DOM_SID *tmp = (DOM_SID *)malloc(sizeof(DOM_SID));
- int i;
-
- if (!tmp) return NULL;
- tmp->ver = sid->ver;
- tmp->auths = sid->auths;
- for (i=0; i<6; i++) {
- tmp->auth[i] = sid->auth[i];
- }
- for (i=0; i<tmp->auths&&i<MAXSUBAUTHS; i++) {
- tmp->sub_auths[i] = sid->sub_auths[i];
- }
- return tmp;
-}
-
-/*
- * Allocate space for an ACE and duplicate the registry encoded one passed in
- */
-ACE *dup_ace(REG_ACE *ace)
-{
- ACE *tmp = NULL;
-
- tmp = (ACE *)malloc(sizeof(ACE));
-
- if (!tmp) return NULL;
-
- tmp->type = CVAL(&ace->type);
- tmp->flags = CVAL(&ace->flags);
- tmp->perms = IVAL(&ace->perms);
- tmp->trustee = dup_sid(&ace->trustee);
- return tmp;
-}
-
-/*
- * Allocate space for an ACL and duplicate the registry encoded one passed in
- */
-ACL *dup_acl(REG_ACL *acl)
-{
- ACL *tmp = NULL;
- REG_ACE* ace;
- int i, num_aces;
-
- num_aces = IVAL(&acl->num_aces);
-
- tmp = (ACL *)malloc(sizeof(ACL) + (num_aces - 1)*sizeof(ACE *));
- if (!tmp) return NULL;
-
- tmp->num_aces = num_aces;
- tmp->refcnt = 1;
- tmp->rev = SVAL(&acl->rev);
- ace = (REG_ACE *)&acl->aces;
- for (i=0; i<num_aces; i++) {
- tmp->aces[i] = dup_ace(ace);
- ace = (REG_ACE *)((char *)ace + SVAL(&ace->length));
- /* XXX: FIXME, should handle malloc errors */
- }
-
- return tmp;
-}
-
-SEC_DESC *process_sec_desc(REGF *regf, REG_SEC_DESC *sec_desc)
-{
- SEC_DESC *tmp = NULL;
-
- tmp = (SEC_DESC *)malloc(sizeof(SEC_DESC));
-
- if (!tmp) {
- return NULL;
- }
-
- tmp->rev = SVAL(&sec_desc->rev);
- tmp->type = SVAL(&sec_desc->type);
- tmp->owner = dup_sid((DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->owner_off)));
- if (!tmp->owner) {
- free(tmp);
- return NULL;
- }
- tmp->group = dup_sid((DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->group_off)));
- if (!tmp->group) {
- free(tmp);
- return NULL;
- }
-
- /* Now pick up the SACL and DACL */
-
- if (sec_desc->sacl_off)
- tmp->sacl = dup_acl((REG_ACL *)((char *)sec_desc + IVAL(&sec_desc->sacl_off)));
- else
- tmp->sacl = NULL;
-
- if (sec_desc->dacl_off)
- tmp->dacl = dup_acl((REG_ACL *)((char *)sec_desc + IVAL(&sec_desc->dacl_off)));
- else
- tmp->dacl = NULL;
-
- return tmp;
-}
-
-KEY_SEC_DESC *process_sk(REGF *regf, SK_HDR *sk_hdr, int sk_off, int size)
-{
- KEY_SEC_DESC *tmp = NULL;
- int sk_next_off, sk_prev_off, sk_size;
- REG_SEC_DESC *sec_desc;
-
- if (!sk_hdr) return NULL;
-
- if (SVAL(&sk_hdr->SK_ID) != REG_SK_ID) {
- fprintf(stderr, "Unrecognized SK Header ID: %08X, %s\n", (int)sk_hdr,
- regf->regfile_name);
- return NULL;
- }
-
- if (-size < (sk_size = IVAL(&sk_hdr->rec_size))) {
- fprintf(stderr, "Incorrect SK record size: %d vs %d. %s\n",
- -size, sk_size, regf->regfile_name);
- return NULL;
- }
-
- /*
- * Now, we need to look up the SK Record in the map, and return it
- * Since the map contains the SK_OFF mapped to KEY_SEC_DESC, we can
- * use that
- */
-
- if (regf->sk_map &&
- ((tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off)) != NULL)
- && (tmp->state == SEC_DESC_OCU)) {
- tmp->ref_cnt++;
- return tmp;
- }
-
- /* Here, we have an item in the map that has been reserved, or tmp==NULL. */
-
- assert(tmp == NULL || (tmp && tmp->state != SEC_DESC_NON));
-
- /*
- * Now, allocate a KEY_SEC_DESC, and parse the structure here, and add the
- * new KEY_SEC_DESC to the mapping structure, since the offset supplied is
- * the actual offset of structure. The same offset will be used by all
- * all future references to this structure
- * We chould put all this unpleasantness in a function.
- */
-
- if (!tmp) {
- tmp = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC));
- if (!tmp) return NULL;
- bzero(tmp, sizeof(KEY_SEC_DESC));
-
- /*
- * Allocate an entry in the SK_MAP ...
- * We don't need to free tmp, because that is done for us if the
- * sm_map entry can't be expanded when we need more space in the map.
- */
-
- if (!alloc_sk_map_entry(regf, tmp, sk_off)) {
- return NULL;
- }
- }
-
- tmp->ref_cnt++;
- tmp->state = SEC_DESC_OCU;
-
- /*
- * Now, process the actual sec desc and plug the values in
- */
-
- sec_desc = (REG_SEC_DESC *)&sk_hdr->sec_desc[0];
- tmp->sec_desc = process_sec_desc(regf, sec_desc);
-
- /*
- * Now forward and back links. Here we allocate an entry in the sk_map
- * if it does not exist, and mark it reserved
- */
-
- sk_prev_off = IVAL(&sk_hdr->prev_off);
- tmp->prev = lookup_create_sec_key(regf, regf->sk_map, sk_prev_off);
- assert(tmp->prev != NULL);
- sk_next_off = IVAL(&sk_hdr->next_off);
- tmp->next = lookup_create_sec_key(regf, regf->sk_map, sk_next_off);
- assert(tmp->next != NULL);
-
- return tmp;
-}
-
-/*
- * Process a VK header and return a value
- */
-VAL_KEY *process_vk(REGF *regf, VK_HDR *vk_hdr, int size)
-{
- char val_name[1024];
- int nam_len, dat_len, flag, dat_type, dat_off, vk_id;
- const char *val_type;
- VAL_KEY *tmp = NULL;
-
- if (!vk_hdr) return NULL;
-
- if ((vk_id = SVAL(&vk_hdr->VK_ID)) != REG_VK_ID) {
- fprintf(stderr, "Unrecognized VK header ID: %0X, block: %0X, %s\n",
- vk_id, (int)vk_hdr, regf->regfile_name);
- return NULL;
- }
-
- nam_len = SVAL(&vk_hdr->nam_len);
- val_name[nam_len] = '\0';
- flag = SVAL(&vk_hdr->flag);
- dat_type = IVAL(&vk_hdr->dat_type);
- dat_len = IVAL(&vk_hdr->dat_len); /* If top bit, offset contains data */
- dat_off = IVAL(&vk_hdr->dat_off);
-
- tmp = (VAL_KEY *)malloc(sizeof(VAL_KEY));
- if (!tmp) {
- goto error;
- }
- bzero(tmp, sizeof(VAL_KEY));
- tmp->has_name = flag;
- tmp->data_type = dat_type;
-
- if (flag & 0x01) {
- strncpy(val_name, vk_hdr->dat_name, nam_len);
- tmp->name = strdup(val_name);
- if (!tmp->name) {
- goto error;
- }
- }
- else
- strncpy(val_name, "<No Name>", 10);
-
- /*
- * Allocate space and copy the data as a BLOB
- */
-
- if (dat_len) {
-
- char *dtmp = (char *)malloc(dat_len&0x7FFFFFFF);
-
- if (!dtmp) {
- goto error;
- }
-
- tmp->data_blk = dtmp;
-
- if ((dat_len&0x80000000) == 0) { /* The data is pointed to by the offset */
- char *dat_ptr = LOCN(regf->base, dat_off);
- bcopy(dat_ptr, dtmp, dat_len);
- }
- else { /* The data is in the offset */
- dat_len = dat_len & 0x7FFFFFFF;
- bcopy(&dat_off, dtmp, dat_len);
- }
-
- tmp->data_len = dat_len;
- }
-
- val_type = val_to_str(dat_type, reg_type_names);
-
- /*
- * We need to save the data area as well
- */
-
- if (verbose) fprintf(stdout, " %s : %s : \n", val_name, val_type);
-
- return tmp;
-
- error:
- /* XXX: FIXME, free the partially allocated struct */
- return NULL;
-
-}
-
-/*
- * Process a VL Header and return a list of values
- */
-VAL_LIST *process_vl(REGF *regf, VL_TYPE vl, int count, int size)
-{
- int i, vk_off;
- VK_HDR *vk_hdr;
- VAL_LIST *tmp = NULL;
-
- if (!vl) return NULL;
-
- if (-size < (count+1)*sizeof(int)){
- fprintf(stderr, "Error in VL header format. Size less than space required. %d\n", -size);
- return NULL;
- }
-
- tmp = (VAL_LIST *)malloc(sizeof(VAL_LIST) + (count - 1) * sizeof(VAL_KEY *));
- if (!tmp) {
- goto error;
- }
-
- for (i=0; i<count; i++) {
- vk_off = IVAL(&vl[i]);
- vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off);
- tmp->vals[i] = process_vk(regf, vk_hdr, BLK_SIZE(vk_hdr));
- if (!tmp->vals[i]){
- goto error;
- }
- }
-
- tmp->val_count = count;
-
- return tmp;
-
- error:
- /* XXX: FIXME, free the partially allocated structure */
- return NULL;
-}
-
-/*
- * Process an LF Header and return a list of sub-keys
- */
-KEY_LIST *process_lf(REGF *regf, LF_HDR *lf_hdr, int size)
-{
- int count, i, nk_off;
- unsigned int lf_id;
- KEY_LIST *tmp;
-
- if (!lf_hdr) return NULL;
-
- if ((lf_id = SVAL(&lf_hdr->LF_ID)) != REG_LF_ID) {
- fprintf(stderr, "Unrecognized LF Header format: %0X, Block: %0X, %s.\n",
- lf_id, (int)lf_hdr, regf->regfile_name);
- return NULL;
- }
-
- assert(size < 0);
-
- count = SVAL(&lf_hdr->key_count);
-
- if (count <= 0) return NULL;
-
- /* Now, we should allocate a KEY_LIST struct and fill it in ... */
-
- tmp = (KEY_LIST *)malloc(sizeof(KEY_LIST) + (count - 1) * sizeof(REG_KEY *));
- if (!tmp) {
- goto error;
- }
-
- tmp->key_count = count;
-
- for (i=0; i<count; i++) {
- NK_HDR *nk_hdr;
-
- nk_off = IVAL(&lf_hdr->hr[i].nk_off);
- nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off);
- tmp->keys[i] = nt_get_key_tree(regf, nk_hdr, BLK_SIZE(nk_hdr));
- if (!tmp->keys[i]) {
- goto error;
- }
- }
-
- return tmp;
-
- error:
- /* XXX: FIXME, free the partially allocated structure */
- return NULL;
-}
-
-/*
- * This routine is passed a NK_HDR pointer and retrieves the entire tree
- * from there down. It return a REG_KEY *.
- */
-REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size)
-{
- REG_KEY *tmp = NULL;
- int name_len, clsname_len, lf_off, val_off, val_count, sk_off;
- unsigned int nk_id;
- LF_HDR *lf_hdr;
- VL_TYPE *vl;
- SK_HDR *sk_hdr;
- char key_name[1024], cls_name[1024];
-
- if (!nk_hdr) return NULL;
-
- if ((nk_id = SVAL(&nk_hdr->NK_ID)) != REG_NK_ID) {
- fprintf(stderr, "Unrecognized NK Header format: %08X, Block: %0X. %s\n",
- nk_id, (int)nk_hdr, regf->regfile_name);
- return NULL;
- }
-
- assert(size < 0);
-
- name_len = SVAL(&nk_hdr->nam_len);
- clsname_len = SVAL(&nk_hdr->clsnam_len);
-
- /*
- * The value of -size should be ge
- * (sizeof(NK_HDR) - 1 + name_len)
- * The -1 accounts for the fact that we included the first byte of
- * the name in the structure. clsname_len is the length of the thing
- * pointed to by clsnam_off
- */
-
- if (-size < (sizeof(NK_HDR) - 1 + name_len)) {
- fprintf(stderr, "Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr);
- fprintf(stderr, "Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n",
- sizeof(NK_HDR), name_len, clsname_len);
- /*return NULL;*/
- }
-
- if (verbose) fprintf(stdout, "NK HDR: Name len: %d, class name len: %d\n",
- name_len, clsname_len);
-
- /* Fish out the key name and process the LF list */
-
- assert(name_len < sizeof(key_name));
-
- /* Allocate the key struct now */
- tmp = (REG_KEY *)malloc(sizeof(REG_KEY));
- if (!tmp) return tmp;
- bzero(tmp, sizeof(REG_KEY));
-
- tmp->type = (SVAL(&nk_hdr->type)==0x2C?REG_ROOT_KEY:REG_SUB_KEY);
-
- strncpy(key_name, nk_hdr->key_nam, name_len);
- key_name[name_len] = '\0';
-
- if (verbose) fprintf(stdout, "Key name: %s\n", key_name);
-
- tmp->name = strdup(key_name);
- if (!tmp->name) {
- goto error;
- }
-
- /*
- * Fish out the class name, it is in UNICODE, while the key name is
- * ASCII :-)
- */
-
- if (clsname_len) { /* Just print in Ascii for now */
- char *clsnamep;
- int clsnam_off;
-
- clsnam_off = IVAL(&nk_hdr->clsnam_off);
- clsnamep = LOCN(regf->base, clsnam_off);
-
- bzero(cls_name, clsname_len);
- uni_to_ascii(clsnamep, cls_name, sizeof(cls_name), clsname_len);
-
- /*
- * I am keeping class name as an ascii string for the moment.
- * That means it needs to be converted on output.
- * XXX: FIXME
- */
-
- tmp->class_name = strdup(cls_name);
- if (!tmp->class_name) {
- goto error;
- }
-
- if (verbose) fprintf(stdout, " Class Name: %s\n", cls_name);
-
- }
-
- /*
- * If there are any values, process them here
- */
-
- val_count = IVAL(&nk_hdr->val_cnt);
-
- if (val_count) {
-
- val_off = IVAL(&nk_hdr->val_off);
- vl = (VL_TYPE *)LOCN(regf->base, val_off);
-
- tmp->values = process_vl(regf, *vl, val_count, BLK_SIZE(vl));
- if (!tmp->values) {
- goto error;
- }
-
- }
-
- /*
- * Also handle the SK header ...
- */
-
- sk_off = IVAL(&nk_hdr->sk_off);
- sk_hdr = (SK_HDR *)LOCN(regf->base, sk_off);
-
- if (sk_off != -1) {
-
- tmp->security = process_sk(regf, sk_hdr, sk_off, BLK_SIZE(sk_hdr));
-
- }
-
- lf_off = IVAL(&nk_hdr->lf_off);
-
- /*
- * No more subkeys if lf_off == -1
- */
-
- if (lf_off != -1) {
-
- lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off);
-
- tmp->sub_keys = process_lf(regf, lf_hdr, BLK_SIZE(lf_hdr));
- if (!tmp->sub_keys){
- goto error;
- }
-
- }
-
- return tmp;
-
- error:
- if (tmp) nt_delete_reg_key(tmp);
- return NULL;
-}
-
-int nt_load_registry(REGF *regf)
-{
- REGF_HDR *regf_hdr;
- unsigned int regf_id, hbin_id;
- HBIN_HDR *hbin_hdr;
- NK_HDR *first_key;
-
- /* Get the header */
-
- if ((regf_hdr = nt_get_regf_hdr(regf)) == NULL) {
- return -1;
- }
-
- /* Now process that header and start to read the rest in */
-
- if ((regf_id = IVAL(&regf_hdr->REGF_ID)) != REG_REGF_ID) {
- fprintf(stderr, "Unrecognized NT registry header id: %0X, %s\n",
- regf_id, regf->regfile_name);
- return -1;
- }
-
- /*
- * Validate the header ...
- */
- if (!valid_regf_hdr(regf_hdr)) {
- fprintf(stderr, "Registry file header does not validate: %s\n",
- regf->regfile_name);
- return -1;
- }
-
- /* Update the last mod date, and then go get the first NK record and on */
-
- TTTONTTIME(regf, IVAL(&regf_hdr->tim1), IVAL(&regf_hdr->tim2));
-
- /*
- * The hbin hdr seems to be just uninteresting garbage. Check that
- * it is there, but that is all.
- */
-
- hbin_hdr = (HBIN_HDR *)(regf->base + REGF_HDR_BLKSIZ);
-
- if ((hbin_id = IVAL(&hbin_hdr->HBIN_ID)) != REG_HBIN_ID) {
- fprintf(stderr, "Unrecognized registry hbin hdr ID: %0X, %s\n",
- hbin_id, regf->regfile_name);
- return -1;
- }
-
- /*
- * Get a pointer to the first key from the hreg_hdr
- */
-
- first_key = (NK_HDR *)LOCN(regf->base, IVAL(&regf_hdr->first_key));
-
- /*
- * Now, get the registry tree by processing that NK recursively
- */
-
- regf->root = nt_get_key_tree(regf, first_key, BLK_SIZE(first_key));
-
- assert(regf->root != NULL);
-
- return 1;
-}
-
-/*
- * Routines to parse a REGEDIT4 file
- *
- * The file consists of:
- *
- * REGEDIT4
- * \[[-]key-path\]\n
- * <value-spec>*
- *
- * There can be more than one key-path and value-spec.
- *
- * Since we want to support more than one type of file format, we
- * construct a command-file structure that keeps info about the command file
- */
-
-#define FMT_UNREC -1
-#define FMT_REGEDIT4 0
-#define FMT_EDITREG1_1 1
-
-typedef struct command_s {
- int cmd;
- char *key;
- void *val_spec_list;
-} CMD;
-
-/*
- * We seek to offset 0, read in the required number of bytes,
- * and compare to the correct value.
- * We then seek back to the original location
- */
-int regedit4_file_type(int fd)
-{
- int cur_ofs = 0;
-
- cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */
- if (cur_ofs < 0) {
- fprintf(stderr, "Unable to get current offset: %s\n", strerror(errno));
- exit(1);
- }
-
- if (cur_ofs) {
- lseek(fd, 0, SEEK_SET);
- }
-
- return FMT_UNREC;
-}
-
-CMD *regedit4_get_cmd(int fd)
-{
- return NULL;
-}
-
-int regedit4_exec_cmd(CMD *cmd)
-{
-
- return 0;
-}
-
-int editreg_1_1_file_type(int fd)
-{
-
- return FMT_UNREC;
-}
-
-CMD *editreg_1_1_get_cmd(int fd)
-{
- return NULL;
-}
-
-int editreg_1_1_exec_cmd(CMD *cmd)
-{
-
- return -1;
-}
-
-typedef struct command_ops_s {
- int type;
- int (*file_type)(int fd);
- CMD *(*get_cmd)(int fd);
- int (*exec_cmd)(CMD *cmd);
-} CMD_OPS;
-
-CMD_OPS default_cmd_ops[] = {
- {0, regedit4_file_type, regedit4_get_cmd, regedit4_exec_cmd},
- {1, editreg_1_1_file_type, editreg_1_1_get_cmd, editreg_1_1_exec_cmd},
- {-1, NULL, NULL, NULL}
-};
-
-typedef struct command_file_s {
- char *name;
- int type, fd;
- CMD_OPS cmd_ops;
-} CMD_FILE;
-
-/*
- * Create a new command file structure
- */
-
-CMD_FILE *cmd_file_create(char *file)
-{
- CMD_FILE *tmp;
- struct stat sbuf;
- int i = 0;
-
- /*
- * Let's check if the file exists ...
- * No use creating the cmd_file structure if the file does not exist
- */
-
- if (stat(file, &sbuf) < 0) { /* Not able to access file */
-
- return NULL;
- }
-
- tmp = (CMD_FILE *)malloc(sizeof(CMD_FILE));
- if (!tmp) {
- return NULL;
- }
-
- /*
- * Let's fill in some of the fields;
- */
-
- tmp->name = strdup(file);
-
- if ((tmp->fd = open(file, O_RDONLY, 666)) < 0) {
- free(tmp);
- return NULL;
- }
-
- /*
- * Now, try to find the format by indexing through the table
- */
- while (default_cmd_ops[i].type != -1) {
- if ((tmp->type = default_cmd_ops[i].file_type(tmp->fd)) >= 0) {
- tmp->cmd_ops = default_cmd_ops[i];
- return tmp;
- }
- i++;
- }
-
- /*
- * If we got here, return NULL, as we could not figure out the type
- * of command file.
- *
- * What about errors?
- */
-
- free(tmp);
- return NULL;
-}
-
-/*
- * Extract commands from the command file, and execute them.
- * We pass a table of command callbacks for that
- */
-
-/*
- * Main code from here on ...
- */
-
-/*
- * key print function here ...
- */
-
-int print_key(const char *path, char *name, char *class_name, int root,
- int terminal, int vals)
-{
-
- if (terminal) fprintf(stdout, "%s\\%s\n", path, name);
-
- return 1;
-}
-
-/*
- * Sec Desc print functions
- */
-
-void print_sid(DOM_SID *sid)
-{
- int i, comps = sid->auths;
- fprintf(stdout, "S-%u-%u", sid->ver, sid->auth[5]);
-
- for (i = 0; i < comps; i++) {
-
- fprintf(stdout, "-%u", sid->sub_auths[i]);
-
- }
- fprintf(stdout, "\n");
-}
-
-int print_sec(SEC_DESC *sec_desc)
-{
-
- fprintf(stdout, " SECURITY\n");
- fprintf(stdout, " Owner: ");
- print_sid(sec_desc->owner);
- fprintf(stdout, " Group: ");
- print_sid(sec_desc->group);
- return 1;
-}
-
-/*
- * Value print function here ...
- */
-int print_val(const char *path, char *val_name, int val_type, int data_len,
- void *data_blk, int terminal, int first, int last)
-{
- char data_asc[1024];
-
- bzero(data_asc, sizeof(data_asc));
- if (!terminal && first)
- fprintf(stdout, "%s\n", path);
- data_to_ascii((unsigned char *)data_blk, data_len, val_type, data_asc,
- sizeof(data_asc) - 1);
- fprintf(stdout, " %s : %s : %s\n", (val_name?val_name:"<No Name>"),
- val_to_str(val_type, reg_type_names), data_asc);
- return 1;
-}
-
-int main(int argc, char *argv[])
-{
- REGF *regf;
- int opt;
- static char *cmd_file = NULL;
- poptContext pc;
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "Sets verbose mode" },
- { "command-file", 'c', POPT_ARG_STRING, &cmd_file, 'c', "Specifies a command file" },
- { 0, 0, 0, 0 }
- };
-
- pc = poptGetContext("editreg", argc, (const char **)argv, long_options,
- POPT_CONTEXT_KEEP_FIRST);
-
- poptSetOtherOptionHelp(pc, "<registry-file>");
-
- while((opt = poptGetNextOpt(pc)) != -1)
- switch(opt) {
- case 'v':
- verbose++;
- break;
- }
-
- poptGetArg(pc); /* For argv[0] */
-
- if (!poptPeekArg(pc)) {
- poptPrintUsage(pc, stderr, 0);
- exit(1);
- }
-
- if ((regf = nt_create_regf()) == NULL) {
- fprintf(stderr, "Could not create registry object: %s\n", strerror(errno));
- exit(2);
- }
-
- if (!nt_set_regf_input_file(regf, poptPeekArg(pc))) {
- fprintf(stderr, "Could not set name of registry file: %s, %s\n",
- poptPeekArg(pc), strerror(errno));
- exit(3);
- }
-
- /* Now, open it, and bring it into memory :-) */
-
- if (nt_load_registry(regf) < 0) {
- fprintf(stderr, "Could not load registry: %s\n", poptPeekArg(pc));
- exit(4);
- }
-
- /*
- * At this point, we should have a registry in memory and should be able
- * to iterate over it.
- */
-
- nt_key_iterator(regf, regf->root, 0, "", print_key, print_sec, print_val);
- poptFreeContext(pc);
- return 0;
-}
diff --git a/source3/utils/net.c b/source3/utils/net.c
index 3ab34e7aa9..7588771fbc 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -78,6 +78,8 @@ static int opt_machine_pass = 0;
BOOL opt_have_ip = False;
struct in_addr opt_dest_ip;
+extern BOOL AllowDebugChange;
+
/*
run a function from a function table. If not found then
call the specified usage function
@@ -511,14 +513,18 @@ static struct functable net_func[] = {
int argc_new = 0;
const char ** argv_new;
poptContext pc;
+ static char *servicesf = dyn_CONFIGFILE;
+ static char *debuglevel = NULL;
struct poptOption long_options[] = {
{"help", 'h', POPT_ARG_NONE, 0, 'h'},
{"workgroup", 'w', POPT_ARG_STRING, &opt_target_workgroup},
+ {"myworkgroup", 'W', POPT_ARG_STRING, &opt_workgroup},
{"user", 'U', POPT_ARG_STRING, &opt_user_name, 'U'},
{"ipaddress", 'I', POPT_ARG_STRING, 0,'I'},
{"port", 'p', POPT_ARG_INT, &opt_port},
{"myname", 'n', POPT_ARG_STRING, &opt_requester_name},
+ {"conf", 's', POPT_ARG_STRING, &servicesf},
{"server", 'S', POPT_ARG_STRING, &opt_host},
{"container", 'c', POPT_ARG_STRING, &opt_container},
{"comment", 'C', POPT_ARG_STRING, &opt_comment},
@@ -530,8 +536,8 @@ static struct functable net_func[] = {
{"force", 'f', POPT_ARG_NONE, &opt_force},
{"timeout", 't', POPT_ARG_INT, &opt_timeout},
{"machine-pass",'P', POPT_ARG_NONE, &opt_machine_pass},
- {"myworkgroup", 'W', POPT_ARG_STRING, &opt_workgroup},
- POPT_COMMON_SAMBA
+ {"debuglevel", 'd', POPT_ARG_STRING, &debuglevel},
+ {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version},
{ 0, 0, 0, 0}
};
@@ -571,8 +577,13 @@ static struct functable net_func[] = {
exit(1);
}
}
-
- lp_load(dyn_CONFIGFILE,True,False,False);
+
+ if (debuglevel) {
+ debug_parse_levels(debuglevel);
+ AllowDebugChange = False;
+ }
+
+ lp_load(servicesf,True,False,False);
argv_new = (const char **)poptGetArgs(pc);
@@ -625,10 +636,6 @@ static struct functable net_func[] = {
exit(1);
}
}
-
- if (!opt_password) {
- opt_password = getenv("PASSWD");
- }
rc = net_run_function(argc_new-1, argv_new+1, net_func, net_help);
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 0f2d673b4b..b4697d73dd 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -124,7 +124,6 @@ static ADS_STRUCT *ads_startup(void)
ADS_STATUS status;
BOOL need_password = False;
BOOL second_time = False;
- char *realm;
ads = ads_init(NULL, NULL, opt_host);
@@ -151,16 +150,6 @@ retry:
ads->auth.user_name = strdup(opt_user_name);
- /*
- * If the username is of the form "name@realm",
- * extract the realm and convert to upper case.
- */
- if ((realm = strchr(ads->auth.user_name, '@'))) {
- *realm++ = '\0';
- ads->auth.realm = strdup(realm);
- strupper(ads->auth.realm);
- }
-
status = ads_connect(ads);
if (!ADS_ERR_OK(status)) {
if (!need_password && !second_time) {
diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c
index 07409aec22..4000a248ff 100644
--- a/source3/utils/net_help.c
+++ b/source3/utils/net_help.c
@@ -42,12 +42,11 @@ int net_common_flags_usage(int argc, const char **argv)
d_printf("Valid miscellaneous options are:\n"); /* misc options */
d_printf("\t-p or --port=<port>\t\tconnection port on target\n");
d_printf("\t-W or --myworkgroup=<wg>\tclient workgroup\n");
- d_printf("\t-d or --debuglevel=<level>\t\tdebug level (0-10)\n");
+ d_printf("\t-d or --debug=<level>\t\tdebug level (0-10)\n");
d_printf("\t-n or --myname=<name>\t\tclient name\n");
d_printf("\t-U or --user=<name>\t\tuser name\n");
- d_printf("\t-s or --configfile=<path>\t\tpathname of smb.conf file\n");
+ d_printf("\t-s or --conf=<path>\t\tpathname of smb.conf file\n");
d_printf("\t-l or --long\t\t\tDisplay full information\n");
- d_printf("\t-V or --version\t\tPrint samba version information\n");
d_printf("\t-P or --machine-pass\t\tAuthenticate as machine account\n");
return -1;
}
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 69cf28f995..922fc027e6 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -1880,7 +1880,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
int num_domains, i, pad_len, col_len = 20;
DOM_SID *domain_sids;
char **trusted_dom_names;
- fstring pdc_name, dummy;
+ fstring pdc_name;
/* trusting domains listing variables */
POLICY_HND domain_hnd;
@@ -1927,10 +1927,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
};
/* query info level 5 to obtain sid of a domain being queried */
- nt_status = cli_lsa_query_info_policy(
- cli, mem_ctx, &connect_hnd, 5 /* info level */,
- dummy, &queried_dom_sid);
-
+ nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
+ 5 /* info level */, domain_name, &queried_dom_sid);
if (NT_STATUS_IS_ERR(nt_status)) {
DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
nt_errstr(nt_status)));
diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c
index 0b78cd54ce..f811d76f68 100644
--- a/source3/utils/net_rpc_samsync.c
+++ b/source3/utils/net_rpc_samsync.c
@@ -362,7 +362,7 @@ sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta)
}
#if 0
-/* No kickoff time in the delta? */
+ /* No kickoff time in the delta? */
if (!nt_time_is_zero(&delta->kickoff_time)) {
unix_time = nt_time_to_unix(&delta->kickoff_time);
stored_time = pdb_get_kickoff_time(account);
diff --git a/source3/utils/nmblookup.c b/source3/utils/nmblookup.c
index d2c5cbc00e..7e0ed4a203 100644
--- a/source3/utils/nmblookup.c
+++ b/source3/utils/nmblookup.c
@@ -2,7 +2,6 @@
Unix SMB/CIFS implementation.
NBT client - used to lookup netbios names
Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Jelmer Vernooij 2003 (Conversion to popt)
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
@@ -55,6 +54,31 @@ static BOOL open_sockets(void)
return True;
}
+
+/****************************************************************************
+usage on the program
+****************************************************************************/
+static void usage(void)
+{
+ d_printf("Usage: nmblookup [options] name\n");
+ d_printf("Version %s\n",VERSION);
+ d_printf("\t-d debuglevel set the debuglevel\n");
+ d_printf("\t-B broadcast address the address to use for broadcasts\n");
+ d_printf("\t-f list the NMB flags returned\n");
+ d_printf("\t-U unicast address the address to use for unicast\n");
+ d_printf("\t-M searches for a master browser\n");
+ d_printf("\t-R set recursion desired in packet\n");
+ d_printf("\t-S lookup node status as well\n");
+ d_printf("\t-T translate IP addresses into names\n");
+ d_printf("\t-r Use root port 137 (Win95 only replies to this)\n");
+ d_printf("\t-A Do a node status on <name> as an IP Address\n");
+ d_printf("\t-i NetBIOS scope Use the given NetBIOS scope for name queries\n");
+ d_printf("\t-s smb.conf file Use the given path to the smb.conf file\n");
+ d_printf("\t-h Print this help message.\n");
+ d_printf("\n If you specify -M and name is \"-\", nmblookup looks up __MSBROWSE__<01>\n");
+ d_printf("\n");
+}
+
/****************************************************************************
turn a node status flags field into a string
****************************************************************************/
@@ -187,106 +211,130 @@ int main(int argc,char *argv[])
int opt;
unsigned int lookup_type = 0x0;
fstring lookup;
- static BOOL find_master=False;
- static BOOL lookup_by_ip = False;
- poptContext pc;
-
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- { "broadcast", 'B', POPT_ARG_STRING, NULL, 'B', "Specify address to use for broadcasts", "BROADCAST-ADDRESS" },
- { "flags", 'f', POPT_ARG_VAL, &give_flags, True, "List the NMB flags returned" },
- { "unicast", 'U', POPT_ARG_STRING, NULL, 'U', "Specify address to use for unicast" },
- { "master-browser", 'M', POPT_ARG_VAL, &find_master, True, "Search for a master browser" },
- { "recursion", 'R', POPT_ARG_VAL, &recursion_desired, True, "Set recursion desired in package" },
- { "status", 'S', POPT_ARG_VAL, &find_status, True, "Lookup node status as well" },
- { "translate", 'T', POPT_ARG_NONE, NULL, 'T', "Translate IP addresses into names" },
- { "root-port", 'r', POPT_ARG_VAL, &RootPort, True, "Use root port 137 (Win95 only replies to this)" },
- { "lookup-by-ip", 'A', POPT_ARG_VAL, &lookup_by_ip, True, "Do a node status on <name> as an IP Address" },
- POPT_COMMON_SAMBA
- POPT_COMMON_CONNECTION
- { 0, 0, 0, 0 }
- };
-
- *lookup = 0;
+ extern int optind;
+ extern char *optarg;
+ BOOL find_master=False;
+ int i;
+ BOOL lookup_by_ip = False;
+ int commandline_debuglevel = -2;
- setup_logging(argv[0],True);
+ DEBUGLEVEL = 1;
+ /* Prevent smb.conf setting from overridding */
+ AllowDebugChange = False;
- pc = poptGetContext("nmblookup", argc, (const char **)argv, long_options,
- POPT_CONTEXT_KEEP_FIRST);
-
- poptSetOtherOptionHelp(pc, "<NODE> ...");
-
- while ((opt = poptGetNextOpt(pc)) != -1) {
- switch (opt) {
- case 'B':
- bcast_addr = *interpret_addr2(poptGetOptArg(pc));
- got_bcast = True;
- use_bcast = True;
- break;
- case 'U':
- bcast_addr = *interpret_addr2(poptGetOptArg(pc));
- got_bcast = True;
- use_bcast = False;
- break;
- case 'T':
- translate_addresses = !translate_addresses;
- break;
- }
- }
+ *lookup = 0;
- poptGetArg(pc); /* Remove argv[0] */
+ setup_logging(argv[0],True);
- if(!poptPeekArg(pc)) {
- poptPrintUsage(pc, stderr, 0);
- exit(1);
+ while ((opt = getopt(argc, argv, "d:fB:U:i:s:SMrhART")) != EOF)
+ switch (opt)
+ {
+ case 'B':
+ bcast_addr = *interpret_addr2(optarg);
+ got_bcast = True;
+ use_bcast = True;
+ break;
+ case 'f':
+ give_flags = True;
+ break;
+ case 'U':
+ bcast_addr = *interpret_addr2(optarg);
+ got_bcast = True;
+ use_bcast = False;
+ break;
+ case 'T':
+ translate_addresses = !translate_addresses;
+ break;
+ case 'i':
+ set_global_scope(optarg);
+ break;
+ case 'M':
+ find_master = True;
+ break;
+ case 'S':
+ find_status = True;
+ break;
+ case 'R':
+ recursion_desired = True;
+ break;
+ case 'd':
+ commandline_debuglevel = DEBUGLEVEL = atoi(optarg);
+ break;
+ case 's':
+ pstrcpy(dyn_CONFIGFILE, optarg);
+ break;
+ case 'r':
+ RootPort = True;
+ break;
+ case 'h':
+ usage();
+ exit(0);
+ break;
+ case 'A':
+ lookup_by_ip = True;
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+
+ if (argc < 2) {
+ usage();
+ exit(1);
}
if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
- fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
+ fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
}
+ /*
+ * Ensure we reset DEBUGLEVEL if someone specified it
+ * on the command line.
+ */
+
+ if(commandline_debuglevel != -2)
+ DEBUGLEVEL = commandline_debuglevel;
+
load_interfaces();
if (!open_sockets()) return(1);
- while(poptPeekArg(pc))
+ for (i=optind;i<argc;i++)
{
- char *p;
- struct in_addr ip;
-
- fstrcpy(lookup,poptGetArg(pc));
-
- if(lookup_by_ip)
- {
- ip = *interpret_addr2(lookup);
- fstrcpy(lookup,"*");
- do_node_status(ServerFD, lookup, lookup_type, ip);
- continue;
- }
-
- if (find_master) {
- if (*lookup == '-') {
- fstrcpy(lookup,"\01\02__MSBROWSE__\02");
- lookup_type = 1;
- } else {
- lookup_type = 0x1d;
- }
- }
-
- p = strchr_m(lookup,'#');
- if (p) {
- *p = '\0';
- sscanf(++p,"%x",&lookup_type);
- }
-
- if (!query_one(lookup, lookup_type)) {
- d_printf( "name_query failed to find name %s", lookup );
- if( 0 != lookup_type )
- d_printf( "#%02x", lookup_type );
- d_printf( "\n" );
- }
+ char *p;
+ struct in_addr ip;
+
+ fstrcpy(lookup,argv[i]);
+
+ if(lookup_by_ip)
+ {
+ fstrcpy(lookup,"*");
+ ip = *interpret_addr2(argv[i]);
+ do_node_status(ServerFD, lookup, lookup_type, ip);
+ continue;
+ }
+
+ if (find_master) {
+ if (*lookup == '-') {
+ fstrcpy(lookup,"\01\02__MSBROWSE__\02");
+ lookup_type = 1;
+ } else {
+ lookup_type = 0x1d;
+ }
+ }
+
+ p = strchr_m(lookup,'#');
+ if (p) {
+ *p = '\0';
+ sscanf(++p,"%x",&lookup_type);
+ }
+
+ if (!query_one(lookup, lookup_type)) {
+ d_printf( "name_query failed to find name %s", lookup );
+ if( 0 != lookup_type )
+ d_printf( "#%02x", lookup_type );
+ d_printf( "\n" );
+ }
}
-
- poptFreeContext(pc);
-
+
return(0);
}
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 88913c8051..0bead042fd 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -735,8 +735,7 @@ enum {
{ "request-lm-key", 0, POPT_ARG_NONE, &request_lm_key, OPT_LM_KEY, "Retreive LM session key"},
{ "request-nt-key", 0, POPT_ARG_NONE, &request_nt_key, OPT_NT_KEY, "Retreive NT session key"},
{ "diagnostics", 0, POPT_ARG_NONE, &diagnostics, OPT_DIAGNOSTICS, "Perform diagnostics on the authentictaion chain"},
- POPT_COMMON_SAMBA
- POPT_TABLEEND
+ { NULL, 0, 0, NULL, 0, NULL}
};
/* Samba client initialisation */
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
index bf42fb805f..99d3e01fd2 100644
--- a/source3/utils/pdbedit.c
+++ b/source3/utils/pdbedit.c
@@ -516,7 +516,7 @@ int main (int argc, char **argv)
poptContext pc;
struct poptOption long_options[] = {
POPT_AUTOHELP
- {"list", 'L', POPT_ARG_NONE, &list_users, 0, "list all users", NULL},
+ {"list", 'l', POPT_ARG_NONE, &list_users, 0, "list all users", NULL},
{"verbose", 'v', POPT_ARG_NONE, &verbose, 0, "be verbose", NULL },
{"smbpasswd-style", 'w',POPT_ARG_NONE, &spstyle, 0, "give output in smbpasswd style", NULL},
{"user", 'u', POPT_ARG_STRING, &user_name, 0, "use username", "USER" },
@@ -534,10 +534,11 @@ int main (int argc, char **argv)
{"export", 'e', POPT_ARG_STRING, &backend_out, 0, "export user accounts to this backend", NULL},
{"group", 'g', POPT_ARG_NONE, &transfer_groups, 0, "use -i and -e for groups", NULL},
{"account-policy", 'P', POPT_ARG_STRING, &account_policy, 0,"value of an account policy (like maximum password age)",NULL},
- {"value", 'C', POPT_ARG_LONG, &account_policy_value, 'C',"set the account policy to this value", NULL},
+ {"value", 'V', POPT_ARG_LONG, &account_policy_value, 'V',"set the account policy to this value", NULL},
{"account-control", 'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL},
- POPT_COMMON_SAMBA
- POPT_TABLEEND
+ { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
+ { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
+ {0,0,0,0}
};
setup_logging("pdbedit", True);
diff --git a/source3/utils/profiles.c b/source3/utils/profiles.c
index 7c2d820c81..2ed102b677 100644
--- a/source3/utils/profiles.c
+++ b/source3/utils/profiles.c
@@ -1,7 +1,6 @@
/*
Samba Unix/Linux SMB client utility profiles.c
Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com
- Copyright (C) 2003 Jelmer Vernooij (conversion to popt)
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
@@ -35,7 +34,7 @@ times...
the "regf"-Block
================
-"regf" is obviously the abbreviation for "Registry file". "regf" is the
+"regf" is obviosly the abbreviation for "Registry file". "regf" is the
signature of the header-block which is always 4kb in size, although only
the first 64 bytes seem to be used and a checksum is calculated over
the first 0x200 bytes only!
@@ -392,14 +391,14 @@ typedef struct acl_struct {
#define OFF(f) (0x1000 + (f) + 4)
-static void print_sid(DOM_SID *sid);
+void print_sid(DOM_SID *sid);
int verbose = 1;
DOM_SID old_sid, new_sid;
int change = 0, new = 0;
/* Compare two SIDs for equality */
-static int my_sid_equal(DOM_SID *s1, DOM_SID *s2)
+int my_sid_equal(DOM_SID *s1, DOM_SID *s2)
{
int sa1, sa2;
@@ -418,7 +417,7 @@ static int my_sid_equal(DOM_SID *s1, DOM_SID *s2)
* Quick and dirty to read a SID in S-1-5-21-x-y-z-rid format and
* construct a DOM_SID
*/
-static int get_sid(DOM_SID *sid, char *sid_str)
+int get_sid(DOM_SID *sid, char *sid_str)
{
int i = 0, auth;
char *lstr;
@@ -461,7 +460,7 @@ static int get_sid(DOM_SID *sid, char *sid_str)
* This routine does not need to deal with endianism as
* long as the incoming SIDs are both in the same (LE) format.
*/
-static void change_sid(DOM_SID *s1, DOM_SID *s2)
+void change_sid(DOM_SID *s1, DOM_SID *s2)
{
int i;
@@ -470,7 +469,7 @@ static void change_sid(DOM_SID *s1, DOM_SID *s2)
}
}
-static void print_sid(DOM_SID *sid)
+void print_sid(DOM_SID *sid)
{
int i, comps = sid->num_auths;
fprintf(stdout, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]);
@@ -483,7 +482,7 @@ static void print_sid(DOM_SID *sid)
fprintf(stdout, "\n");
}
-static void process_sid(DOM_SID *sid, DOM_SID *o_sid, DOM_SID *n_sid)
+void process_sid(DOM_SID *sid, DOM_SID *o_sid, DOM_SID *n_sid)
{
int i;
if (my_sid_equal(sid, o_sid)) {
@@ -497,7 +496,7 @@ static void process_sid(DOM_SID *sid, DOM_SID *o_sid, DOM_SID *n_sid)
}
-static void process_acl(ACL *acl, const char *prefix)
+void process_acl(ACL *acl, const char *prefix)
{
int ace_cnt, i;
ACE *ace;
@@ -515,8 +514,21 @@ static void process_acl(ACL *acl, const char *prefix)
}
}
+void usage(void)
+{
+ fprintf(stderr, "usage: profiles [-c <OLD-SID> -n <NEW-SID>] <profilefile>\n");
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, "\n\t-v\t sets verbose mode");
+ fprintf(stderr, "\n\t-c S-1-5-21-z-y-x-oldrid - provides SID to change");
+ fprintf(stderr, "\n\t-n S-1-5-21-a-b-c-newrid - provides SID to change to");
+ fprintf(stderr, "\n\t\tBoth must be present if the other is.");
+ fprintf(stderr, "\n\t\tIf neither present, just report the SIDs found\n");
+}
+
int main(int argc, char *argv[])
{
+ extern char *optarg;
+ extern int optind;
int opt;
int fd, start = 0;
char *base;
@@ -528,75 +540,63 @@ int main(int argc, char *argv[])
DWORD first_sk_off, sk_off;
MY_SEC_DESC *sec_desc;
int *ptr;
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "Sets verbose mode" },
- { "change-sid", 'c', POPT_ARG_STRING, NULL, 'c', "Provides SID to change" },
- { "new-sid", 'n', POPT_ARG_STRING, NULL, 'n', "Provides SID to change to" },
- { 0, 0, 0, 0 }
- };
-
- poptContext pc;
- pc = poptGetContext("profiles", argc, (const char **)argv, long_options,
- POPT_CONTEXT_KEEP_FIRST);
-
- poptSetOtherOptionHelp(pc, "<profilefile>");
+ if (argc < 2) {
+ usage();
+ exit(1);
+ }
/*
* Now, process the arguments
*/
- while ((opt = poptGetNextOpt(pc)) != -1) {
+ while ((opt = getopt(argc, argv, "c:n:v")) != EOF) {
switch (opt) {
- case 'c':
- change = 1;
- if (!get_sid(&old_sid, poptGetOptArg(pc))) {
- fprintf(stderr, "Argument to -c should be a SID in form of S-1-5-...\n");
- poptPrintUsage(pc, stderr, 0);
- exit(254);
- }
- break;
-
- case 'n':
- new = 1;
- if (!get_sid(&new_sid, poptGetOptArg(pc))) {
- fprintf(stderr, "Argument to -n should be a SID in form of S-1-5-...\n");
- poptPrintUsage(pc, stderr, 0);
- exit(253);
- }
-
- break;
-
- case 'v':
- verbose++;
- break;
- }
- }
+ case 'c':
+ change = 1;
+ if (!get_sid(&old_sid, optarg)) {
+ fprintf(stderr, "Argument to -c should be a SID in form of S-1-5-...\n");
+ usage();
+ exit(254);
+ }
+ break;
+
+ case 'n':
+ new = 1;
+ if (!get_sid(&new_sid, optarg)) {
+ fprintf(stderr, "Argument to -n should be a SID in form of S-1-5-...\n");
+ usage();
+ exit(253);
+ }
+
+ break;
+
+ case 'v':
+ verbose++;
+ break;
- if (!poptPeekArg(pc)) {
- poptPrintUsage(pc, stderr, 0);
- exit(1);
+ default:
+ usage();
+ exit(255);
+ }
}
if ((!change & new) || (change & !new)) {
- fprintf(stderr, "You must specify both -c and -n if one or the other is set!\n");
- poptPrintUsage(pc, stderr, 0);
- exit(252);
+ fprintf(stderr, "You must specify both -c and -n if one or the other is set!\n");
+ usage();
+ exit(252);
}
- poptGetArg(pc); /* To get argv[0] */
-
- fd = open(poptPeekArg(pc), O_RDWR, 0000);
+ fd = open(argv[optind], O_RDWR, 0000);
if (fd < 0) {
- fprintf(stderr, "Could not open %s: %s\n", poptPeekArg(pc),
+ fprintf(stderr, "Could not open %s: %s\n", argv[optind],
strerror(errno));
exit(2);
}
if (fstat(fd, &sbuf) < 0) {
- fprintf(stderr, "Could not stat file %s, %s\n", poptPeekArg(pc),
+ fprintf(stderr, "Could not stat file %s, %s\n", argv[optind],
strerror(errno));
exit(3);
}
@@ -609,7 +609,7 @@ int main(int argc, char *argv[])
base = mmap(&start, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if ((int)base == -1) {
- fprintf(stderr, "Could not mmap file: %s, %s\n", poptPeekArg(pc),
+ fprintf(stderr, "Could not mmap file: %s, %s\n", argv[optind],
strerror(errno));
exit(4);
}
@@ -640,7 +640,7 @@ int main(int argc, char *argv[])
if (verbose) fprintf(stdout, "Registry file size: %u\n", (unsigned int)sbuf.st_size);
if (IVAL(&regf_hdr->REGF_ID, 0) != REG_REGF_ID) {
- fprintf(stderr, "Incorrect Registry file (doesn't have header ID): %s\n", poptPeekArg(pc));
+ fprintf(stderr, "Incorrect Registry file (doesn't have header ID): %s\n", argv[optind]);
exit(5);
}
@@ -655,7 +655,7 @@ int main(int argc, char *argv[])
*/
if (IVAL(&hbin_hdr->HBIN_ID, 0) != REG_HBIN_ID) {
- fprintf(stderr, "Incorrect hbin hdr: %s\n", poptPeekArg(pc));
+ fprintf(stderr, "Incorrect hbin hdr: %s\n", argv[optind]);
exit(6);
}
@@ -666,7 +666,7 @@ int main(int argc, char *argv[])
nk_hdr = (NK_HDR *)(base + 0x1000 + IVAL(&regf_hdr->first_key, 0) + 4);
if (SVAL(&nk_hdr->NK_ID, 0) != REG_NK_ID) {
- fprintf(stderr, "Incorrect NK Header: %s\n", poptPeekArg(pc));
+ fprintf(stderr, "Incorrect NK Header: %s\n", argv[optind]);
exit(7);
}
@@ -724,8 +724,6 @@ int main(int argc, char *argv[])
munmap(base, sbuf.st_size);
- poptFreeContext(pc);
-
close(fd);
return 0;
}
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index 9d8a657726..069ac56c67 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -5,7 +5,6 @@
Copyright (C) Andrew Tridgell 2000
Copyright (C) Tim Potter 2000
Copyright (C) Jeremy Allison 2000
- Copyright (C) Jelmer Vernooij 2003
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
@@ -24,9 +23,12 @@
#include "includes.h"
+static fstring password;
+static pstring username;
static pstring owner_username;
static fstring server;
-static int test_args = False;
+static int got_pass;
+static int test_args;
static TALLOC_CTX *ctx;
#define CREATE_ACCESS_READ READ_CONTROL_ACCESS
@@ -34,7 +36,7 @@ static TALLOC_CTX *ctx;
/* numeric is set when the user wants numeric SIDs and ACEs rather
than going via LSA calls to resolve them */
-static BOOL numeric = False;
+static int numeric;
enum acl_mode {SMB_ACL_SET, SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD };
enum chown_mode {REQUEST_NONE, REQUEST_CHOWN, REQUEST_CHGRP};
@@ -713,19 +715,19 @@ static struct cli_state *connect_one(const char *share)
NTSTATUS nt_status;
zero_ip(&ip);
- if (!cmdline_auth_info.got_pass) {
+ if (!got_pass) {
char *pass = getpass("Password: ");
if (pass) {
- pstrcpy(cmdline_auth_info.password, pass);
- cmdline_auth_info.got_pass = True;
+ fstrcpy(password, pass);
+ got_pass = True;
}
}
if (NT_STATUS_IS_OK(nt_status = cli_full_connection(&c, global_myname(), server,
&ip, 0,
share, "?????",
- cmdline_auth_info.username, lp_workgroup(),
- cmdline_auth_info.password, 0, NULL))) {
+ username, lp_workgroup(),
+ password, 0, NULL))) {
return c;
} else {
DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
@@ -733,34 +735,45 @@ static struct cli_state *connect_one(const char *share)
}
}
+
+static void usage(void)
+{
+ printf(
+"Usage: smbcacls //server1/share1 filename [options]\n\
+\n\
+\t-D <acls> delete an acl\n\
+\t-M <acls> modify an acl\n\
+\t-A <acls> add an acl\n\
+\t-S <acls> set acls\n\
+\t-C username change ownership of a file\n\
+\t-G username change group ownership of a file\n\
+\t-n don't resolve sids or masks to names\n\
+\t-h print help\n\
+\t-d debuglevel set debug output level\n\
+\t-U username user to autheticate as\n\
+\n\
+The username can be of the form username%%password or\n\
+workgroup\\username%%password.\n\n\
+An acl is of the form ACL:<SID>:type/flags/mask\n\
+You can string acls together with spaces, commas or newlines\n\
+");
+}
+
/****************************************************************************
main program
****************************************************************************/
- int main(int argc, const char *argv[])
+ int main(int argc,char *argv[])
{
char *share;
+ pstring filename;
+ extern char *optarg;
+ extern int optind;
int opt;
+ char *p;
enum acl_mode mode = SMB_ACL_SET;
- static char *the_acl = NULL;
+ char *the_acl = NULL;
enum chown_mode change_mode = REQUEST_NONE;
int result;
- fstring path;
- pstring filename;
- poptContext pc;
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- { "delete", 'D', POPT_ARG_STRING, NULL, 'D', "Delete an acl", "ACL" },
- { "modify", 'M', POPT_ARG_STRING, NULL, 'M', "Modify an acl", "ACL" },
- { "add", 'A', POPT_ARG_STRING, NULL, 'A', "Add an acl", "ACL" },
- { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls", "ACLS" },
- { "chown", 'C', POPT_ARG_STRING, NULL, 'C', "Change ownership of a file", "USERNAME" },
- { "chgrp", 'G', POPT_ARG_STRING, NULL, 'G', "Change group ownership of a file", "GROUPNAME" },
- { "numeric", 0, POPT_ARG_NONE, &numeric, True, "Don't resolve sids or masks to names" },
- { "test-args", 't', POPT_ARG_NONE, &test_args, True, "Test arguments"},
- POPT_COMMON_SAMBA
- POPT_COMMON_CREDENTIALS
- { NULL }
- };
struct cli_state *cli;
@@ -770,72 +783,118 @@ static struct cli_state *connect_one(const char *share)
dbf = x_stderr;
+ if (argc < 3 || argv[1][0] == '-') {
+ usage();
+ talloc_destroy(ctx);
+ exit(EXIT_PARSE_ERROR);
+ }
+
setup_logging(argv[0],True);
+ share = argv[1];
+ pstrcpy(filename, argv[2]);
+ all_string_sub(share,"/","\\",0);
+
+ argc -= 2;
+ argv += 2;
+
lp_load(dyn_CONFIGFILE,True,False,False);
load_interfaces();
- pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
-
- poptSetOtherOptionHelp(pc, "//server1/share1 filename");
+ if (getenv("USER")) {
+ pstrcpy(username,getenv("USER"));
- while ((opt = poptGetNextOpt(pc)) != -1) {
+ if ((p=strchr_m(username,'%'))) {
+ *p = 0;
+ fstrcpy(password,p+1);
+ got_pass = True;
+ memset(strchr_m(getenv("USER"), '%') + 1, 'X',
+ strlen(password));
+ }
+ }
+
+ while ((opt = getopt(argc, argv, "U:nhS:D:A:M:C:G:td:")) != EOF) {
switch (opt) {
+ case 'U':
+ pstrcpy(username,optarg);
+ p = strchr_m(username,'%');
+ if (p) {
+ *p = 0;
+ fstrcpy(password, p+1);
+ got_pass = 1;
+ }
+ break;
+
case 'S':
- the_acl = smb_xstrdup(poptGetOptArg(pc));
+ the_acl = optarg;
mode = SMB_ACL_SET;
break;
case 'D':
- the_acl = smb_xstrdup(poptGetOptArg(pc));
+ the_acl = optarg;
mode = SMB_ACL_DELETE;
break;
case 'M':
- the_acl = smb_xstrdup(poptGetOptArg(pc));
+ the_acl = optarg;
mode = SMB_ACL_MODIFY;
break;
case 'A':
- the_acl = smb_xstrdup(poptGetOptArg(pc));
+ the_acl = optarg;
mode = SMB_ACL_ADD;
break;
case 'C':
- pstrcpy(owner_username,poptGetOptArg(pc));
+ pstrcpy(owner_username,optarg);
change_mode = REQUEST_CHOWN;
break;
case 'G':
- pstrcpy(owner_username,poptGetOptArg(pc));
+ pstrcpy(owner_username,optarg);
change_mode = REQUEST_CHGRP;
break;
+
+ case 'n':
+ numeric = 1;
+ break;
+
+ case 't':
+ test_args = 1;
+ break;
+
+ case 'h':
+ usage();
+ talloc_destroy(ctx);
+ exit(EXIT_PARSE_ERROR);
+
+ case 'd':
+ DEBUGLEVEL = atoi(optarg);
+ break;
+
+ default:
+ printf("Unknown option %c (%d)\n", (char)opt, opt);
+ talloc_destroy(ctx);
+ exit(EXIT_PARSE_ERROR);
}
}
- /* Make connection to server */
- if(!poptPeekArg(pc)) {
- poptPrintUsage(pc, stderr, 0);
- return -1;
- }
-
- fstrcpy(path, poptGetArg(pc));
-
- if(!poptPeekArg(pc)) {
- poptPrintUsage(pc, stderr, 0);
- return -1;
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ usage();
+ talloc_destroy(ctx);
+ exit(EXIT_PARSE_ERROR);
}
-
- pstrcpy(filename, poptGetArg(pc));
- all_string_sub(path,"/","\\",0);
+ /* Make connection to server */
- fstrcpy(server,path+2);
+ fstrcpy(server,share+2);
share = strchr_m(server,'\\');
if (!share) {
share = strchr_m(server,'/');
if (!share) {
- printf("Invalid argument: %s\n", share);
return -1;
}
}
@@ -875,3 +934,4 @@ static struct cli_state *connect_one(const char *share)
return result;
}
+
diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c
index 8b984d9bd1..ec4f41cad6 100644
--- a/source3/utils/smbcontrol.c
+++ b/source3/utils/smbcontrol.c
@@ -1,11 +1,8 @@
/*
Unix SMB/CIFS implementation.
-
- Send messages to other Samba daemons
-
- Copyright (C) Tim Potter 2003
+ program to send control messages to Samba processes
Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Martin Pool 2001-2002
+ Copyright (C) 2001, 2002 by Martin Pool
Copyright (C) Simo Sorce 2002
This program is free software; you can redistribute it and/or modify
@@ -25,718 +22,698 @@
#include "includes.h"
-/* Default timeout value when waiting for replies (in seconds) */
-
-#define DEFAULT_TIMEOUT 10
-
-static int timeout = DEFAULT_TIMEOUT;
-static int num_replies; /* Used by message callback fns */
+extern BOOL AllowDebugChange;
-/* Send a message to a destination pid. Zero means broadcast smbd. */
-
-static BOOL send_message(pid_t pid, int msg_type, void *buf, int len,
- BOOL duplicates)
-{
- TDB_CONTEXT *tdb;
- BOOL ret;
- int n_sent = 0;
-
- if (!message_init())
- return False;
-
- if (pid != 0)
- return message_send_pid(pid, msg_type, buf, len, duplicates);
-
- tdb = tdb_open_log(lock_path("connections.tdb"), 0,
- TDB_DEFAULT, O_RDWR, 0);
- if (!tdb) {
- fprintf(stderr,"Failed to open connections database"
- ": %s\n", strerror(errno));
- return False;
- }
-
- ret = message_send_all(tdb,msg_type, buf, len, duplicates,
- &n_sent);
- DEBUG(10,("smbcontrol/send_message: broadcast message to "
- "%d processes\n", n_sent));
-
- tdb_close(tdb);
-
- return ret;
-}
-
-/* Wait for one or more reply messages */
-
-static void wait_replies(BOOL multiple_replies)
-{
- time_t start_time = time(NULL);
+static const struct {
+ const char *name;
+ int value;
+} msg_types[] = {
+ {"debug", MSG_DEBUG},
+ {"force-election", MSG_FORCE_ELECTION},
+ {"ping", MSG_PING},
+ {"profile", MSG_PROFILE},
+ {"profilelevel", MSG_REQ_PROFILELEVEL},
+ {"debuglevel", MSG_REQ_DEBUGLEVEL},
+ {"printnotify", MSG_PRINTER_NOTIFY2 },
+ {"close-share", MSG_SMB_FORCE_TDIS},
+ {"samsync", MSG_SMB_SAM_SYNC},
+ {"samrepl", MSG_SMB_SAM_REPL},
+ {"pool-usage", MSG_REQ_POOL_USAGE },
+ {"dmalloc-mark", MSG_REQ_DMALLOC_MARK },
+ {"dmalloc-log-changed", MSG_REQ_DMALLOC_LOG_CHANGED },
+ {"shutdown", MSG_SHUTDOWN },
+ {"drvupgrade", MSG_PRINTER_DRVUPGRADE},
+ {"tallocdump", MSG_REQ_TALLOC_USAGE},
+ {NULL, -1}
+};
- /* Wait around a bit. This is pretty disgusting - we have to
- busy-wait here as there is no nicer way to do it. */
+time_t timeout_start;
- do {
- message_dispatch();
- if (num_replies > 0 && !multiple_replies)
- break;
- sleep(1);
- } while (timeout - (time(NULL) - start_time) > 0);
-}
+#define MAX_WAIT 10
-/* Message handler callback that displays a string on stdout */
+/* we need these because we link to printing*.o */
-static void print_string_cb(int msg_type, pid_t pid, void *buf, size_t len)
-{
- printf("%.*s", (int)len, (const char *)buf);
- num_replies++;
-}
+void become_root(void) {}
+void unbecome_root(void) {}
-/* Send no message. Useful for testing. */
-static BOOL do_noop(const pid_t pid, const int argc, char **argv)
+static void usage(BOOL doexit)
{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
- return False;
+ int i;
+ if (doexit) {
+ printf("Usage: smbcontrol -i -s configfile\n");
+ printf(" smbcontrol <destination> <message-type> <parameters>\n\n");
+ } else {
+ printf("<destination> <message-type> <parameters>\n\n");
}
-
- /* Move along, nothing to see here */
-
- return True;
+ printf("\t<destination> is one of \"nmbd\", \"smbd\" or a process ID\n");
+ printf("\t<message-type> is one of:\n");
+ for (i=0; msg_types[i].name; i++)
+ printf("\t\t%s\n", msg_types[i].name);
+ printf("\n");
+ if (doexit) exit(1);
}
-/* Send a debug string */
-
-static BOOL do_debug(const pid_t pid, const int argc, char **argv)
+static int pong_count;
+static BOOL got_level;
+static BOOL got_pool;
+static BOOL pong_registered = False;
+static BOOL debuglevel_registered = False;
+static BOOL poolusage_registered = False;
+static BOOL profilelevel_registered = False;
+
+
+/**
+ * Wait for replies for up to @p *max_secs seconds, or until @p
+ * max_replies are received. max_replies may be NULL in which case it
+ * is ignored.
+ *
+ * @note This is a pretty lame timeout; all it means is that after
+ * max_secs we won't look for any more messages.
+ **/
+static void wait_for_replies(int max_secs, int *max_replies)
{
- if (argc != 2) {
- fprintf(stderr, "Usage: smbcontrol <dest> debug "
- "<debug-string>\n");
- return False;
- }
+ time_t timeout_end = time(NULL) + max_secs;
- return send_message(
- pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
-}
-
-/* Force a browser election */
-
-static BOOL do_election(const pid_t pid, const int argc, char **argv)
-{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
- return False;
+ while ((!max_replies || (*max_replies)-- > 0)
+ && (time(NULL) < timeout_end)) {
+ message_dispatch();
}
-
- return send_message(
- pid, MSG_FORCE_ELECTION, NULL, 0, False);
}
-/* Ping a samba daemon process */
-static void pong_cb(int msg_type, pid_t pid, void *buf, size_t len)
+/****************************************************************************
+a useful function for testing the message system
+****************************************************************************/
+void pong_function(int msg_type, pid_t src, void *buf, size_t len)
{
- printf("PONG from pid %u\n", (unsigned int)pid);
- num_replies++;
+ pong_count++;
+ printf("PONG from PID %u\n",(unsigned int)src);
}
-static BOOL do_ping(const pid_t pid, const int argc, char **argv)
+/****************************************************************************
+ Prints out the current talloc list.
+****************************************************************************/
+void tallocdump_function(int msg_type, pid_t src, void *buf, size_t len)
{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
- return False;
- }
-
- /* Send a message and register our interest in a reply */
-
- if (!send_message(pid, MSG_PING, NULL, 0, False))
- return False;
-
- message_register(MSG_PONG, pong_cb);
-
- wait_replies(pid == 0);
-
- /* No replies were received within the timeout period */
-
- if (num_replies == 0)
- printf("No replies received\n");
-
- message_deregister(MSG_PONG);
-
- return num_replies;
+ char *info = (char *)buf;
+
+ printf("Current talloc contexts for process %u\n", (unsigned int)src );
+ if (len == 0)
+ printf("None returned\n");
+ else
+ printf(info);
+ printf("\n");
+ got_pool = True;
}
-/* Set profiling options */
-
-static BOOL do_profile(const pid_t pid, const int argc, char **argv)
+/****************************************************************************
+Prints out the current Debug level returned by MSG_DEBUGLEVEL
+****************************************************************************/
+void debuglevel_function(int msg_type, pid_t src, void *buf, size_t len)
{
- int v;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: smbcontrol <dest> profile "
- "<off|count|on|flush>\n");
- return False;
- }
-
- if (strcmp(argv[1], "off") == 0) {
- v = 0;
- } else if (strcmp(argv[1], "count") == 0) {
- v = 1;
- } else if (strcmp(argv[1], "on") == 0) {
- v = 2;
- } else if (strcmp(argv[1], "flush") == 0) {
- v = 3;
- } else {
- fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
- return False;
- }
+ const char *levels = (char *)buf;
- return send_message(pid, MSG_PROFILE, &v, sizeof(int), False);
+ printf("Current debug levels of PID %u are:\n",(unsigned int)src);
+ printf("%s\n", levels);
+
+ got_level = True;
}
-/* Return the profiling level */
-
-static void profilelevel_cb(int msg_type, pid_t pid, void *buf, size_t len)
+/****************************************************************************
+Prints out the current Profile level returned by MSG_PROFILELEVEL
+****************************************************************************/
+void profilelevel_function(int msg_type, pid_t src, void *buf, size_t len)
{
- int level;
- const char *s;
+ int level;
+ const char *s=NULL;
+ memcpy(&level, buf, sizeof(int));
- num_replies++;
-
- if (len != sizeof(int)) {
- fprintf(stderr, "invalid message length %d returned\n", len);
- return;
- }
-
- memcpy(&level, buf, sizeof(int));
-
- switch (level) {
- case 0:
- s = "not enabled";
- break;
- case 1:
+ if (level) {
+ switch (level) {
+ case 1:
s = "off";
break;
- case 3:
+ case 3:
s = "count only";
break;
- case 7:
+ case 7:
s = "count and time";
break;
- default:
- s = "BOGUS";
- break;
+ default:
+ s = "BOGUS";
+ break;
+ }
+ printf("Profiling %s on PID %u\n",s,(unsigned int)src);
+ } else {
+ printf("Profiling not available on PID %u\n",(unsigned int)src);
}
-
- printf("Profiling %s on pid %u\n",s,(unsigned int)pid);
+ got_level = True;
}
-static void profilelevel_rqst(int msg_type, pid_t pid, void *buf, size_t len)
+/**
+ * Handle reply from POOL_USAGE.
+ **/
+static void pool_usage_cb(int msg_type, pid_t src_pid, void *buf, size_t len)
{
- int v = 0;
-
- /* Send back a dummy reply */
-
- send_message(pid, MSG_PROFILELEVEL, &v, sizeof(int), False);
+ printf("Got POOL_USAGE reply from pid%u:\n%.*s",
+ (unsigned int) src_pid, (int) len, (const char *) buf);
}
-static BOOL do_profilelevel(const pid_t pid, const int argc, char **argv)
-{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
- return False;
- }
-
- /* Send a message and register our interest in a reply */
-
- if (!send_message(pid, MSG_REQ_PROFILELEVEL, NULL, 0, False))
- return False;
-
- message_register(MSG_PROFILELEVEL, profilelevel_cb);
- message_register(MSG_REQ_PROFILELEVEL, profilelevel_rqst);
- wait_replies(pid == 0);
-
- /* No replies were received within the timeout period */
-
- if (num_replies == 0)
- printf("No replies received\n");
+/**
+ * Send a message to a named destination
+ *
+ * @return False if an error occurred.
+ **/
+static BOOL send_message(char *dest, int msg_type, void *buf, int len, BOOL duplicates)
+{
+ pid_t pid;
+ /* "smbd" is the only broadcast operation */
+ if (strequal(dest,"smbd")) {
+ TDB_CONTEXT *tdb;
+ BOOL ret;
+ int n_sent = 0;
+
+ tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDWR, 0);
+ if (!tdb) {
+ fprintf(stderr,"Failed to open connections database in send_message.\n");
+ return False;
+ }
- message_deregister(MSG_PROFILE);
+ ret = message_send_all(tdb,msg_type, buf, len, duplicates,
+ &n_sent);
+ DEBUG(10,("smbcontrol/send_message: broadcast message to "
+ "%d processes\n", n_sent));
+ tdb_close(tdb);
+
+ return ret;
+ } else if (strequal(dest,"nmbd")) {
+ pid = pidfile_pid(dest);
+ if (pid == 0) {
+ fprintf(stderr,"Can't find pid for nmbd\n");
+ return False;
+ }
+ } else if (strequal(dest,"self")) {
+ pid = sys_getpid();
+ } else {
+ pid = atoi(dest);
+ if (pid == 0) {
+ fprintf(stderr,"Not a valid pid\n");
+ return False;
+ }
+ }
- return num_replies;
+ DEBUG(10,("smbcontrol/send_message: send message to pid%d\n", pid));
+ return message_send_pid(pid, msg_type, buf, len, duplicates);
}
-/* Display debug level settings */
-
-static BOOL do_debuglevel(const pid_t pid, const int argc, char **argv)
+/****************************************************************************
+evaluate a message type string
+****************************************************************************/
+static int parse_type(char *mtype)
{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
- return False;
+ int i;
+ for (i=0;msg_types[i].name;i++) {
+ if (strequal(mtype, msg_types[i].name)) return msg_types[i].value;
}
+ return -1;
+}
- /* Send a message and register our interest in a reply */
- if (!send_message(pid, MSG_REQ_DEBUGLEVEL, NULL, 0, False))
- return False;
+static void register_all(void)
+{
+ message_register(MSG_POOL_USAGE, pool_usage_cb);
+}
- message_register(MSG_DEBUGLEVEL, print_string_cb);
+/* This guy is here so we can link printing/notify.c to the smbcontrol
+ binary without having to pull in tons of other crap. */
- wait_replies(pid == 0);
+TDB_CONTEXT *conn_tdb_ctx(void)
+{
+ static TDB_CONTEXT *tdb;
- /* No replies were received within the timeout period */
+ if (tdb)
+ return tdb;
- if (num_replies == 0)
- printf("No replies received\n");
+ tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0);
- message_deregister(MSG_DEBUGLEVEL);
+ if (!tdb)
+ DEBUG(3, ("Failed to open connections database in send_spoolss_notify2_msg\n"));
- return num_replies;
+ return tdb;
}
-/* Send a print notify message */
-
-static BOOL do_printnotify(const pid_t pid, const int argc, char **argv)
+/****************************************************************************
+do command
+****************************************************************************/
+static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
{
- char *cmd;
-
- /* Check for subcommand */
-
- if (argc == 1) {
- fprintf(stderr, "Must specify subcommand:\n");
- fprintf(stderr, "\tqueuepause <printername>\n");
- fprintf(stderr, "\tqueueresume <printername>\n");
- fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
- fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
- fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
- fprintf(stderr, "\tprinter <printername> <comment|port|"
- "driver> <value>\n");
-
- return False;
+ int i, n, v;
+ int mtype;
+ BOOL retval=False;
+ BOOL check_notify_msgs = False;
+
+ mtype = parse_type(msg_name);
+ if (mtype == -1) {
+ fprintf(stderr,"Couldn't resolve message type: %s\n", msg_name);
+ return(False);
}
- cmd = argv[1];
+ switch (mtype) {
+ case MSG_DEBUG: {
+ char *buf, *b;
+ char **p;
+ int dim = 0;
- if (strcmp(cmd, "queuepause") == 0) {
-
- if (argc != 3) {
- fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
- " queuepause <printername>\n");
- return False;
+ if (!params || !params[0]) {
+ fprintf(stderr,"MSG_DEBUG needs a parameter\n");
+ return(False);
}
-
- notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
- goto send;
-
- } else if (strcmp(cmd, "queueresume") == 0) {
-
- if (argc != 3) {
- fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
- " queuereume <printername>\n");
- return False;
+ /* first pass retrieve total lenght */
+ for (p = params; p && *p ; p++)
+ dim += (strnlen(*p, 1024) +1); /* lenght + space */
+ b = buf = malloc(dim);
+ if (!buf) {
+ fprintf(stderr, "Out of memory!");
+ return(False);
}
-
- notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
-
- goto send;
-
- } else if (strcmp(cmd, "jobpause") == 0) {
- int jobid;
-
- if (argc != 4) {
- fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
- " jobpause <printername> <unix-jobid>\n");
- return False;
+ /* now build a single string with all parameters */
+ for(p = params; p && *p; p++) {
+ int l = strnlen(*p, 1024);
+ strncpy(b, *p, l);
+ b[l] = ' ';
+ b = b + l + 1;
}
+ b[-1] = '\0';
- jobid = atoi(argv[3]);
+ send_message(dest, MSG_DEBUG, buf, dim, False);
- notify_job_status_byname(
- argv[2], jobid, JOB_STATUS_PAUSED,
- SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
-
- goto send;
-
- } else if (strcmp(cmd, "jobresume") == 0) {
- int jobid;
+ free(buf);
+
+ break;
+ }
- if (argc != 4) {
- fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
- " jobpause <printername> <unix-jobid>\n");
- return False;
+ case MSG_PROFILE:
+ if (!params || !params[0]) {
+ fprintf(stderr,"MSG_PROFILE needs a parameter\n");
+ return(False);
}
-
- jobid = atoi(argv[3]);
-
- notify_job_status_byname(
- argv[2], jobid, JOB_STATUS_QUEUED,
- SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
-
- goto send;
-
- } else if (strcmp(cmd, "jobdelete") == 0) {
- int jobid;
-
- if (argc != 4) {
- fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
- " jobpause <printername> <unix-jobid>\n");
- return False;
+ if (strequal(params[0], "off")) {
+ v = 0;
+ } else if (strequal(params[0], "count")) {
+ v = 1;
+ } else if (strequal(params[0], "on")) {
+ v = 2;
+ } else if (strequal(params[0], "flush")) {
+ v = 3;
+ } else {
+ fprintf(stderr,
+ "MSG_PROFILE parameter must be off, count, on, or flush\n");
+ return(False);
}
+ send_message(dest, MSG_PROFILE, &v, sizeof(int), False);
+ break;
- jobid = atoi(argv[3]);
-
- notify_job_status_byname(
- argv[2], jobid, JOB_STATUS_DELETING,
- SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
-
- notify_job_status_byname(
- argv[2], jobid, JOB_STATUS_DELETING|
- JOB_STATUS_DELETED,
- SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
-
- goto send;
-
- } else if (strcmp(cmd, "printer") == 0) {
- uint32 attribute;
-
- if (argc != 5) {
- fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
- "printer <printername> <comment|port|driver> "
- "<value>\n");
- return False;
+ case MSG_FORCE_ELECTION:
+ if (!strequal(dest, "nmbd")) {
+ fprintf(stderr,"force-election can only be sent to nmbd\n");
+ return(False);
}
+ send_message(dest, MSG_FORCE_ELECTION, NULL, 0, False);
+ break;
- if (strcmp(argv[3], "comment") == 0) {
- attribute = PRINTER_NOTIFY_COMMENT;
- } else if (strcmp(argv[3], "port") == 0) {
- attribute = PRINTER_NOTIFY_PORT_NAME;
- } else if (strcmp(argv[3], "driver") == 0) {
- attribute = PRINTER_NOTIFY_DRIVER_NAME;
- } else {
- fprintf(stderr, "Invalid printer command '%s'\n",
- argv[3]);
- return False;
+ case MSG_REQ_PROFILELEVEL:
+ if (!profilelevel_registered) {
+ message_register(MSG_PROFILELEVEL, profilelevel_function);
+ profilelevel_registered = True;
}
+ got_level = False;
+ retval = send_message(dest, MSG_REQ_PROFILELEVEL, NULL, 0, True);
+ if (retval) {
+ timeout_start = time(NULL);
+ while (!got_level) {
+ message_dispatch();
+ if ((time(NULL) - timeout_start) > MAX_WAIT) {
+ fprintf(stderr,"profilelevel timeout\n");
+ break;
+ }
+ }
+ }
+ break;
- notify_printer_byname(argv[2], attribute, argv[4]);
-
- goto send;
- }
-
- fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
- return False;
-
-send:
- print_notify_send_messages(0);
- return True;
-}
-
-/* Close a share */
-
-static BOOL do_closeshare(const pid_t pid, const int argc, char **argv)
-{
- if (argc != 2) {
- fprintf(stderr, "Usage: smbcontrol <dest> close-share "
- "<sharename>\n");
- return False;
- }
-
- return send_message(
- pid, MSG_SMB_FORCE_TDIS, argv[1], strlen(argv[1]) + 1, False);
-}
-
-/* Force a SAM synchronisation */
-
-static BOOL do_samsync(const pid_t pid, const int argc, char **argv)
-{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
- return False;
- }
-
- return send_message(
- pid, MSG_SMB_SAM_SYNC, NULL, 0, False);
-}
-
-/* Force a SAM replication */
-
-static BOOL do_samrepl(const pid_t pid, const int argc, char **argv)
-{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
- return False;
- }
-
- return send_message(
- pid, MSG_SMB_SAM_REPL, NULL, 0, False);
-}
-
-/* Display talloc pool usage */
-
-static BOOL do_poolusage(const pid_t pid, const int argc, char **argv)
-{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
- return False;
- }
-
- /* Send a message and register our interest in a reply */
-
- if (!send_message(pid, MSG_REQ_POOL_USAGE, NULL, 0, False))
- return False;
+ case MSG_REQ_TALLOC_USAGE:
+ if (!poolusage_registered) {
+ message_register(MSG_TALLOC_USAGE, tallocdump_function);
+ poolusage_registered = True;
+ }
+ got_pool = False;
+ retval = send_message(dest, MSG_REQ_TALLOC_USAGE, NULL, 0, True);
+ if (retval) {
+ timeout_start = time(NULL);
+ while (!got_pool) {
+ message_dispatch();
+ if ((time(NULL) - timeout_start) > MAX_WAIT) {
+ fprintf(stderr,"tallocdump timeout\n");
+ break;
+ }
+ }
+ }
+ break;
- message_register(MSG_POOL_USAGE, print_string_cb);
+ case MSG_REQ_DEBUGLEVEL:
+ if (!debuglevel_registered) {
+ message_register(MSG_DEBUGLEVEL, debuglevel_function);
+ debuglevel_registered = True;
+ }
+ got_level = False;
+ retval = send_message(dest, MSG_REQ_DEBUGLEVEL, NULL, 0, True);
+ if (retval) {
+ timeout_start = time(NULL);
+ while (!got_level) {
+ message_dispatch();
+ if ((time(NULL) - timeout_start) > MAX_WAIT) {
+ fprintf(stderr,"debuglevel timeout\n");
+ break;
+ }
+ }
+ }
+ break;
- wait_replies(pid == 0);
+ /* Send a notification message to a printer */
- /* No replies were received within the timeout period */
+ case MSG_PRINTER_NOTIFY2: {
+ char *cmd;
- if (num_replies == 0)
- printf("No replies received\n");
+ /* Read subcommand */
- message_deregister(MSG_POOL_USAGE);
+ if (!params || !params[0]) {
+ fprintf(stderr, "Must specify subcommand:\n");
+ fprintf(stderr, "\tqueuepause <printername>\n");
+ fprintf(stderr, "\tqueueresume <printername>\n");
+ fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
+ fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
+ fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
+ fprintf(stderr, "\tprinter <printername> <comment|port|driver> <new value>\n");
+ return False;
+ }
- return num_replies;
-}
+ cmd = params[0];
-/* Perform a dmalloc mark */
+ check_notify_msgs = True;
-static BOOL do_dmalloc_mark(const pid_t pid, const int argc, char **argv)
-{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
- return False;
- }
+ /* Pause a print queue */
- return send_message(
- pid, MSG_REQ_DMALLOC_MARK, NULL, 0, False);
-}
+ if (strequal(cmd, "queuepause")) {
-/* Perform a dmalloc changed */
+ if (!params[1]) {
+ fprintf(stderr, "queuepause command requires a printer name\n");
+ return False;
+ }
-static BOOL do_dmalloc_changed(const pid_t pid, const int argc,
- char **argv)
-{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> "
- "dmalloc-log-changed\n");
- return False;
- }
+ notify_printer_status_byname(params[1], PRINTER_STATUS_PAUSED);
+ break;
+ }
- return send_message(
- pid, MSG_REQ_DMALLOC_LOG_CHANGED, NULL, 0, False);
-}
+ /* Resume a print queue */
-/* Shutdown a server process */
+ if (strequal(cmd, "queueresume")) {
-static BOOL do_shutdown(const pid_t pid, const int argc, char **argv)
-{
- if (argc != 1) {
- fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
- return False;
- }
+ if (!params[1]) {
+ fprintf(stderr, "queueresume command requires a printer name\n");
+ return False;
+ }
- return send_message(pid, MSG_SHUTDOWN, NULL, 0, False);
-}
+ notify_printer_status_byname(params[1], PRINTER_STATUS_OK);
+ break;
+ }
-/* Notify a driver upgrade */
+ /* Pause a print job */
-static BOOL do_drvupgrade(const pid_t pid, const int argc, char **argv)
-{
- if (argc != 2) {
- fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
- "<driver-name>\n");
- return False;
- }
+ if (strequal(cmd, "jobpause")) {
+ int jobid;
- return send_message(
- pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
-}
+ if (!params[1] || !params[2]) {
+ fprintf(stderr, "jobpause command requires a printer name and a jobid\n");
+ return False;
+ }
-/* A list of message type supported */
+ jobid = atoi(params[2]);
-static const struct {
- const char *name; /* Option name */
- BOOL (*fn)(const pid_t pid, const int argc, char **argv);
- const char *help; /* Short help text */
-} msg_types[] = {
- { "debug", do_debug, "Set debuglevel" },
- { "force-election", do_election,
- "Force a browse election" },
- { "ping", do_ping, "Elicit a response" },
- { "profile", do_profile, "" },
- { "profilelevel", do_profilelevel, "" },
- { "debuglevel", do_debuglevel, "Display current debuglevels" },
- { "printnotify", do_printnotify, "Send a print notify message" },
- { "close-share", do_closeshare, "Forcibly disconnect a share" },
- { "samsync", do_samsync, "Initiate SAM synchronisation" },
- { "samrepl", do_samrepl, "Initiate SAM replication" },
- { "pool-usage", do_poolusage, "Display talloc memory usage" },
- { "dmalloc-mark", do_dmalloc_mark, "" },
- { "dmalloc-log-changed", do_dmalloc_changed, "" },
- { "shutdown", do_shutdown, "Shut down daemon" },
- { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
- { "noop", do_noop, "Do nothing" },
- { NULL }
-};
+ notify_job_status_byname(
+ params[1], jobid, JOB_STATUS_PAUSED,
+ SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
+ break;
+ }
-/* Yuck - we need these because we link to printing*.o even though
- they aren't used. */
+ /* Resume a print job */
-void become_root(void) {}
-void unbecome_root(void) {}
+ if (strequal(cmd, "jobresume")) {
+ int jobid;
-/* Display usage information */
+ if (!params[1] || !params[2]) {
+ fprintf(stderr, "jobresume command requires a printer name and a jobid\n");
+ return False;
+ }
-static void usage(poptContext *pc)
-{
- int i;
+ jobid = atoi(params[2]);
- poptPrintHelp(*pc, stderr, 0);
+ notify_job_status_byname(
+ params[1], jobid, JOB_STATUS_QUEUED,
+ SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
+ break;
+ }
- fprintf(stderr, "\n");
- fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\" or a "
- "process ID\n");
+ /* Delete a print job */
- fprintf(stderr, "\n");
- fprintf(stderr, "<message-type> is one of:\n");
+ if (strequal(cmd, "jobdelete")) {
+ int jobid;
- for (i = 0; msg_types[i].name; i++)
- fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
- msg_types[i].help);
+ if (!params[1] || !params[2]) {
+ fprintf(stderr, "jobdelete command requires a printer name and a jobid\n");
+ return False;
+ }
- fprintf(stderr, "\n");
+ jobid = atoi(params[2]);
- exit(1);
-}
+ notify_job_status_byname(
+ params[1], jobid, JOB_STATUS_DELETING,
+ SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
-/* Return the pid number for a string destination */
+ notify_job_status_byname(
+ params[1], jobid, JOB_STATUS_DELETING|
+ JOB_STATUS_DELETED,
+ SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
+ }
+
+ /* printer change notify */
+
+ if (strequal(cmd, "printer")) {
+ int attribute = -1;
+
+ if (!params[1] || !params[2] || !params[3]) {
+ fprintf(stderr, "printer command requires an and attribute name and value!\n");
+ fprintf(stderr, "supported attributes:\n");
+ fprintf(stderr, "\tcomment:\n");
+ fprintf(stderr, "\tport:\n");
+ fprintf(stderr, "\tdriver:\n");
+ return False;
+ }
+ if ( strequal(params[2], "comment") )
+ attribute = PRINTER_NOTIFY_COMMENT;
+ else if ( strequal(params[2], "port") )
+ attribute = PRINTER_NOTIFY_PORT_NAME;
+ else if ( strequal(params[2], "driver") )
+ attribute = PRINTER_NOTIFY_DRIVER_NAME;
+
+ if ( attribute == -1 ) {
+ fprintf(stderr, "bad attribute!\n");
+ return False;
+ }
+
+ notify_printer_byname( params[1], attribute, params[3]);
+
+ break;
+ }
+
+ break;
+ }
-static pid_t parse_dest(char *dest)
-{
- pid_t pid;
- /* Zero is a special return value for broadcast smbd */
+ case MSG_SMB_FORCE_TDIS:
+ if (!strequal(dest, "smbd")) {
+ fprintf(stderr,"close-share can only be sent to smbd\n");
+ return(False);
+ }
+ if (!params || !params[0]) {
+ fprintf(stderr, "close-share needs a share name or '*'\n");
+ return (False);
+ }
+ retval = send_message(dest, MSG_SMB_FORCE_TDIS, params[0],
+ strlen(params[0]) + 1, False);
+ break;
- if (strequal(dest, "smbd"))
- return 0;
+ case MSG_SMB_SAM_SYNC:
+ if (!strequal(dest, "smbd")) {
+ fprintf(stderr, "samsync can only be sent to smbd\n");
+ return False;
+ }
- /* Try self - useful for testing */
+ if (params) {
+ fprintf(stderr, "samsync does not take any parameters\n");
+ return False;
+ }
- if (strequal(dest, "self"))
- return sys_getpid();
+ retval = send_message(dest, MSG_SMB_SAM_SYNC, NULL, 0, False);
- /* Check for numeric pid number */
+ break;
- if ((pid = atoi(dest)) != 0)
- return pid;
+ case MSG_SMB_SAM_REPL: {
+ uint32 seqnum;
- /* Look up other destinations in pidfile directory */
+ if (!strequal(dest, "smbd")) {
+ fprintf(stderr, "sam repl can only be sent to smbd\n");
+ return False;
+ }
- if ((pid = pidfile_pid(dest)) != 0)
- return pid;
+ if (!params || !params[0]) {
+ fprintf(stderr, "SAM_REPL needs a parameter\n");
+ return False;
+ }
- fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
+ seqnum = atoi(params[0]);
- return -1;
-}
+ retval = send_message(dest, MSG_SMB_SAM_SYNC,
+ (char *)&seqnum, sizeof(uint32), False);
-/* Execute smbcontrol command */
+ break;
+ }
-static BOOL do_command(int argc, char **argv)
-{
- char *dest = argv[0], *command = argv[1];
- pid_t pid;
- int i;
+ case MSG_PING:
+ if (!pong_registered) {
+ message_register(MSG_PONG, pong_function);
+ pong_registered = True;
+ }
+ if (!params || !params[0]) {
+ fprintf(stderr,"MSG_PING needs a parameter\n");
+ return(False);
+ }
+ n = atoi(params[0]);
+ pong_count = 0;
+ for (i=0;i<n;i++) {
+ if (iparams > 1)
+ retval = send_message(dest, MSG_PING, params[1], strlen(params[1]) + 1, True);
+ else
+ retval = send_message(dest, MSG_PING, NULL, 0, True);
+ if (retval == False)
+ return False;
+ }
+ wait_for_replies(MAX_WAIT, &n);
+ if (n > 0) {
+ fprintf(stderr,"PING timeout\n");
+ }
+ break;
- /* Check destination */
+ case MSG_REQ_POOL_USAGE:
+ if (!send_message(dest, MSG_REQ_POOL_USAGE, NULL, 0, True))
+ return False;
+ wait_for_replies(MAX_WAIT, NULL);
+
+ break;
- if ((pid = parse_dest(dest)) == -1)
- return False;
+ case MSG_REQ_DMALLOC_LOG_CHANGED:
+ case MSG_REQ_DMALLOC_MARK:
+ if (!send_message(dest, mtype, NULL, 0, False))
+ return False;
+ break;
- /* Check command */
+ case MSG_SHUTDOWN:
+ if (!send_message(dest, MSG_SHUTDOWN, NULL, 0, False))
+ return False;
+ break;
+ case MSG_PRINTER_DRVUPGRADE:
+ if (!params || !params[0]) {
+ fprintf(stderr,"drvupgrade needs a parameter\n");
+ return(False);
+ }
- for (i = 0; msg_types[i].name; i++) {
- if (strequal(command, msg_types[i].name))
- return msg_types[i].fn(pid, argc - 1, argv + 1);
+ if (!send_message(dest, MSG_PRINTER_DRVUPGRADE, params[0], 0, False))
+ return False;
+ break;
}
- fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
+ /* check if we have any pending print notify messages */
- return False;
+ if ( check_notify_msgs )
+ print_notify_send_messages(0);
+
+ return (True);
}
-/* Main program */
-
-int main(int argc, char **argv)
+ int main(int argc, char *argv[])
{
- poptContext pc;
int opt;
+ char temp[255];
+ extern int optind;
+ BOOL interactive = False;
- struct poptOption wbinfo_options[] = {
- { "timeout", 't', POPT_ARG_INT, &timeout, 't',
- "Set timeout value in seconds", "TIMEOUT" },
-
- { "configfile", 's', POPT_ARG_STRING, NULL, 's',
- "Use alternative configuration file", "CONFIGFILE" },
-
- POPT_TABLEEND
- };
-
- struct poptOption options[] = {
- { NULL, 0, POPT_ARG_INCLUDE_TABLE, wbinfo_options, 0,
- "Options" },
-
- POPT_AUTOHELP
- POPT_COMMON_VERSION
- POPT_TABLEEND
- };
+ AllowDebugChange = False;
+ DEBUGLEVEL = 0;
setup_logging(argv[0],True);
- /* Parse command line arguments using popt */
-
- pc = poptGetContext(
- "smbcontrol", argc, (const char **)argv, options, 0);
-
- poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
- "<parameters>");
-
- if (argc == 1)
- usage(&pc);
+ if (argc < 2) usage(True);
- while ((opt = poptGetNextOpt(pc)) != -1) {
- switch(opt) {
- case 't': /* --timeout */
- argc -= 2;
+ while ((opt = getopt(argc, argv,"is:")) != EOF) {
+ switch (opt) {
+ case 'i':
+ interactive = True;
break;
- case 's': /* --configfile */
+ case 's':
pstrcpy(dyn_CONFIGFILE, optarg);
- argc -= 2;
break;
default:
- fprintf(stderr, "Invalid option\n");
- poptPrintHelp(pc, stderr, 0);
- break;
+ printf("Unknown option %c (%d)\n", (char)opt, opt);
+ usage(True);
}
}
- /* We should now have the remaining command line arguments in
- argv. The argc parameter should have been decremented to the
- correct value in the above switch statement. */
+ lp_load(dyn_CONFIGFILE,False,False,False);
- argv = (char **)poptGetArgs(pc);
- argc--; /* Don't forget about argv[0] */
+ if (!message_init()) exit(1);
- if (argc == 1)
- usage(&pc);
+ argc -= optind;
+ argv = &argv[optind];
- lp_load(dyn_CONFIGFILE,False,False,False);
+ register_all();
- /* Need to invert sense of return code -- samba
- * routines mostly return True==1 for success, but
- * shell needs 0. */
-
- return !do_command(argc, argv);
+ if (!interactive) {
+ if (argc < 2) usage(True);
+ /* Need to invert sense of return code -- samba
+ * routines mostly return True==1 for success, but
+ * shell needs 0. */
+ return ! do_command(argv[0],argv[1], argc-2, argc > 2 ? &argv[2] : 0);
+ }
+
+ while (True) {
+ char *myargv[4];
+ int myargc;
+
+ printf("smbcontrol> ");
+ if (!fgets(temp, sizeof(temp)-1, stdin)) break;
+ myargc = 0;
+ while ((myargc < 4) &&
+ (myargv[myargc] = strtok(myargc?NULL:temp," \t\n"))) {
+ myargc++;
+ }
+ if (!myargc) break;
+ if (strequal(myargv[0],"q")) break;
+ if (myargc < 2)
+ usage(False);
+ else if (!do_command(myargv[0],myargv[1],myargc-2,myargc > 2 ? &myargv[2] : 0))
+ usage(False);
+ }
+ return(0);
}
+
diff --git a/source3/utils/smbtree.c b/source3/utils/smbtree.c
index cbe1bd448f..940120d644 100644
--- a/source3/utils/smbtree.c
+++ b/source3/utils/smbtree.c
@@ -3,7 +3,6 @@
Network neighbourhood browser.
Copyright (C) Tim Potter 2000
- Copyright (C) Jelmer Vernooij 2003
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
@@ -24,11 +23,34 @@
static BOOL use_bcast;
+struct user_auth_info {
+ pstring username;
+ pstring password;
+ pstring workgroup;
+};
+
/* How low can we go? */
enum tree_level {LEV_WORKGROUP, LEV_SERVER, LEV_SHARE};
static enum tree_level level = LEV_SHARE;
+static void usage(void)
+{
+ printf(
+"Usage: smbtree [options]\n\
+\n\
+\t-d debuglevel set debug output level\n\
+\t-U username user to autheticate as\n\
+\t-W workgroup workgroup of user to authenticate as\n\
+\t-D list only domains (workgroups) of tree\n\
+\t-S list domains and servers of tree\n\
+\t-b use bcast instead of using the master browser\n\
+\n\
+The username can be of the form username%%password or\n\
+workgroup\\username%%password.\n\n\
+");
+}
+
/* Holds a list of workgroups or servers */
struct name_list {
@@ -65,6 +87,62 @@ static void add_name(const char *machine_name, uint32 server_type,
DLIST_ADD(*name_list, new_name);
}
+/* Return a cli_state pointing at the IPC$ share for the given server */
+
+static struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
+ struct user_auth_info *user_info)
+{
+ struct cli_state *cli;
+ pstring myname;
+ NTSTATUS nt_status;
+
+ get_myname(myname);
+
+ nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
+ user_info->username, lp_workgroup(), user_info->password,
+ CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, NULL);
+
+ if (NT_STATUS_IS_OK(nt_status)) {
+ return cli;
+ } else {
+ return NULL;
+ }
+}
+
+/* Return the IP address and workgroup of a master browser on the
+ network. */
+
+static BOOL find_master_ip_bcast(pstring workgroup, struct in_addr *server_ip)
+{
+ struct in_addr *ip_list;
+ int i, count;
+
+ /* Go looking for workgroups by broadcasting on the local network */
+
+ if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
+ return False;
+ }
+
+ for (i = 0; i < count; i++) {
+ static fstring name;
+
+ if (!name_status_find("*", 0, 0x1d, ip_list[i], name))
+ continue;
+
+ if (!find_master_ip(name, server_ip))
+ continue;
+
+ pstrcpy(workgroup, name);
+
+ DEBUG(4, ("found master browser %s, %s\n",
+ name, inet_ntoa(ip_list[i])));
+
+ return True;
+ }
+
+ return False;
+}
+
/****************************************************************************
display tree of smb workgroups, servers and shares
****************************************************************************/
@@ -80,21 +158,19 @@ static BOOL get_workgroups(struct user_auth_info *user_info)
pstrcpy(master_workgroup, lp_workgroup());
- if (!use_bcast && !find_master_ip(lp_workgroup(), &server_ip)) {
- DEBUG(4, ("Unable to find master browser for workgroup %s, falling back to broadcast\n",
+ if (use_bcast || !find_master_ip(lp_workgroup(), &server_ip)) {
+ DEBUG(4, ("Unable to find master browser for workgroup %s\n",
master_workgroup));
- use_bcast = True;
- } else if(!use_bcast) {
- if (!(cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info)))
- return False;
- }
-
- if (!(cli = get_ipc_connect_master_ip_bcast(master_workgroup, user_info))) {
+ if (!find_master_ip_bcast(master_workgroup, &server_ip)) {
DEBUG(4, ("Unable to find master browser by "
"broadcast\n"));
return False;
+ }
}
+ if (!(cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info)))
+ return False;
+
if (!cli_NetServerEnum(cli, master_workgroup,
SV_TYPE_DOMAIN_ENUM, add_name, &workgroups))
return False;
@@ -191,17 +267,13 @@ static BOOL print_tree(struct user_auth_info *user_info)
****************************************************************************/
int main(int argc,char *argv[])
{
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- { "broadcast", 'b', POPT_ARG_VAL, &use_bcast, True, "Use broadcast instead of using the master browser" },
- { "domains", 'D', POPT_ARG_VAL, &level, LEV_WORKGROUP, "List only domains (workgroups) of tree" },
- { "servers", 'S', POPT_ARG_VAL, &level, LEV_SERVER, "List domains(workgroups) and servers of tree" },
- POPT_COMMON_SAMBA
- POPT_COMMON_CREDENTIALS
- POPT_TABLEEND
- };
- poptContext pc;
-
+ extern char *optarg;
+ extern int optind;
+ int opt;
+ char *p;
+ struct user_auth_info user_info;
+ BOOL got_pass = False;
+
/* Initialise samba stuff */
setlinebuf(stdout);
@@ -210,27 +282,86 @@ static BOOL print_tree(struct user_auth_info *user_info)
setup_logging(argv[0],True);
- pc = poptGetContext("smbtree", argc, (const char **)argv, long_options,
- POPT_CONTEXT_KEEP_FIRST);
- while(poptGetNextOpt(pc) != -1);
- poptFreeContext(pc);
-
lp_load(dyn_CONFIGFILE,True,False,False);
load_interfaces();
+ if (getenv("USER")) {
+ pstrcpy(user_info.username, getenv("USER"));
+
+ if ((p=strchr(user_info.username, '%'))) {
+ *p = 0;
+ pstrcpy(user_info.password, p+1);
+ got_pass = True;
+ memset(strchr(getenv("USER"), '%') + 1, 'X',
+ strlen(user_info.password));
+ }
+ }
+
+ pstrcpy(user_info.workgroup, lp_workgroup());
+
/* Parse command line args */
- if (!cmdline_auth_info.got_pass) {
+ while ((opt = getopt(argc, argv, "U:hd:W:DSb")) != EOF) {
+ switch (opt) {
+ case 'U':
+ pstrcpy(user_info.username,optarg);
+ p = strchr(user_info.username,'%');
+ if (p) {
+ *p = 0;
+ pstrcpy(user_info.password, p+1);
+ got_pass = 1;
+ }
+ break;
+
+ case 'b':
+ use_bcast = True;
+ break;
+
+ case 'h':
+ usage();
+ exit(1);
+
+ case 'd':
+ DEBUGLEVEL = atoi(optarg);
+ break;
+
+ case 'W':
+ pstrcpy(user_info.workgroup, optarg);
+ break;
+
+ case 'D':
+ level = LEV_WORKGROUP;
+ break;
+
+ case 'S':
+ level = LEV_SERVER;
+ break;
+
+ default:
+ printf("Unknown option %c (%d)\n", (char)opt, opt);
+ exit(1);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ usage();
+ exit(1);
+ }
+
+ if (!got_pass) {
char *pass = getpass("Password: ");
if (pass) {
- pstrcpy(cmdline_auth_info.password, pass);
+ pstrcpy(user_info.password, pass);
}
- cmdline_auth_info.got_pass = True;
+ got_pass = True;
}
/* Now do our stuff */
- if (!print_tree(&cmdline_auth_info))
+ if (!print_tree(&user_info))
return 1;
return 0;
diff --git a/source3/utils/status.c b/source3/utils/status.c
index 7e87701752..8014b133d9 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -559,8 +559,10 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
{"profile", 'P', POPT_ARG_NONE, &profile_only, 'P', "Do profiling" },
#endif /* WITH_PROFILE */
{"byterange", 'B', POPT_ARG_NONE, &show_brl, 'B', "Include byte range locks"},
- POPT_COMMON_SAMBA
- POPT_TABLEEND
+ { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
+ { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version},
+ { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
+ { 0, 0, 0, 0}
};
setup_logging(argv[0],True);
diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c
index e3d6ce0274..ec58f906ed 100644
--- a/source3/utils/testparm.c
+++ b/source3/utils/testparm.c
@@ -177,21 +177,18 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_
printf("'algorithmic rid base' must be even.\n");
}
-#ifndef HAVE_DLOPEN
- if (lp_preload_modules()) {
- printf("WARNING: 'preload modules = ' set while loading plugins not supported.\n");
- }
-#endif
-
return ret;
}
- int main(int argc, const char *argv[])
+int main(int argc, const char *argv[])
{
+ extern char *optarg;
+ extern int optind;
const char *config_file = dyn_CONFIGFILE;
int s;
static BOOL silent_mode = False;
int ret = 0;
+ int opt;
poptContext pc;
static const char *term_code = "";
static char *new_local_machine = NULL;
@@ -205,15 +202,15 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_
{"verbose", 'v', POPT_ARG_NONE, &show_defaults, 1, "Show default options too"},
{"server", 'L',POPT_ARG_STRING, &new_local_machine, 0, "Set %%L macro to servername\n"},
{"encoding", 't', POPT_ARG_STRING, &term_code, 0, "Print parameters with encoding"},
- POPT_COMMON_VERSION
- POPT_TABLEEND
+ {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version},
+ {0,0,0,0}
};
pc = poptGetContext(NULL, argc, argv, long_options,
POPT_CONTEXT_KEEP_FIRST);
poptSetOtherOptionHelp(pc, "[OPTION...] <config-file> [host-name] [host-ip]");
- while(poptGetNextOpt(pc) != -1);
+ while((opt = poptGetNextOpt(pc)) != -1);
setup_logging(poptGetArg(pc), True);