Made the necessary changes. Kindly review.

On Fri, Aug 12, 2011 at 2:17 AM, Mike Christie <micha...@cs.wisc.edu> wrote:

> I agree with Ulrich.
>
> On 08/11/2011 01:53 AM, Ulrich Windl wrote:
> >>>> Vivek S <vivek...@gmail.com> schrieb am 10.08.2011 um 19:50 in
> Nachricht
> > <caapu5rp9mby1dednehsgrhhhygmvmnaku+dv4kjjkboe8uy...@mail.gmail.com>:
> >> Hi Mike/Ulrich
> >>
> >> Attaching the updated patch based on your comments.
> >
> > Hi!
> >
> > Looks a lot better IMHO, but anyway a comment on style:
> >
> > +     {"r", "Session ID to use. This is either a positive integer or a \
> > +sysfs path like /sys/devices/platform/hostH/sessionS/targetH:B:I"},
> >
> > Since ANSI-C (many years now) you can concatenate strings using "string1"
> "string2". In you case it may look nicer to avoid the backslash at the end
> of the line and use double doublequotes instead. The other advantage is that
> you can indent the continuation to align the first line quite nicely.
> >
> > Likewise, when printing a larger block of text that is one logical unit,
> you might also use that. Consider the block starting with
> >
> > +             printf("\nExample:\n\tTo login to a target\n");
> > +             print_str("\t\t",
> > +             "iscsiadm -m node -T
> iqn.2005-06.com.mydomain.openiscsi:test1 "
> > +             "-p 192.168.1.2:3260 -l");
> >
> > You could use one printf()
> >
> > Side note: a better return value that "-1" for the error in get_cols()
> might be "80", as you are not checking the error when using the return
> value.
> >
> > +             sprintf(fmt, "%s%c%c%d%c%c", tabs, '%', '.', idx, 's',
> '\n');
> > +             printf(fmt, str);
> >
> > I wonder whether this is the same as
> >
> > printf("%s%.*s\n", tabs, idx, str);
> >
> > On "find_last_space(&str[cols-1], (cols-1), 0);":
> >
> > "&str[cols-1]" is simply "str + cols - 1". It's also confusing that your
> start_idx is larger than the end_idx in find_last_space(). Maybe using
> strchr(), strrchr() or strtok(str, " \t") could help you also.
> >
> > For texts like:
> >
> > +             printf("discoverydb\ndiscovery [DEPRECATED]\nnode\n"
> > +                             "session\niface\nfw\nhost\n\n");
> >
> > I'd prefer the formatting like this (if you like those newlines):
> >               printf("discoverydb\n"
> >                  "discovery [DEPRECATED]\n"
> >                  "node\n"
> >                  "session\n"
> >                  "iface\n"
> >                  "fw\n"
> >                  "host\n"
> >                  "\n");
> >
> >
> > For the many
> > +             print_str("\t\t",
> >
> > I'd probably either
> > #define HELP_INDENT "\t\"
> > and use print_str(HELP_INDENT,
> >
> > or define a ``const char *help_indent = "\t\t";''  and use that. Also, it
> seems your print_str() doesn't count your "tabs" correctly when considering
> line breaks. A possible improvement would be to automatically scan for
> leading whitespace (SPC, TAB) at the beginning of a string, and use that as
> indentation if lines are wrapped. I have the impression that your
> print_str() only truncates long lines, but doesn't actually wrap them. Ah,
> sorry, I overlooked the recursion!
> >
> > For the long block starting at
> >
> > +             printf("\nExample:\n");
> > +             printf("\tTo discover a target\n");
> > +             print_str("\t\t",
> > +             "iscsiadm -m discoverydb -t st -p 192.168.1.2:3260 -D");
> > +             printf("\tTo discover and login\n");
> > +             print_str("\t\t",
> > +             "iscsiadm -m discoverydb -t st -p 192.168.1.2:3260 -Dl");
> > +             print_str("\t",
> > +             "To specify an interface during discovery and login");
> > +             print_str("\t\t",
> > +             "iscsiadm -m discoverydb -t st -p 192.168.1.2:3260 -I eth0
> "
> > +             "-Dl");
> >
> > I'd probably separate code and data like this
> >
> > const char *help_text[] = {
> >     "Example:",
> >     "\tTo discover a target",
> >     "\t\tiscsiadm -m discoverydb -t st -p 192.168.1.2:3260 -Dl",
> >     ...,
> >     NULL
> > };
> >
> > const char **txt;
> > for (txt = help_text; *txt; ++txt)
> >     print_str(*txt); // new implementation!
> >
> >
> > Regards,
> > Ulrich
> >
> >>
> >> I did not paste the patch contents as it was pretty long.
> >>
> >> On Tue, Aug 9, 2011 at 8:24 AM, Mike Christie <micha...@cs.wisc.edu>
> wrote:
> >>
> >>> On 07/22/2011 12:09 PM, Vivek S wrote:
> >>>> Changed the way iscsiadm displays usage help about its commands.
> Rather
> >>> than
> >>>> simply displaying each possible mode along with its options on a
> single
> >>>> line,
> >>>> the user can now ask help for each mode separately which describes the
> >>>> various options and also provides some examples.
> >>>>
> >>>
> >>>
> >>>> +        printf("\n");
> >>>> +        switch (mode)
> >>>> +        {
> >>>> +            case MODE_DISCOVERYDB:
> >>>> +                printf("iscsiadm -m discoverydb [options...]\n\n");
> >>>> +                options = CMD_LINE_OPTION_PORTAL |
> CMD_LINE_OPTION_IFACE
> >>> |
> >>>> CMD_LINE_OPTION_OP \
> >>>> +
> >>>
> >>> Not sure if it is the mailer but just try to keep things around 80
> >>> columns in the code like the other code is doing unless it is a string
> >>> and breaking it up makes it more difficult to read.
> >>>
> >>> For example if you hit 80 cols in the middle of a target name
> >>> "iqn.2005-06.com.mydomain.openiscsi.test1" then I would not split that
> >>> up into "iqn.2005-06.com.mydom" and "ain.openiscsi.test1" just to make
> >>> it 80 cols.
> >>>
> >>> But, something like the above could be
> >>>
> >>> options = CMD_LINE_OPTION_PORTAL | CMD_LINE_OPTION_IFACE | \
> >>>                CMD_LINE_OPTION_OP \
> >>>
> >
> >
> >
> >
> >
>
> --
> 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 2f6eb00a8fb0ba49ae01371d33c630005fd23123 Mon Sep 17 00:00:00 2001
From: Vivek Subbarao <vivek...@gmail.com>
Date: Sun, 28 Aug 2011 15:12:43 +0530
Subject: [PATCH 1/1] iscsiadm help update


Signed-off-by: Vivek Subbarao <vivek...@gmail.com>
---
 usr/Makefile   |    2 +-
 usr/iscsiadm.c |  431 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 412 insertions(+), 21 deletions(-)

diff --git a/usr/Makefile b/usr/Makefile
index 3ee0cb4..43d4c54 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -59,7 +59,7 @@ iscsid: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(DISCOVERY_SRCS) \
 	$(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns
 
 iscsiadm: $(ISCSI_LIB_SRCS) $(DISCOVERY_SRCS) iscsiadm.o session_mgmt.o
-	$(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns
+	$(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns -ltermcap
 
 iscsistart: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(FW_BOOT_SRCS) \
 		iscsistart.o statics.o
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index 03b779e..6d805d2 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,411 @@ 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)
+
+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"
+};
+
+/*
+ * String name for each mode.
+ */
+const char *mode_str[] = {
+	"discovery",
+	"discoverydb",
+	"node",
+	"session",
+	"host",
+	"iface",
+	"fw"
+};
+
+/*
+ * Examples for each mode. This should be in the same order
+ * as the modes decalred in the enum above.
+ */
+const char *examples[] = {
+	"\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"
+	,
+	
+	"\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"
+	,
+
+	"\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"
+	,
+	
+	"\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"
+	,
+	
+	""
+	,
+
+	"\nExample:\n\n"
+	"To add a iface record\n"
+	"iscsiadm -m iface -I eth1 -o new\n"
+	,
+
+	""
+
+};
+
+/*
+ * Structure to hold all iscsiadm command line options and their description.
+ */
+struct option_help
+{
+	char *option;
+	const char *help_str;
+}opt_help[] = {
+	{"p",	"Portal in ip:port format. If only ip address is specified "
+		"then the value 3260 is assumed for the port."},
+	{"T",	"Iqn name of the target."},
+	{"I",	"Interface to use for the operation. This is the name of file "
+		"in /etc/iscsi/ifaces/ directory. Multiple interfaces can be "
+		"specified."},
+	{"o",	"One of the new, delete, update, show or nonpersistent "
+		"operations."},
+	{"t",	"Type of discovery. Sendtargets, slp, isns or fw."},
+	{"n",	"Name of the field to use in the update operation."},
+	{"v",	"Value to use for the specified field in the update "
+		"operation."},
+	{"H",	"SCSI host to use for the operation."},
+	{"r",	"Session ID to use. This is either a positive integer or a "
+		"sysfs path like /sys/devices/platform/hostH/sessionS/targetH:"
+		"B:I"},
+	{"R",	"Rescan all sessions if no SID is specified, else scan only "
+		"that session."},
+	{"P",	"Level of information output. 0 to display a single line and "
+		"1 to display detailed information in tree format."},
+	{"D",	"Discover targets."},
+	{"l",	"Login to the discovered or specified target."},
+	{"L",	"Login to all sessions with the specified node or connection "
+		"startup value or all session if all is passed."},
+	{"u",	"Logout of the specified node or session."},
+	{"U",	"Logout of all sessions with the specified node or connection "
+		"startup value or all sessions if all is passed."},
+	{"s",	"Display session statistics"},
+	{"k",	"Kill iscsid."},
+	{"d",	"Print debugging information. Valid values are 0 to 8."},
+	{"S",	"Show masked values during information display."},
+	{"V",	"Display iscsiadm version."},
+	{"h",	"Display this help."},
+	{NULL,	NULL}
+};
+
+/*
+ * Global defines for all iscsiadm command line options.
+ */
+#define CMD_LINE_OPTION_PORTAL		0
+#define CMD_LINE_OPTION_TGTNAME		1
+#define CMD_LINE_OPTION_IFACE		2
+#define CMD_LINE_OPTION_OP		3
+#define CMD_LINE_OPTION_TYPE		4
+#define CMD_LINE_OPTION_NAME		5
+#define CMD_LINE_OPTION_VALUE		6
+#define CMD_LINE_OPTION_HOST		7
+#define CMD_LINE_OPTION_SID		8
+#define CMD_LINE_OPTION_RESCAN		9
+#define CMD_LINE_OPTION_PRINT		10
+#define CMD_LINE_OPTION_DSCVR		11
+#define CMD_LINE_OPTION_LOGIN		12
+#define CMD_LINE_OPTION_LOGINALL	13
+#define CMD_LINE_OPTION_LOGOUT		14
+#define CMD_LINE_OPTION_LOGOUTALL	15
+#define CMD_LINE_OPTION_STATS		16
+#define CMD_LINE_OPTION_KILLISCSID	17
+#define CMD_LINE_OPTION_DEBUG		18
+#define CMD_LINE_OPTION_SHOW		19
+#define CMD_LINE_OPTION_VERSION		20
+#define CMD_LINE_OPTION_HELP		21
+
+
+/*
+ * Struture containing pointers to option_help structures describing all options
+ * for each mode supported by iscsiadm.
+ */
+struct mode_help
+{
+	struct option_help *op_h[MAX_CMD_OPTIONS];
+}m_help[] = {
+	{
+	{
+	/*
+	 * Mode discovery
+	 */
+	&opt_help[CMD_LINE_OPTION_PORTAL], &opt_help[CMD_LINE_OPTION_IFACE],
+	&opt_help[CMD_LINE_OPTION_OP], &opt_help[CMD_LINE_OPTION_TYPE],
+	&opt_help[CMD_LINE_OPTION_PRINT], &opt_help[CMD_LINE_OPTION_DSCVR],
+       	&opt_help[CMD_LINE_OPTION_LOGIN], &opt_help[CMD_LINE_OPTION_DEBUG],
+	&opt_help[CMD_LINE_OPTION_HELP], NULL
+	}
+	},
+
+	{
+	/*
+	 * Mode discoverydb
+	 */
+	{
+	&opt_help[CMD_LINE_OPTION_PORTAL], &opt_help[CMD_LINE_OPTION_IFACE],
+	&opt_help[CMD_LINE_OPTION_OP], &opt_help[CMD_LINE_OPTION_TYPE],
+	&opt_help[CMD_LINE_OPTION_PRINT], &opt_help[CMD_LINE_OPTION_DSCVR],
+	&opt_help[CMD_LINE_OPTION_LOGIN], &opt_help[CMD_LINE_OPTION_DEBUG], 
+	&opt_help[CMD_LINE_OPTION_HELP], &opt_help[CMD_LINE_OPTION_NAME],
+	&opt_help[CMD_LINE_OPTION_VALUE], NULL
+	}
+	},
+
+	{
+	/*
+	 * Mode node
+	 */
+	{
+	&opt_help[CMD_LINE_OPTION_PORTAL], &opt_help[CMD_LINE_OPTION_IFACE],
+	&opt_help[CMD_LINE_OPTION_DEBUG], &opt_help[CMD_LINE_OPTION_LOGOUTALL],
+	&opt_help[CMD_LINE_OPTION_LOGIN], &opt_help[CMD_LINE_OPTION_LOGINALL],
+	&opt_help[CMD_LINE_OPTION_LOGOUT], &opt_help[CMD_LINE_OPTION_PRINT],
+	&opt_help[CMD_LINE_OPTION_TGTNAME], &opt_help[CMD_LINE_OPTION_SHOW],
+	&opt_help[CMD_LINE_OPTION_RESCAN], &opt_help[CMD_LINE_OPTION_STATS],
+	&opt_help[CMD_LINE_OPTION_HELP], &opt_help[CMD_LINE_OPTION_OP],
+	&opt_help[CMD_LINE_OPTION_NAME], &opt_help[CMD_LINE_OPTION_VALUE], NULL
+	}
+	},
+
+	{
+	/*
+	 * Mode session
+	 */
+	{
+	&opt_help[CMD_LINE_OPTION_SID], &opt_help[CMD_LINE_OPTION_RESCAN],
+	&opt_help[CMD_LINE_OPTION_LOGOUT], &opt_help[CMD_LINE_OPTION_STATS],
+	&opt_help[CMD_LINE_OPTION_OP], &opt_help[CMD_LINE_OPTION_NAME],
+	&opt_help[CMD_LINE_OPTION_VALUE], &opt_help[CMD_LINE_OPTION_DEBUG],
+	&opt_help[CMD_LINE_OPTION_PRINT], &opt_help[CMD_LINE_OPTION_HELP], NULL
+	}
+	},
+
+	{
+	/*
+	 * Mode host
+	 */
+	{
+	&opt_help[CMD_LINE_OPTION_IFACE], &opt_help[CMD_LINE_OPTION_OP],
+	&opt_help[CMD_LINE_OPTION_NAME], &opt_help[CMD_LINE_OPTION_VALUE],
+	&opt_help[CMD_LINE_OPTION_DEBUG], &opt_help[CMD_LINE_OPTION_PRINT],
+	&opt_help[CMD_LINE_OPTION_HELP], NULL
+	}
+	},
+
+	{
+	/*
+	 * Mode iface
+	 */
+	{
+	&opt_help[CMD_LINE_OPTION_LOGIN], NULL
+	}
+	},
+
+	{
+	/*
+	 * Mode fw
+	 */
+	{
+	&opt_help[CMD_LINE_OPTION_HOST], &opt_help[CMD_LINE_OPTION_PRINT], NULL
+	}
+	}
+};
+
+
+/*
+ * 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;
+} 
+
+
+/*
+ * Get width of the TAB character.
+ */
+int get_tab_width(void)
+{
+	char *buf = NULL;
+	int tab_width = 0, ret = 0;
+	char *term = getenv("TERM");
+	
+	if (term == NULL)
+		return 8;
+
+	ret = tgetent(buf, term);
+	if (ret == 0 || ret < 0)
+		return 8;
+	
+	tab_width = tgetnum("it");
+	if (tab_width == -1)
+	{
+		/*
+		* Calling tgetent again frees the buffer
+		* allocated by it.
+		*/
+		tgetent(buf, term);
+		return 8;
+	}
+	
+	return tab_width;
+}
+
+/*
+ * 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 *temp_str = (char *)str;
+	char buf[1024] = {0};
+	char *p = NULL, *q = NULL;
+	int max_cols = get_cols();
+	int tab_width = get_tab_width();
+	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 - temp_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 (temp_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, temp_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, temp_str);
+	}
+	else
+	{
+		print_len = str_len;
+		printf("%s%.*s", tabs, str_len, temp_str);
+	}
+
+	print_str(tabs, temp_str+print_len);
+}
+
+static void usage(int status, int mode)
 {
-	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;
+
+	printf("\n");
+
+	if ((status != 0) || (mode == -1) || (mode > MODE_FW))
+	{
+		print_str("", generic_help[0]);
+	}
+	else
+	{
+		printf(	"iscsiadm -m %s [options...]\n\n"
+			"Options\tDescription\n"
+			"-------\t-----------\n", mode_str[mode]);
+
+		for (i=0 ; m_help[mode].op_h[i] != 0 ; i++)
+		{
+			printf("%s",
+			m_help[mode].op_h[i]->option); 
+			print_str("\t",
+			m_help[mode].op_h[i]->help_str);
+			printf("\n");
+		}
+				
+		print_str("", examples[mode]); 
+		printf("\nSEE MAN PAGE FOR MORE DETAILS\n\n");
 	}
+
 	exit(status);
 }
 
@@ -377,7 +768,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 +838,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 +2614,7 @@ main(int argc, char **argv)
 				ISCSI_VERSION_STR);
 			return 0;
 		case 'h':
-			usage(0);
+			usage(0, mode);
 		}
 	}
 
@@ -2239,7 +2630,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