From 69f863ed7e7475db5aa13b89fbc10b3f9152413c Mon Sep 17 00:00:00 2001 From: "Sijmen J. Mulder" Date: Fri, 15 Jun 2018 09:37:43 +0200 Subject: Add NO_WORDEXP codepaths for OpenBSD OpenBSD does not implement wordexp(). For rationale, see: http://openbsd-archive.7691.n7.nabble.com/patch-libc-wordexp-support-td159368.html This commit adds support for a NO_WORDEXP macro and enables it on OpenBSD. If the macro is defined, shell expansion is simply skipped. --- src/Makefile | 5 ++++ src/cmds_command.c | 79 +++++++++++++++++++++++++++++++++++++++--------------- src/file.c | 35 +++++++++++++++--------- src/main.c | 36 ++++++++++++++++--------- 4 files changed, 109 insertions(+), 46 deletions(-) diff --git a/src/Makefile b/src/Makefile index cf183d2..bfe6124 100755 --- a/src/Makefile +++ b/src/Makefile @@ -92,6 +92,11 @@ ifneq ($(shell uname -s),FreeBSD) LDLIBS += -ldl endif +# OpenBSD does not implement wordexp() +ifeq ($(shell uname -s),OpenBSD) + CFLAGS += -DNO_WORDEXP +endif + ifneq (, $(shell which pkg-config)) # Any system with pkg-config diff --git a/src/cmds_command.c b/src/cmds_command.c index 5765343..3194e47 100644 --- a/src/cmds_command.c +++ b/src/cmds_command.c @@ -46,7 +46,11 @@ #include #include #include // for isprint() + +#ifndef NO_WORDEXP #include +#endif + #include "sc.h" // for rescol #include "conf.h" #include "cmds_command.h" @@ -404,33 +408,51 @@ void do_commandmode(struct block * sb) { send_to_interp(inputline); } else if ( ! wcsncmp(inputline, L"load", 4) ) { - char cline [BUFFERSIZE]; + char name [BUFFERSIZE]; + int name_ok = 0; int force_rewrite = 0; + #ifndef NO_WORDEXP wordexp_t p; - wcstombs(cline, inputline, BUFFERSIZE); + #endif + + wcstombs(name, inputline, BUFFERSIZE); if ( ! wcsncmp(inputline, L"load! ", 6) ) { force_rewrite = 1; - del_range_chars(cline, 4, 4); + del_range_chars(name, 4, 4); } - del_range_chars(cline, 0, 4); - wordexp(cline, &p, 0); - if ( ! strlen(cline) ) { + del_range_chars(name, 0, 4); + if ( ! strlen(name) ) { sc_error("Path to file to load is missing !"); - } else if ( p.we_wordc < 1 ) { - sc_error("Failed expanding filepath"); } else if ( modflg && ! force_rewrite ) { sc_error("Changes were made since last save. Use '!' to force the load"); - } else if ( ! file_exists(p.we_wordv[0])) { - sc_error("File %s does not exists!", p.we_wordv[0]); } else { - delete_structures(); - create_structures(); - readfile(p.we_wordv[0], 0); - ui_show_header(); + #ifdef NO_WORDEXP + name_ok = 1; + #else + if ( p.we_wordc < 1 ) { + sc_error("Failed expanding filepath"); + } else if ( strlcpy(name, p.we_wordv[0], sizeof(name)) + >= sizeof(name) ) { + sc_error("File path too long"); + wordfree(&p); + } else { + name_ok = 1; + wordfree(&p); + } + #endif } - wordfree(&p); + if ( name_ok ) { + if ( ! file_exists(name)) { + sc_error("File %s does not exists!", name); + } else { + delete_structures(); + create_structures(); + readfile(name, 0); + ui_show_header(); + } + } } else if ( ! wcsncmp(inputline, L"hiderow ", 8) || ! wcsncmp(inputline, L"showrow ", 8) || ! wcsncmp(inputline, L"showcol ", 8) || @@ -832,25 +854,40 @@ void do_commandmode(struct block * sb) { } else if ( ! wcsncmp(inputline, L"file ", 5) ) { - char cline [BUFFERSIZE]; + char name [BUFFERSIZE]; + int name_ok = 0; + #ifndef NO_WORDEXP wordexp_t p; + #endif - wcstombs(cline, inputline, BUFFERSIZE); - del_range_chars(cline, 0, 4); - wordexp(cline, &p, 0); + wcstombs(name, inputline, BUFFERSIZE); + del_range_chars(name, 0, 4); + #ifdef NO_WORDEXP + name_ok = 1; + #else + wordexp(name, &p, 0); if ( p.we_wordc < 1 ) { sc_error("Failed to expand filename"); + } else if ( strlcpy(name, p.we_wordv[0], sizeof(name)) + >= sizeof(name) ) { + sc_error("File path too long"); + wordfree(&p); } else { + name_ok = 1; + wordfree(&p); + } + #endif + + if (name_ok) { #ifdef AUTOBACKUP // check if backup of curfile exists. // if it exists, remove it. if (strlen(curfile) && backup_exists(curfile)) remove_backup(curfile); #endif - strncpy(curfile, p.we_wordv[0], PATHLEN - 1); + strncpy(curfile, name, PATHLEN - 1); sc_info("File name set to \"%s\"", curfile); } - wordfree(&p); } else if ( ! wcscmp(inputline, L"file") ) { diff --git a/src/file.c b/src/file.c index 7fe945c..e66d174 100644 --- a/src/file.c +++ b/src/file.c @@ -53,7 +53,10 @@ #include #include #include + +#ifndef NO_WORDEXP #include +#endif #include "conf.h" #include "maps.h" @@ -187,8 +190,9 @@ int modcheck() { int savefile() { int force_rewrite = 0; char name[BUFFERSIZE]; + #ifndef NO_WORDEXP wordexp_t p; - + #endif if (! curfile[0] && wcslen(inputline) < 3) { // casos ":w" ":w!" ":x" ":x!" sc_error("There is no filename"); @@ -198,13 +202,23 @@ int savefile() { if (inputline[1] == L'!') force_rewrite = 1; wcstombs(name, inputline, BUFFERSIZE); - del_range_chars(name, 0, 1 + force_rewrite); + + #ifndef NO_WORDEXP wordexp(name, &p, 0); + if (pe.we_wordc < 1) { + sc_error("Failed expanding filepath"); + return -1; + } else if (strlcpy(name, p.we_wordv[0], sizeof(name)) >= sizeof(name)) { + sc_error("File path too long"); + wordfree(&p); + return -1; + } + wordfree(&p); + #endif - if (! force_rewrite && p.we_wordv[0] && file_exists(p.we_wordv[0])) { + if (! force_rewrite && file_exists(name)) { sc_error("File already exists. Use \"!\" to force rewrite."); - wordfree(&p); return -1; } @@ -216,18 +230,17 @@ int savefile() { // check if backup of newfilename exists. // if it exists and '!' is set, remove it. // if it exists and no '!' is set, return. - if (!strlen(curfile) && backup_exists(p.we_wordv[0])) { + if (!strlen(curfile) && backup_exists(name)) { if (!force_rewrite) { - sc_error("Backup file of %s exists. Use \"!\" to force the write process.", p.we_wordv[0]); - wordfree(&p); + sc_error("Backup file of %s exists. Use \"!\" to force the write process.", name); return -1; - } else remove_backup(p.we_wordv[0]); + } else remove_backup(name); } #endif // copy newfilename to curfile if (wcslen(inputline) > 2) { - strcpy(curfile, p.we_wordv[0]); + strcpy(curfile, name); } // add sc extension if not present @@ -239,23 +252,19 @@ int savefile() { } else if (strlen(curfile) > 4 && (! strcasecmp( & curfile[strlen(curfile)-4], ".csv"))) { export_delim(curfile, ',', 0, 0, maxrow, maxcol, 1); modflg = 0; - wordfree(&p); return 0; // treat tab } else if (strlen(curfile) > 4 && (! strcasecmp( & curfile[strlen(curfile)-4], ".tsv") || ! strcasecmp( & curfile[strlen(curfile)-4], ".tab"))){ export_delim(curfile, '\t', 0, 0, maxrow, maxcol, 1); modflg = 0; - wordfree(&p); return 0; } // save in sc format if (writefile(curfile, 0, 0, maxrow, maxcol, 1) < 0) { sc_error("File could not be saved"); - wordfree(&p); return -1; } - wordfree(&p); return 0; } diff --git a/src/main.c b/src/main.c index 28c6e8d..3038dd0 100644 --- a/src/main.c +++ b/src/main.c @@ -60,9 +60,12 @@ #include // for F_GETFL O_NONBLOCK F_SETFL #include #include -#include #include // for ioctl +#ifndef NO_WORDEXP +#include +#endif + #include "main.h" #include "shift.h" #include "macros.h" @@ -551,28 +554,37 @@ void read_argv(int argc, char ** argv) { */ void load_sc() { + char name[PATHLEN]; + int c; + #ifndef NO_WORDEXP wordexp_t p; - wordexp(loadingfile, &p, 0); + #endif - int c; - char word[PATHLEN] = ""; + #ifdef NO_WORDEXP + if (strlcpy(name, loadingfile, sizeof(name)) >= sizeof(name)) { + sc_info("File path too long: '%s'", loadingfile); + return; + } + #else + wordexp(loadingfile, &p, 0); for (c=0; c < p.we_wordc; c++) { - if (c) sprintf(word + strlen(word), " "); - sprintf(word + strlen(word), "%s", p.we_wordv[c]); + if (c) sprintf(name + strlen(name), " "); + sprintf(name + strlen(name), "%s", p.we_wordv[c]); } - if (strlen(word) != 0) { - sc_readfile_result result = readfile(word, 0); + wordfree(&p); + #endif + + if (strlen(name) != 0) { + sc_readfile_result result = readfile(name, 0); if (!atoi((char *) get_conf_value("nocurses"))) { if (result == SC_READFILE_DOESNTEXIST) { // It's a new record! - sc_info("New file: \"%s\"", word); + sc_info("New file: \"%s\"", name); } else if (result == SC_READFILE_ERROR) { - sc_info("\"%s\" is not a SC-IM compatible file", word); + sc_info("\"%s\" is not a SC-IM compatible file", name); } } } - wordfree(&p); - return; } /** -- cgit v1.2.3