77
88#include " config.h"
99
10- #include < stdlib.h >
10+ #include < cstdlib >
1111#include < unistd.h>
12- #include < string.h >
13- #include < stdarg.h >
14- #include < signal.h >
12+ #include < cstring >
13+ #include < cstdarg >
14+ #include < csignal >
1515#include < sys/wait.h>
1616#include < fcntl.h>
17+ #include < vector>
18+ #include < iostream>
1719
1820#include " lib.misc.h"
1921#include " lib.error.h"
2022
2123/* Array indices for input/output file descriptors as used by pipe() */
22- # define PIPE_IN 1
23- # define PIPE_OUT 0
24+ constexpr int PIPE_IN = 1 ;
25+ constexpr int PIPE_OUT = 0 ;
2426
2527const int def_stdio_fd[3 ] = { STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO };
2628
27- int execute (const char *cmd, const char **args, int nargs, int stdio_fd[3 ], int err2out)
29+ int execute (const std::string& cmd, const std::vector<std::string>& args,
30+ std::array<int , 3 >& stdio_fd, bool err2out)
2831{
29- pid_t pid, child_pid;
30- int redirect;
31- int status;
32- int pipe_fd[3 ][2 ];
33- char **argv;
34- int i, dir;
35-
36- if ( (argv=(char **) malloc ((nargs+2 )*sizeof (char *)))==NULL ) return -1 ;
37-
3832 if ( err2out ) stdio_fd[2 ] = FDREDIR_NONE;
3933
40- redirect = ( stdio_fd[0 ]!=FDREDIR_NONE ||
41- stdio_fd[1 ]!=FDREDIR_NONE ||
42- stdio_fd[2 ]!=FDREDIR_NONE );
34+ const bool redirect = ( stdio_fd[0 ]!=FDREDIR_NONE ||
35+ stdio_fd[1 ]!=FDREDIR_NONE ||
36+ stdio_fd[2 ]!=FDREDIR_NONE );
4337
4438 /* Build the complete argument list for execvp.
4539 * We can const-cast the pointers, since execvp is guaranteed
4640 * not to modify these (or the data pointed to).
4741 */
48- argv[0 ] = (char *) cmd;
49- for (i=0 ; i<nargs; i++) argv[i+1 ] = (char *) args[i];
50- argv[nargs+1 ] = NULL ;
42+ std::vector<char *> argv;
43+ argv.push_back (const_cast <char *>(cmd.c_str ()));
44+ for (const auto & arg : args) {
45+ argv.push_back (const_cast <char *>(arg.c_str ()));
46+ }
47+ argv.push_back (nullptr );
5148
49+ int pipe_fd[3 ][2 ];
5250 /* Open pipes for IO redirection */
53- for (i=0 ; i<3 ; i++) {
54- if ( stdio_fd[i]==FDREDIR_PIPE && pipe (pipe_fd[i])!=0 ) goto ret_error ;
51+ for (int i=0 ; i<3 ; i++) {
52+ if ( stdio_fd[i]==FDREDIR_PIPE && pipe (pipe_fd[i])!=0 ) return - 1 ;
5553 }
5654
55+ pid_t child_pid;
5756 switch ( child_pid = fork () ) {
5857 case -1 : /* error */
59- free (argv);
6058 return -1 ;
6159
6260 case 0 : /* child process */
6361 /* Connect pipes to command stdin/stdout/stderr and close unneeded fd's */
64- for (i=0 ; i<3 ; i++) {
62+ for (int i=0 ; i<3 ; i++) {
6563 if ( stdio_fd[i]==FDREDIR_PIPE ) {
6664 /* stdin must be connected to the pipe output,
6765 stdout/stderr to the pipe input: */
68- dir = (i==0 ? PIPE_OUT : PIPE_IN);
69- if ( dup2 (pipe_fd[i][dir],def_stdio_fd[i])<0 ) goto ret_error ;
70- if ( close (pipe_fd[i][dir])!=0 ) goto ret_error ;
71- if ( close (pipe_fd[i][1 -dir])!=0 ) goto ret_error ;
66+ const int dir = (i==0 ? PIPE_OUT : PIPE_IN);
67+ if ( dup2 (pipe_fd[i][dir],def_stdio_fd[i])<0 ) return - 1 ;
68+ if ( close (pipe_fd[i][dir])!=0 ) return - 1 ;
69+ if ( close (pipe_fd[i][1 -dir])!=0 ) return - 1 ;
7270 }
7371 if ( stdio_fd[i]>=0 ) {
74- if ( dup2 (stdio_fd[i],def_stdio_fd[i])<0 ) goto ret_error ;
75- if ( close (stdio_fd[i])!=0 ) goto ret_error ;
72+ if ( dup2 (stdio_fd[i],def_stdio_fd[i])<0 ) return - 1 ;
73+ if ( close (stdio_fd[i])!=0 ) return - 1 ;
7674 }
7775 }
7876 /* Redirect stderr to stdout */
79- if ( err2out && dup2 (STDOUT_FILENO,STDERR_FILENO)<0 ) goto ret_error ;
77+ if ( err2out && dup2 (STDOUT_FILENO,STDERR_FILENO)<0 ) return - 1 ;
8078
8179 /* Replace child with command */
82- execvp (cmd, argv);
80+ execvp (cmd. c_str (), argv. data () );
8381 abort ();
8482
8583 default : /* parent process */
8684
87- free (argv);
88-
8985 /* Set and close file descriptors */
90- for (i=0 ; i<3 ; i++) {
86+ for (int i=0 ; i<3 ; i++) {
9187 if ( stdio_fd[i]==FDREDIR_PIPE ) {
9288 /* parent process output must connect to the input of
9389 the pipe to child, and vice versa for stdout/stderr: */
94- dir = (i==0 ? PIPE_IN : PIPE_OUT);
90+ const int dir = (i==0 ? PIPE_IN : PIPE_OUT);
9591 stdio_fd[i] = pipe_fd[i][dir];
9692 if ( close (pipe_fd[i][1 -dir])!=0 ) return -1 ;
9793 }
@@ -101,6 +97,8 @@ int execute(const char *cmd, const char **args, int nargs, int stdio_fd[3], int
10197 if ( redirect ) return child_pid;
10298
10399 /* Wait for the child command to finish */
100+ int status;
101+ pid_t pid;
104102 while ( (pid = wait (&status))!=-1 && pid!=child_pid );
105103 if ( pid!=child_pid ) return -1 ;
106104
@@ -115,21 +113,15 @@ int execute(const char *cmd, const char **args, int nargs, int stdio_fd[3], int
115113
116114 /* This should never be reached */
117115 return -2 ;
118-
119- /* Handle resources before returning on error */
120- ret_error:
121- free (argv);
122- return -1 ;
123116}
124117
125118
126119void version (const char *prog, const char *vers)
127120{
128- printf (" \
129- %s -- part of DOMjudge version %s\n \
130- Written by the DOMjudge developers\n\n \
131- DOMjudge comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n \
132- are welcome to redistribute it under certain conditions. See the GNU\n \
133- General Public Licence for details.\n " , prog, vers);
121+ std::cout << prog << " -- part of DOMjudge version " << vers << std::endl
122+ << " Written by the DOMjudge developers" << std::endl << std::endl
123+ << " DOMjudge comes with ABSOLUTELY NO WARRANTY. This is free software, and you" << std::endl
124+ << " are welcome to redistribute it under certain conditions. See the GNU" << std::endl
125+ << " General Public Licence for details." << std::endl;
134126 exit (0 );
135127}
0 commit comments