Added comments for structures and functions.

As for being a masochist, I tried, but couldn't take it ;-P.

On Tue, Aug 30, 2011 at 12:31 PM, Ulrich Windl <
ulrich.wi...@rz.uni-regensburg.de> wrote:

> >>> Vivek S <vivek...@gmail.com> schrieb am 29.08.2011 um 21:00 in
> Nachricht
> <CAAPU5rPY1F3bkYYyASAFbOtb6JrfGw7JSb6m=--KKUEZVmc=w...@mail.gmail.com>:
> > Removed ordering constrains between #defines and structure elements.
> > Removed calculating tab width and defaulting to 8.
> >
> > Hope this will do :-)
>
> Hi!
>
> It looks like converging ;-)
>
> You could (I know it's non-hacker-like) add some comments on the struct
> def:
>
>        int option;
>        char *option_str;
>        const char *help_str;
>
> BTW: shouldn't "option_str" be "const char" also?
>
> On
> +/*
> + * Global defines for all iscsiadm command line options.
> + */
> +#define CMD_LINE_OPTION_PORTAL         (1 << 0)
>
> Improve the comment by saying why you use bitmasks there, or say what those
> defines are going to be used for.
>
> If you feel like a masochist today, you could temporarily add some of the
> gcc options that I used myself years ago:
> -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings
> -Wtraditional -Wstrict-prototypes -Wnested-externs -Wredundant-decls
> -Wconversion
>
> Maybe this helps you to clean out a few edges.
>
> Regards,
> Ulrich
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "open-iscsi" group.
> To post to this group, send email to open-iscsi@googlegroups.com.
> To unsubscribe from this group, send email to
> open-iscsi+unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/open-iscsi?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com.
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/open-iscsi?hl=en.

From 2d5d4046d71ee79581404000a0f97d6e853615ae Mon Sep 17 00:00:00 2001
From: Vivek Subbarao <vivek...@gmail.com>
Date: Tue, 30 Aug 2011 20:41:05 +0530
Subject: [PATCH 1/1] Added descriptive help for iscsiadm with a few examples.


Signed-off-by: Vivek Subbarao <vivek...@gmail.com>
---
 usr/iscsiadm.c |  407 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 387 insertions(+), 20 deletions(-)

diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index 03b779e..793602e 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -28,6 +28,8 @@
 #include <string.h>
 #include <signal.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <termcap.h>
 
 #include "initiator.h"
 #include "discovery.h"
@@ -77,6 +79,8 @@ enum iscsiadm_op {
 	OP_APPLY_ALL		= 0x40
 };
 
+#define MAX_CMD_OPTIONS	22
+
 static struct option const long_options[] =
 {
 	{"mode", required_argument, NULL, 'm'},
@@ -106,24 +110,387 @@ static struct option const long_options[] =
 };
 static char *short_options = "RlDVhm:p:P:T:H:I:U:k:L:d:r:n:v:o:sSt:u";
 
-static void usage(int status)
+/*
+ * Generic help message which displays the modes supported by iscsiadm
+ * and points the user to the way in which to query detailed help for
+ * each mode. Displayed when iscsiadm is executed without any arguments
+ * and also during wrong arguments being passed.
+ */
+const char *generic_help[] = {
+	"Iscsiadm supports the following modes. "
+	"The user should enter atleast one of them. "
+	"For help about a particular mode, enter "
+	"'iscsiadm -m mode -h'.\n\n"
+	"discoverydb\n"
+	"discovery [DEPRECATED]\n"
+	"node\n"
+	"session\n"
+	"iface\n"
+	"fw\n"
+	"host\n"
+	"\n"
+	"NOTE: To kill iscsid, use 'iscsiadm -k priority' "
+	"with a priority of 0.\n\n"
+};
+
+
+/*
+ * Bit fields representing all command line options for iscsiadm.
+ * Bitwise or of these bitmasks is used to determine the options
+ * supported by a particular mode.
+ */
+#define CMD_LINE_OPTION_PORTAL		(1 << 0)
+#define CMD_LINE_OPTION_TGTNAME		(1 << 1)
+#define CMD_LINE_OPTION_IFACE		(1 << 3)
+#define CMD_LINE_OPTION_OP		(1 << 4)
+#define CMD_LINE_OPTION_TYPE		(1 << 5)
+#define CMD_LINE_OPTION_NAME		(1 << 6)
+#define CMD_LINE_OPTION_VALUE		(1 << 7)
+#define CMD_LINE_OPTION_HOST		(1 << 8)
+#define CMD_LINE_OPTION_SID		(1 << 9)
+#define CMD_LINE_OPTION_RESCAN		(1 << 10)
+#define CMD_LINE_OPTION_PRINT		(1 << 11)
+#define CMD_LINE_OPTION_DSCVR		(1 << 12)
+#define CMD_LINE_OPTION_LOGIN		(1 << 13)
+#define CMD_LINE_OPTION_LOGINALL	(1 << 14)
+#define CMD_LINE_OPTION_LOGOUT		(1 << 15)
+#define CMD_LINE_OPTION_LOGOUTALL	(1 << 16)
+#define CMD_LINE_OPTION_STATS		(1 << 17)
+#define CMD_LINE_OPTION_KILLISCSID	(1 << 18)
+#define CMD_LINE_OPTION_DEBUG		(1 << 19)
+#define CMD_LINE_OPTION_SHOW		(1 << 20)
+#define CMD_LINE_OPTION_VERSION		(1 << 21)
+#define CMD_LINE_OPTION_HELP		(1 << 22)
+
+
+/*
+ * Structure to hold all iscsiadm command line options and their description.
+ * Each element contains an option identifier (one of the above bitmasks), 
+ * option string and it description.
+ */
+struct option_help
+{
+	int option;		//Option identifier
+	const char *option_str;	//Option string
+	const char *help_str;	//Option description
+}opt_help[] = {
+	{CMD_LINE_OPTION_PORTAL, 
+	"p",	"Portal in ip:port format. If only ip address is specified "
+		"then the value 3260 is assumed for the port."},
+	{CMD_LINE_OPTION_TGTNAME,
+	"T",	"Iqn name of the target."},
+	{CMD_LINE_OPTION_IFACE,
+	"I",	"Interface to use for the operation. This is the name of file "
+		"in /etc/iscsi/ifaces/ directory. Multiple interfaces can be "
+		"specified."},
+	{CMD_LINE_OPTION_OP,
+	"o",	"One of the new, delete, update, show or nonpersistent "
+		"operations."},
+	{CMD_LINE_OPTION_TYPE,
+	"t",	"Type of discovery. Sendtargets, slp, isns or fw."},
+	{CMD_LINE_OPTION_NAME,
+	"n",	"Name of the field to use in the update operation."},
+	{CMD_LINE_OPTION_VALUE,
+	"v",	"Value to use for the specified field in the update "
+		"operation."},
+	{CMD_LINE_OPTION_HOST,
+	"H",	"SCSI host to use for the operation."},
+	{CMD_LINE_OPTION_SID,
+	"r",	"Session ID to use. This is either a positive integer or a "
+		"sysfs path like /sys/devices/platform/hostH/sessionS/targetH:"
+		"B:I"},
+	{CMD_LINE_OPTION_RESCAN,
+	"R",	"Rescan all sessions if no SID is specified, else scan only "
+		"that session."},
+	{CMD_LINE_OPTION_PRINT,
+	"P",	"Level of information output. 0 to display a single line and "
+		"1 to display detailed information in tree format."},
+	{CMD_LINE_OPTION_DSCVR,
+	"D",	"Discover targets."},
+	{CMD_LINE_OPTION_LOGIN,
+	"l",	"Login to the discovered or specified target."},
+	{CMD_LINE_OPTION_LOGINALL,
+	"L",	"Login to all sessions with the specified node or connection "
+		"startup value or all session if all is passed."},
+	{CMD_LINE_OPTION_LOGOUT,
+	"u",	"Logout of the specified node or session."},
+	{CMD_LINE_OPTION_LOGOUTALL,
+	"U",	"Logout of all sessions with the specified node or connection "
+		"startup value or all sessions if all is passed."},
+	{CMD_LINE_OPTION_STATS,
+	"s",	"Display session statistics"},
+	{CMD_LINE_OPTION_KILLISCSID,
+	"k",	"Kill iscsid."},
+	{CMD_LINE_OPTION_DEBUG,
+	"d",	"Print debugging information. Valid values are 0 to 8."},
+	{CMD_LINE_OPTION_SHOW,
+	"S",	"Show masked values during information display."},
+	{CMD_LINE_OPTION_VERSION,
+	"V",	"Display iscsiadm version."},
+	{CMD_LINE_OPTION_HELP,
+	"h",	"Display this help."},
+	{0, 	
+	NULL,	NULL}
+};
+
+
+/*
+ * Structure containing descriptive help for each mode. All help messages
+ * and examples for a mode are to be added here.
+ */
+struct mode_help {
+	int mode;		// Mode identifier. One of the enums declared above.
+	const char *mode_str;	// Mode name.
+	unsigned int options;	// Command line options supported by this mode. Bitwise or
+				// of the bitmasks described above.
+	const char *example;	// Few examples for this mode.
+}m_h[] = {
+	{	
+	MODE_DISCOVERY, "discovery",
+	CMD_LINE_OPTION_PORTAL	| CMD_LINE_OPTION_IFACE |
+	CMD_LINE_OPTION_OP	| CMD_LINE_OPTION_TYPE	|
+	CMD_LINE_OPTION_PRINT	| CMD_LINE_OPTION_DSCVR |
+       	CMD_LINE_OPTION_LOGIN	| CMD_LINE_OPTION_DEBUG |
+	CMD_LINE_OPTION_HELP,	
+	"\nExample:\n\n"
+	"To discover a target\n"
+	"iscsiadm -m discovery -t slp -p 192.168.1.1:3260 -D\n\n"
+	"To discover and login to a target\n"
+	"iscsiadm -m discovery -t slp -p 192.168.1.1:3260 -Dl\n\n"
+	"To specify an interface\n"
+	"iscsiadm -m discovery -t slp -p 192.168.1.1:3260 -I eth0\n"
+	},
+
+	{
+	MODE_DISCOVERYDB, "discoverydb",
+	CMD_LINE_OPTION_PORTAL	| CMD_LINE_OPTION_IFACE	|
+	CMD_LINE_OPTION_OP	| CMD_LINE_OPTION_TYPE	|
+	CMD_LINE_OPTION_PRINT	| CMD_LINE_OPTION_DSCVR |
+	CMD_LINE_OPTION_LOGIN	| CMD_LINE_OPTION_DEBUG	|
+	CMD_LINE_OPTION_HELP	| CMD_LINE_OPTION_NAME	|
+	CMD_LINE_OPTION_VALUE,
+	"\nExample:\n\n"
+	"To discover a target\n"
+	"iscsiadm -m discoverydb -t st -p 192.168.1.2:3260 -D\n\n"
+	"To discover and login\n"
+	"iscsiadm -m discoverydb -t st -p 192.168.1.2:3260 -Dl\n\n"
+	"To specify an interface during discovery and login\n"
+	"iscsiadm -m discoverydb -t st -p 192.168.1.2:3260 -I eth0 -Dl\n\n"
+	"To add or delete a record\n"
+	"iscsiadm -m discoverydb -t st -p 192.168.1.2:3260 -o new/delete\n\n"
+	"To update a record\n"
+	"iscsiadm -m discoverydb -t st -p 192.168.1.2:3260 -o "
+	"update -n discovery.startup -v manual\n\n"
+	"To display records from discovery database\n"
+	"iscsiadm -m discoverydb\n"
+	},
+
+	{
+	MODE_NODE, "node",
+	CMD_LINE_OPTION_PORTAL	| CMD_LINE_OPTION_IFACE		|
+	CMD_LINE_OPTION_DEBUG	| CMD_LINE_OPTION_LOGOUTALL 	|
+	CMD_LINE_OPTION_LOGIN	| CMD_LINE_OPTION_LOGINALL 	|
+	CMD_LINE_OPTION_LOGOUT	| CMD_LINE_OPTION_PRINT 	|
+	CMD_LINE_OPTION_TGTNAME | CMD_LINE_OPTION_SHOW 		|
+	CMD_LINE_OPTION_RESCAN 	| CMD_LINE_OPTION_STATS 	|
+	CMD_LINE_OPTION_HELP 	| CMD_LINE_OPTION_OP 		|
+	CMD_LINE_OPTION_NAME 	| CMD_LINE_OPTION_VALUE,
+	"\nExample:\n\n"
+	"To login to a target\n"
+	"iscsiadm -m node -T iqn.2005-06.com.mydomain.openiscsi:test1 "
+	"-p 192.168.1.2:3260 -l\n\n"
+	"To login to all targets with node or connection startup type as "
+	"manual\n"
+	"iscsiadm -m node -L manual\n\n"
+	"To logout of all targets with node or connection startup type as "
+	"automatic\n"
+	"iscsiadm -m node -U automatic\n\n"
+	"To rescan the session passing through a target\n"
+	"iscsiadm -m node -T iqn.2005-06.com.mydomain.openiscsi.test1 -p"
+	"192.168.1.2:3260 -R\n\n"
+	"To display statistics about a session passing through a target\n"
+	"iscsiadm -m node -T iqn.2005-06.com.mydomain.openiscsi:test1 -p"
+	"192.168.1.2:3260 -s\n\n"
+	"To add a new node record\n"
+	"iscsiadm -m node -T iqn.2005-06.com.mydomain.openiscsi:test1 -p"
+	"192.168.1.2:3260 -o new\n"
+	},
+	
+	{
+	MODE_SESSION, "session",
+	CMD_LINE_OPTION_SID	| CMD_LINE_OPTION_RESCAN|
+	CMD_LINE_OPTION_LOGOUT	| CMD_LINE_OPTION_STATS	|
+	CMD_LINE_OPTION_OP	| CMD_LINE_OPTION_NAME	|
+	CMD_LINE_OPTION_VALUE	| CMD_LINE_OPTION_DEBUG	|
+	CMD_LINE_OPTION_PRINT	| CMD_LINE_OPTION_HELP,
+	"\nExample:\n\n"
+	"To logout of a session\n"
+	"iscsiadm -m session -r 1 -u\n\n"
+	"To delete a session record\n"
+	"iscsiadm -m session -r 2 -o delete\n"
+	},
+	
+	{
+	MODE_HOST, "host",
+	CMD_LINE_OPTION_IFACE	| CMD_LINE_OPTION_OP	|
+	CMD_LINE_OPTION_NAME	| CMD_LINE_OPTION_VALUE	|
+	CMD_LINE_OPTION_DEBUG	| CMD_LINE_OPTION_PRINT	|
+	CMD_LINE_OPTION_HELP,
+	""
+	},
+
+	{
+	MODE_IFACE, "iface",
+	CMD_LINE_OPTION_LOGIN,
+	"\nExample:\n\n"
+	"To add a iface record\n"
+	"iscsiadm -m iface -I eth1 -o new\n"
+	},
+
+	{
+	MODE_FW, "fw",
+	CMD_LINE_OPTION_HOST	| CMD_LINE_OPTION_PRINT,
+	""
+	},
+
+	{
+	-1, "",
+	0,
+	""
+	}
+};
+
+
+#define TAB_WIDTH 8
+
+/*
+ * Get terminal width or number of columns.
+ */
+int get_cols(void)
+{
+	struct winsize ws;
+	
+	if (ioctl(0,TIOCGWINSZ,&ws)!=0) 
+	{
+		return 80;
+	}
+	return ws.ws_col;
+} 
+
+
+/*
+ * Print string to the terminal taking into account the terminal
+ * width.
+ */
+void print_str(const char *tabs, const char *str)
+{
+	int num_tabs = 0, print_len = 0;
+	char buf[1024] = {0};
+	char *p = NULL, *q = NULL;
+	int max_cols = get_cols();
+	int str_len = 0, i = 0;
+
+	/*
+	 * End of string
+	 */
+	if (str[0] == 0)
+		return ;
+
+	/*
+	 * Find the first occurence of '\n' character in the string.
+	 */
+	p = strchr(str, '\n');
+	if (p)
+		str_len = p - str + 1;
+	else
+		str_len = strlen(str);
+
+	/*
+	 * Find the number of TAB characters in the string from the
+	 * start to the occurence of the first '\n' character.
+	 */
+	for (i=0 ; i<str_len ; i++)
+	{
+		if (str[i] == '\t')
+			num_tabs++;
+	}
+	
+	/*
+	 * If the string length including the tab width in greater than
+	 * max_cols, wrap text.
+	 */
+	if ( (str_len + (num_tabs * TAB_WIDTH) - num_tabs) > max_cols )
+	{
+		memcpy(buf, str, max_cols);
+		q = strrchr(buf, ' ');
+		if (q)
+			print_len = q - buf + 1;
+		else
+			print_len = max_cols;
+
+		printf("%s%.*s\n", tabs, print_len, str);
+	}
+	else
+	{
+		print_len = str_len;
+		printf("%s%.*s", tabs, str_len, str);
+	}
+
+	print_str(tabs, str+print_len);
+}
+
+
+/*
+ * Print the options and their description specified by the options
+ * bitmask.
+ */
+void print_option_help(unsigned int options)
 {
-	if (status != 0)
-		fprintf(stderr, "Try `%s --help' for more information.\n",
-			program_name);
-	else {
-		printf("\
-iscsiadm -m discoverydb [ -hV ] [ -d debug_level ] [-P printlevel] [ -t type -p ip:port -I ifaceN ... [ -Dl ] ] | [ [ -p ip:port -t type] \
-[ -o operation ] [ -n name ] [ -v value ] [ -lD ] ] \n\
-iscsiadm -m discovery [ -hV ] [ -d debug_level ] [-P printlevel] [ -t type -p ip:port -I ifaceN ... [ -l ] ] | [ [ -p ip:port ] [ -l | -D ] ] \n\
-iiscsiadm -m node [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port -I ifaceN ] [ -l | -u | -R | -s] ] \
-[ [ -o  operation  ] [ -n name ] [ -v value ] ]\n\
-iscsiadm -m session [ -hV ] [ -d debug_level ] [ -P  printlevel] [ -r sessionid | sysfsdir [ -R | -u | -s ] [ -o operation ] [ -n name ] [ -v value ] ]\n\
-iscsiadm -m iface [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -I ifacename | -H hostno|MAC ] [ [ -o  operation  ] [ -n name ] [ -v value ] ]\n\
-iscsiadm -m fw [ -l ]\n\
-iscsiadm -m host [ -P printlevel ] [ -H hostno|MAC ]\n\
-iscsiadm -k priority\n");
+	int i = 0;
+
+	for (i=0 ; opt_help[i].option != 0 ; i++)
+	{
+		if (opt_help[i].option & options)
+		{
+			printf("%s", opt_help[i].option_str);
+			print_str("\t", opt_help[i].help_str);
+			printf("\n");
+		}
 	}
+}
+
+/*
+ * Function to print iscsiadm usage help.
+ */
+static void usage(int status, int mode)
+{
+	int i = 0;
+
+	printf("\n");
+
+	if ((status != 0) || (mode == -1) || (mode > MODE_FW))
+		print_str("", generic_help[0]);
+	else
+	{
+
+		for (i=0 ; m_h[i].mode != -1 ; i++)
+		{
+			if (m_h[i].mode == mode)
+			{
+				printf(	"iscsiadm -m %s [options...]\n\n"
+					"Options\tDescription\n"
+					"-------\t-----------\n",
+					m_h[i].mode_str);
+
+				print_option_help(m_h[i].options);
+				print_str("", m_h[i].example);
+				break;
+			}
+		}
+				
+		printf("\nSEE MAN PAGE FOR MORE DETAILS\n\n");
+	}
+
 	exit(status);
 }
 
@@ -377,7 +744,7 @@ logout_by_startup(char *mode)
 	if (!mode || !(!strcmp(mode, "automatic") || !strcmp(mode, "all") ||
 	    !strcmp(mode,"manual"))) {
 		log_error("Invalid logoutall option %s.", mode);
-		usage(ISCSI_ERR_INVAL);
+		usage(ISCSI_ERR_INVAL, 0);
 		return ISCSI_ERR_INVAL;
 	}
 
@@ -447,7 +814,7 @@ login_by_startup(char *mode)
 	if (!mode || !(!strcmp(mode, "automatic") || !strcmp(mode, "all") ||
 		       !strcmp(mode,"manual") || !strcmp(mode, "onboot"))) {
 		log_error("Invalid loginall option %s.", mode);
-		usage(ISCSI_ERR_INVAL);
+		usage(ISCSI_ERR_INVAL, 0);
 		return ISCSI_ERR_INVAL;
 	}
 
@@ -2223,7 +2590,7 @@ main(int argc, char **argv)
 				ISCSI_VERSION_STR);
 			return 0;
 		case 'h':
-			usage(0);
+			usage(0, mode);
 		}
 	}
 
@@ -2239,7 +2606,7 @@ main(int argc, char **argv)
 	}
 
 	if (mode < 0)
-		usage(ISCSI_ERR_INVAL);
+		usage(ISCSI_ERR_INVAL, 0);
 
 	if (mode == MODE_FW) {
 		if ((rc = verify_mode_params(argc, argv, "ml", 0))) {
-- 
1.7.4.1

Reply via email to