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