/*
 * 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/>.
 */

/* ftop.h - main declarations for ftop */

#ifndef __FTOP_H__
#define __FTOP_H__

#define _FILE_OFFSET_BITS 64
#include <sys/types.h>      /* pid_t, uid_t, off_t */
#include <unistd.h>         /* size_t */
#include <sys/stat.h>       /* struct stat */
#include <sys/time.h>       /* struct timeval */
#include <inttypes.h>       /* uint32_t */
#include <termios.h>        /* struct termios */
#include <sys/ioctl.h>      /* struct winsize */
#include <pwd.h>            /* struct passwd */

#include "config.h"

#define FTOP_COPYRIGHT_STRING "Copyright (C) 2009 Jason Todd"
#define FTOP_LICENSE_SUMMARY \
    "This program comes with ABSOLUTELY NO WARRANTY.  This is free " \
    "software, and you are welcome to redistribute it under certain " \
    "conditions.  See the GPL for more details; a copy of the GPL is " \
    "included below."

#define HELP_OPT_PART1      "Press "
#define HELP_OPT_PART2      " for help, "
#define HELP_OPT_PART3      " for options"
#define HELP_OPT_STRING HELP_OPT_PART1 "X" HELP_OPT_PART2 "X" HELP_OPT_PART3

#define SCROLL_BASE         5       /* first scrollable line (starting at 0) */

#define ACTIVITY_TIMEOUT    3000    /* how many ms before "stalled" */
#define FMT_OFF_T           "llu"

/* initial sizes/counts */
#define INITIAL_FILES       (8 * sizeof(file_info))
#define INITIAL_NAMES       1024
#define INITIAL_READLINK    80
#define INITIAL_LOG         1024
#define INITIAL_CMDS        4096
#define INITIAL_READ        512

/* limits */
#define MAX_INPUT_BUF       200
#define MAX_SCRATCH_BUF     4096
#define MAX_LOOKUP_USERS    256
#define MAX_CLOSED_PATH     400

#define LOG_NONE            0
#define LOG_ERR             1       /* errors (unexpected results) */
#define LOG_WARN            2       /* warnings */
#define LOG_INFO            4       /* informational messages */
#define LOG_DEBUG           8       /* debug output */
#define LOG_ALL             (LOG_ERR | LOG_WARN | LOG_INFO | LOG_DEBUG)

#define NUM_TYPES           7       /* f, d, c, b, p, s, x */

/* to-do: basic mode: no fancy in or out */
#define MODE_AUTO           0       /* auto-select the output mode */
#define MODE_LIMITED        1       /* limited mode: fancy in, no fancy out */
#define MODE_FULL           2       /* full mode: fancy in, fancy out */

#define READ_TYPE_TEXT      0       /* anything is allowed */
#define READ_TYPE_NUM       1       /* integers only */
#define READ_TYPE_NUM_FRAC  2       /* integers with optional 10ths/100ths */
#define READ_TYPE_LIST      3       /* comma-separated list */
#define READ_TYPE_LIST_EQ   4       /* list of "...=..." pairs */

#define FLAG_SHOW           0x01    /* matchies all criteria */
#define FLAG_ADD            0x02    /* is an additional file/fs */
#define FLAG_FS             0x04    /* is a file system */
#define FLAG_FSTYPE         0x08    /* fs specified via fstype option */
#define FLAG_CLOSED         0x10    /* was closed */
#define FLAG_MISC           0x20    /* not of any known types */

struct _file_info;

typedef struct _process_info
{
    pid_t pid;
    uid_t uid;
    char *cmdline;
    size_t num_files;
    struct _file_info *file;

    /* the following are entirely contained within show_output() */
    int show;
    size_t last_file;
    size_t num_closed;
    size_t last_closed;
    struct _file_info *closed;
} process_info;

typedef struct _file_info
{
    char *path;
    int fd;
    int fdinfo_flags;
    off_t pos;
    struct stat st;

    /* the following are [almost] entirely contained within show_output() */
    int flags;
    struct _file_info *prev;
    int prev_path_changed;
    off_t prev_pos;
    off_t avg_rate;
    struct timeval last_activity;
} file_info;

typedef struct _snapshot
{
    size_t alloc_processes;
    size_t num_processes;
    size_t num_unreadable_processes;
    size_t files_buf_size;
    size_t num_files;
    size_t num_reg;
    size_t num_dir;
    size_t num_chr;
    size_t num_blk;
    size_t num_pipe;
    size_t num_sock;
    size_t num_misc;
    size_t paths_buf_size;
    size_t paths_buf_used;
    size_t readlink_buf_size;
    size_t log_size;
    size_t log_used;
    size_t cmds_buf_size;
    size_t cmds_buf_used;
    size_t read_buf_size;
    struct timeval tv;
    uint32_t log_flags;
    process_info *proc;
    file_info *file;
    char *paths_buf;
    char *readlink_buf;
    char *log;
    char *cmds_buf;
    char *read_buf;
} snapshot;

struct _ftop_data;

typedef int (*snapshot_fixup_function)(snapshot *s, char *new_buf);
typedef int (*parse_function)(struct _ftop_data *p, char *str);

typedef struct _ftop_data
{
    size_t s_idx;
    snapshot s[2];
    int mode;                   /* MODE_AUTO, MODE_LIMITED, MODE_FULL */
    struct termios term_orig;
    struct termios term_raw;
    struct winsize term_size;
    int cur_row;
    int shift_rows;
    int scrolled_rows;
    int output_rows;
    int do_printf;
    int cur_col;
    size_t partial_buf_size;
    char *partial_buf;
    uid_t lookup_user_uid[MAX_LOOKUP_USERS];
    char lookup_user_name[MAX_LOOKUP_USERS][16];
    size_t num_lookup_users;
    uint32_t iter;
    uint32_t no_match_iters;
    int had_match;
    char input_buf[MAX_INPUT_BUF];
    char scratch_buf[MAX_SCRATCH_BUF];
    char *prompt;
    size_t input_max;
    int input_type;
    parse_function parse_input;
    int input_dots;
    int input_need_eq;
    char *error;
    struct timeval error_time;
    size_t mtab_size;
    char *mtab_buf;

    char *opt_add_path;         /* NUL-separated (NUL-NUL-terminated) list */
    file_info *opt_add_info;    /* all-zeros-terminated list (path == NULL) */
    file_info *opt_add_prev;    /* all-zeros-terminated list (path == NULL) */
    int opt_add_only;           /* bool */
    int opt_expand_atbegin;     /* bool */
    uint32_t opt_closed;        /* parsed value */
    uint32_t opt_delay_ms;      /* parsed & converted value */
    int opt_hide_dir;           /* bool */
    int opt_expand_atend;       /* bool */
    char *opt_file;             /* NUL-separated (NUL-NUL-terminated) list */
    int opt_unexp_files;        /* bool */
    int opt_help;               /* bool */
    int opt_log;                /* parsed flags */
    int opt_view_log;           /* bool */
    int opt_mode[3];          /* list O_RDONLY/O_WRONLY/O_RDWR, pad w/repeat */
    uint32_t opt_iterations;    /* parsed value */
    int opt_fd_numbers;         /* bool */
    int opt_options;            /* bool */
    int opt_switch_output;      /* bool */
    pid_t *opt_procs_pid;       /* parsed zero-terminated list */
    char *opt_procs_keyword;    /* NUL-separated (NUL-NUL-terminated) list */
    int opt_unexp_procs;        /* bool */
    int opt_quit;               /* bool */
    int opt_quiet;              /* bool */
    int opt_refresh;            /* bool */
    char opt_type[NUM_TYPES + 1]; /* parsed into char sequence string */
    int opt_uid_specified;      /* bool */
    uid_t opt_uid;              /* parsed value */
    int opt_units_base10;       /* bool */
    int opt_version;            /* bool */
    uint32_t opt_max_no_match;  /* parsed value */
    char *opt_fstype;           /* NUL-separated (NUL-NUL-terminated) list */
    char *opt_size_keyword;     /* NUL-separated (NUL-NUL-terminated) list */
    off_t *opt_size_val;        /* parsed zero-terminated list */
} ftop_data;

int screen_title(ftop_data *p, char *title, char return_key);
int add_lookup_user(ftop_data *p, struct passwd *pw);
char *lookup_user(ftop_data *p, uid_t uid);
int label_value(ftop_data *p, char *buf, size_t max, off_t value);
int compare_file_activity(const void *va, const void *vb);
int calc_rate(file_info *file, struct timeval *tv_then,
              struct timeval *tv_now);

#endif  /* __FTOP_H__ */
