- Functions warn() and die() replaced by GNU-like error(3) function - Register cleanup() with atexit(3) - Functions called by cleanup() are marked with CLEANUP and are not allowed to call exit(3)master
@@ -30,7 +30,6 @@ | |||||
#define _IMAGE_CONFIG | #define _IMAGE_CONFIG | ||||
#include "config.h" | #include "config.h" | ||||
void cleanup(void); | |||||
void remove_file(int, bool); | void remove_file(int, bool); | ||||
void load_image(int); | void load_image(int); | ||||
void open_info(void); | void open_info(void); | ||||
@@ -64,7 +63,6 @@ bool cg_quit(arg_t _) | |||||
printf("%s\n", files[i].name); | printf("%s\n", files[i].name); | ||||
} | } | ||||
} | } | ||||
cleanup(); | |||||
exit(EXIT_SUCCESS); | exit(EXIT_SUCCESS); | ||||
} | } | ||||
@@ -16,6 +16,7 @@ | |||||
* along with sxiv. If not, see <http://www.gnu.org/licenses/>. | * along with sxiv. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
#include <errno.h> | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
@@ -149,7 +150,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||||
gif = DGifOpenFileName(file->path); | gif = DGifOpenFileName(file->path); | ||||
#endif | #endif | ||||
if (gif == NULL) { | if (gif == NULL) { | ||||
warn("could not open gif file: %s", file->name); | |||||
error(0, 0, "%s: Error opening gif image", file->name); | |||||
return false; | return false; | ||||
} | } | ||||
bg = gif->SBackGroundColor; | bg = gif->SBackGroundColor; | ||||
@@ -274,7 +275,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||||
#endif | #endif | ||||
if (err && (file->flags & FF_WARN)) | if (err && (file->flags & FF_WARN)) | ||||
warn("corrupted gif file: %s", file->name); | |||||
error(0, 0, "%s: Corrupted gif file", file->name); | |||||
if (img->multi.cnt > 1) { | if (img->multi.cnt > 1) { | ||||
imlib_context_set_image(img->im); | imlib_context_set_image(img->im); | ||||
@@ -300,7 +301,7 @@ bool img_load(img_t *img, const fileinfo_t *file) | |||||
(img->im = imlib_load_image(file->path)) == NULL) | (img->im = imlib_load_image(file->path)) == NULL) | ||||
{ | { | ||||
if (file->flags & FF_WARN) | if (file->flags & FF_WARN) | ||||
warn("could not open image: %s", file->name); | |||||
error(0, 0, "%s: Error opening image", file->name); | |||||
return false; | return false; | ||||
} | } | ||||
@@ -325,7 +326,7 @@ bool img_load(img_t *img, const fileinfo_t *file) | |||||
return true; | return true; | ||||
} | } | ||||
void img_close(img_t *img, bool decache) | |||||
CLEANUP void img_close(img_t *img, bool decache) | |||||
{ | { | ||||
int i; | int i; | ||||
@@ -464,7 +465,7 @@ void img_render(img_t *img) | |||||
if (imlib_image_has_alpha()) { | if (imlib_image_has_alpha()) { | ||||
if ((bg = imlib_create_image(dw, dh)) == NULL) | if ((bg = imlib_create_image(dw, dh)) == NULL) | ||||
die("could not allocate memory"); | |||||
error(EXIT_FAILURE, ENOMEM, NULL); | |||||
imlib_context_set_image(bg); | imlib_context_set_image(bg); | ||||
imlib_image_set_has_alpha(0); | imlib_image_set_has_alpha(0); | ||||
@@ -69,7 +69,7 @@ typedef struct { | |||||
void img_init(img_t*, win_t*); | void img_init(img_t*, win_t*); | ||||
bool img_load(img_t*, const fileinfo_t*); | bool img_load(img_t*, const fileinfo_t*); | ||||
void img_close(img_t*, bool); | |||||
CLEANUP void img_close(img_t*, bool); | |||||
void img_render(img_t*); | void img_render(img_t*); | ||||
@@ -42,11 +42,6 @@ | |||||
#define _MAPPINGS_CONFIG | #define _MAPPINGS_CONFIG | ||||
#include "config.h" | #include "config.h" | ||||
typedef struct { | |||||
const char *name; | |||||
char *cmd; | |||||
} exec_t; | |||||
typedef struct { | typedef struct { | ||||
struct timeval when; | struct timeval when; | ||||
bool active; | bool active; | ||||
@@ -75,15 +70,20 @@ bool extprefix; | |||||
bool resized = false; | bool resized = false; | ||||
typedef struct { | |||||
int err; | |||||
char *cmd; | |||||
} extcmd_t; | |||||
struct { | struct { | ||||
char *cmd; | |||||
extcmd_t f; | |||||
int fd; | int fd; | ||||
unsigned int i, lastsep; | unsigned int i, lastsep; | ||||
bool open; | bool open; | ||||
} info; | } info; | ||||
struct { | struct { | ||||
char *cmd; | |||||
extcmd_t f; | |||||
bool warned; | bool warned; | ||||
} keyhandler; | } keyhandler; | ||||
@@ -97,26 +97,24 @@ timeout_t timeouts[] = { | |||||
void cleanup(void) | void cleanup(void) | ||||
{ | { | ||||
static bool in = false; | |||||
if (!in) { | |||||
in = true; | |||||
img_close(&img, false); | |||||
tns_free(&tns); | |||||
win_close(&win); | |||||
} | |||||
img_close(&img, false); | |||||
tns_free(&tns); | |||||
win_close(&win); | |||||
} | } | ||||
void check_add_file(char *filename, bool given) | void check_add_file(char *filename, bool given) | ||||
{ | { | ||||
char *path; | |||||
const char *bn; | const char *bn; | ||||
if (*filename == '\0') | if (*filename == '\0') | ||||
return; | return; | ||||
if (access(filename, R_OK) < 0) { | |||||
if (access(filename, R_OK) < 0 || | |||||
(path = realpath(filename, NULL)) == NULL) | |||||
{ | |||||
if (given) | if (given) | ||||
warn("could not open file: %s", filename); | |||||
error(0, errno, "%s", filename); | |||||
return; | return; | ||||
} | } | ||||
@@ -126,12 +124,8 @@ void check_add_file(char *filename, bool given) | |||||
memset(&files[filecnt/2], 0, filecnt/2 * sizeof(*files)); | memset(&files[filecnt/2], 0, filecnt/2 * sizeof(*files)); | ||||
} | } | ||||
if ((files[fileidx].path = realpath(filename, NULL)) == NULL) { | |||||
warn("could not get real path of file: %s\n", filename); | |||||
return; | |||||
} | |||||
files[fileidx].name = estrdup(filename); | files[fileidx].name = estrdup(filename); | ||||
files[fileidx].path = path; | |||||
if ((bn = strrchr(files[fileidx].name , '/')) != NULL && bn[1] != '\0') | if ((bn = strrchr(files[fileidx].name , '/')) != NULL && bn[1] != '\0') | ||||
files[fileidx].base = ++bn; | files[fileidx].base = ++bn; | ||||
else | else | ||||
@@ -149,7 +143,6 @@ void remove_file(int n, bool manual) | |||||
if (filecnt == 1) { | if (filecnt == 1) { | ||||
if (!manual) | if (!manual) | ||||
fprintf(stderr, "sxiv: no more files to display, aborting\n"); | fprintf(stderr, "sxiv: no more files to display, aborting\n"); | ||||
cleanup(); | |||||
exit(manual ? EXIT_SUCCESS : EXIT_FAILURE); | exit(manual ? EXIT_SUCCESS : EXIT_FAILURE); | ||||
} | } | ||||
if (files[n].flags & FF_MARK) | if (files[n].flags & FF_MARK) | ||||
@@ -232,7 +225,7 @@ void open_info(void) | |||||
static pid_t pid; | static pid_t pid; | ||||
int pfd[2]; | int pfd[2]; | ||||
if (info.cmd == NULL || info.open || win.bar.h == 0) | |||||
if (info.f.err != 0 || info.open || win.bar.h == 0) | |||||
return; | return; | ||||
if (info.fd != -1) { | if (info.fd != -1) { | ||||
close(info.fd); | close(info.fd); | ||||
@@ -246,9 +239,8 @@ void open_info(void) | |||||
if ((pid = fork()) == 0) { | if ((pid = fork()) == 0) { | ||||
close(pfd[0]); | close(pfd[0]); | ||||
dup2(pfd[1], 1); | dup2(pfd[1], 1); | ||||
execl(info.cmd, info.cmd, files[fileidx].name, NULL); | |||||
warn("could not exec: %s", info.cmd); | |||||
exit(EXIT_FAILURE); | |||||
execl(info.f.cmd, info.f.cmd, files[fileidx].name, NULL); | |||||
error(EXIT_FAILURE, errno, "exec: %s", info.f.cmd); | |||||
} | } | ||||
close(pfd[1]); | close(pfd[1]); | ||||
if (pid < 0) { | if (pid < 0) { | ||||
@@ -386,7 +378,7 @@ void update_info(void) | |||||
bar_put(r, "%0*d/%d | ", fn, img.multi.sel + 1, img.multi.cnt); | bar_put(r, "%0*d/%d | ", fn, img.multi.sel + 1, img.multi.cnt); | ||||
} | } | ||||
bar_put(r, "%0*d/%d", fw, fileidx + 1, filecnt); | bar_put(r, "%0*d/%d", fw, fileidx + 1, filecnt); | ||||
ow_info = info.cmd == NULL; | |||||
ow_info = info.f.err != 0; | |||||
} | } | ||||
if (ow_info) { | if (ow_info) { | ||||
fn = strlen(files[fileidx].name); | fn = strlen(files[fileidx].name); | ||||
@@ -469,14 +461,14 @@ void run_key_handler(const char *key, unsigned int mask) | |||||
FILE *pfs; | FILE *pfs; | ||||
bool marked = mode == MODE_THUMB && markcnt > 0; | bool marked = mode == MODE_THUMB && markcnt > 0; | ||||
bool changed = false; | bool changed = false; | ||||
int f, i, pfd[2], retval, status; | |||||
int f, i, pfd[2], status; | |||||
int fcnt = marked ? markcnt : 1; | int fcnt = marked ? markcnt : 1; | ||||
char kstr[32]; | char kstr[32]; | ||||
struct stat *oldst, st; | struct stat *oldst, st; | ||||
if (keyhandler.cmd == NULL) { | |||||
if (keyhandler.f.err != 0) { | |||||
if (!keyhandler.warned) { | if (!keyhandler.warned) { | ||||
warn("key handler not installed"); | |||||
error(0, keyhandler.f.err, "%s", keyhandler.f.cmd); | |||||
keyhandler.warned = true; | keyhandler.warned = true; | ||||
} | } | ||||
return; | return; | ||||
@@ -485,12 +477,12 @@ void run_key_handler(const char *key, unsigned int mask) | |||||
return; | return; | ||||
if (pipe(pfd) < 0) { | if (pipe(pfd) < 0) { | ||||
warn("could not create pipe for key handler"); | |||||
error(0, errno, "pipe"); | |||||
return; | return; | ||||
} | } | ||||
if ((pfs = fdopen(pfd[1], "w")) == NULL) { | if ((pfs = fdopen(pfd[1], "w")) == NULL) { | ||||
error(0, errno, "open pipe"); | |||||
close(pfd[0]), close(pfd[1]); | close(pfd[0]), close(pfd[1]); | ||||
warn("could not open pipe for key handler"); | |||||
return; | return; | ||||
} | } | ||||
oldst = emalloc(fcnt * sizeof(*oldst)); | oldst = emalloc(fcnt * sizeof(*oldst)); | ||||
@@ -507,14 +499,13 @@ void run_key_handler(const char *key, unsigned int mask) | |||||
if ((pid = fork()) == 0) { | if ((pid = fork()) == 0) { | ||||
close(pfd[1]); | close(pfd[1]); | ||||
dup2(pfd[0], 0); | dup2(pfd[0], 0); | ||||
execl(keyhandler.cmd, keyhandler.cmd, kstr, NULL); | |||||
warn("could not exec key handler"); | |||||
exit(EXIT_FAILURE); | |||||
execl(keyhandler.f.cmd, keyhandler.f.cmd, kstr, NULL); | |||||
error(EXIT_FAILURE, errno, "exec: %s", keyhandler.f.cmd); | |||||
} | } | ||||
close(pfd[0]); | close(pfd[0]); | ||||
if (pid < 0) { | if (pid < 0) { | ||||
error(0, errno, "fork"); | |||||
fclose(pfs); | fclose(pfs); | ||||
warn("could not fork key handler"); | |||||
goto end; | goto end; | ||||
} | } | ||||
@@ -527,9 +518,8 @@ void run_key_handler(const char *key, unsigned int mask) | |||||
} | } | ||||
fclose(pfs); | fclose(pfs); | ||||
waitpid(pid, &status, 0); | waitpid(pid, &status, 0); | ||||
retval = WEXITSTATUS(status); | |||||
if (WIFEXITED(status) == 0 || retval != 0) | |||||
warn("key handler exited with non-zero return value: %d", retval); | |||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) | |||||
error(0, 0, "%s: Exited abnormally", keyhandler.f.cmd); | |||||
for (f = i = 0; f < fcnt; i++) { | for (f = i = 0; f < fcnt; i++) { | ||||
if ((marked && (files[i].flags & FF_MARK)) || (!marked && i == fileidx)) { | if ((marked && (files[i].flags & FF_MARK)) || (!marked && i == fileidx)) { | ||||
@@ -550,7 +540,7 @@ end: | |||||
if (changed) { | if (changed) { | ||||
img_close(&img, true); | img_close(&img, true); | ||||
load_image(fileidx); | load_image(fileidx); | ||||
} else if (info.cmd != NULL) { | |||||
} else if (info.f.err == 0) { | |||||
info.open = false; | info.open = false; | ||||
open_info(); | open_info(); | ||||
} | } | ||||
@@ -819,18 +809,18 @@ int main(int argc, char **argv) | |||||
filename = options->filenames[i]; | filename = options->filenames[i]; | ||||
if (stat(filename, &fstats) < 0) { | if (stat(filename, &fstats) < 0) { | ||||
warn("could not stat file: %s", filename); | |||||
error(0, errno, "%s", filename); | |||||
continue; | continue; | ||||
} | } | ||||
if (!S_ISDIR(fstats.st_mode)) { | if (!S_ISDIR(fstats.st_mode)) { | ||||
check_add_file(filename, true); | check_add_file(filename, true); | ||||
} else { | } else { | ||||
if (!options->recursive) { | if (!options->recursive) { | ||||
warn("ignoring directory: %s", filename); | |||||
error(0, 0, "%s: Is a directory", filename); | |||||
continue; | continue; | ||||
} | } | ||||
if (r_opendir(&dir, filename) < 0) { | if (r_opendir(&dir, filename) < 0) { | ||||
warn("could not open directory: %s", filename); | |||||
error(0, errno, "%s", filename); | |||||
continue; | continue; | ||||
} | } | ||||
start = fileidx; | start = fileidx; | ||||
@@ -844,10 +834,8 @@ int main(int argc, char **argv) | |||||
} | } | ||||
} | } | ||||
if (fileidx == 0) { | |||||
fprintf(stderr, "sxiv: no valid image file given, aborting\n"); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
if (fileidx == 0) | |||||
error(EXIT_FAILURE, 0, "No valid image file given, aborting"); | |||||
filecnt = fileidx; | filecnt = fileidx; | ||||
fileidx = options->startnum < filecnt ? options->startnum : 0; | fileidx = options->startnum < filecnt ? options->startnum : 0; | ||||
@@ -860,20 +848,18 @@ int main(int argc, char **argv) | |||||
dsuffix = "/.config"; | dsuffix = "/.config"; | ||||
} | } | ||||
if (homedir != NULL) { | if (homedir != NULL) { | ||||
char **cmd[] = { &info.cmd, &keyhandler.cmd }; | |||||
extcmd_t *cmd[] = { &info.f, &keyhandler.f }; | |||||
const char *name[] = { "image-info", "key-handler" }; | const char *name[] = { "image-info", "key-handler" }; | ||||
for (i = 0; i < ARRLEN(cmd); i++) { | for (i = 0; i < ARRLEN(cmd); i++) { | ||||
n = strlen(homedir) + strlen(dsuffix) + strlen(name[i]) + 12; | n = strlen(homedir) + strlen(dsuffix) + strlen(name[i]) + 12; | ||||
*cmd[i] = (char*) emalloc(n); | |||||
snprintf(*cmd[i], n, "%s%s/sxiv/exec/%s", homedir, dsuffix, name[i]); | |||||
if (access(*cmd[i], X_OK) != 0) { | |||||
free(*cmd[i]); | |||||
*cmd[i] = NULL; | |||||
} | |||||
cmd[i]->cmd = (char*) emalloc(n); | |||||
snprintf(cmd[i]->cmd, n, "%s%s/sxiv/exec/%s", homedir, dsuffix, name[i]); | |||||
if (access(cmd[i]->cmd, X_OK) != 0) | |||||
cmd[i]->err = errno; | |||||
} | } | ||||
} else { | } else { | ||||
warn("could not locate exec directory"); | |||||
error(0, 0, "Exec directory not found"); | |||||
} | } | ||||
info.fd = -1; | info.fd = -1; | ||||
@@ -890,10 +876,11 @@ int main(int argc, char **argv) | |||||
win_open(&win); | win_open(&win); | ||||
win_set_cursor(&win, CURSOR_WATCH); | win_set_cursor(&win, CURSOR_WATCH); | ||||
atexit(cleanup); | |||||
set_timeout(redraw, 25, false); | set_timeout(redraw, 25, false); | ||||
run(); | run(); | ||||
cleanup(); | |||||
return 0; | return 0; | ||||
} | } |
@@ -47,6 +47,9 @@ void parse_options(int argc, char **argv) | |||||
char *end, *s; | char *end, *s; | ||||
const char *scalemodes = "dfwh"; | const char *scalemodes = "dfwh"; | ||||
progname = strrchr(argv[0], '/'); | |||||
progname = progname ? progname + 1 : argv[0]; | |||||
_options.from_stdin = false; | _options.from_stdin = false; | ||||
_options.to_stdout = false; | _options.to_stdout = false; | ||||
_options.recursive = false; | _options.recursive = false; | ||||
@@ -86,10 +89,8 @@ void parse_options(int argc, char **argv) | |||||
break; | break; | ||||
case 'G': | case 'G': | ||||
n = strtol(optarg, &end, 0); | n = strtol(optarg, &end, 0); | ||||
if (*end != '\0') { | |||||
fprintf(stderr, "sxiv: invalid argument for option -G: %s\n", optarg); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
if (*end != '\0') | |||||
error(EXIT_FAILURE, 0, "Invalid argument for option -G: %s", optarg); | |||||
_options.gamma = n; | _options.gamma = n; | ||||
break; | break; | ||||
case 'g': | case 'g': | ||||
@@ -103,10 +104,8 @@ void parse_options(int argc, char **argv) | |||||
break; | break; | ||||
case 'n': | case 'n': | ||||
n = strtol(optarg, &end, 0); | n = strtol(optarg, &end, 0); | ||||
if (*end != '\0' || n <= 0) { | |||||
fprintf(stderr, "sxiv: invalid argument for option -n: %s\n", optarg); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
if (*end != '\0' || n <= 0) | |||||
error(EXIT_FAILURE, 0, "Invalid argument for option -n: %s", optarg); | |||||
_options.startnum = n - 1; | _options.startnum = n - 1; | ||||
break; | break; | ||||
case 'N': | case 'N': | ||||
@@ -123,18 +122,14 @@ void parse_options(int argc, char **argv) | |||||
break; | break; | ||||
case 'S': | case 'S': | ||||
n = strtol(optarg, &end, 0); | n = strtol(optarg, &end, 0); | ||||
if (*end != '\0' || n <= 0) { | |||||
fprintf(stderr, "sxiv: invalid argument for option -S: %s\n", optarg); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
if (*end != '\0' || n <= 0) | |||||
error(EXIT_FAILURE, 0, "Invalid argument for option -S: %s", optarg); | |||||
_options.slideshow = n; | _options.slideshow = n; | ||||
break; | break; | ||||
case 's': | case 's': | ||||
s = strchr(scalemodes, optarg[0]); | s = strchr(scalemodes, optarg[0]); | ||||
if (s == NULL || *s == '\0' || strlen(optarg) != 1) { | |||||
fprintf(stderr, "sxiv: invalid argument for option -s: %s\n", optarg); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
if (s == NULL || *s == '\0' || strlen(optarg) != 1) | |||||
error(EXIT_FAILURE, 0, "Invalid argument for option -s: %s", optarg); | |||||
_options.scalemode = s - scalemodes; | _options.scalemode = s - scalemodes; | ||||
break; | break; | ||||
case 't': | case 't': | ||||
@@ -149,10 +144,8 @@ void parse_options(int argc, char **argv) | |||||
break; | break; | ||||
case 'z': | case 'z': | ||||
n = strtol(optarg, &end, 0); | n = strtol(optarg, &end, 0); | ||||
if (*end != '\0' || n <= 0) { | |||||
fprintf(stderr, "sxiv: invalid argument for option -z: %s\n", optarg); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
if (*end != '\0' || n <= 0) | |||||
error(EXIT_FAILURE, 0, "Invalid argument for option -z: %s", optarg); | |||||
_options.scalemode = SCALE_ZOOM; | _options.scalemode = SCALE_ZOOM; | ||||
_options.zoom = (float) n / 100.0; | _options.zoom = (float) n / 100.0; | ||||
break; | break; | ||||
@@ -16,6 +16,7 @@ | |||||
* along with sxiv. If not, see <http://www.gnu.org/licenses/>. | * along with sxiv. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
#include <errno.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
@@ -122,7 +123,7 @@ void tns_clean_cache(tns_t *tns) | |||||
r_dir_t dir; | r_dir_t dir; | ||||
if (r_opendir(&dir, cache_dir) < 0) { | if (r_opendir(&dir, cache_dir) < 0) { | ||||
warn("could not open thumbnail cache directory: %s", cache_dir); | |||||
error(0, errno, "%s", cache_dir); | |||||
return; | return; | ||||
} | } | ||||
@@ -140,7 +141,7 @@ void tns_clean_cache(tns_t *tns) | |||||
} | } | ||||
if (delete) { | if (delete) { | ||||
if (unlink(cfile) < 0) | if (unlink(cfile) < 0) | ||||
warn("could not delete cache file: %s", cfile); | |||||
error(0, errno, "%s", cfile); | |||||
} | } | ||||
free(cfile); | free(cfile); | ||||
} | } | ||||
@@ -181,11 +182,11 @@ void tns_init(tns_t *tns, fileinfo_t *files, const int *cnt, int *sel, | |||||
cache_dir = (char*) emalloc(len); | cache_dir = (char*) emalloc(len); | ||||
snprintf(cache_dir, len, "%s%s/sxiv", homedir, dsuffix); | snprintf(cache_dir, len, "%s%s/sxiv", homedir, dsuffix); | ||||
} else { | } else { | ||||
warn("could not locate thumbnail cache directory"); | |||||
error(0, 0, "Cache directory not found"); | |||||
} | } | ||||
} | } | ||||
void tns_free(tns_t *tns) | |||||
CLEANUP void tns_free(tns_t *tns) | |||||
{ | { | ||||
int i; | int i; | ||||
@@ -222,7 +223,7 @@ Imlib_Image tns_scale_down(Imlib_Image im, int dim) | |||||
im = imlib_create_cropped_scaled_image(0, 0, w, h, | im = imlib_create_cropped_scaled_image(0, 0, w, h, | ||||
MAX(z * w, 1), MAX(z * h, 1)); | MAX(z * w, 1), MAX(z * h, 1)); | ||||
if (im == NULL) | if (im == NULL) | ||||
die("could not allocate memory"); | |||||
error(EXIT_FAILURE, ENOMEM, NULL); | |||||
imlib_free_image_and_decache(); | imlib_free_image_and_decache(); | ||||
} | } | ||||
return im; | return im; | ||||
@@ -316,7 +317,7 @@ bool tns_load(tns_t *tns, int n, bool force, bool cache_only) | |||||
} | } | ||||
if (w >= maxwh || h >= maxwh) { | if (w >= maxwh || h >= maxwh) { | ||||
if ((im = imlib_create_cropped_image(x, y, w, h)) == NULL) | if ((im = imlib_create_cropped_image(x, y, w, h)) == NULL) | ||||
die("could not allocate memory"); | |||||
error(EXIT_FAILURE, ENOMEM, NULL); | |||||
} | } | ||||
imlib_free_image_and_decache(); | imlib_free_image_and_decache(); | ||||
} | } | ||||
@@ -332,7 +333,7 @@ bool tns_load(tns_t *tns, int n, bool force, bool cache_only) | |||||
(im = imlib_load_image(file->path)) == NULL)) | (im = imlib_load_image(file->path)) == NULL)) | ||||
{ | { | ||||
if (file->flags & FF_WARN) | if (file->flags & FF_WARN) | ||||
warn("could not open image: %s", file->name); | |||||
error(0, 0, "%s: Error opening image", file->name); | |||||
return false; | return false; | ||||
} | } | ||||
imlib_context_set_image(im); | imlib_context_set_image(im); | ||||
@@ -58,7 +58,7 @@ typedef struct { | |||||
void tns_clean_cache(tns_t*); | void tns_clean_cache(tns_t*); | ||||
void tns_init(tns_t*, fileinfo_t*, const int*, int*, win_t*); | void tns_init(tns_t*, fileinfo_t*, const int*, int*, win_t*); | ||||
void tns_free(tns_t*); | |||||
CLEANUP void tns_free(tns_t*); | |||||
bool tns_load(tns_t*, int, bool, bool); | bool tns_load(tns_t*, int, bool, bool); | ||||
void tns_unload(tns_t*, int); | void tns_unload(tns_t*, int); | ||||
@@ -21,6 +21,8 @@ | |||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#define CLEANUP | |||||
typedef enum { | typedef enum { | ||||
BO_BIG_ENDIAN, | BO_BIG_ENDIAN, | ||||
BO_LITTLE_ENDIAN | BO_LITTLE_ENDIAN | ||||
@@ -26,7 +26,7 @@ | |||||
#include "options.h" | #include "options.h" | ||||
#include "util.h" | #include "util.h" | ||||
void cleanup(void); | |||||
const char *progname; | |||||
void* emalloc(size_t size) | void* emalloc(size_t size) | ||||
{ | { | ||||
@@ -34,7 +34,7 @@ void* emalloc(size_t size) | |||||
ptr = malloc(size); | ptr = malloc(size); | ||||
if (ptr == NULL) | if (ptr == NULL) | ||||
die("could not allocate memory"); | |||||
error(EXIT_FAILURE, errno, NULL); | |||||
return ptr; | return ptr; | ||||
} | } | ||||
@@ -42,7 +42,7 @@ void* erealloc(void *ptr, size_t size) | |||||
{ | { | ||||
ptr = realloc(ptr, size); | ptr = realloc(ptr, size); | ||||
if (ptr == NULL) | if (ptr == NULL) | ||||
die("could not allocate memory"); | |||||
error(EXIT_FAILURE, errno, NULL); | |||||
return ptr; | return ptr; | ||||
} | } | ||||
@@ -53,40 +53,27 @@ char* estrdup(const char *s) | |||||
d = malloc(n); | d = malloc(n); | ||||
if (d == NULL) | if (d == NULL) | ||||
die("could not allocate memory"); | |||||
error(EXIT_FAILURE, errno, NULL); | |||||
memcpy(d, s, n); | memcpy(d, s, n); | ||||
return d; | return d; | ||||
} | } | ||||
void warn(const char* fmt, ...) | |||||
void error(int eval, int err, const char* fmt, ...) | |||||
{ | { | ||||
va_list args; | |||||
if (fmt == NULL || options->quiet) | |||||
return; | |||||
va_start(args, fmt); | |||||
fprintf(stderr, "sxiv: warning: "); | |||||
vfprintf(stderr, fmt, args); | |||||
fprintf(stderr, "\n"); | |||||
va_end(args); | |||||
} | |||||
void die(const char* fmt, ...) | |||||
{ | |||||
va_list args; | |||||
if (fmt == NULL) | |||||
return; | |||||
va_start(args, fmt); | |||||
fprintf(stderr, "sxiv: error: "); | |||||
vfprintf(stderr, fmt, args); | |||||
fprintf(stderr, "\n"); | |||||
va_end(args); | |||||
cleanup(); | |||||
exit(EXIT_FAILURE); | |||||
va_list ap; | |||||
fflush(stdout); | |||||
fprintf(stderr, "%s: ", progname); | |||||
va_start(ap, fmt); | |||||
if (fmt != NULL) | |||||
vfprintf(stderr, fmt, ap); | |||||
va_end(ap); | |||||
if (err != 0) | |||||
fprintf(stderr, "%s%s", fmt != NULL ? ": " : "", strerror(err)); | |||||
fputc('\n', stderr); | |||||
if (eval != 0) | |||||
exit(eval); | |||||
} | } | ||||
void size_readable(float *size, const char **unit) | void size_readable(float *size, const char **unit) | ||||
@@ -185,7 +172,7 @@ char* r_readdir(r_dir_t *rdir) | |||||
rdir->name = rdir->stack[--rdir->stlen]; | rdir->name = rdir->stack[--rdir->stlen]; | ||||
rdir->d = 1; | rdir->d = 1; | ||||
if ((rdir->dir = opendir(rdir->name)) == NULL) | if ((rdir->dir = opendir(rdir->name)) == NULL) | ||||
warn("could not open directory: %s", rdir->name); | |||||
error(0, errno, "%s", rdir->name); | |||||
continue; | continue; | ||||
} | } | ||||
/* no more entries */ | /* no more entries */ | ||||
@@ -215,7 +202,7 @@ int r_mkdir(const char *path) | |||||
*d = '\0'; | *d = '\0'; | ||||
if (access(dir, F_OK) < 0 && errno == ENOENT) { | if (access(dir, F_OK) < 0 && errno == ENOENT) { | ||||
if (mkdir(dir, 0755) < 0) { | if (mkdir(dir, 0755) < 0) { | ||||
warn("could not create directory: %s", dir); | |||||
error(0, errno, "%s", dir); | |||||
err = -1; | err = -1; | ||||
} | } | ||||
} else if (stat(dir, &stats) < 0 || !S_ISDIR(stats.st_mode)) { | } else if (stat(dir, &stats) < 0 || !S_ISDIR(stats.st_mode)) { | ||||
@@ -61,12 +61,13 @@ typedef struct { | |||||
int stlen; | int stlen; | ||||
} r_dir_t; | } r_dir_t; | ||||
extern const char *progname; | |||||
void* emalloc(size_t); | void* emalloc(size_t); | ||||
void* erealloc(void*, size_t); | void* erealloc(void*, size_t); | ||||
char* estrdup(const char*); | char* estrdup(const char*); | ||||
void warn(const char*, ...); | |||||
void die(const char*, ...); | |||||
void error(int, int, const char*, ...); | |||||
void size_readable(float*, const char**); | void size_readable(float*, const char**); | ||||
@@ -80,7 +80,7 @@ void win_init_font(Display *dpy, const char *fontstr) | |||||
if ((font.xfont = XLoadQueryFont(dpy, fontstr)) == NULL && | if ((font.xfont = XLoadQueryFont(dpy, fontstr)) == NULL && | ||||
(font.xfont = XLoadQueryFont(dpy, "fixed")) == NULL) | (font.xfont = XLoadQueryFont(dpy, "fixed")) == NULL) | ||||
{ | { | ||||
die("could not load font: %s", fontstr); | |||||
error(EXIT_FAILURE, 0, "Error loading font '%s'", fontstr); | |||||
} | } | ||||
font.ascent = font.xfont->ascent; | font.ascent = font.xfont->ascent; | ||||
font.descent = font.xfont->descent; | font.descent = font.xfont->descent; | ||||
@@ -97,7 +97,7 @@ unsigned long win_alloc_color(win_t *win, const char *name) | |||||
DefaultColormap(win->env.dpy, win->env.scr), | DefaultColormap(win->env.dpy, win->env.scr), | ||||
name, &col, &col) == 0) | name, &col, &col) == 0) | ||||
{ | { | ||||
die("could not allocate color: %s", name); | |||||
error(EXIT_FAILURE, 0, "Error allocating color '%s'", name); | |||||
} | } | ||||
return col.pixel; | return col.pixel; | ||||
} | } | ||||
@@ -143,7 +143,7 @@ void win_init(win_t *win) | |||||
e = &win->env; | e = &win->env; | ||||
if ((e->dpy = XOpenDisplay(NULL)) == NULL) | if ((e->dpy = XOpenDisplay(NULL)) == NULL) | ||||
die("could not open display"); | |||||
error(EXIT_FAILURE, 0, "Error opening X display"); | |||||
e->scr = DefaultScreen(e->dpy); | e->scr = DefaultScreen(e->dpy); | ||||
e->scrw = DisplayWidth(e->dpy, e->scr); | e->scrw = DisplayWidth(e->dpy, e->scr); | ||||
@@ -153,7 +153,7 @@ void win_init(win_t *win) | |||||
e->depth = DefaultDepth(e->dpy, e->scr); | e->depth = DefaultDepth(e->dpy, e->scr); | ||||
if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0) | if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0) | ||||
warn("no locale support"); | |||||
error(0, 0, "No locale support"); | |||||
win_init_font(e->dpy, BAR_FONT); | win_init_font(e->dpy, BAR_FONT); | ||||
@@ -236,7 +236,7 @@ void win_open(win_t *win) | |||||
win->x, win->y, win->w, win->h, 0, | win->x, win->y, win->w, win->h, 0, | ||||
e->depth, InputOutput, e->vis, 0, NULL); | e->depth, InputOutput, e->vis, 0, NULL); | ||||
if (win->xwin == None) | if (win->xwin == None) | ||||
die("could not create window"); | |||||
error(EXIT_FAILURE, 0, "Error creating X window"); | |||||
XSelectInput(e->dpy, win->xwin, | XSelectInput(e->dpy, win->xwin, | ||||
ButtonReleaseMask | ButtonPressMask | KeyPressMask | | ButtonReleaseMask | ButtonPressMask | KeyPressMask | | ||||
@@ -249,7 +249,7 @@ void win_open(win_t *win) | |||||
if (XAllocNamedColor(e->dpy, DefaultColormap(e->dpy, e->scr), "black", | if (XAllocNamedColor(e->dpy, DefaultColormap(e->dpy, e->scr), "black", | ||||
&col, &col) == 0) | &col, &col) == 0) | ||||
{ | { | ||||
die("could not allocate color: black"); | |||||
error(EXIT_FAILURE, 0, "Error allocating color 'black'"); | |||||
} | } | ||||
none = XCreateBitmapFromData(e->dpy, win->xwin, none_data, 8, 8); | none = XCreateBitmapFromData(e->dpy, win->xwin, none_data, 8, 8); | ||||
cnone = XCreatePixmapCursor(e->dpy, none, none, &col, &col, 0, 0); | cnone = XCreatePixmapCursor(e->dpy, none, none, &col, &col, 0, 0); | ||||
@@ -306,7 +306,7 @@ void win_open(win_t *win) | |||||
win_toggle_fullscreen(win); | win_toggle_fullscreen(win); | ||||
} | } | ||||
void win_close(win_t *win) | |||||
CLEANUP void win_close(win_t *win) | |||||
{ | { | ||||
XFreeCursor(win->env.dpy, carrow); | XFreeCursor(win->env.dpy, carrow); | ||||
XFreeCursor(win->env.dpy, cnone); | XFreeCursor(win->env.dpy, cnone); | ||||
@@ -341,7 +341,7 @@ void win_toggle_fullscreen(win_t *win) | |||||
if (!fs_support) { | if (!fs_support) { | ||||
if (!fs_warned) { | if (!fs_warned) { | ||||
warn("window manager does not support fullscreen"); | |||||
error(0, 0, "No fullscreen support"); | |||||
fs_warned = True; | fs_warned = True; | ||||
} | } | ||||
return; | return; | ||||
@@ -90,7 +90,7 @@ extern Atom atoms[ATOM_COUNT]; | |||||
void win_init(win_t*); | void win_init(win_t*); | ||||
void win_open(win_t*); | void win_open(win_t*); | ||||
void win_close(win_t*); | |||||
CLEANUP void win_close(win_t*); | |||||
bool win_configure(win_t*, XConfigureEvent*); | bool win_configure(win_t*, XConfigureEvent*); | ||||