From a72eafee542c2b15e1ffb369d277209b63daa0e9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 9 Apr 2003 05:52:01 +0000 Subject: Rewrite of smbcontrol - it was a bit of a mess. It should now be much nicer to use and more hackable. - converted to popt - text message destinations (except for broadcast smbd) are resolved using files in piddir so the string 'winbindd' is now a destination - added --timeout option to specify timeout value - deleted complicated handling of debug args as separate command line arguments: use shell quoting instead - deleted interactive mode as punishment for using strtok() (-: - much improved command line argument checking Some of this stuff was broken before I started (print notify, profiling) but the basics still work (ping, pool-usage, debug, debuglevel). (This used to be commit 269f838dee257ee9badcae190f2c70b898676bc5) --- source3/utils/smbcontrol.c | 1103 +++++++++++++++++++++++--------------------- 1 file changed, 573 insertions(+), 530 deletions(-) (limited to 'source3/utils') diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index 44b18d57cd..8b984d9bd1 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -1,8 +1,11 @@ /* Unix SMB/CIFS implementation. - program to send control messages to Samba processes + + Send messages to other Samba daemons + + Copyright (C) Tim Potter 2003 Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) 2001, 2002 by Martin Pool + Copyright (C) Martin Pool 2001-2002 Copyright (C) Simo Sorce 2002 This program is free software; you can redistribute it and/or modify @@ -22,678 +25,718 @@ #include "includes.h" -extern BOOL AllowDebugChange; +/* Default timeout value when waiting for replies (in seconds) */ -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}, - {NULL, -1} -}; +#define DEFAULT_TIMEOUT 10 -time_t timeout_start; +static int timeout = DEFAULT_TIMEOUT; +static int num_replies; /* Used by message callback fns */ -#define MAX_WAIT 10 +/* Send a message to a destination pid. Zero means broadcast smbd. */ -/* we need these because we link to printing*.o */ +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; +} -void become_root(void) {} -void unbecome_root(void) {} +/* Wait for one or more reply messages */ + +static void wait_replies(BOOL multiple_replies) +{ + time_t start_time = time(NULL); + /* Wait around a bit. This is pretty disgusting - we have to + busy-wait here as there is no nicer way to do it. */ -static void usage(BOOL doexit) + do { + message_dispatch(); + if (num_replies > 0 && !multiple_replies) + break; + sleep(1); + } while (timeout - (time(NULL) - start_time) > 0); +} + +/* Message handler callback that displays a string on stdout */ + +static void print_string_cb(int msg_type, pid_t pid, void *buf, size_t len) { - int i; - if (doexit) { - printf("Usage: smbcontrol -i -s configfile\n"); - printf(" smbcontrol \n\n"); - } else { - printf(" \n\n"); + printf("%.*s", (int)len, (const char *)buf); + num_replies++; +} + +/* Send no message. Useful for testing. */ + +static BOOL do_noop(const pid_t pid, const int argc, char **argv) +{ + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol noop\n"); + return False; } - printf("\t is one of \"nmbd\", \"smbd\" or a process ID\n"); - printf("\t 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); + + /* Move along, nothing to see here */ + + return True; } -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) +/* Send a debug string */ + +static BOOL do_debug(const pid_t pid, const int argc, char **argv) { - time_t timeout_end = time(NULL) + max_secs; + if (argc != 2) { + fprintf(stderr, "Usage: smbcontrol debug " + "\n"); + return False; + } - while ((!max_replies || (*max_replies)-- > 0) - && (time(NULL) < timeout_end)) { - message_dispatch(); + 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 force-election\n"); + return False; } + + return send_message( + pid, MSG_FORCE_ELECTION, NULL, 0, False); } +/* Ping a samba daemon process */ -/**************************************************************************** -a useful function for testing the message system -****************************************************************************/ -void pong_function(int msg_type, pid_t src, void *buf, size_t len) +static void pong_cb(int msg_type, pid_t pid, void *buf, size_t len) { - pong_count++; - printf("PONG from PID %u\n",(unsigned int)src); + printf("PONG from pid %u\n", (unsigned int)pid); + num_replies++; } -/**************************************************************************** - Prints out the current talloc list. -****************************************************************************/ -void tallocdump_function(int msg_type, pid_t src, void *buf, size_t len) +static BOOL do_ping(const pid_t pid, const int argc, char **argv) { - 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; + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol 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; } -/**************************************************************************** -Prints out the current Debug level returned by MSG_DEBUGLEVEL -****************************************************************************/ -void debuglevel_function(int msg_type, pid_t src, void *buf, size_t len) +/* Set profiling options */ + +static BOOL do_profile(const pid_t pid, const int argc, char **argv) { - const char *levels = (char *)buf; + int v; - printf("Current debug levels of PID %u are:\n",(unsigned int)src); - printf("%s\n", levels); - - got_level = True; + if (argc != 2) { + fprintf(stderr, "Usage: smbcontrol profile " + "\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; + } + + return send_message(pid, MSG_PROFILE, &v, sizeof(int), False); } -/**************************************************************************** -Prints out the current Profile level returned by MSG_PROFILELEVEL -****************************************************************************/ -void profilelevel_function(int msg_type, pid_t src, void *buf, size_t len) +/* Return the profiling level */ + +static void profilelevel_cb(int msg_type, pid_t pid, void *buf, size_t len) { - int level; - const char *s=NULL; - memcpy(&level, buf, sizeof(int)); + int level; + const char *s; + + num_replies++; + + if (len != sizeof(int)) { + fprintf(stderr, "invalid message length %d returned\n", len); + return; + } - if (level) { - switch (level) { - case 1: + memcpy(&level, buf, sizeof(int)); + + switch (level) { + case 0: + s = "not enabled"; + break; + 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; - } - printf("Profiling %s on PID %u\n",s,(unsigned int)src); - } else { - printf("Profiling not available on PID %u\n",(unsigned int)src); + default: + s = "BOGUS"; + break; } - got_level = True; + + printf("Profiling %s on pid %u\n",s,(unsigned int)pid); } -/** - * Handle reply from POOL_USAGE. - **/ -static void pool_usage_cb(int msg_type, pid_t src_pid, void *buf, size_t len) +static void profilelevel_rqst(int msg_type, pid_t pid, void *buf, size_t len) { - printf("Got POOL_USAGE reply from pid %u:\n%.*s", - (unsigned int) src_pid, (int) len, (const char *) buf); -} + int v = 0; + + /* Send back a dummy reply */ + send_message(pid, MSG_PROFILELEVEL, &v, sizeof(int), False); +} -/** - * 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) +static BOOL do_profilelevel(const pid_t pid, const int argc, char **argv) { - 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; - } + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol profilelevel\n"); + 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; - } 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; - } - } + /* 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); - DEBUG(10,("smbcontrol/send_message: send message to pid%d\n", pid)); - return message_send_pid(pid, msg_type, buf, len, duplicates); + wait_replies(pid == 0); + + /* No replies were received within the timeout period */ + + if (num_replies == 0) + printf("No replies received\n"); + + message_deregister(MSG_PROFILE); + + return num_replies; } -/**************************************************************************** -evaluate a message type string -****************************************************************************/ -static int parse_type(char *mtype) +/* Display debug level settings */ + +static BOOL do_debuglevel(const pid_t pid, const int argc, char **argv) { - int i; - for (i=0;msg_types[i].name;i++) { - if (strequal(mtype, msg_types[i].name)) return msg_types[i].value; + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol debuglevel\n"); + return False; } - return -1; -} + /* Send a message and register our interest in a reply */ -static void register_all(void) -{ - message_register(MSG_POOL_USAGE, pool_usage_cb); -} + if (!send_message(pid, MSG_REQ_DEBUGLEVEL, NULL, 0, False)) + return False; -/* This guy is here so we can link printing/notify.c to the smbcontrol - binary without having to pull in tons of other crap. */ + message_register(MSG_DEBUGLEVEL, print_string_cb); -TDB_CONTEXT *conn_tdb_ctx(void) -{ - static TDB_CONTEXT *tdb; + wait_replies(pid == 0); - if (tdb) - return tdb; + /* No replies were received within the timeout period */ - tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0); + if (num_replies == 0) + printf("No replies received\n"); - if (!tdb) - DEBUG(3, ("Failed to open connections database in send_spoolss_notify2_msg\n")); + message_deregister(MSG_DEBUGLEVEL); - return tdb; + return num_replies; } -/**************************************************************************** -do command -****************************************************************************/ -static BOOL do_command(char *dest, char *msg_name, int iparams, char **params) +/* Send a print notify message */ + +static BOOL do_printnotify(const pid_t pid, const int argc, char **argv) { - 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); + char *cmd; + + /* Check for subcommand */ + + if (argc == 1) { + fprintf(stderr, "Must specify subcommand:\n"); + fprintf(stderr, "\tqueuepause \n"); + fprintf(stderr, "\tqueueresume \n"); + fprintf(stderr, "\tjobpause \n"); + fprintf(stderr, "\tjobresume \n"); + fprintf(stderr, "\tjobdelete \n"); + fprintf(stderr, "\tprinter \n"); + + return False; } - switch (mtype) { - case MSG_DEBUG: { - char *buf, *b; - char **p; - int dim = 0; + cmd = argv[1]; - if (!params || !params[0]) { - fprintf(stderr,"MSG_DEBUG needs a parameter\n"); - return(False); - } + if (strcmp(cmd, "queuepause") == 0) { - /* 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); - } - /* 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; + if (argc != 3) { + fprintf(stderr, "Usage: smbcontrol printnotify" + " queuepause \n"); + return False; } - b[-1] = '\0'; + + notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED); - send_message(dest, MSG_DEBUG, buf, dim, False); + goto send; - free(buf); - - break; - } + } else if (strcmp(cmd, "queueresume") == 0) { - case MSG_PROFILE: - if (!params || !params[0]) { - fprintf(stderr,"MSG_PROFILE needs a parameter\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); + if (argc != 3) { + fprintf(stderr, "Usage: smbcontrol printnotify" + " queuereume \n"); + return False; } - send_message(dest, MSG_PROFILE, &v, sizeof(int), False); - break; + + notify_printer_status_byname(argv[2], PRINTER_STATUS_OK); - 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; + goto send; - 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; - } - } + } else if (strcmp(cmd, "jobpause") == 0) { + int jobid; + + if (argc != 4) { + fprintf(stderr, "Usage: smbcontrol printnotify" + " jobpause \n"); + return False; } - break; - case MSG_REQ_DEBUGLEVEL: - if (!debuglevel_registered) { - message_register(MSG_DEBUGLEVEL, debuglevel_function); - debuglevel_registered = True; + jobid = atoi(argv[3]); + + 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; + + if (argc != 4) { + fprintf(stderr, "Usage: smbcontrol printnotify" + " jobpause \n"); + return False; } - 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; - } - } + + 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 printnotify" + " jobpause \n"); + return False; } - break; - /* Send a notification message to a printer */ + 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); - case MSG_PRINTER_NOTIFY2: { - char *cmd; + goto send; - /* Read subcommand */ + } else if (strcmp(cmd, "printer") == 0) { + uint32 attribute; + + if (argc != 5) { + fprintf(stderr, "Usage: smbcontrol printnotify " + "printer " + "\n"); + return False; + } - if (!params || !params[0]) { - fprintf(stderr, "Must specify subcommand:\n"); - fprintf(stderr, "\tqueuepause \n"); - fprintf(stderr, "\tqueueresume \n"); - fprintf(stderr, "\tjobpause \n"); - fprintf(stderr, "\tjobresume \n"); - fprintf(stderr, "\tjobdelete \n"); - fprintf(stderr, "\tprinter \n"); + 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; } - cmd = params[0]; + notify_printer_byname(argv[2], attribute, argv[4]); - check_notify_msgs = True; + goto send; + } - /* Pause a print queue */ + fprintf(stderr, "Invalid subcommand '%s'\n", cmd); + return False; - if (strequal(cmd, "queuepause")) { +send: + print_notify_send_messages(0); + return True; +} - if (!params[1]) { - fprintf(stderr, "queuepause command requires a printer name\n"); - return False; - } +/* Close a share */ - notify_printer_status_byname(params[1], PRINTER_STATUS_PAUSED); - break; - } +static BOOL do_closeshare(const pid_t pid, const int argc, char **argv) +{ + if (argc != 2) { + fprintf(stderr, "Usage: smbcontrol close-share " + "\n"); + return False; + } - /* Resume a print queue */ + return send_message( + pid, MSG_SMB_FORCE_TDIS, argv[1], strlen(argv[1]) + 1, False); +} - if (strequal(cmd, "queueresume")) { +/* Force a SAM synchronisation */ - if (!params[1]) { - fprintf(stderr, "queueresume command requires a printer name\n"); - return False; - } +static BOOL do_samsync(const pid_t pid, const int argc, char **argv) +{ + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol samsync\n"); + return False; + } - notify_printer_status_byname(params[1], PRINTER_STATUS_OK); - break; - } + return send_message( + pid, MSG_SMB_SAM_SYNC, NULL, 0, False); +} - /* Pause a print job */ +/* Force a SAM replication */ - if (strequal(cmd, "jobpause")) { - int jobid; +static BOOL do_samrepl(const pid_t pid, const int argc, char **argv) +{ + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol samrepl\n"); + return False; + } - if (!params[1] || !params[2]) { - fprintf(stderr, "jobpause command requires a printer name and a jobid\n"); - return False; - } + return send_message( + pid, MSG_SMB_SAM_REPL, NULL, 0, False); +} - jobid = atoi(params[2]); +/* Display talloc pool usage */ - notify_job_status_byname( - params[1], jobid, JOB_STATUS_PAUSED, - SPOOLSS_NOTIFY_MSG_UNIX_JOBID); - break; - } +static BOOL do_poolusage(const pid_t pid, const int argc, char **argv) +{ + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol pool-usage\n"); + return False; + } - /* Resume a print job */ + /* Send a message and register our interest in a reply */ - if (strequal(cmd, "jobresume")) { - int jobid; + if (!send_message(pid, MSG_REQ_POOL_USAGE, NULL, 0, False)) + return False; - if (!params[1] || !params[2]) { - fprintf(stderr, "jobresume command requires a printer name and a jobid\n"); - return False; - } + message_register(MSG_POOL_USAGE, print_string_cb); - jobid = atoi(params[2]); + wait_replies(pid == 0); - notify_job_status_byname( - params[1], jobid, JOB_STATUS_QUEUED, - SPOOLSS_NOTIFY_MSG_UNIX_JOBID); - break; - } + /* No replies were received within the timeout period */ - /* Delete a print job */ + if (num_replies == 0) + printf("No replies received\n"); - if (strequal(cmd, "jobdelete")) { - int jobid; + message_deregister(MSG_POOL_USAGE); - if (!params[1] || !params[2]) { - fprintf(stderr, "jobdelete command requires a printer name and a jobid\n"); - return False; - } + return num_replies; +} - jobid = atoi(params[2]); +/* Perform a dmalloc mark */ - notify_job_status_byname( - params[1], jobid, JOB_STATUS_DELETING, - SPOOLSS_NOTIFY_MSG_UNIX_JOBID); +static BOOL do_dmalloc_mark(const pid_t pid, const int argc, char **argv) +{ + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol dmalloc-mark\n"); + return False; + } - 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; - } + return send_message( + pid, MSG_REQ_DMALLOC_MARK, NULL, 0, False); +} +/* Perform a dmalloc changed */ - 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; +static BOOL do_dmalloc_changed(const pid_t pid, const int argc, + char **argv) +{ + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol " + "dmalloc-log-changed\n"); + return False; + } - case MSG_SMB_SAM_SYNC: - if (!strequal(dest, "smbd")) { - fprintf(stderr, "samsync can only be sent to smbd\n"); - return False; - } + return send_message( + pid, MSG_REQ_DMALLOC_LOG_CHANGED, NULL, 0, False); +} - if (params) { - fprintf(stderr, "samsync does not take any parameters\n"); - return False; - } +/* Shutdown a server process */ - retval = send_message(dest, MSG_SMB_SAM_SYNC, NULL, 0, False); +static BOOL do_shutdown(const pid_t pid, const int argc, char **argv) +{ + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol shutdown\n"); + return False; + } - break; + return send_message(pid, MSG_SHUTDOWN, NULL, 0, False); +} - case MSG_SMB_SAM_REPL: { - uint32 seqnum; +/* Notify a driver upgrade */ - if (!strequal(dest, "smbd")) { - fprintf(stderr, "sam repl can only be sent to smbd\n"); - return False; - } +static BOOL do_drvupgrade(const pid_t pid, const int argc, char **argv) +{ + if (argc != 2) { + fprintf(stderr, "Usage: smbcontrol drvupgrade " + "\n"); + return False; + } - if (!params || !params[0]) { - fprintf(stderr, "SAM_REPL needs a parameter\n"); - return False; - } + return send_message( + pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False); +} - seqnum = atoi(params[0]); +/* A list of message type supported */ - retval = send_message(dest, MSG_SMB_SAM_SYNC, - (char *)&seqnum, sizeof(uint32), False); +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 } +}; - break; - } +/* Yuck - we need these because we link to printing*.o even though + they aren't used. */ - 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 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; +void become_root(void) {} +void unbecome_root(void) {} - 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; +/* Display usage information */ - case MSG_REQ_DMALLOC_LOG_CHANGED: - case MSG_REQ_DMALLOC_MARK: - if (!send_message(dest, mtype, NULL, 0, False)) - return False; - break; +static void usage(poptContext *pc) +{ + int i; - 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); - } + poptPrintHelp(*pc, stderr, 0); - if (!send_message(dest, MSG_PRINTER_DRVUPGRADE, params[0], 0, False)) - return False; - break; + fprintf(stderr, "\n"); + fprintf(stderr, " is one of \"nmbd\", \"smbd\" or a " + "process ID\n"); + + fprintf(stderr, "\n"); + fprintf(stderr, " is one of:\n"); + + for (i = 0; msg_types[i].name; i++) + fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, + msg_types[i].help); + + fprintf(stderr, "\n"); + + exit(1); +} + +/* Return the pid number for a string destination */ + +static pid_t parse_dest(char *dest) +{ + pid_t pid; + + /* Zero is a special return value for broadcast smbd */ + + if (strequal(dest, "smbd")) + return 0; + + /* Try self - useful for testing */ + + if (strequal(dest, "self")) + return sys_getpid(); + + /* Check for numeric pid number */ + + if ((pid = atoi(dest)) != 0) + return pid; + + /* Look up other destinations in pidfile directory */ + + if ((pid = pidfile_pid(dest)) != 0) + return pid; + + fprintf(stderr,"Can't find pid for destination '%s'\n", dest); + + return -1; +} + +/* Execute smbcontrol command */ + +static BOOL do_command(int argc, char **argv) +{ + char *dest = argv[0], *command = argv[1]; + pid_t pid; + int i; + + /* Check destination */ + + if ((pid = parse_dest(dest)) == -1) + return False; + + /* Check command */ + + 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); } - /* check if we have any pending print notify messages */ + fprintf(stderr, "smbcontrol: unknown command '%s'\n", command); - if ( check_notify_msgs ) - print_notify_send_messages(0); - - return (True); + return False; } - int main(int argc, char *argv[]) +/* Main program */ + +int main(int argc, char **argv) { + poptContext pc; int opt; - char temp[255]; - extern int optind; - BOOL interactive = False; - AllowDebugChange = False; - DEBUGLEVEL = 0; + 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 + }; setup_logging(argv[0],True); - if (argc < 2) usage(True); + /* Parse command line arguments using popt */ + + pc = poptGetContext( + "smbcontrol", argc, (const char **)argv, options, 0); + + poptSetOtherOptionHelp(pc, "[OPTION...] " + ""); + + if (argc == 1) + usage(&pc); - while ((opt = getopt(argc, argv,"is:")) != EOF) { - switch (opt) { - case 'i': - interactive = True; + while ((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + case 't': /* --timeout */ + argc -= 2; break; - case 's': + case 's': /* --configfile */ pstrcpy(dyn_CONFIGFILE, optarg); + argc -= 2; break; default: - printf("Unknown option %c (%d)\n", (char)opt, opt); - usage(True); + fprintf(stderr, "Invalid option\n"); + poptPrintHelp(pc, stderr, 0); + break; } } - lp_load(dyn_CONFIGFILE,False,False,False); - - if (!message_init()) exit(1); + /* 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. */ - argc -= optind; - argv = &argv[optind]; + argv = (char **)poptGetArgs(pc); + argc--; /* Don't forget about argv[0] */ - register_all(); + if (argc == 1) + usage(&pc); - 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; + lp_load(dyn_CONFIGFILE,False,False,False); - 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); + /* Need to invert sense of return code -- samba + * routines mostly return True==1 for success, but + * shell needs 0. */ + + return !do_command(argc, argv); } - -- cgit From 291e8e4589308938042d86bbc858a421bc29c2a0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 9 Apr 2003 14:35:14 +0000 Subject: Use fprintf(f, ...) instead of plain printf() - patch by Ronan Waide (This used to be commit 49926d706f9d24dbdd7a878e2362a27667175a5c) --- source3/utils/smbcacls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/utils') diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 562fd9943f..9d8a657726 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -406,7 +406,7 @@ static void sec_desc_print(FILE *f, SEC_DESC *sd) fstring sidstr; uint32 i; - printf("REVISION:%d\n", sd->revision); + fprintf(f, "REVISION:%d\n", sd->revision); /* Print owner and group sid */ @@ -416,7 +416,7 @@ static void sec_desc_print(FILE *f, SEC_DESC *sd) fstrcpy(sidstr, ""); } - printf("OWNER:%s\n", sidstr); + fprintf(f, "OWNER:%s\n", sidstr); if (sd->grp_sid) { SidToString(sidstr, sd->grp_sid); -- cgit From 803e23f403bdb38d2523d73fd12083da486bca2f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 9 Apr 2003 15:47:06 +0000 Subject: This is the netlogon schannel client code. Try a rpcclient -S pdc -U% -c "samlogon user password" and it should work with the schannel. Needs testing platforms different from NT4SP6. Volker (This used to be commit ecd0ee4d248e750168597ccf79c389513bb0f740) --- source3/utils/net_rpc_samsync.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'source3/utils') diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index e42c8f5637..0b78cd54ce 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -209,19 +209,17 @@ int rpc_samdump(int argc, const char **argv) return 1; } - if (!cli_nt_session_open(cli, PI_NETLOGON)) { - DEBUG(0,("Error connecting to NETLOGON pipe\n")); - goto fail; - } + fstrcpy(cli->domain, lp_workgroup()); - if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_password, NULL)) { - d_printf("Could not retrieve domain trust secret\n"); + if (!secrets_fetch_trust_account_password(lp_workgroup(), + trust_password, + NULL)) { + DEBUG(0,("Could not fetch trust account password\n")); goto fail; } - - result = cli_nt_setup_creds(cli, SEC_CHAN_BDC, trust_password, &neg_flags, 2); - if (!NT_STATUS_IS_OK(result)) { - d_printf("Failed to setup BDC creds\n"); + + if (!cli_nt_open_netlogon(cli, trust_password, SEC_CHAN_BDC)) { + DEBUG(0,("Error connecting to NETLOGON pipe\n")); goto fail; } -- cgit From 5b51fc4f065e9e68eefb530eb99ad8da9f4e5d28 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 11 Apr 2003 23:32:00 +0000 Subject: smbcquota patch from metze (This used to be commit 74fab8f0d24004b1dfd5ce0fd7402895652f941f) --- source3/utils/smbcquotas.c | 545 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 545 insertions(+) create mode 100644 source3/utils/smbcquotas.c (limited to 'source3/utils') diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c new file mode 100644 index 0000000000..c5d0aa869b --- /dev/null +++ b/source3/utils/smbcquotas.c @@ -0,0 +1,545 @@ +/* + Unix SMB/CIFS implementation. + QUOTA get/set utility + + Copyright (C) Andrew Tridgell 2000 + Copyright (C) Tim Potter 2000 + Copyright (C) Jeremy Allison 2000 + Copyright (C) Stefan (metze) Metzmacher 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 + 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. +*/ + +#include "includes.h" + +static pstring server; + +/* numeric is set when the user wants numeric SIDs and ACEs rather + than going via LSA calls to resolve them */ +static BOOL numeric; +static BOOL verbose; + +enum todo_values {NOOP_QUOTA=0,FS_QUOTA,USER_QUOTA,LIST_QUOTA,SET_QUOTA}; +enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR}; + +static struct cli_state *cli_ipc = NULL; +static POLICY_HND pol; +static BOOL got_policy_hnd; + +static struct cli_state *connect_one(const char *share); + +/* Open cli connection and policy handle */ + +static BOOL cli_open_policy_hnd(void) +{ + /* Initialise cli LSA connection */ + + if (!cli_ipc) { + cli_ipc = connect_one("IPC$"); + if (!cli_nt_session_open (cli_ipc, PI_LSARPC)) { + return False; + } + } + + /* Open policy handle */ + + if (!got_policy_hnd) { + + /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED, + but NT sends 0x2000000 so we might as well do it too. */ + + if (!NT_STATUS_IS_OK(cli_lsa_open_policy(cli_ipc, cli_ipc->mem_ctx, True, + GENERIC_EXECUTE_ACCESS, &pol))) { + return False; + } + + got_policy_hnd = True; + } + + return True; +} + +/* convert a SID to a string, either numeric or username/group */ +static void SidToString(fstring str, DOM_SID *sid, BOOL _numeric) +{ + char **domains = NULL; + char **names = NULL; + uint32 *types = NULL; + + sid_to_string(str, sid); + + if (_numeric) return; + + /* Ask LSA to convert the sid to a name */ + + if (!cli_open_policy_hnd() || + !NT_STATUS_IS_OK(cli_lsa_lookup_sids(cli_ipc, cli_ipc->mem_ctx, + &pol, 1, sid, &domains, + &names, &types)) || + !domains || !domains[0] || !names || !names[0]) { + return; + } + + /* Converted OK */ + + slprintf(str, sizeof(fstring) - 1, "%s%s%s", + domains[0], lp_winbind_separator(), + names[0]); + +} + +/* convert a string to a SID, either numeric or username/group */ +static BOOL StringToSid(DOM_SID *sid, const char *str) +{ + uint32 *types = NULL; + DOM_SID *sids = NULL; + BOOL result = True; + + if (strncmp(str, "S-", 2) == 0) { + return string_to_sid(sid, str); + } + + if (!cli_open_policy_hnd() || + !NT_STATUS_IS_OK(cli_lsa_lookup_names(cli_ipc, cli_ipc->mem_ctx, + &pol, 1, &str, &sids, + &types))) { + result = False; + goto done; + } + + sid_copy(sid, &sids[0]); + done: + + return result; +} + +#define QUOTA_GET 1 +#define QUOTA_SETLIM 2 +#define QUOTA_SETFLAGS 3 +#define QUOTA_LIST 4 + +enum {PARSE_FLAGS,PARSE_LIM}; + +static int parse_quota_set(pstring set_str, pstring username_str, enum SMB_QUOTA_TYPE *qtype, int *cmd, SMB_NTQUOTA_STRUCT *pqt) +{ + char *p = set_str,*p2; + int todo; + BOOL stop = False; + BOOL enable = False; + BOOL deny = False; + + if (strncasecmp(set_str,"UQLIM:",6)==0) { + p += 6; + *qtype = SMB_USER_QUOTA_TYPE; + *cmd = QUOTA_SETLIM; + todo = PARSE_LIM; + if ((p2=strstr(p,":"))==NULL) { + return -1; + } + + *p2 = '\0'; + p2++; + + fstrcpy(username_str,p); + p = p2; + } else if (strncasecmp(set_str,"FSQLIM:",7)==0) { + p +=7; + *qtype = SMB_USER_FS_QUOTA_TYPE; + *cmd = QUOTA_SETLIM; + todo = PARSE_LIM; + } else if (strncasecmp(set_str,"FSQFLAGS:",9)==0) { + p +=9; + todo = PARSE_FLAGS; + *qtype = SMB_USER_FS_QUOTA_TYPE; + *cmd = QUOTA_SETFLAGS; + } else { + return -1; + } + + switch (todo) { + case PARSE_LIM: +#if defined(HAVE_LONGLONG) + if (sscanf(p,"%llu/%llu",&pqt->softlim,&pqt->hardlim)!=2) { +#else + if (sscanf(p,"%lu/%lu",&pqt->softlim,&pqt->hardlim)!=2) { +#endif + return -1; + } + + break; + case PARSE_FLAGS: + while (!stop) { + + if ((p2=strstr(p,"/"))==NULL) { + stop = True; + } else { + *p2 = '\0'; + p2++; + } + + if (strncasecmp(p,"QUOTA_ENABLED",13)==0) { + enable = True; + } else if (strncasecmp(p,"DENY_DISK",9)==0) { + deny = True; + } else if (strncasecmp(p,"LOG_SOFTLIMIT",13)==0) { + pqt->qflags |= QUOTAS_LOG_THRESHOLD; + } else if (strncasecmp(p,"LOG_HARDLIMIT",13)==0) { + pqt->qflags |= QUOTAS_LOG_LIMIT; + } else { + return -1; + } + + p=p2; + } + + if (deny) { + pqt->qflags |= QUOTAS_DENY_DISK; + } else if (enable) { + pqt->qflags |= QUOTAS_ENABLED; + } + + break; + } + + return 0; +} + +static int do_quota(struct cli_state *cli, enum SMB_QUOTA_TYPE qtype, uint16 cmd, pstring username_str, SMB_NTQUOTA_STRUCT *pqt) +{ + uint32 fs_attrs = 0; + int quota_fnum = 0; + SMB_NTQUOTA_LIST *qtl = NULL; + SMB_NTQUOTA_STRUCT qt; + ZERO_STRUCT(qt); + + if (!cli_get_fs_attr_info(cli, &fs_attrs)) { + d_printf("Failed to get the filesystem attributes %s.\n", + cli_errstr(cli)); + return -1; + } + + if (!(fs_attrs & FILE_VOLUME_QUOTAS)) { + d_printf("Quotas are not supported by the server.\n"); + return 0; + } + + if (!cli_get_quota_handle(cli, "a_fnum)) { + d_printf("Failed to open \\%s %s.\n", + FAKE_FILE_NAME_QUOTA,cli_errstr(cli)); + return -1; + } + + switch(qtype) { + case SMB_USER_QUOTA_TYPE: + if (!StringToSid(&qt.sid, username_str)) { + d_printf("StringToSid() failed for [%s]\n",username_str); + return -1; + } + + switch(cmd) { + case QUOTA_GET: + if (!cli_get_user_quota(cli, quota_fnum, &qt)) { + d_printf("%s cli_get_user_quota %s\n", + cli_errstr(cli),username_str); + return -1; + } + dump_ntquota(&qt,verbose,numeric,SidToString); + break; + case QUOTA_SETLIM: + pqt->sid = qt.sid; + if (!cli_set_user_quota(cli, quota_fnum, pqt)) { + d_printf("%s cli_set_user_quota %s\n", + cli_errstr(cli),username_str); + return -1; + } + if (!cli_get_user_quota(cli, quota_fnum, &qt)) { + d_printf("%s cli_get_user_quota %s\n", + cli_errstr(cli),username_str); + return -1; + } + dump_ntquota(&qt,verbose,numeric,SidToString); + break; + case QUOTA_LIST: + if (!cli_list_user_quota(cli, quota_fnum, &qtl)) { + d_printf("%s cli_set_user_quota %s\n", + cli_errstr(cli),username_str); + return -1; + } + dump_ntquota_list(&qtl,verbose,numeric,SidToString); + free_ntquota_list(&qtl); + break; + default: + d_printf("Unknown Error\n"); + return -1; + } + break; + case SMB_USER_FS_QUOTA_TYPE: + switch(cmd) { + case QUOTA_GET: + if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) { + d_printf("%s cli_get_fs_quota_info\n", + cli_errstr(cli)); + return -1; + } + dump_ntquota(&qt,True,numeric,NULL); + break; + case QUOTA_SETLIM: + if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) { + d_printf("%s cli_get_fs_quota_info\n", + cli_errstr(cli)); + return -1; + } + qt.softlim = pqt->softlim; + qt.hardlim = pqt->hardlim; + if (!cli_set_fs_quota_info(cli, quota_fnum, &qt)) { + d_printf("%s cli_set_fs_quota_info\n", + cli_errstr(cli)); + return -1; + } + if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) { + d_printf("%s cli_get_fs_quota_info\n", + cli_errstr(cli)); + return -1; + } + dump_ntquota(&qt,True,numeric,NULL); + break; + case QUOTA_SETFLAGS: + if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) { + d_printf("%s cli_get_fs_quota_info\n", + cli_errstr(cli)); + return -1; + } + qt.qflags = pqt->qflags; + if (!cli_set_fs_quota_info(cli, quota_fnum, &qt)) { + d_printf("%s cli_set_fs_quota_info\n", + cli_errstr(cli)); + return -1; + } + if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) { + d_printf("%s cli_get_fs_quota_info\n", + cli_errstr(cli)); + return -1; + } + dump_ntquota(&qt,True,numeric,NULL); + break; + default: + d_printf("Unknown Error\n"); + return -1; + } + break; + default: + d_printf("Unknown Error\n"); + return -1; + } + + cli_close(cli, quota_fnum); + + return 0; +} + +/***************************************************** +return a connection to a server +*******************************************************/ +static struct cli_state *connect_one(const char *share) +{ + struct cli_state *c; + struct in_addr ip; + NTSTATUS nt_status; + zero_ip(&ip); + + if (!cmdline_auth_info.got_pass) { + char *pass = getpass("Password: "); + if (pass) { + pstrcpy(cmdline_auth_info.password, pass); + cmdline_auth_info.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))) { + return c; + } else { + DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status))); + return NULL; + } +} + +/**************************************************************************** + main program +****************************************************************************/ + int main(int argc, const char *argv[]) +{ + char *share; + int opt; + int result; + int todo = 0; + pstring username_str = {0}; + pstring path = {0}; + pstring set_str = {0}; + enum SMB_QUOTA_TYPE qtype; + int cmd = 0; + BOOL test_args = False; + struct cli_state *cli; + BOOL fix_user = False; + SMB_NTQUOTA_STRUCT qt; + poptContext pc; + struct poptOption long_options[] = { + POPT_AUTOHELP + { "user", 'u', POPT_ARG_STRING, NULL, 'u', "Show quotas for user", "user" }, + { "list", 'L', POPT_ARG_NONE, NULL, 'L', "List user quotas" }, + { "fs", 'F', POPT_ARG_NONE, NULL, 'F', "Show filesystem quotas" }, + { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls\n\ +SETSTRING:\n\ +UQLIM:// for user quotas\n\ +FSQLIM:/ for filesystem defaults\n\ +FSQFLAGS:QUOTA_ENABLED/DENY_DISK/LOG_SOFTLIMIT/LOG_HARD_LIMIT", "SETSTRING" }, + { "numeric", 'n', POPT_ARG_NONE, &numeric, True, "Don't resolve sids or limits to names" }, + { "verbose", 'v', POPT_ARG_NONE, &verbose, True, "be verbose" }, + { "test-args", 't', POPT_ARG_NONE, &test_args, True, "Test arguments"}, + POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS + { NULL } + }; + + ZERO_STRUCT(qt); + + setlinebuf(stdout); + + dbf = x_stderr; + + fault_setup(NULL); + + setup_logging(argv[0],True); + + + lp_load(dyn_CONFIGFILE,True,False,False); + load_interfaces(); + + pc = poptGetContext("smbcquotas", argc, argv, long_options, 0); + + poptSetOtherOptionHelp(pc, "//server1/share1"); + + while ((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case 'L': + if (todo != 0) { + d_printf("Please specify only one option of <-L|-F|-S|-u>\n"); + exit(EXIT_PARSE_ERROR); + } + todo = LIST_QUOTA; + break; + + case 'F': + if (todo != 0) { + d_printf("Please specify only one option of <-L|-F|-S|-u>\n"); + exit(EXIT_PARSE_ERROR); + } + todo = FS_QUOTA; + break; + + case 'u': + if (todo != 0) { + d_printf("Please specify only one option of <-L|-F|-S|-u>\n"); + exit(EXIT_PARSE_ERROR); + } + pstrcpy(username_str,poptGetOptArg(pc)); + todo = USER_QUOTA; + fix_user = True; + break; + + case 'S': + if (todo != 0) { + d_printf("Please specify only one option of <-L|-F|-S|-u>\n"); + exit(EXIT_PARSE_ERROR); + } + pstrcpy(set_str,poptGetOptArg(pc)); + todo = SET_QUOTA; + break; + } + } + + if (todo == 0) + todo = USER_QUOTA; + + if (!fix_user) + pstrcpy(username_str,cmdline_auth_info.username); + + /* Make connection to server */ + if(!poptPeekArg(pc)) { + poptPrintUsage(pc, stderr, 0); + exit(EXIT_PARSE_ERROR); + } + + pstrcpy(path, poptGetArg(pc)); + + all_string_sub(path,"/","\\",0); + + pstrcpy(server,path+2); + share = strchr_m(server,'\\'); + if (!share) { + share = strchr_m(server,'/'); + if (!share) { + printf("Invalid argument: %s\n", share); + exit(EXIT_PARSE_ERROR); + } + } + + *share = 0; + share++; + + if (todo == SET_QUOTA) { + if (parse_quota_set(set_str, username_str, &qtype, &cmd, &qt)) { + printf("Invalid argument: -S %s\n", set_str); + exit(EXIT_PARSE_ERROR); + } + } + + if (!test_args) { + cli = connect_one(share); + if (!cli) { + exit(EXIT_FAILED); + } + } else { + exit(EXIT_OK); + } + + + /* Perform requested action */ + + switch (todo) { + case FS_QUOTA: + result = do_quota(cli,SMB_USER_FS_QUOTA_TYPE, QUOTA_GET, username_str, NULL); + break; + case LIST_QUOTA: + result = do_quota(cli,SMB_USER_QUOTA_TYPE, QUOTA_LIST, username_str, NULL); + break; + case USER_QUOTA: + result = do_quota(cli,SMB_USER_QUOTA_TYPE, QUOTA_GET, username_str, NULL); + break; + case SET_QUOTA: + result = do_quota(cli, qtype, cmd, username_str, &qt); + break; + default: + + result = EXIT_FAILED; + break; + } + + return result; +} + -- cgit