/*
 * ftop - show progress of open files and file systems
 * Copyright (C) 2009  Jason Todd <jtodd1@earthlink.net>
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */

/* options.h - ftop option descriptions & declarations */

#ifndef __OPTIONS_H__
#define __OPTIONS_H__

#include "ftop.h"

#define DEFAULT_ADD         ""
#define DEFAULT_CLOSED      "0"
#define DEFAULT_DELAY       "1.00"
#define DEFAULT_FILE        ""
#define DEFAULT_LOG         "none"
#define DEFAULT_MODE        "all"
#define DEFAULT_ITERATIONS  "0"
#define DEFAULT_PROCS       ""
#define DEFAULT_TYPE        "f,d"
#define DEFAULT_UID         ""
#define DEFAULT_EXIT_ITERS  "0"
#define DEFAULT_FSTYPE      ""
#define DEFAULT_SIZE        ""

#define OPT_ADD_CHAR            'a'
#define OPT_ADD_STR             "Additional files/fs"
#define OPT_ADD_HELP \
    "Manually specify files or file systems to monitor.  These are in " \
    "addition to all currently open files.  If any directories are " \
    "specified, their file system usage is displayed.  This option is " \
    "useful for monitoring files written by NFS clients, or for observing " \
    "the addition of a large number of files to a file system (for example, " \
    "while extracting a large archive or restoring from a backup)."

#define OPT_ADD_ONLY_CHAR       'A'
#define OPT_ADD_ONLY_STR        "Addl. files/fs only"
#define OPT_ADD_ONLY_HELP \
    "Only show the files and file systems specified in '" OPT_ADD_STR "' " \
    "(see above) and '" OPT_FSTYPE_STR "' (see below)."

#define OPT_EXPAND_ATBEGIN_CHAR 'B'
#define OPT_EXPAND_ATBEGIN_STR  "Expand at-beginning"
#define OPT_EXPAND_ATBEGIN_HELP \
    "Show the progress bar for files that are still at the beginning.  When " \
    "this option is disabled, a file's progress bar doesn't appear until " \
    "there has been some activity.  Often, there are processes that hold " \
    "log files open for append, but haven't yet written anything new.  " \
    "Leaving this disabled reduces the clutter in the presence of those " \
    "(and similar) situations."

#define OPT_CLOSED_CHAR         'c'
#define OPT_CLOSED_STR          "Closed files count"
#define OPT_CLOSED_HELP \
    "Additionally show the specified number of most recently closed files " \
    "for each displayed process."

#define OPT_DELAY_CHAR          'd'
#define OPT_DELAY_STR           "Delay"
#define OPT_DELAY_HELP \
    "Change the time between updates.  The value is specified in seconds, " \
    "with optional tenths or hundredths (for example: 1 or 0.5 or 1.25 are " \
    "all valid)."

#define OPT_HIDE_DIR_CHAR       'D'
#define OPT_HIDE_DIR_STR        "Hide path directories"
#define OPT_HIDE_DIR_HELP \
    "Hide all leading directory components of each file path.  If the file " \
    "path refers to an unnamed pipe or socket, or otherwise is not valid, " \
    "then the full path will still be displayed."

#define OPT_EXPAND_ATEND_CHAR   'E'
#define OPT_EXPAND_ATEND_STR    "Expand at-end"
#define OPT_EXPAND_ATEND_HELP \
    "Show the progress bar for files that are at the end.  When this option " \
    "is disabled, a file's progress bar disappears once the process reaches " \
    "the end of the file.  Whenever a process writes to a file, the " \
    "resulting position is at the end.  Processes that write to log files " \
    "tend to have several files open in this state.  Leaving this disabled "\
    "reduces the clutter in the presence of those (and similar) " \
    "situations.  See also '" OPT_SIZE_STR "' below."

#define OPT_FILE_CHAR           'f'
#define OPT_FILE_STR            "File keywords"
#define OPT_FILE_HELP \
    "Only show files whose path contains, anywhere within, one of the " \
    "specified keywords.  For instance, if a file /tmp/live-cd.iso is open, " \
    "and the keyword list contains cd.i, then that file will be shown."

#define OPT_UNEXP_FILES_CHAR    'F'
#define OPT_UNEXP_FILES_STR     "Show un-expanded files"
#define OPT_UNEXP_FILES_HELP \
    "Show all files that are open within the displayed processes.  See also " \
    "'" OPT_UNEXP_PROCS_STR "' below."

#define OPT_HELP_CHAR           'h'
#define OPT_HELP_STR            "Help"
#define OPT_HELP_HELP \
    "Toggle this help screen."

#define OPT_LOG_CHAR            'l'
#define OPT_LOG_STR             "Log types"
#define OPT_LOG_HELP \
    "Specify the type(s) of messages to log.  Valid types are none, all, or " \
    "one or more of the following: err, warn, info, debug.  The value none " \
    "disables logging.  If logging is enabled, and '" OPT_SWITCH_OUTPUT_STR \
    "' (see below) is enabled, the log is output on stderr.  See also '" \
    OPT_VIEW_LOG_STR "' below."

#define OPT_VIEW_LOG_CHAR       'L'
#define OPT_VIEW_LOG_STR        "View log"
#define OPT_VIEW_LOG_HELP \
    "Toggle the log screen, if logging is enabled."

#define OPT_MODE_CHAR           'm'
#define OPT_MODE_STR            "Access modes"
#define OPT_MODE_STR_HELP \
    "Specify the access mode(s) of files to show.  Valid modes are one or " \
    "more of the following: r, w, rw.  If r is specified, files open for " \
    "read-only access will be shown.  If w is specified, files open for " \
    "write-only access will be shown.  If rw is specified, then files open " \
    "for read and write will be shown.  Note, rw does not include read-only " \
    "or write-only files."

#define OPT_ITERATIONS_CHAR     'n'
#define OPT_ITERATIONS_STR      "Iterations"
#define OPT_ITERATIONS_HELP \
    "Specify the total number of update iterations to run, after which ftop " \
    "will exit."

#define OPT_FD_NUMBERS_CHAR     'N'
#define OPT_FD_NUMBERS_STR      "Show all FDs numeric"
#define OPT_FD_NUMBERS_HELP \
    "Display all file descriptors as their numeric values.  When this " \
    "option is disabled, file descriptors 0, 1, and 2 are given the " \
    "symbolic names in, out, and err, respectively, to reflect stdin, " \
    "stdout, and stderr."

#define OPT_OPTIONS_CHAR        'o'
#define OPT_OPTIONS_STR         "View options"
#define OPT_OPTIONS_HELP \
    "Toggle the options summary screen."

#define OPT_SWITCH_OUTPUT_CHAR  'O'
#define OPT_SWITCH_OUTPUT_STR   "Limited output mode"
#define OPT_SWITCH_OUTPUT_HELP \
    "Toggle between full output mode and limited output mode.  By default, " \
    "full mode is selected if the ncurses library is available and stdout " \
    "is a terminal (e.g. not redirected or piped).  If neither of the above " \
    "is true, then only limited mode will be available.  If this option is " \
    "specified on the command line, limited mode will be used initially.  " \
    "In limited mode, all control keys can still be used, but scrolling is " \
    "not available."

#define OPT_PROCS_CHAR          'p'
#define OPT_PROCS_STR           "Process keywords/PIDs"
#define OPT_PROCS_HELP \
    "Show only processes whose command line contains, anywhere within, one " \
    "the specified keywords, or whose PID equals a specified value.  For " \
    "instance, the list 1,bash,X will show the init process, all instances " \
    "of bash, and any running X servers (if X is within their command " \
    "line).  Note, processes with no open files that match any of the other " \
    "criteria will still not be shown.  See also '" OPT_UNEXP_PROCS_STR \
    "' below."

#define OPT_UNEXP_PROCS_CHAR    'P'
#define OPT_UNEXP_PROCS_STR     "Show un-expanded procs"
#define OPT_UNEXP_PROCS_HELP \
    "Show all processes.  See also '" OPT_UNEXP_FILES_STR "' and '" \
    OPT_PROCS_STR "' above."

#define OPT_QUIT_CHAR           'q'
#define OPT_QUIT_STR            "Quit"
#define OPT_QUIT_HELP \
    "Exit from ftop."

#define OPT_QUIET_CHAR          'Q'
#define OPT_QUIET_STR           "Hide tput & est. time"
#define OPT_QUIET_HELP \
    "Do not show any throughput or estimated time remaining calculations.  " \
    "This is useful when simply monitoring how far into files the processes " \
    "are, especially if used with a very small delay (see '" OPT_DELAY_STR \
    "' above)."

#define OPT_REFRESH_CHAR        'r'
#define OPT_REFRESH_STR         "Refresh display"
#define OPT_REFRESH_HELP \
    "Force a refresh of the display."

#define OPT_TYPE_CHAR           't'
#define OPT_TYPE_STR            "File types"
#define OPT_TYPE_HELP \
    "Specify the type(s) of files to show.  Valid types are all, or one or " \
    "more of the following: f, d, c, b, p, s, x.  Also allowed is r, an " \
    "alias for f.  The meaning of each is: f (regular file), d (directory), " \
    "c (character device), b (block device), p (pipe/FIFO), s (socket), and " \
    "x (miscellaneous - unknown or unclassifiable)."

#define OPT_UID_CHAR            'u'
#define OPT_UID_STR             "User name/UID"
#define OPT_UID_HELP \
    "Only show processes with the given real user id.  The user can be " \
    "specified either as a name or as a UID."

#define OPT_UNITS_BASE10_CHAR   'U'
#define OPT_UNITS_BASE10_STR    "Units in base 10"
#define OPT_UNITS_BASE10_HELP \
    "If this option is disabled, sizes and throughputs will be reported in " \
    "units based on powers of 2.  Specifically, M (megabyte) corresponds to " \
    "2 to the 20th power and G (gigabyte) corresponds to 2 to the 30th.  If " \
    "this option is enabled, the units e6 (million bytes) and e9 (billion " \
    "bytes) will be used instead.  Note, either form is always acceptable " \
    "when entering size values, regardless of this setting."

#define OPT_VERSION_CHAR        'v'
#define OPT_VERSION_STR         "Version and license"
#define OPT_VERSION_HELP \
    "Toggle the version and license screen."

#define OPT_MAX_NO_MATCH_CHAR   'x'
#define OPT_MAX_NO_MATCH_STR    "Max no-match iterations"
#define OPT_MAX_NO_MATCH_HELP \
    "Specify the number of iterations to remain running when there are no " \
    "open files matching any of the other criteria.  At least one match has " \
    "to have been shown, and subsequently been closed, before the remaining " \
    "iterations are counted.  If during those iterations, another matching " \
    "file is shown, the counter is reset.  See also '" OPT_ITERATIONS_STR \
    "' above."

#define OPT_FSTYPE_CHAR         'y'
#define OPT_FSTYPE_STR          "File system types"
#define OPT_FSTYPE_HELP \
    "Show all mounted filesystems of the specified types.  Valid types are " \
    "all, or one or more of the types supported by the kernel (refer to " \
    "/proc/filesystems).  The display is updated to reflect the mounting " \
    "or unmounting of matching file systems."

#define OPT_SIZE_CHAR           'z'
#define OPT_SIZE_STR            "File keywords & sizes"
#define OPT_SIZE_HELP \
    "Specify pre-determined final sizes to use for files opened for write " \
    "access and for file systems (see '" OPT_ADD_STR "' above).  The values " \
    "in the list must be of the form keyword=size, where keyword is applied " \
    "as in '" OPT_FILE_STR "' (see above) and size is given in bytes, " \
    "megabytes (or million bytes), or gigabytes (or billion bytes) with " \
    "optional tenths value.  See '" OPT_UNITS_BASE10_STR "' above.  The " \
    "following is an example of a valid list: " \
    "data_out.bin=1.5G,/tmp/=700e6,some_file.copy=120000"

#define OPT_PROMPT_SUFFIX       " (blank for default): "
#define OPT_ADD_PROMPT          OPT_ADD_STR OPT_PROMPT_SUFFIX
#define OPT_CLOSED_PROMPT       OPT_CLOSED_STR OPT_PROMPT_SUFFIX
#define OPT_DELAY_PROMPT        OPT_DELAY_STR OPT_PROMPT_SUFFIX
#define OPT_FILE_PROMPT         OPT_FILE_STR OPT_PROMPT_SUFFIX
#define OPT_LOG_PROMPT          OPT_LOG_STR OPT_PROMPT_SUFFIX
#define OPT_MODE_PROMPT         OPT_MODE_STR OPT_PROMPT_SUFFIX
#define OPT_ITERATIONS_PROMPT   OPT_ITERATIONS_STR OPT_PROMPT_SUFFIX
#define OPT_PROCS_PROMPT        OPT_PROCS_STR OPT_PROMPT_SUFFIX
#define OPT_TYPE_PROMPT         OPT_TYPE_STR OPT_PROMPT_SUFFIX
#define OPT_UID_PROMPT          OPT_UID_STR OPT_PROMPT_SUFFIX
#define OPT_MAX_NO_MATCH_PROMPT OPT_MAX_NO_MATCH_STR OPT_PROMPT_SUFFIX
#define OPT_FSTYPE_PROMPT       OPT_FSTYPE_STR OPT_PROMPT_SUFFIX
#define OPT_SIZE_PROMPT         OPT_SIZE_STR OPT_PROMPT_SUFFIX

#define OPTION_CASES \
    case OPT_ADD_CHAR: \
        mkstr_add(p); \
        setup_prompt(p, OPT_ADD_PROMPT, 0, READ_TYPE_LIST, parse_add); \
        ret = 0; \
        break; \
    case OPT_ADD_ONLY_CHAR: \
        p->opt_add_only = 1 - p->opt_add_only; \
        break; \
    case OPT_EXPAND_ATBEGIN_CHAR: \
        p->opt_expand_atbegin = 1 - p->opt_expand_atbegin; \
        break; \
    case OPT_CLOSED_CHAR: \
        mkstr_closed(p); \
        setup_prompt(p, OPT_CLOSED_PROMPT, 8, READ_TYPE_NUM, parse_closed); \
        ret = 0; \
        break; \
    case OPT_DELAY_CHAR: \
        mkstr_delay(p); \
        setup_prompt(p, OPT_DELAY_PROMPT, 8, READ_TYPE_NUM_FRAC, \
                     parse_delay); \
        ret = 0; \
        break; \
    case OPT_HIDE_DIR_CHAR: \
        p->opt_hide_dir = 1 - p->opt_hide_dir; \
        break; \
    case OPT_EXPAND_ATEND_CHAR: \
        p->opt_expand_atend = 1 - p->opt_expand_atend; \
        break; \
    case OPT_FILE_CHAR: \
        mkstr_file(p); \
        setup_prompt(p, OPT_FILE_PROMPT, 0, READ_TYPE_LIST, parse_file); \
        ret = 0; \
        break; \
    case OPT_UNEXP_FILES_CHAR: \
        p->opt_unexp_files = 1 - p->opt_unexp_files; \
        break; \
    case OPT_HELP_CHAR: \
        if (!(p->opt_options) && !(p->opt_view_log) && !(p->opt_version)) \
        { \
            p->opt_help = 1 - p->opt_help; \
            p->scrolled_rows = 0; \
        } \
        break; \
    case OPT_LOG_CHAR: \
        mkstr_log(p); \
        setup_prompt(p, OPT_LOG_PROMPT, 32, READ_TYPE_LIST, parse_log); \
        ret = 0; \
        break; \
    case OPT_VIEW_LOG_CHAR: \
        if ((p->opt_log != 0) && !(p->opt_options) && !(p->opt_help) && \
            !(p->opt_version)) \
        { \
            p->opt_view_log = 1 - p->opt_view_log; \
            p->scrolled_rows = 0; \
        } \
        break; \
    case OPT_MODE_CHAR: \
        mkstr_mode(p); \
        setup_prompt(p, OPT_MODE_PROMPT, 8, READ_TYPE_LIST, parse_mode); \
        ret = 0; \
        break; \
    case OPT_ITERATIONS_CHAR: \
        mkstr_iterations(p); \
        setup_prompt(p, OPT_ITERATIONS_PROMPT, 8, READ_TYPE_NUM, \
                     parse_iterations); \
        ret = 0; \
        break; \
    case OPT_FD_NUMBERS_CHAR: \
        p->opt_fd_numbers = 1 - p->opt_fd_numbers; \
        break; \
    case OPT_OPTIONS_CHAR: \
        if (!(p->opt_view_log) && !(p->opt_help) && !(p->opt_version)) \
        { \
            p->opt_options = 1 - p->opt_options; \
            p->scrolled_rows = 0; \
        } \
        break; \
    case OPT_SWITCH_OUTPUT_CHAR: \
        p->opt_switch_output = 1; \
        break; \
    case OPT_PROCS_CHAR: \
        mkstr_procs(p); \
        setup_prompt(p, OPT_PROCS_PROMPT, 0, READ_TYPE_LIST, parse_procs); \
        ret = 0; \
        break; \
    case OPT_UNEXP_PROCS_CHAR: \
        p->opt_unexp_procs = 1 - p->opt_unexp_procs; \
        break; \
    case OPT_QUIT_CHAR: \
        p->opt_quit = 1; \
        break; \
    case OPT_QUIET_CHAR: \
        p->opt_quiet = 1 - p->opt_quiet; \
        break; \
    case OPT_REFRESH_CHAR: \
        p->opt_refresh = 1; \
        break; \
    case OPT_TYPE_CHAR: \
        mkstr_type(p); \
        setup_prompt(p, OPT_TYPE_PROMPT, NUM_TYPES * 2, READ_TYPE_LIST, \
                     parse_type); \
        ret = 0; \
        break; \
    case OPT_UID_CHAR: \
        mkstr_uid(p); \
        setup_prompt(p, OPT_UID_PROMPT, 16, READ_TYPE_TEXT, parse_uid); \
        ret = 0; \
        break; \
    case OPT_UNITS_BASE10_CHAR: \
        p->opt_units_base10 = 1 - p->opt_units_base10; \
        break; \
    case OPT_VERSION_CHAR: \
        if (!(p->opt_view_log) && !(p->opt_help) && !(p->opt_options)) \
        { \
            p->opt_version = 1 - p->opt_version; \
            p->scrolled_rows = 0; \
        } \
        break; \
    case OPT_MAX_NO_MATCH_CHAR: \
        mkstr_max_no_match(p); \
        setup_prompt(p, OPT_MAX_NO_MATCH_PROMPT, 8, READ_TYPE_NUM, \
                     parse_max_no_match); \
        ret = 0; \
        break; \
    case OPT_FSTYPE_CHAR: \
        mkstr_fstype(p); \
        setup_prompt(p, OPT_FSTYPE_PROMPT, 0, READ_TYPE_LIST, \
                     parse_fstype); \
        ret = 0; \
        break; \
    case OPT_SIZE_CHAR: \
        mkstr_size(p); \
        setup_prompt(p, OPT_SIZE_PROMPT, 0, READ_TYPE_LIST_EQ, parse_size); \
        ret = 0; \
        break;

typedef int (*mkstr_function)(ftop_data *p);

int set_defaults(ftop_data *p);
int check_opt_char(ftop_data *p, char c, char *param);
int parse_add(ftop_data *p, char *str);
int parse_closed(ftop_data *p, char *str);
int parse_delay(ftop_data *p, char *str);
int parse_file(ftop_data *p, char *str);
int parse_log(ftop_data *p, char *str);
int parse_mode(ftop_data *p, char *str);
int parse_iterations(ftop_data *p, char *str);
int parse_procs(ftop_data *p, char *str);
int parse_type(ftop_data *p, char *str);
int parse_uid(ftop_data *p, char *str);
int parse_fstype(ftop_data *p, char *str);
int parse_max_no_match(ftop_data *p, char *str);
int parse_size(ftop_data *p, char *str);
int mkstr_add(ftop_data *p);
int mkstr_closed(ftop_data *p);
int mkstr_delay(ftop_data *p);
int mkstr_file(ftop_data *p);
int mkstr_log(ftop_data *p);
int mkstr_mode(ftop_data *p);
int mkstr_iterations(ftop_data *p);
int mkstr_procs(ftop_data *p);
int mkstr_type(ftop_data *p);
int mkstr_uid(ftop_data *p);
int mkstr_fstype(ftop_data *p);
int mkstr_max_no_match(ftop_data *p);
int mkstr_size(ftop_data *p);
int update_add(ftop_data *p);
int update_fstype(ftop_data *p);
int show_option(ftop_data *p, char c, char *str, mkstr_function f,
                int part);
int show_bool(ftop_data *p, char c, char *str, int enabled, int part);
int show_options(ftop_data *p, int part);

#endif  /* __OPTIONS_H__ */
