1
1
Fork 0

Backport argument parser from ncdu 2.x + add a few inverted arguments

This makes way for backporting the various new configuration options
and config file support from 2.x.
This commit is contained in:
Yorhel 2022-11-05 12:21:28 +01:00
parent dc78e8db19
commit 9670ca66ed
6 changed files with 211 additions and 373 deletions

View File

@ -21,7 +21,6 @@ ncdu_SOURCES=\
noinst_HEADERS=\
deps/yopt.h\
deps/khashl.h\
deps/strnatcmp.h\
src/browser.h\
@ -49,6 +48,5 @@ ncdu.1: $(srcdir)/doc/ncdu.pod
# dependencies have minor ncdu-specific changes.
update-deps:
wget -q https://raw.github.com/attractivechaos/klib/master/khashl.h -O "$(srcdir)/deps/khashl.h"
wget -q http://g.blicky.net/ylib.git/plain/yopt.h -O "$(srcdir)/deps/yopt.h"
wget -q https://raw.githubusercontent.com/sourcefrog/natsort/master/strnatcmp.h -O "$(srcdir)/deps/strnatcmp.h"
wget -q https://raw.githubusercontent.com/sourcefrog/natsort/master/strnatcmp.c -O "$(srcdir)/deps/strnatcmp.c"

198
deps/yopt.h vendored
View File

@ -1,198 +0,0 @@
/* Copyright (c) 2012-2013 Yoran Heling
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* This is a simple command-line option parser. Operation is similar to
* getopt_long(), except with a cleaner API.
*
* This is implemented in a single header file, as it's pretty small and you
* generally only use an option parser in a single .c file in your program.
*
* Supports (examples from GNU tar(1)):
* "--gzip"
* "--file <arg>"
* "--file=<arg>"
* "-z"
* "-f <arg>"
* "-f<arg>"
* "-zf <arg>"
* "-zf<arg>"
* "--" (To stop looking for further options)
* "<arg>" (Non-option arguments)
*
* Issues/non-features:
* - An option either requires an argument or it doesn't.
* - No way to specify how often an option can/should be used.
* - No way to specify the type of an argument (filename/integer/enum/whatever)
*/
#ifndef YOPT_H
#define YOPT_H
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct {
/* Value yopt_next() will return for this option */
int val;
/* Whether this option needs an argument */
int needarg;
/* Name(s) of this option, prefixed with '-' or '--' and separated by a
* comma. E.g. "-z", "--gzip", "-z,--gzip".
* An option can have any number of aliases.
*/
const char *name;
} yopt_opt_t;
typedef struct {
int argc;
int cur;
int argsep; /* '--' found */
char **argv;
char *sh;
const yopt_opt_t *opts;
char errbuf[128];
} yopt_t;
/* opts must be an array of options, terminated with an option with val=0 */
static inline void yopt_init(yopt_t *o, int argc, char **argv, const yopt_opt_t *opts) {
o->argc = argc;
o->argv = argv;
o->opts = opts;
o->cur = 0;
o->argsep = 0;
o->sh = NULL;
}
static inline const yopt_opt_t *_yopt_find(const yopt_opt_t *o, const char *v) {
const char *tn, *tv;
for(; o->val; o++) {
tn = o->name;
while(*tn) {
tv = v;
while(*tn && *tn != ',' && *tv && *tv != '=' && *tn == *tv) {
tn++;
tv++;
}
if(!(*tn && *tn != ',') && !(*tv && *tv != '='))
return o;
while(*tn && *tn != ',')
tn++;
while(*tn == ',')
tn++;
}
}
return NULL;
}
static inline int _yopt_err(yopt_t *o, char **val, const char *fmt, ...) {
va_list va;
va_start(va, fmt);
vsnprintf(o->errbuf, sizeof(o->errbuf), fmt, va);
va_end(va);
*val = o->errbuf;
return -2;
}
/* Return values:
* 0 -> Non-option argument, val is its value
* -1 -> Last argument has been processed
* -2 -> Error, val will contain the error message.
* x -> Option with val = x found. If the option requires an argument, its
* value will be in val.
*/
static inline int yopt_next(yopt_t *o, char **val) {
const yopt_opt_t *opt;
char sh[3];
*val = NULL;
if(o->sh)
goto inshort;
if(++o->cur >= o->argc)
return -1;
if(!o->argsep && o->argv[o->cur][0] == '-' && o->argv[o->cur][1] == '-' && o->argv[o->cur][2] == 0) {
o->argsep = 1;
if(++o->cur >= o->argc)
return -1;
}
if(o->argsep || *o->argv[o->cur] != '-') {
*val = o->argv[o->cur];
return 0;
}
if(o->argv[o->cur][1] != '-') {
o->sh = o->argv[o->cur]+1;
goto inshort;
}
/* Now we're supposed to have a long option */
if(!(opt = _yopt_find(o->opts, o->argv[o->cur])))
return _yopt_err(o, val, "Unknown option '%s'", o->argv[o->cur]);
if((*val = strchr(o->argv[o->cur], '=')) != NULL)
(*val)++;
if(!opt->needarg && *val)
return _yopt_err(o, val, "Option '%s' does not accept an argument", o->argv[o->cur]);
if(opt->needarg && !*val) {
if(o->cur+1 >= o->argc)
return _yopt_err(o, val, "Option '%s' requires an argument", o->argv[o->cur]);
*val = o->argv[++o->cur];
}
return opt->val;
/* And here we're supposed to have a short option */
inshort:
sh[0] = '-';
sh[1] = *o->sh;
sh[2] = 0;
if(!(opt = _yopt_find(o->opts, sh)))
return _yopt_err(o, val, "Unknown option '%s'", sh);
o->sh++;
if(opt->needarg && *o->sh)
*val = o->sh;
else if(opt->needarg) {
if(++o->cur >= o->argc)
return _yopt_err(o, val, "Option '%s' requires an argument", sh);
*val = o->argv[o->cur];
}
if(!*o->sh || opt->needarg)
o->sh = NULL;
return opt->val;
}
#endif
/* vim: set noet sw=4 ts=4: */

View File

@ -54,12 +54,12 @@ directory with many files. 10.000 files will get you an export in the order of
gzip. This scales linearly, so be prepared to handle a few tens of megabytes
when dealing with millions of files.
=item B<-e>
=item B<-e>, B<--extended>, B<--no-extended>
Enable extended information mode. This will, in addition to the usual file
information, also read the ownership, permissions and last modification time
for each file. This will result in higher memory usage (by roughly ~30%) and in
a larger output file when exporting.
Enable/disable extended information mode. This will, in addition to the usual
file information, also read the ownership, permissions and last modification
time for each file. This will result in higher memory usage (by roughly ~30%)
and in a larger output file when exporting.
When using the file export/import function, this flag will need to be added
both when exporting (to make sure the information is added to the export), and
@ -99,12 +99,13 @@ Provide a full-screen ncurses interface while scanning a directory or importing
a file. This is the only interface that provides feedback on any non-fatal
errors while scanning.
=item B<-q>
=item B<-q>, B<--slow-ui-updates>, B<--fast-ui-updates>
Quiet mode. While scanning or importing the directory, ncdu will update the
screen 10 times a second by default, this will be decreased to once every 2
seconds in quiet mode. Use this feature to save bandwidth over remote
connections. This option has no effect when C<-0> is used.
Change the UI update interval while scanning or importing. Ncdu will update the
screen 10 times a second by default (C<--fast-ui-updates>), this can be
decreased to once every 2 seconds with C<-q> or C<--slow-ui-updates>. This
feature can be used to save bandwidth over remote connections. This option has
no effect when C<-0> is used.
=item B<-r>
@ -123,16 +124,16 @@ C<-rr>).
In addition to C<-r>, this will also disable the shell spawning feature of the
file browser.
=item B<--si>
=item B<--si>, B<--no-si>
List sizes using base 10 prefixes, that is, powers of 1000 (KB, MB, etc), as
defined in the International System of Units (SI), instead of the usual base 2
prefixes, that is, powers of 1024 (KiB, MiB, etc).
=item B<--confirm-quit>
=item B<--confirm-quit>, B<--no-confirm-quit>
Requires a confirmation before quitting ncdu. Very helpful when you
accidentally press 'q' during or after a very long scan.
Require a confirmation before quitting ncdu. Very helpful when you accidentally
press 'q' during or after a very long scan.
=item B<--color> I<SCHEME>
@ -152,11 +153,16 @@ directory information from a file.
=over
=item B<-x>
=item B<-x>, B<--one-file-system>
Do not cross filesystem boundaries, i.e. only count files and directories on
the same filesystem as the directory being scanned.
=item B<--cross-file-system>
Do cross filesystem boundaries. This is the default, but can be specified to
overrule a previously given C<-x>.
=item B<--exclude> I<PATTERN>
Exclude files that match I<PATTERN>. The files will still be displayed by
@ -168,27 +174,28 @@ can be added multiple times to add more patterns.
Exclude files that match any pattern in I<FILE>. Patterns should be separated
by a newline.
=item B<--exclude-caches>
=item B<--include-caches>, B<--exclude-caches>
Exclude directories containing CACHEDIR.TAG. The directories will still be
displayed, but not their content, and they are not counted towards the disk
usage statistics.
See http://www.brynosaurus.com/cachedir/
Include (default) or exclude directories containing CACHEDIR.TAG. The
directories will still be displayed, but their contents will not be scanned or
counted towards the disk usage statistics.
L<http://www.brynosaurus.com/cachedir/>
=item B<-L>, B<--follow-symlinks>
=item B<-L>, B<--follow-symlinks>, B<--no-follow-symlinks>
Follow symlinks and count the size of the file they point to. As of ncdu 1.14,
this option will not follow symlinks to directories and will count each
symlinked file as a unique file (i.e. unlike how hard links are handled). This
is subject to change in later versions.
Follow (or not) symlinks and count the size of the file they point to. As of
ncdu 1.14, this option will not follow symlinks to directories and will count
each symlinked file as a unique file (i.e. unlike how hard links are handled).
This is subject to change in later versions.
=item B<--exclude-firmlinks>
=item B<--exclude-firmlinks>, B<--follow-firmlinks>
(MacOS only) Exclude firmlinks.
(MacOS only) Exclude or follow firmlinks.
=item B<--exclude-kernfs>
=item B<--include-kernfs>, B<--exclude-kernfs>
(Linux only) Exclude Linux pseudo filesystems, e.g. /proc (procfs), /sys (sysfs).
(Linux only) Include (default) or exclude Linux pseudo filesystems, e.g. /proc
(procfs), /sys (sysfs).
The complete list of currently known pseudo filesystems is: binfmt, bpf, cgroup,
cgroup2, debug, devpts, proc, pstore, security, selinux, sys, trace.

View File

@ -33,8 +33,6 @@
#include <unistd.h>
#include <sys/time.h>
#include <yopt.h>
int pstate;
int read_only = 0;
@ -113,153 +111,184 @@ int input_handle(int wait) {
}
/* parse command line */
/* This is a backport of the argument parser in the Zig version.
* Minor differences in that this implementation can modify argv in-place and has a slightly different API. */
struct argparser {
int argc;
char **argv;
char *shortopt;
char *last;
char *last_arg;
char shortbuf[2];
char argsep;
} argparser_state;
static char *argparser_pop(struct argparser *p) {
char *a;
if(p->argc == 0) return NULL;
a = *p->argv;
p->argv++;
p->argc--;
return a;
}
static int argparser_shortopt(struct argparser *p, char *buf) {
p->shortbuf[0] = '-';
p->shortbuf[1] = *buf;
p->shortopt = buf[1] ? buf+1 : NULL;
p->last = p->shortbuf;
return 1;
}
/* Returns 0 when done, 1 if there's an option, 2 if there's a positional argument. */
static int argparser_next(struct argparser *p) {
if(p->last_arg) die("Option '%s' does not expect an argument.\n", p->last);
if(p->shortopt) return argparser_shortopt(p, p->shortopt);
p->last = argparser_pop(p);
if(!p->last) return 0;
if(p->argsep || !*p->last || *p->last != '-') return 2;
if(!p->last[1]) die("Invalid option '-'.\n");
if(p->last[1] == '-' && !p->last[2]) { /* '--' argument separator */
p->argsep = 1;
return argparser_next(p);
}
if(p->last[1] == '-') { /* long option */
p->last_arg = strchr(p->last, '=');
if(p->last_arg) {
*p->last_arg = 0;
p->last_arg++;
}
return 1;
}
/* otherwise: short option */
return argparser_shortopt(p, p->last+1);
}
static char *argparser_arg(struct argparser *p) {
char *tmp;
if(p->shortopt) {
tmp = p->shortopt;
p->shortopt = NULL;
return tmp;
}
if(p->last_arg) {
tmp = p->last_arg;
p->last_arg = NULL;
return tmp;
}
tmp = argparser_pop(p);
if(!tmp) die("Option '%s' requires an argument.\n", p->last);
return tmp;
}
#define OPT(_s) (strcmp(argparser_state.last, (_s)) == 0)
#define ARG (argparser_arg(&argparser_state))
static int arg_option(void) {
char *arg;
if(OPT("-q") || OPT("--slow-ui-updates")) update_delay = 2000;
else if(OPT("--fast-ui-updates")) update_delay = 100;
else if(OPT("-x") || OPT("--one-file-system")) dir_scan_smfs = 1;
else if(OPT("--cross-file-system")) dir_scan_smfs = 0;
else if(OPT("-e") || OPT("--extended")) extended_info = 1;
else if(OPT("--no-extended")) extended_info = 0;
else if(OPT("-r")) read_only++;
else if(OPT("-0")) dir_ui = 0;
else if(OPT("-1")) dir_ui = 1;
else if(OPT("-2")) dir_ui = 2;
else if(OPT("--si")) si = 1;
else if(OPT("--no-si")) si = 0;
else if(OPT("-L") || OPT("--follow-symlinks")) follow_symlinks = 1;
else if(OPT("--no-follow-symlinks")) follow_symlinks = 0;
else if(OPT("--exclude")) exclude_add(ARG);
else if(OPT("-X") || OPT("--exclude-form")) {
arg = ARG;
if(exclude_addfile(arg)) die("Can't open %s: %s\n", arg, strerror(errno));
} else if(OPT("--exclude-caches")) cachedir_tags = 1;
else if(OPT("--include-caches")) cachedir_tags = 0;
else if(OPT("--exclude-kernfs")) exclude_kernfs = 1;
else if(OPT("--include-kernfs")) exclude_kernfs = 0;
else if(OPT("--follow-firmlinks")) follow_firmlinks = 1;
else if(OPT("--exclude-firmlinks")) follow_firmlinks = 0;
else if(OPT("--confirm-quit")) confirm_quit = 1;
else if(OPT("--no-confirm-quit")) confirm_quit = 0;
else if(OPT("--color")) {
arg = ARG;
if(strcmp(arg, "off") == 0) uic_theme = 0;
else if(strcmp(arg, "dark") == 0) uic_theme = 1;
else if(strcmp(arg, "dark-bg") == 0) uic_theme = 2;
else die("Unknown --color option: %s\n", arg);
} else return 0;
return 1;
}
static void arg_help(void) {
printf("ncdu <options> <directory>\n\n");
printf(" -h,--help This help message\n");
printf(" -q Quiet mode, refresh interval 2 seconds\n");
printf(" -v,-V,--version Print version\n");
printf(" -x Same filesystem\n");
printf(" -e Enable extended information\n");
printf(" -r Read only\n");
printf(" -o FILE Export scanned directory to FILE\n");
printf(" -f FILE Import scanned directory from FILE\n");
printf(" -0,-1,-2 UI to use when scanning (0=none,2=full ncurses)\n");
printf(" --si Use base 10 (SI) prefixes instead of base 2\n");
printf(" --exclude PATTERN Exclude files that match PATTERN\n");
printf(" -X, --exclude-from FILE Exclude files that match any pattern in FILE\n");
printf(" -L, --follow-symlinks Follow symbolic links (excluding directories)\n");
printf(" --exclude-caches Exclude directories containing CACHEDIR.TAG\n");
#if HAVE_LINUX_MAGIC_H && HAVE_SYS_STATFS_H && HAVE_STATFS
printf(" --exclude-kernfs Exclude Linux pseudo filesystems (procfs,sysfs,cgroup,...)\n");
#endif
#if HAVE_SYS_ATTR_H && HAVE_GETATTRLIST && HAVE_DECL_ATTR_CMNEXT_NOFIRMLINKPATH
printf(" --exclude-firmlinks Exclude firmlinks on macOS\n");
#endif
printf(" --confirm-quit Confirm quitting ncdu\n");
printf(" --color SCHEME Set color scheme (off/dark/dark-bg)\n");
exit(0);
}
static void argv_parse(int argc, char **argv) {
yopt_t yopt;
int v;
char *val;
int r;
char *export = NULL;
char *import = NULL;
char *dir = NULL;
static yopt_opt_t opts[] = {
{ 'h', 0, "-h,-?,--help" },
{ 'q', 0, "-q" },
{ 'v', 0, "-v,-V,--version" },
{ 'x', 0, "-x" },
{ 'e', 0, "-e" },
{ 'r', 0, "-r" },
{ 'o', 1, "-o" },
{ 'f', 1, "-f" },
{ '0', 0, "-0" },
{ '1', 0, "-1" },
{ '2', 0, "-2" },
{ 1, 1, "--exclude" },
{ 'X', 1, "-X,--exclude-from" },
{ 'L', 0, "-L,--follow-symlinks" },
{ 'C', 0, "--exclude-caches" },
{ 2, 0, "--exclude-kernfs" },
{ 3, 0, "--follow-firmlinks" }, /* undocumented, this behavior is the current default */
{ 4, 0, "--exclude-firmlinks" },
{ 's', 0, "--si" },
{ 'Q', 0, "--confirm-quit" },
{ 'c', 1, "--color" },
{0,0,NULL}
};
uic_theme = getenv("NO_COLOR") ? 0 : 2;
dir_ui = -1;
si = 0;
yopt_init(&yopt, argc, argv, opts);
while((v = yopt_next(&yopt, &val)) != -1) {
switch(v) {
case 0 : dir = val; break;
case 'h':
printf("ncdu <options> <directory>\n\n");
printf(" -h,--help This help message\n");
printf(" -q Quiet mode, refresh interval 2 seconds\n");
printf(" -v,-V,--version Print version\n");
printf(" -x Same filesystem\n");
printf(" -e Enable extended information\n");
printf(" -r Read only\n");
printf(" -o FILE Export scanned directory to FILE\n");
printf(" -f FILE Import scanned directory from FILE\n");
printf(" -0,-1,-2 UI to use when scanning (0=none,2=full ncurses)\n");
printf(" --si Use base 10 (SI) prefixes instead of base 2\n");
printf(" --exclude PATTERN Exclude files that match PATTERN\n");
printf(" -X, --exclude-from FILE Exclude files that match any pattern in FILE\n");
printf(" -L, --follow-symlinks Follow symbolic links (excluding directories)\n");
printf(" --exclude-caches Exclude directories containing CACHEDIR.TAG\n");
#if HAVE_LINUX_MAGIC_H && HAVE_SYS_STATFS_H && HAVE_STATFS
printf(" --exclude-kernfs Exclude Linux pseudo filesystems (procfs,sysfs,cgroup,...)\n");
#endif
#if HAVE_SYS_ATTR_H && HAVE_GETATTRLIST && HAVE_DECL_ATTR_CMNEXT_NOFIRMLINKPATH
printf(" --exclude-firmlinks Exclude firmlinks on macOS\n");
#endif
printf(" --confirm-quit Confirm quitting ncdu\n");
printf(" --color SCHEME Set color scheme (off/dark/dark-bg)\n");
exit(0);
case 'q': update_delay = 2000; break;
case 'v':
memset(&argparser_state, 0, sizeof(struct argparser));
argparser_state.argv = argv;
argparser_state.argc = argc;
argparser_next(&argparser_state); /* skip program name */
while((r = argparser_next(&argparser_state)) > 0) {
if(r == 2) dir = argparser_state.last;
else if(OPT("-v") || OPT("-V") || OPT("--version")) {
printf("ncdu %s\n", PACKAGE_VERSION);
exit(0);
case 'x': dir_scan_smfs = 1; break;
case 'e': extended_info = 1; break;
case 'r': read_only++; break;
case 's': si = 1; break;
case 'o': export = val; break;
case 'f': import = val; break;
case '0': dir_ui = 0; break;
case '1': dir_ui = 1; break;
case '2': dir_ui = 2; break;
case 'Q': confirm_quit = 1; break;
case 1 : exclude_add(val); break; /* --exclude */
case 'X':
if(exclude_addfile(val)) {
fprintf(stderr, "Can't open %s: %s\n", val, strerror(errno));
exit(1);
}
break;
case 'L': follow_symlinks = 1; break;
case 'C':
cachedir_tags = 1;
break;
case 2 : /* --exclude-kernfs */
#if HAVE_LINUX_MAGIC_H && HAVE_SYS_STATFS_H && HAVE_STATFS
exclude_kernfs = 1; break;
#else
fprintf(stderr, "This feature is not supported on your platform\n");
exit(1);
#endif
case 3 : /* --follow-firmlinks */
#if HAVE_SYS_ATTR_H && HAVE_GETATTRLIST && HAVE_DECL_ATTR_CMNEXT_NOFIRMLINKPATH
follow_firmlinks = 1; break;
#else
fprintf(stderr, "This feature is not supported on your platform\n");
exit(1);
#endif
case 4 : /* --exclude-firmlinks */
#if HAVE_SYS_ATTR_H && HAVE_GETATTRLIST && HAVE_DECL_ATTR_CMNEXT_NOFIRMLINKPATH
follow_firmlinks = 0; break;
#else
fprintf(stderr, "This feature is not supported on your platform\n");
exit(1);
#endif
case 'c':
if(strcmp(val, "off") == 0) { uic_theme = 0; }
else if(strcmp(val, "dark") == 0) { uic_theme = 1; }
else if(strcmp(val, "dark-bg") == 0) { uic_theme = 2; }
else {
fprintf(stderr, "Unknown --color option: %s\n", val);
exit(1);
}
break;
case -2:
fprintf(stderr, "ncdu: %s.\n", val);
exit(1);
}
} else if(OPT("-h") || OPT("-?") || OPT("--help")) arg_help();
else if(OPT("-o")) export = ARG;
else if(OPT("-f")) import = ARG;
else if(!arg_option()) die("Unknown option '%s'.\n", argparser_state.last);
}
#if !(HAVE_LINUX_MAGIC_H && HAVE_SYS_STATFS_H && HAVE_STATFS)
if(exclude_kernfs) die("The --exclude-kernfs flag is currently only supported on Linux.\n");
#endif
if(export) {
if(dir_export_init(export)) {
fprintf(stderr, "Can't open %s: %s\n", export, strerror(errno));
exit(1);
}
if(strcmp(export, "-") == 0)
ncurses_tty = 1;
if(dir_export_init(export)) die("Can't open %s: %s\n", export, strerror(errno));
if(strcmp(export, "-") == 0) ncurses_tty = 1;
} else
dir_mem_init(NULL);
if(import) {
if(dir_import_init(import)) {
fprintf(stderr, "Can't open %s: %s\n", import, strerror(errno));
exit(1);
}
if(strcmp(import, "-") == 0)
ncurses_tty = 1;
if(dir_import_init(import)) die("Can't open %s: %s\n", import, strerror(errno));
if(strcmp(import, "-") == 0) ncurses_tty = 1;
} else
dir_scan_init(dir ? dir : ".");
@ -282,10 +311,7 @@ static void init_nc(void) {
if(ncurses_tty) {
tty = fopen("/dev/tty", "r+");
if(!tty) {
fprintf(stderr, "Error opening /dev/tty: %s\n", strerror(errno));
exit(1);
}
if(!tty) die("Error opening /dev/tty: %s\n", strerror(errno));
term = newterm(NULL, tty, tty);
if(term)
set_term(term);
@ -294,17 +320,11 @@ static void init_nc(void) {
/* Make sure the user doesn't accidentally pipe in data to ncdu's standard
* input without using "-f -". An annoying input sequence could result in
* the deletion of your files, which we want to prevent at all costs. */
if(!isatty(0)) {
fprintf(stderr, "Standard input is not a TTY. Did you mean to import a file using '-f -'?\n");
exit(1);
}
if(!isatty(0)) die("Standard input is not a TTY. Did you mean to import a file using '-f -'?\n");
ok = !!initscr();
}
if(!ok) {
fprintf(stderr, "Error while initializing ncurses.\n");
exit(1);
}
if(!ok) die("Error while initializing ncurses.\n");
uic_init();
cbreak();
@ -326,7 +346,6 @@ void close_nc(void) {
}
/* main program */
int main(int argc, char **argv) {
read_locale();
argv_parse(argc, argv);

View File

@ -41,6 +41,15 @@ int si;
static char thou_sep;
void die(const char *fmt, ...) {
va_list arg;
va_start(arg, fmt);
vfprintf(stderr, fmt, arg);
va_end(arg);
exit(1);
}
char *cropstr(const char *from, int s) {
static char dat[4096];
int i, j, o = strlen(from);

View File

@ -30,6 +30,9 @@
#include <ncurses.h>
void die(const char *, ...);
/* UI colors: (foreground, background, attrs)
* NAME OFF DARK DARK-BG */
#define UI_COLORS \