nsxivd3a70a2
Revised error handling
- 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)
+108 −138
12 files changed
- M commands.c +0 −2
- M image.c +6 −5
- M image.h +1 −1
- M main.c +44 −57
- M options.c +13 −20
- M thumbs.c +8 −7
- M thumbs.h +1 −1
- M types.h +2 −0
- M util.c +21 −34
- M util.h +3 −2
- M window.c +8 −8
- M window.h +1 −1
| @@ -30,7 +30,6 @@ | |||
| 30 | 30 | #define _IMAGE_CONFIG | |
| 31 | 31 | #include "config.h" | |
| 32 | 32 | ||
| 33 | − | void cleanup(void); | |
| 34 | 33 | void remove_file(int, bool); | |
| 35 | 34 | void load_image(int); | |
| 36 | 35 | void open_info(void); | |
| @@ -64,7 +63,6 @@ bool cg_quit(arg_t _) | |||
| 64 | 63 | printf("%s\n", files[i].name); | |
| 65 | 64 | } | |
| 66 | 65 | } | |
| 67 | − | cleanup(); | |
| 68 | 66 | exit(EXIT_SUCCESS); | |
| 69 | 67 | } | |
| 70 | 68 | ||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | * along with sxiv. If not, see <http://www.gnu.org/licenses/>. | |
| 17 | 17 | */ | |
| 18 | 18 | ||
| 19 | + | #include <errno.h> | |
| 19 | 20 | #include <stdlib.h> | |
| 20 | 21 | #include <string.h> | |
| 21 | 22 | #include <sys/types.h> | |
| @@ -149,7 +150,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||
| 149 | 150 | gif = DGifOpenFileName(file->path); | |
| 150 | 151 | #endif | |
| 151 | 152 | if (gif == NULL) { | |
| 152 | − | warn("could not open gif file: %s", file->name); | |
| 153 | + | error(0, 0, "%s: Error opening gif image", file->name); | |
| 153 | 154 | return false; | |
| 154 | 155 | } | |
| 155 | 156 | bg = gif->SBackGroundColor; | |
| @@ -274,7 +275,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||
| 274 | 275 | #endif | |
| 275 | 276 | ||
| 276 | 277 | if (err && (file->flags & FF_WARN)) | |
| 277 | − | warn("corrupted gif file: %s", file->name); | |
| 278 | + | error(0, 0, "%s: Corrupted gif file", file->name); | |
| 278 | 279 | ||
| 279 | 280 | if (img->multi.cnt > 1) { | |
| 280 | 281 | imlib_context_set_image(img->im); | |
| @@ -300,7 +301,7 @@ bool img_load(img_t *img, const fileinfo_t *file) | |||
| 300 | 301 | (img->im = imlib_load_image(file->path)) == NULL) | |
| 301 | 302 | { | |
| 302 | 303 | if (file->flags & FF_WARN) | |
| 303 | − | warn("could not open image: %s", file->name); | |
| 304 | + | error(0, 0, "%s: Error opening image", file->name); | |
| 304 | 305 | return false; | |
| 305 | 306 | } | |
| 306 | 307 | ||
| @@ -325,7 +326,7 @@ bool img_load(img_t *img, const fileinfo_t *file) | |||
| 325 | 326 | return true; | |
| 326 | 327 | } | |
| 327 | 328 | ||
| 328 | − | void img_close(img_t *img, bool decache) | |
| 329 | + | CLEANUP void img_close(img_t *img, bool decache) | |
| 329 | 330 | { | |
| 330 | 331 | int i; | |
| 331 | 332 | ||
| @@ -464,7 +465,7 @@ void img_render(img_t *img) | |||
| 464 | 465 | ||
| 465 | 466 | if (imlib_image_has_alpha()) { | |
| 466 | 467 | if ((bg = imlib_create_image(dw, dh)) == NULL) | |
| 467 | − | die("could not allocate memory"); | |
| 468 | + | error(EXIT_FAILURE, ENOMEM, NULL); | |
| 468 | 469 | imlib_context_set_image(bg); | |
| 469 | 470 | imlib_image_set_has_alpha(0); | |
| 470 | 471 | ||
| @@ -69,7 +69,7 @@ typedef struct { | |||
| 69 | 69 | void img_init(img_t*, win_t*); | |
| 70 | 70 | ||
| 71 | 71 | bool img_load(img_t*, const fileinfo_t*); | |
| 72 | − | void img_close(img_t*, bool); | |
| 72 | + | CLEANUP void img_close(img_t*, bool); | |
| 73 | 73 | ||
| 74 | 74 | void img_render(img_t*); | |
| 75 | 75 | ||
| @@ -42,11 +42,6 @@ | |||
| 42 | 42 | #define _MAPPINGS_CONFIG | |
| 43 | 43 | #include "config.h" | |
| 44 | 44 | ||
| 45 | − | typedef struct { | |
| 46 | − | const char *name; | |
| 47 | − | char *cmd; | |
| 48 | − | } exec_t; | |
| 49 | − | ||
| 50 | 45 | typedef struct { | |
| 51 | 46 | struct timeval when; | |
| 52 | 47 | bool active; | |
| @@ -75,15 +70,20 @@ bool extprefix; | |||
| 75 | 70 | ||
| 76 | 71 | bool resized = false; | |
| 77 | 72 | ||
| 73 | + | typedef struct { | |
| 74 | + | int err; | |
| 75 | + | char *cmd; | |
| 76 | + | } extcmd_t; | |
| 77 | + | ||
| 78 | 78 | struct { | |
| 79 | − | char *cmd; | |
| 79 | + | extcmd_t f; | |
| 80 | 80 | int fd; | |
| 81 | 81 | unsigned int i, lastsep; | |
| 82 | 82 | bool open; | |
| 83 | 83 | } info; | |
| 84 | 84 | ||
| 85 | 85 | struct { | |
| 86 | − | char *cmd; | |
| 86 | + | extcmd_t f; | |
| 87 | 87 | bool warned; | |
| 88 | 88 | } keyhandler; | |
| 89 | 89 | ||
| @@ -97,26 +97,24 @@ timeout_t timeouts[] = { | |||
| 97 | 97 | ||
| 98 | 98 | void cleanup(void) | |
| 99 | 99 | { | |
| 100 | − | static bool in = false; | |
| 101 | − | ||
| 102 | − | if (!in) { | |
| 103 | − | in = true; | |
| 104 | − | img_close(&img, false); | |
| 105 | − | tns_free(&tns); | |
| 106 | − | win_close(&win); | |
| 107 | − | } | |
| 100 | + | img_close(&img, false); | |
| 101 | + | tns_free(&tns); | |
| 102 | + | win_close(&win); | |
| 108 | 103 | } | |
| 109 | 104 | ||
| 110 | 105 | void check_add_file(char *filename, bool given) | |
| 111 | 106 | { | |
| 107 | + | char *path; | |
| 112 | 108 | const char *bn; | |
| 113 | 109 | ||
| 114 | 110 | if (*filename == '\0') | |
| 115 | 111 | return; | |
| 116 | 112 | ||
| 117 | − | if (access(filename, R_OK) < 0) { | |
| 113 | + | if (access(filename, R_OK) < 0 || | |
| 114 | + | (path = realpath(filename, NULL)) == NULL) | |
| 115 | + | { | |
| 118 | 116 | if (given) | |
| 119 | − | warn("could not open file: %s", filename); | |
| 117 | + | error(0, errno, "%s", filename); | |
| 120 | 118 | return; | |
| 121 | 119 | } | |
| 122 | 120 | ||
| @@ -126,12 +124,8 @@ void check_add_file(char *filename, bool given) | |||
| 126 | 124 | memset(&files[filecnt/2], 0, filecnt/2 * sizeof(*files)); | |
| 127 | 125 | } | |
| 128 | 126 | ||
| 129 | − | if ((files[fileidx].path = realpath(filename, NULL)) == NULL) { | |
| 130 | − | warn("could not get real path of file: %s\n", filename); | |
| 131 | − | return; | |
| 132 | − | } | |
| 133 | − | ||
| 134 | 127 | files[fileidx].name = estrdup(filename); | |
| 128 | + | files[fileidx].path = path; | |
| 135 | 129 | if ((bn = strrchr(files[fileidx].name , '/')) != NULL && bn[1] != '\0') | |
| 136 | 130 | files[fileidx].base = ++bn; | |
| 137 | 131 | else | |
| @@ -149,7 +143,6 @@ void remove_file(int n, bool manual) | |||
| 149 | 143 | if (filecnt == 1) { | |
| 150 | 144 | if (!manual) | |
| 151 | 145 | fprintf(stderr, "sxiv: no more files to display, aborting\n"); | |
| 152 | − | cleanup(); | |
| 153 | 146 | exit(manual ? EXIT_SUCCESS : EXIT_FAILURE); | |
| 154 | 147 | } | |
| 155 | 148 | if (files[n].flags & FF_MARK) | |
| @@ -232,7 +225,7 @@ void open_info(void) | |||
| 232 | 225 | static pid_t pid; | |
| 233 | 226 | int pfd[2]; | |
| 234 | 227 | ||
| 235 | − | if (info.cmd == NULL || info.open || win.bar.h == 0) | |
| 228 | + | if (info.f.err != 0 || info.open || win.bar.h == 0) | |
| 236 | 229 | return; | |
| 237 | 230 | if (info.fd != -1) { | |
| 238 | 231 | close(info.fd); | |
| @@ -246,9 +239,8 @@ void open_info(void) | |||
| 246 | 239 | if ((pid = fork()) == 0) { | |
| 247 | 240 | close(pfd[0]); | |
| 248 | 241 | dup2(pfd[1], 1); | |
| 249 | − | execl(info.cmd, info.cmd, files[fileidx].name, NULL); | |
| 250 | − | warn("could not exec: %s", info.cmd); | |
| 251 | − | exit(EXIT_FAILURE); | |
| 242 | + | execl(info.f.cmd, info.f.cmd, files[fileidx].name, NULL); | |
| 243 | + | error(EXIT_FAILURE, errno, "exec: %s", info.f.cmd); | |
| 252 | 244 | } | |
| 253 | 245 | close(pfd[1]); | |
| 254 | 246 | if (pid < 0) { | |
| @@ -386,7 +378,7 @@ void update_info(void) | |||
| 386 | 378 | bar_put(r, "%0*d/%d | ", fn, img.multi.sel + 1, img.multi.cnt); | |
| 387 | 379 | } | |
| 388 | 380 | bar_put(r, "%0*d/%d", fw, fileidx + 1, filecnt); | |
| 389 | − | ow_info = info.cmd == NULL; | |
| 381 | + | ow_info = info.f.err != 0; | |
| 390 | 382 | } | |
| 391 | 383 | if (ow_info) { | |
| 392 | 384 | fn = strlen(files[fileidx].name); | |
| @@ -469,14 +461,14 @@ void run_key_handler(const char *key, unsigned int mask) | |||
| 469 | 461 | FILE *pfs; | |
| 470 | 462 | bool marked = mode == MODE_THUMB && markcnt > 0; | |
| 471 | 463 | bool changed = false; | |
| 472 | − | int f, i, pfd[2], retval, status; | |
| 464 | + | int f, i, pfd[2], status; | |
| 473 | 465 | int fcnt = marked ? markcnt : 1; | |
| 474 | 466 | char kstr[32]; | |
| 475 | 467 | struct stat *oldst, st; | |
| 476 | 468 | ||
| 477 | − | if (keyhandler.cmd == NULL) { | |
| 469 | + | if (keyhandler.f.err != 0) { | |
| 478 | 470 | if (!keyhandler.warned) { | |
| 479 | − | warn("key handler not installed"); | |
| 471 | + | error(0, keyhandler.f.err, "%s", keyhandler.f.cmd); | |
| 480 | 472 | keyhandler.warned = true; | |
| 481 | 473 | } | |
| 482 | 474 | return; | |
| @@ -485,12 +477,12 @@ void run_key_handler(const char *key, unsigned int mask) | |||
| 485 | 477 | return; | |
| 486 | 478 | ||
| 487 | 479 | if (pipe(pfd) < 0) { | |
| 488 | − | warn("could not create pipe for key handler"); | |
| 480 | + | error(0, errno, "pipe"); | |
| 489 | 481 | return; | |
| 490 | 482 | } | |
| 491 | 483 | if ((pfs = fdopen(pfd[1], "w")) == NULL) { | |
| 484 | + | error(0, errno, "open pipe"); | |
| 492 | 485 | close(pfd[0]), close(pfd[1]); | |
| 493 | − | warn("could not open pipe for key handler"); | |
| 494 | 486 | return; | |
| 495 | 487 | } | |
| 496 | 488 | oldst = emalloc(fcnt * sizeof(*oldst)); | |
| @@ -507,14 +499,13 @@ void run_key_handler(const char *key, unsigned int mask) | |||
| 507 | 499 | if ((pid = fork()) == 0) { | |
| 508 | 500 | close(pfd[1]); | |
| 509 | 501 | dup2(pfd[0], 0); | |
| 510 | − | execl(keyhandler.cmd, keyhandler.cmd, kstr, NULL); | |
| 511 | − | warn("could not exec key handler"); | |
| 512 | − | exit(EXIT_FAILURE); | |
| 502 | + | execl(keyhandler.f.cmd, keyhandler.f.cmd, kstr, NULL); | |
| 503 | + | error(EXIT_FAILURE, errno, "exec: %s", keyhandler.f.cmd); | |
| 513 | 504 | } | |
| 514 | 505 | close(pfd[0]); | |
| 515 | 506 | if (pid < 0) { | |
| 507 | + | error(0, errno, "fork"); | |
| 516 | 508 | fclose(pfs); | |
| 517 | − | warn("could not fork key handler"); | |
| 518 | 509 | goto end; | |
| 519 | 510 | } | |
| 520 | 511 | ||
| @@ -527,9 +518,8 @@ void run_key_handler(const char *key, unsigned int mask) | |||
| 527 | 518 | } | |
| 528 | 519 | fclose(pfs); | |
| 529 | 520 | waitpid(pid, &status, 0); | |
| 530 | − | retval = WEXITSTATUS(status); | |
| 531 | − | if (WIFEXITED(status) == 0 || retval != 0) | |
| 532 | − | warn("key handler exited with non-zero return value: %d", retval); | |
| 521 | + | if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) | |
| 522 | + | error(0, 0, "%s: Exited abnormally", keyhandler.f.cmd); | |
| 533 | 523 | ||
| 534 | 524 | for (f = i = 0; f < fcnt; i++) { | |
| 535 | 525 | if ((marked && (files[i].flags & FF_MARK)) || (!marked && i == fileidx)) { | |
| @@ -550,7 +540,7 @@ end: | |||
| 550 | 540 | if (changed) { | |
| 551 | 541 | img_close(&img, true); | |
| 552 | 542 | load_image(fileidx); | |
| 553 | − | } else if (info.cmd != NULL) { | |
| 543 | + | } else if (info.f.err == 0) { | |
| 554 | 544 | info.open = false; | |
| 555 | 545 | open_info(); | |
| 556 | 546 | } | |
| @@ -819,18 +809,18 @@ int main(int argc, char **argv) | |||
| 819 | 809 | filename = options->filenames[i]; | |
| 820 | 810 | ||
| 821 | 811 | if (stat(filename, &fstats) < 0) { | |
| 822 | − | warn("could not stat file: %s", filename); | |
| 812 | + | error(0, errno, "%s", filename); | |
| 823 | 813 | continue; | |
| 824 | 814 | } | |
| 825 | 815 | if (!S_ISDIR(fstats.st_mode)) { | |
| 826 | 816 | check_add_file(filename, true); | |
| 827 | 817 | } else { | |
| 828 | 818 | if (!options->recursive) { | |
| 829 | − | warn("ignoring directory: %s", filename); | |
| 819 | + | error(0, 0, "%s: Is a directory", filename); | |
| 830 | 820 | continue; | |
| 831 | 821 | } | |
| 832 | 822 | if (r_opendir(&dir, filename) < 0) { | |
| 833 | − | warn("could not open directory: %s", filename); | |
| 823 | + | error(0, errno, "%s", filename); | |
| 834 | 824 | continue; | |
| 835 | 825 | } | |
| 836 | 826 | start = fileidx; | |
| @@ -844,10 +834,8 @@ int main(int argc, char **argv) | |||
| 844 | 834 | } | |
| 845 | 835 | } | |
| 846 | 836 | ||
| 847 | − | if (fileidx == 0) { | |
| 848 | − | fprintf(stderr, "sxiv: no valid image file given, aborting\n"); | |
| 849 | − | exit(EXIT_FAILURE); | |
| 850 | − | } | |
| 837 | + | if (fileidx == 0) | |
| 838 | + | error(EXIT_FAILURE, 0, "No valid image file given, aborting"); | |
| 851 | 839 | ||
| 852 | 840 | filecnt = fileidx; | |
| 853 | 841 | fileidx = options->startnum < filecnt ? options->startnum : 0; | |
| @@ -860,20 +848,18 @@ int main(int argc, char **argv) | |||
| 860 | 848 | dsuffix = "/.config"; | |
| 861 | 849 | } | |
| 862 | 850 | if (homedir != NULL) { | |
| 863 | − | char **cmd[] = { &info.cmd, &keyhandler.cmd }; | |
| 851 | + | extcmd_t *cmd[] = { &info.f, &keyhandler.f }; | |
| 864 | 852 | const char *name[] = { "image-info", "key-handler" }; | |
| 865 | 853 | ||
| 866 | 854 | for (i = 0; i < ARRLEN(cmd); i++) { | |
| 867 | 855 | n = strlen(homedir) + strlen(dsuffix) + strlen(name[i]) + 12; | |
| 868 | − | *cmd[i] = (char*) emalloc(n); | |
| 869 | − | snprintf(*cmd[i], n, "%s%s/sxiv/exec/%s", homedir, dsuffix, name[i]); | |
| 870 | − | if (access(*cmd[i], X_OK) != 0) { | |
| 871 | − | free(*cmd[i]); | |
| 872 | − | *cmd[i] = NULL; | |
| 873 | − | } | |
| 856 | + | cmd[i]->cmd = (char*) emalloc(n); | |
| 857 | + | snprintf(cmd[i]->cmd, n, "%s%s/sxiv/exec/%s", homedir, dsuffix, name[i]); | |
| 858 | + | if (access(cmd[i]->cmd, X_OK) != 0) | |
| 859 | + | cmd[i]->err = errno; | |
| 874 | 860 | } | |
| 875 | 861 | } else { | |
| 876 | − | warn("could not locate exec directory"); | |
| 862 | + | error(0, 0, "Exec directory not found"); | |
| 877 | 863 | } | |
| 878 | 864 | info.fd = -1; | |
| 879 | 865 | ||
| @@ -890,10 +876,11 @@ int main(int argc, char **argv) | |||
| 890 | 876 | win_open(&win); | |
| 891 | 877 | win_set_cursor(&win, CURSOR_WATCH); | |
| 892 | 878 | ||
| 879 | + | atexit(cleanup); | |
| 880 | + | ||
| 893 | 881 | set_timeout(redraw, 25, false); | |
| 894 | 882 | ||
| 895 | 883 | run(); | |
| 896 | − | cleanup(); | |
| 897 | 884 | ||
| 898 | 885 | return 0; | |
| 899 | 886 | } | |
| @@ -47,6 +47,9 @@ void parse_options(int argc, char **argv) | |||
| 47 | 47 | char *end, *s; | |
| 48 | 48 | const char *scalemodes = "dfwh"; | |
| 49 | 49 | ||
| 50 | + | progname = strrchr(argv[0], '/'); | |
| 51 | + | progname = progname ? progname + 1 : argv[0]; | |
| 52 | + | ||
| 50 | 53 | _options.from_stdin = false; | |
| 51 | 54 | _options.to_stdout = false; | |
| 52 | 55 | _options.recursive = false; | |
| @@ -86,10 +89,8 @@ void parse_options(int argc, char **argv) | |||
| 86 | 89 | break; | |
| 87 | 90 | case 'G': | |
| 88 | 91 | n = strtol(optarg, &end, 0); | |
| 89 | − | if (*end != '\0') { | |
| 90 | − | fprintf(stderr, "sxiv: invalid argument for option -G: %s\n", optarg); | |
| 91 | − | exit(EXIT_FAILURE); | |
| 92 | − | } | |
| 92 | + | if (*end != '\0') | |
| 93 | + | error(EXIT_FAILURE, 0, "Invalid argument for option -G: %s", optarg); | |
| 93 | 94 | _options.gamma = n; | |
| 94 | 95 | break; | |
| 95 | 96 | case 'g': | |
| @@ -103,10 +104,8 @@ void parse_options(int argc, char **argv) | |||
| 103 | 104 | break; | |
| 104 | 105 | case 'n': | |
| 105 | 106 | n = strtol(optarg, &end, 0); | |
| 106 | − | if (*end != '\0' || n <= 0) { | |
| 107 | − | fprintf(stderr, "sxiv: invalid argument for option -n: %s\n", optarg); | |
| 108 | − | exit(EXIT_FAILURE); | |
| 109 | − | } | |
| 107 | + | if (*end != '\0' || n <= 0) | |
| 108 | + | error(EXIT_FAILURE, 0, "Invalid argument for option -n: %s", optarg); | |
| 110 | 109 | _options.startnum = n - 1; | |
| 111 | 110 | break; | |
| 112 | 111 | case 'N': | |
| @@ -123,18 +122,14 @@ void parse_options(int argc, char **argv) | |||
| 123 | 122 | break; | |
| 124 | 123 | case 'S': | |
| 125 | 124 | n = strtol(optarg, &end, 0); | |
| 126 | − | if (*end != '\0' || n <= 0) { | |
| 127 | − | fprintf(stderr, "sxiv: invalid argument for option -S: %s\n", optarg); | |
| 128 | − | exit(EXIT_FAILURE); | |
| 129 | − | } | |
| 125 | + | if (*end != '\0' || n <= 0) | |
| 126 | + | error(EXIT_FAILURE, 0, "Invalid argument for option -S: %s", optarg); | |
| 130 | 127 | _options.slideshow = n; | |
| 131 | 128 | break; | |
| 132 | 129 | case 's': | |
| 133 | 130 | s = strchr(scalemodes, optarg[0]); | |
| 134 | − | if (s == NULL || *s == '\0' || strlen(optarg) != 1) { | |
| 135 | − | fprintf(stderr, "sxiv: invalid argument for option -s: %s\n", optarg); | |
| 136 | − | exit(EXIT_FAILURE); | |
| 137 | − | } | |
| 131 | + | if (s == NULL || *s == '\0' || strlen(optarg) != 1) | |
| 132 | + | error(EXIT_FAILURE, 0, "Invalid argument for option -s: %s", optarg); | |
| 138 | 133 | _options.scalemode = s - scalemodes; | |
| 139 | 134 | break; | |
| 140 | 135 | case 't': | |
| @@ -149,10 +144,8 @@ void parse_options(int argc, char **argv) | |||
| 149 | 144 | break; | |
| 150 | 145 | case 'z': | |
| 151 | 146 | n = strtol(optarg, &end, 0); | |
| 152 | − | if (*end != '\0' || n <= 0) { | |
| 153 | − | fprintf(stderr, "sxiv: invalid argument for option -z: %s\n", optarg); | |
| 154 | − | exit(EXIT_FAILURE); | |
| 155 | − | } | |
| 147 | + | if (*end != '\0' || n <= 0) | |
| 148 | + | error(EXIT_FAILURE, 0, "Invalid argument for option -z: %s", optarg); | |
| 156 | 149 | _options.scalemode = SCALE_ZOOM; | |
| 157 | 150 | _options.zoom = (float) n / 100.0; | |
| 158 | 151 | break; | |
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | * along with sxiv. If not, see <http://www.gnu.org/licenses/>. | |
| 17 | 17 | */ | |
| 18 | 18 | ||
| 19 | + | #include <errno.h> | |
| 19 | 20 | #include <stdio.h> | |
| 20 | 21 | #include <stdlib.h> | |
| 21 | 22 | #include <string.h> | |
| @@ -122,7 +123,7 @@ void tns_clean_cache(tns_t *tns) | |||
| 122 | 123 | r_dir_t dir; | |
| 123 | 124 | ||
| 124 | 125 | if (r_opendir(&dir, cache_dir) < 0) { | |
| 125 | − | warn("could not open thumbnail cache directory: %s", cache_dir); | |
| 126 | + | error(0, errno, "%s", cache_dir); | |
| 126 | 127 | return; | |
| 127 | 128 | } | |
| 128 | 129 | ||
| @@ -140,7 +141,7 @@ void tns_clean_cache(tns_t *tns) | |||
| 140 | 141 | } | |
| 141 | 142 | if (delete) { | |
| 142 | 143 | if (unlink(cfile) < 0) | |
| 143 | − | warn("could not delete cache file: %s", cfile); | |
| 144 | + | error(0, errno, "%s", cfile); | |
| 144 | 145 | } | |
| 145 | 146 | free(cfile); | |
| 146 | 147 | } | |
| @@ -181,11 +182,11 @@ void tns_init(tns_t *tns, fileinfo_t *files, const int *cnt, int *sel, | |||
| 181 | 182 | cache_dir = (char*) emalloc(len); | |
| 182 | 183 | snprintf(cache_dir, len, "%s%s/sxiv", homedir, dsuffix); | |
| 183 | 184 | } else { | |
| 184 | − | warn("could not locate thumbnail cache directory"); | |
| 185 | + | error(0, 0, "Cache directory not found"); | |
| 185 | 186 | } | |
| 186 | 187 | } | |
| 187 | 188 | ||
| 188 | − | void tns_free(tns_t *tns) | |
| 189 | + | CLEANUP void tns_free(tns_t *tns) | |
| 189 | 190 | { | |
| 190 | 191 | int i; | |
| 191 | 192 | ||
| @@ -222,7 +223,7 @@ Imlib_Image tns_scale_down(Imlib_Image im, int dim) | |||
| 222 | 223 | im = imlib_create_cropped_scaled_image(0, 0, w, h, | |
| 223 | 224 | MAX(z * w, 1), MAX(z * h, 1)); | |
| 224 | 225 | if (im == NULL) | |
| 225 | − | die("could not allocate memory"); | |
| 226 | + | error(EXIT_FAILURE, ENOMEM, NULL); | |
| 226 | 227 | imlib_free_image_and_decache(); | |
| 227 | 228 | } | |
| 228 | 229 | return im; | |
| @@ -316,7 +317,7 @@ bool tns_load(tns_t *tns, int n, bool force, bool cache_only) | |||
| 316 | 317 | } | |
| 317 | 318 | if (w >= maxwh || h >= maxwh) { | |
| 318 | 319 | if ((im = imlib_create_cropped_image(x, y, w, h)) == NULL) | |
| 319 | − | die("could not allocate memory"); | |
| 320 | + | error(EXIT_FAILURE, ENOMEM, NULL); | |
| 320 | 321 | } | |
| 321 | 322 | imlib_free_image_and_decache(); | |
| 322 | 323 | } | |
| @@ -332,7 +333,7 @@ bool tns_load(tns_t *tns, int n, bool force, bool cache_only) | |||
| 332 | 333 | (im = imlib_load_image(file->path)) == NULL)) | |
| 333 | 334 | { | |
| 334 | 335 | if (file->flags & FF_WARN) | |
| 335 | − | warn("could not open image: %s", file->name); | |
| 336 | + | error(0, 0, "%s: Error opening image", file->name); | |
| 336 | 337 | return false; | |
| 337 | 338 | } | |
| 338 | 339 | imlib_context_set_image(im); | |
| @@ -58,7 +58,7 @@ typedef struct { | |||
| 58 | 58 | void tns_clean_cache(tns_t*); | |
| 59 | 59 | ||
| 60 | 60 | void tns_init(tns_t*, fileinfo_t*, const int*, int*, win_t*); | |
| 61 | − | void tns_free(tns_t*); | |
| 61 | + | CLEANUP void tns_free(tns_t*); | |
| 62 | 62 | ||
| 63 | 63 | bool tns_load(tns_t*, int, bool, bool); | |
| 64 | 64 | void tns_unload(tns_t*, int); | |
| @@ -21,6 +21,8 @@ | |||
| 21 | 21 | ||
| 22 | 22 | #include <stdbool.h> | |
| 23 | 23 | ||
| 24 | + | #define CLEANUP | |
| 25 | + | ||
| 24 | 26 | typedef enum { | |
| 25 | 27 | BO_BIG_ENDIAN, | |
| 26 | 28 | BO_LITTLE_ENDIAN | |
| @@ -26,7 +26,7 @@ | |||
| 26 | 26 | #include "options.h" | |
| 27 | 27 | #include "util.h" | |
| 28 | 28 | ||
| 29 | − | void cleanup(void); | |
| 29 | + | const char *progname; | |
| 30 | 30 | ||
| 31 | 31 | void* emalloc(size_t size) | |
| 32 | 32 | { | |
| @@ -34,7 +34,7 @@ void* emalloc(size_t size) | |||
| 34 | 34 | ||
| 35 | 35 | ptr = malloc(size); | |
| 36 | 36 | if (ptr == NULL) | |
| 37 | − | die("could not allocate memory"); | |
| 37 | + | error(EXIT_FAILURE, errno, NULL); | |
| 38 | 38 | return ptr; | |
| 39 | 39 | } | |
| 40 | 40 | ||
| @@ -42,7 +42,7 @@ void* erealloc(void *ptr, size_t size) | |||
| 42 | 42 | { | |
| 43 | 43 | ptr = realloc(ptr, size); | |
| 44 | 44 | if (ptr == NULL) | |
| 45 | − | die("could not allocate memory"); | |
| 45 | + | error(EXIT_FAILURE, errno, NULL); | |
| 46 | 46 | return ptr; | |
| 47 | 47 | } | |
| 48 | 48 | ||
| @@ -53,40 +53,27 @@ char* estrdup(const char *s) | |||
| 53 | 53 | ||
| 54 | 54 | d = malloc(n); | |
| 55 | 55 | if (d == NULL) | |
| 56 | − | die("could not allocate memory"); | |
| 56 | + | error(EXIT_FAILURE, errno, NULL); | |
| 57 | 57 | memcpy(d, s, n); | |
| 58 | 58 | return d; | |
| 59 | 59 | } | |
| 60 | 60 | ||
| 61 | − | void warn(const char* fmt, ...) | |
| 61 | + | void error(int eval, int err, const char* fmt, ...) | |
| 62 | 62 | { | |
| 63 | − | va_list args; | |
| 64 | − | ||
| 65 | − | if (fmt == NULL || options->quiet) | |
| 66 | − | return; | |
| 67 | − | ||
| 68 | − | va_start(args, fmt); | |
| 69 | − | fprintf(stderr, "sxiv: warning: "); | |
| 70 | − | vfprintf(stderr, fmt, args); | |
| 71 | − | fprintf(stderr, "\n"); | |
| 72 | − | va_end(args); | |
| 73 | − | } | |
| 74 | − | ||
| 75 | − | void die(const char* fmt, ...) | |
| 76 | − | { | |
| 77 | − | va_list args; | |
| 78 | − | ||
| 79 | − | if (fmt == NULL) | |
| 80 | − | return; | |
| 81 | − | ||
| 82 | − | va_start(args, fmt); | |
| 83 | − | fprintf(stderr, "sxiv: error: "); | |
| 84 | − | vfprintf(stderr, fmt, args); | |
| 85 | − | fprintf(stderr, "\n"); | |
| 86 | − | va_end(args); | |
| 87 | − | ||
| 88 | − | cleanup(); | |
| 89 | − | exit(EXIT_FAILURE); | |
| 63 | + | va_list ap; | |
| 64 | + | ||
| 65 | + | fflush(stdout); | |
| 66 | + | fprintf(stderr, "%s: ", progname); | |
| 67 | + | va_start(ap, fmt); | |
| 68 | + | if (fmt != NULL) | |
| 69 | + | vfprintf(stderr, fmt, ap); | |
| 70 | + | va_end(ap); | |
| 71 | + | if (err != 0) | |
| 72 | + | fprintf(stderr, "%s%s", fmt != NULL ? ": " : "", strerror(err)); | |
| 73 | + | fputc('\n', stderr); | |
| 74 | + | ||
| 75 | + | if (eval != 0) | |
| 76 | + | exit(eval); | |
| 90 | 77 | } | |
| 91 | 78 | ||
| 92 | 79 | void size_readable(float *size, const char **unit) | |
| @@ -185,7 +172,7 @@ char* r_readdir(r_dir_t *rdir) | |||
| 185 | 172 | rdir->name = rdir->stack[--rdir->stlen]; | |
| 186 | 173 | rdir->d = 1; | |
| 187 | 174 | if ((rdir->dir = opendir(rdir->name)) == NULL) | |
| 188 | − | warn("could not open directory: %s", rdir->name); | |
| 175 | + | error(0, errno, "%s", rdir->name); | |
| 189 | 176 | continue; | |
| 190 | 177 | } | |
| 191 | 178 | /* no more entries */ | |
| @@ -215,7 +202,7 @@ int r_mkdir(const char *path) | |||
| 215 | 202 | *d = '\0'; | |
| 216 | 203 | if (access(dir, F_OK) < 0 && errno == ENOENT) { | |
| 217 | 204 | if (mkdir(dir, 0755) < 0) { | |
| 218 | − | warn("could not create directory: %s", dir); | |
| 205 | + | error(0, errno, "%s", dir); | |
| 219 | 206 | err = -1; | |
| 220 | 207 | } | |
| 221 | 208 | } else if (stat(dir, &stats) < 0 || !S_ISDIR(stats.st_mode)) { | |
| @@ -61,12 +61,13 @@ typedef struct { | |||
| 61 | 61 | int stlen; | |
| 62 | 62 | } r_dir_t; | |
| 63 | 63 | ||
| 64 | + | extern const char *progname; | |
| 65 | + | ||
| 64 | 66 | void* emalloc(size_t); | |
| 65 | 67 | void* erealloc(void*, size_t); | |
| 66 | 68 | char* estrdup(const char*); | |
| 67 | 69 | ||
| 68 | − | void warn(const char*, ...); | |
| 69 | − | void die(const char*, ...); | |
| 70 | + | void error(int, int, const char*, ...); | |
| 70 | 71 | ||
| 71 | 72 | void size_readable(float*, const char**); | |
| 72 | 73 | ||
| @@ -80,7 +80,7 @@ void win_init_font(Display *dpy, const char *fontstr) | |||
| 80 | 80 | if ((font.xfont = XLoadQueryFont(dpy, fontstr)) == NULL && | |
| 81 | 81 | (font.xfont = XLoadQueryFont(dpy, "fixed")) == NULL) | |
| 82 | 82 | { | |
| 83 | − | die("could not load font: %s", fontstr); | |
| 83 | + | error(EXIT_FAILURE, 0, "Error loading font '%s'", fontstr); | |
| 84 | 84 | } | |
| 85 | 85 | font.ascent = font.xfont->ascent; | |
| 86 | 86 | font.descent = font.xfont->descent; | |
| @@ -97,7 +97,7 @@ unsigned long win_alloc_color(win_t *win, const char *name) | |||
| 97 | 97 | DefaultColormap(win->env.dpy, win->env.scr), | |
| 98 | 98 | name, &col, &col) == 0) | |
| 99 | 99 | { | |
| 100 | − | die("could not allocate color: %s", name); | |
| 100 | + | error(EXIT_FAILURE, 0, "Error allocating color '%s'", name); | |
| 101 | 101 | } | |
| 102 | 102 | return col.pixel; | |
| 103 | 103 | } | |
| @@ -143,7 +143,7 @@ void win_init(win_t *win) | |||
| 143 | 143 | ||
| 144 | 144 | e = &win->env; | |
| 145 | 145 | if ((e->dpy = XOpenDisplay(NULL)) == NULL) | |
| 146 | − | die("could not open display"); | |
| 146 | + | error(EXIT_FAILURE, 0, "Error opening X display"); | |
| 147 | 147 | ||
| 148 | 148 | e->scr = DefaultScreen(e->dpy); | |
| 149 | 149 | e->scrw = DisplayWidth(e->dpy, e->scr); | |
| @@ -153,7 +153,7 @@ void win_init(win_t *win) | |||
| 153 | 153 | e->depth = DefaultDepth(e->dpy, e->scr); | |
| 154 | 154 | ||
| 155 | 155 | if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0) | |
| 156 | − | warn("no locale support"); | |
| 156 | + | error(0, 0, "No locale support"); | |
| 157 | 157 | ||
| 158 | 158 | win_init_font(e->dpy, BAR_FONT); | |
| 159 | 159 | ||
| @@ -236,7 +236,7 @@ void win_open(win_t *win) | |||
| 236 | 236 | win->x, win->y, win->w, win->h, 0, | |
| 237 | 237 | e->depth, InputOutput, e->vis, 0, NULL); | |
| 238 | 238 | if (win->xwin == None) | |
| 239 | − | die("could not create window"); | |
| 239 | + | error(EXIT_FAILURE, 0, "Error creating X window"); | |
| 240 | 240 | ||
| 241 | 241 | XSelectInput(e->dpy, win->xwin, | |
| 242 | 242 | ButtonReleaseMask | ButtonPressMask | KeyPressMask | | |
| @@ -249,7 +249,7 @@ void win_open(win_t *win) | |||
| 249 | 249 | if (XAllocNamedColor(e->dpy, DefaultColormap(e->dpy, e->scr), "black", | |
| 250 | 250 | &col, &col) == 0) | |
| 251 | 251 | { | |
| 252 | − | die("could not allocate color: black"); | |
| 252 | + | error(EXIT_FAILURE, 0, "Error allocating color 'black'"); | |
| 253 | 253 | } | |
| 254 | 254 | none = XCreateBitmapFromData(e->dpy, win->xwin, none_data, 8, 8); | |
| 255 | 255 | cnone = XCreatePixmapCursor(e->dpy, none, none, &col, &col, 0, 0); | |
| @@ -306,7 +306,7 @@ void win_open(win_t *win) | |||
| 306 | 306 | win_toggle_fullscreen(win); | |
| 307 | 307 | } | |
| 308 | 308 | ||
| 309 | − | void win_close(win_t *win) | |
| 309 | + | CLEANUP void win_close(win_t *win) | |
| 310 | 310 | { | |
| 311 | 311 | XFreeCursor(win->env.dpy, carrow); | |
| 312 | 312 | XFreeCursor(win->env.dpy, cnone); | |
| @@ -341,7 +341,7 @@ void win_toggle_fullscreen(win_t *win) | |||
| 341 | 341 | ||
| 342 | 342 | if (!fs_support) { | |
| 343 | 343 | if (!fs_warned) { | |
| 344 | − | warn("window manager does not support fullscreen"); | |
| 344 | + | error(0, 0, "No fullscreen support"); | |
| 345 | 345 | fs_warned = True; | |
| 346 | 346 | } | |
| 347 | 347 | return; | |
| @@ -90,7 +90,7 @@ extern Atom atoms[ATOM_COUNT]; | |||
| 90 | 90 | ||
| 91 | 91 | void win_init(win_t*); | |
| 92 | 92 | void win_open(win_t*); | |
| 93 | − | void win_close(win_t*); | |
| 93 | + | CLEANUP void win_close(win_t*); | |
| 94 | 94 | ||
| 95 | 95 | bool win_configure(win_t*, XConfigureEvent*); | |
| 96 | 96 | ||