commit 557d33657977f5752a77f1ac50dc51aaab381f41 from: Stefan Sperling via: Thomas Adam date: Fri Apr 14 16:28:04 2023 UTC make tog regress run with pledge active ok jamsek commit - 8641a33271eb0cef324fbeb4440485de8f433134 commit + 557d33657977f5752a77f1ac50dc51aaab381f41 blob - 8afaab18b7d71f4b1b6d555d34c39d3d3df20166 blob + ca273f088abf440f2971a8633e52b3f2fe3bb8c9 --- tog/tog.c +++ tog/tog.c @@ -620,7 +620,8 @@ struct tog_io { FILE *cin; FILE *cout; FILE *f; -}; +} tog_io; +static int using_mock_io; #define TOG_SCREEN_DUMP "SCREENDUMP" #define TOG_SCREEN_DUMP_LEN (sizeof(TOG_SCREEN_DUMP) - 1) @@ -1337,7 +1338,7 @@ view_search_start(struct tog_view *view, int fast_refr cbreak(); noecho(); nodelay(v->window, TRUE); - if (!fast_refresh) + if (!fast_refresh && !using_mock_io) halfdelay(10); if (ret == ERR) return NULL; @@ -1661,7 +1662,7 @@ done: static const struct got_error * view_input(struct tog_view **new, int *done, struct tog_view *view, - struct tog_view_list_head *views, struct tog_io *tog_io, int fast_refresh) + struct tog_view_list_head *views, int fast_refresh) { const struct got_error *err = NULL; struct tog_view *v; @@ -1698,8 +1699,8 @@ view_input(struct tog_view **new, int *done, struct to if (errcode) return got_error_set_errno(errcode, "pthread_mutex_unlock"); - if (tog_io && tog_io->f) { - err = tog_read_script_key(tog_io->f, &ch, done); + if (using_mock_io) { + err = tog_read_script_key(tog_io.f, &ch, done); if (err) return err; } else if (view->count && --view->count) { @@ -1922,24 +1923,22 @@ view_needs_focus_indication(struct tog_view *view) } static const struct got_error * -tog_io_close(struct tog_io *tog_io) +tog_io_close(void) { const struct got_error *err = NULL; - if (tog_io->cin && fclose(tog_io->cin) == EOF) - err = got_ferror(tog_io->cin, GOT_ERR_IO); - if (tog_io->cout && fclose(tog_io->cout) == EOF && err == NULL) - err = got_ferror(tog_io->cout, GOT_ERR_IO); - if (tog_io->f && fclose(tog_io->f) == EOF && err == NULL) - err = got_ferror(tog_io->f, GOT_ERR_IO); - free(tog_io); - tog_io = NULL; + if (tog_io.cin && fclose(tog_io.cin) == EOF) + err = got_ferror(tog_io.cin, GOT_ERR_IO); + if (tog_io.cout && fclose(tog_io.cout) == EOF && err == NULL) + err = got_ferror(tog_io.cout, GOT_ERR_IO); + if (tog_io.f && fclose(tog_io.f) == EOF && err == NULL) + err = got_ferror(tog_io.f, GOT_ERR_IO); return err; } static const struct got_error * -view_loop(struct tog_view *view, struct tog_io *tog_io) +view_loop(struct tog_view *view) { const struct got_error *err = NULL; struct tog_view_list_head views; @@ -1970,11 +1969,10 @@ view_loop(struct tog_view *view, struct tog_io *tog_io while (!TAILQ_EMPTY(&views) && !done && !tog_thread_error && !tog_fatal_signal_received()) { /* Refresh fast during initialization, then become slower. */ - if (fast_refresh && --fast_refresh == 0) + if (fast_refresh && --fast_refresh == 0 && !using_mock_io) halfdelay(10); /* switch to once per second */ - err = view_input(&new_view, &done, view, &views, tog_io, - fast_refresh); + err = view_input(&new_view, &done, view, &views, fast_refresh); if (err) break; @@ -2718,7 +2716,7 @@ draw_commits(struct tog_view *view) } } - if (s->thread_args.commits_needed == 0) + if (s->thread_args.commits_needed == 0 && !using_mock_io) halfdelay(10); /* disable fast refresh */ if (s->thread_args.commits_needed > 0 || s->thread_args.load_all) { @@ -2893,7 +2891,8 @@ trigger_log_thread(struct tog_view *view, int wait) struct tog_log_thread_args *ta = &view->state.log.thread_args; int errcode; - halfdelay(1); /* fast refresh while loading commits */ + if (!using_mock_io) + halfdelay(1); /* fast refresh while loading commits */ while (!ta->log_complete && !tog_thread_error && (ta->commits_needed > 0 || ta->load_all)) { @@ -4162,42 +4161,34 @@ apply_unveil(const char *repo_path, const char *worktr } static const struct got_error * -init_mock_term(struct tog_io **tog_io, const char *test_script_path) +init_mock_term(const char *test_script_path) { const struct got_error *err = NULL; - struct tog_io *io; - if (*tog_io) - *tog_io = NULL; - if (test_script_path == NULL || *test_script_path == '\0') return got_error_msg(GOT_ERR_IO, "GOT_TOG_TEST not defined"); - io = calloc(1, sizeof(*io)); - if (io == NULL) - return got_error_from_errno("calloc"); - - io->f = fopen(test_script_path, "re"); - if (io->f == NULL) { + tog_io.f = fopen(test_script_path, "re"); + if (tog_io.f == NULL) { err = got_error_from_errno_fmt("fopen: %s", test_script_path); goto done; } /* test mode, we don't want any output */ - io->cout = fopen("/dev/null", "w+"); - if (io->cout == NULL) { + tog_io.cout = fopen("/dev/null", "w+"); + if (tog_io.cout == NULL) { err = got_error_from_errno("fopen: /dev/null"); goto done; } - io->cin = fopen("/dev/tty", "r+"); - if (io->cin == NULL) { + tog_io.cin = fopen("/dev/tty", "r+"); + if (tog_io.cin == NULL) { err = got_error_from_errno("fopen: /dev/tty"); goto done; } - if (fseeko(io->f, 0L, SEEK_SET) == -1) { + if (fseeko(tog_io.f, 0L, SEEK_SET) == -1) { err = got_error_from_errno("fseeko"); goto done; } @@ -4206,23 +4197,20 @@ init_mock_term(struct tog_io **tog_io, const char *tes * XXX Perhaps we should define "xterm" as the terminal * type for standardised testing instead of using $TERM? */ - if (newterm(NULL, io->cout, io->cin) == NULL) + if (newterm(NULL, tog_io.cout, tog_io.cin) == NULL) err = got_error_msg(GOT_ERR_IO, "newterm: failed to initialise curses"); + + using_mock_io = 1; done: if (err) - tog_io_close(io); - else - *tog_io = io; + tog_io_close(); return err; } -static const struct got_error * -init_curses(struct tog_io **tog_io) +static void +init_curses(void) { - const struct got_error *err = NULL; - const char *test_script_path; - /* * Override default signal handlers before starting ncurses. * This should prevent ncurses from installing its own @@ -4234,16 +4222,13 @@ init_curses(struct tog_io **tog_io) signal(SIGINT, tog_sigint); signal(SIGTERM, tog_sigterm); - test_script_path = getenv("GOT_TOG_TEST"); - if (test_script_path != NULL) { - err = init_mock_term(tog_io, test_script_path); - if (err) - return err; - } else - initscr(); + if (using_mock_io) /* In test mode we use a fake terminal */ + return; + initscr(); + cbreak(); - halfdelay(1); /* Do fast refresh while initial view is loading. */ + halfdelay(1); /* Fast refresh while initial view is loading. */ noecho(); nonl(); intrflush(stdscr, FALSE); @@ -4254,7 +4239,7 @@ init_curses(struct tog_io **tog_io) use_default_colors(); } - return NULL; + return; } static const struct got_error * @@ -4303,7 +4288,6 @@ cmd_log(int argc, char *argv[]) const char *head_ref_name = NULL; int ch, log_branches = 0; struct tog_view *view; - struct tog_io *tog_io = NULL; int *pack_fds = NULL; while ((ch = getopt(argc, argv, "bc:r:")) != -1) { @@ -4363,9 +4347,7 @@ cmd_log(int argc, char *argv[]) if (error) goto done; - error = init_curses(&tog_io); - if (error) - goto done; + init_curses(); error = apply_unveil(got_repo_get_path(repo), worktree ? got_worktree_get_root_path(worktree) : NULL); @@ -4412,7 +4394,7 @@ cmd_log(int argc, char *argv[]) got_worktree_close(worktree); worktree = NULL; } - error = view_loop(view, tog_io); + error = view_loop(view); done: free(in_repo_path); free(repo_path); @@ -4434,8 +4416,8 @@ done: if (error == NULL) error = pack_err; } - if (tog_io != NULL) { - io_err = tog_io_close(tog_io); + if (using_mock_io) { + io_err = tog_io_close(); if (error == NULL) error = io_err; } @@ -5415,7 +5397,7 @@ open_diff_view(struct tog_view *view, struct got_objec s->parent_view = parent_view; s->repo = repo; - if (has_colors() && getenv("TOG_COLORS") != NULL) { + if (has_colors() && getenv("TOG_COLORS") != NULL && !using_mock_io) { int rc; rc = init_pair(GOT_DIFF_LINE_MINUS, @@ -5819,7 +5801,6 @@ cmd_diff(int argc, char *argv[]) int ch, force_text_diff = 0; const char *errstr; struct tog_view *view; - struct tog_io *tog_io = NULL; int *pack_fds = NULL; while ((ch = getopt(argc, argv, "aC:r:w")) != -1) { @@ -5887,9 +5868,7 @@ cmd_diff(int argc, char *argv[]) if (error) goto done; - error = init_curses(&tog_io); - if (error) - goto done; + init_curses(); error = apply_unveil(got_repo_get_path(repo), NULL); if (error) @@ -5918,7 +5897,7 @@ cmd_diff(int argc, char *argv[]) ignore_whitespace, force_text_diff, NULL, repo); if (error) goto done; - error = view_loop(view, tog_io); + error = view_loop(view); done: free(label1); free(label2); @@ -5937,8 +5916,8 @@ done: if (error == NULL) error = pack_err; } - if (tog_io != NULL) { - io_err = tog_io_close(tog_io); + if (using_mock_io) { + io_err = tog_io_close(); if (error == NULL) error = io_err; } @@ -6574,10 +6553,11 @@ show_blame_view(struct tog_view *view) if (errcode) return got_error_set_errno(errcode, "pthread_create"); - halfdelay(1); /* fast refresh while annotating */ + if (!using_mock_io) + halfdelay(1); /* fast refresh while annotating */ } - if (s->blame_complete) + if (s->blame_complete && !using_mock_io) halfdelay(10); /* disable fast refresh */ err = draw_blame(view); @@ -6925,7 +6905,6 @@ cmd_blame(int argc, char *argv[]) char *commit_id_str = NULL; int ch; struct tog_view *view; - struct tog_io *tog_io = NULL; int *pack_fds = NULL; while ((ch = getopt(argc, argv, "c:r:")) != -1) { @@ -6982,9 +6961,7 @@ cmd_blame(int argc, char *argv[]) if (error) goto done; - error = init_curses(&tog_io); - if (error) - goto done; + init_curses(); error = apply_unveil(got_repo_get_path(repo), NULL); if (error) @@ -7033,7 +7010,7 @@ cmd_blame(int argc, char *argv[]) got_worktree_close(worktree); worktree = NULL; } - error = view_loop(view, tog_io); + error = view_loop(view); done: free(repo_path); free(in_repo_path); @@ -7055,8 +7032,8 @@ done: if (error == NULL) error = pack_err; } - if (tog_io != NULL) { - io_err = tog_io_close(tog_io); + if (using_mock_io) { + io_err = tog_io_close(); if (error == NULL) error = io_err; } @@ -7904,7 +7881,6 @@ cmd_tree(int argc, char *argv[]) const char *head_ref_name = NULL; int ch; struct tog_view *view; - struct tog_io *tog_io = NULL; int *pack_fds = NULL; while ((ch = getopt(argc, argv, "c:r:")) != -1) { @@ -7961,9 +7937,7 @@ cmd_tree(int argc, char *argv[]) if (error) goto done; - error = init_curses(&tog_io); - if (error) - goto done; + init_curses(); error = apply_unveil(got_repo_get_path(repo), NULL); if (error) @@ -8016,7 +7990,7 @@ cmd_tree(int argc, char *argv[]) got_worktree_close(worktree); worktree = NULL; } - error = view_loop(view, tog_io); + error = view_loop(view); done: free(repo_path); free(cwd); @@ -8035,8 +8009,8 @@ done: if (error == NULL) error = pack_err; } - if (tog_io != NULL) { - io_err = tog_io_close(tog_io); + if (using_mock_io) { + io_err = tog_io_close(); if (error == NULL) error = io_err; } @@ -8793,7 +8767,6 @@ cmd_ref(int argc, char *argv[]) char *cwd = NULL, *repo_path = NULL; int ch; struct tog_view *view; - struct tog_io *tog_io = NULL; int *pack_fds = NULL; while ((ch = getopt(argc, argv, "r:")) != -1) { @@ -8842,9 +8815,7 @@ cmd_ref(int argc, char *argv[]) if (error != NULL) goto done; - error = init_curses(&tog_io); - if (error) - goto done; + init_curses(); error = apply_unveil(got_repo_get_path(repo), NULL); if (error) @@ -8869,7 +8840,7 @@ cmd_ref(int argc, char *argv[]) got_worktree_close(worktree); worktree = NULL; } - error = view_loop(view, tog_io); + error = view_loop(view); done: free(repo_path); free(cwd); @@ -8884,8 +8855,8 @@ done: if (error == NULL) error = pack_err; } - if (tog_io != NULL) { - io_err = tog_io_close(tog_io); + if (using_mock_io) { + io_err = tog_io_close(); if (error == NULL) error = io_err; } @@ -9764,10 +9735,24 @@ main(int argc, char *argv[]) { NULL, 0, NULL, 0} }; char *diff_algo_str = NULL; + const char *test_script_path; setlocale(LC_CTYPE, ""); -#if !defined(PROFILE) && !defined(TOG_REGRESS) + /* + * Test mode init must happen before pledge() because "tty" will + * not allow TTY-related ioctls to occur via regular files. + */ + test_script_path = getenv("GOT_TOG_TEST"); + if (test_script_path != NULL) { + error = init_mock_term(test_script_path); + if (error) { + fprintf(stderr, "%s: %s\n", getprogname(), error->msg); + return 1; + } + } + +#if !defined(PROFILE) if (pledge("stdio rpath wpath cpath flock proc tty exec sendfd unveil", NULL) == -1) err(1, "pledge");