Coverage Report

Created: 2025-03-11 06:49

/src/neomutt/system.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file
3
 * Execute external programs
4
 *
5
 * @authors
6
 * Copyright (C) 1996-2000,2013 Michael R. Elkins <me@mutt.org>
7
 * Copyright (C) 2017-2023 Richard Russon <rich@flatcap.org>
8
 *
9
 * @copyright
10
 * This program is free software: you can redistribute it and/or modify it under
11
 * the terms of the GNU General Public License as published by the Free Software
12
 * Foundation, either version 2 of the License, or (at your option) any later
13
 * version.
14
 *
15
 * This program is distributed in the hope that it will be useful, but WITHOUT
16
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18
 * details.
19
 *
20
 * You should have received a copy of the GNU General Public License along with
21
 * this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
/**
25
 * @page neo_system Execute external programs
26
 *
27
 * Execute external programs
28
 */
29
30
#include "config.h"
31
#include <signal.h>
32
#include <stdbool.h>
33
#include <stdlib.h>
34
#include <sys/types.h>
35
#include <sys/wait.h> // IWYU pragma: keep
36
#include <unistd.h>
37
#include "mutt/lib.h"
38
#include "core/lib.h"
39
#include "imap/lib.h"
40
#include "protos.h"
41
42
/**
43
 * mutt_system - Run an external command
44
 * @param cmd Command and arguments
45
 * @retval -1  Error
46
 * @retval >=0 Success (command's return code)
47
 *
48
 * Fork and run an external command with arguments.
49
 *
50
 * @note This function won't return until the command finishes.
51
 */
52
int mutt_system(const char *cmd)
53
0
{
54
0
  int rc = -1;
55
0
  struct sigaction act = { 0 };
56
0
  struct sigaction oldtstp = { 0 };
57
0
  struct sigaction oldcont = { 0 };
58
0
  pid_t pid;
59
60
0
  if (!cmd || (*cmd == '\0'))
61
0
    return 0;
62
63
  /* must ignore SIGINT and SIGQUIT */
64
65
0
  mutt_sig_block_system();
66
67
0
  act.sa_handler = SIG_DFL;
68
/* we want to restart the waitpid() below */
69
0
#ifdef SA_RESTART
70
0
  act.sa_flags = SA_RESTART;
71
0
#endif
72
0
  sigemptyset(&act.sa_mask);
73
0
  sigaction(SIGTSTP, &act, &oldtstp);
74
0
  sigaction(SIGCONT, &act, &oldcont);
75
76
0
  pid = fork();
77
0
  if (pid == 0)
78
0
  {
79
0
    act.sa_flags = 0;
80
81
0
    mutt_sig_unblock_system(false);
82
0
    mutt_sig_reset_child_signals();
83
84
0
    execle(EXEC_SHELL, "sh", "-c", cmd, NULL, NeoMutt->env);
85
0
    _exit(127); /* execl error */
86
0
  }
87
0
  else if (pid != -1)
88
0
  {
89
0
    rc = imap_wait_keep_alive(pid);
90
0
  }
91
92
0
  sigaction(SIGCONT, &oldcont, NULL);
93
0
  sigaction(SIGTSTP, &oldtstp, NULL);
94
95
  /* reset SIGINT, SIGQUIT and SIGCHLD */
96
0
  mutt_sig_unblock_system(true);
97
98
0
  rc = (pid != -1) ? (WIFEXITED(rc) ? WEXITSTATUS(rc) : -1) : -1;
99
100
0
  return rc;
101
0
}