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
44- /* Build the complete argument list for execvp.
45- * We can const-cast the pointers, since execvp is guaranteed
46- * not to modify these (or the data pointed to).
47- */
48- argv[0 ] = (char *) cmd;
49- for (i=0 ; i<nargs; i++) argv[i+1 ] = (char *) args[i];
50- argv[nargs+1 ] = NULL ;
38+ std::vector<char *> argv;
39+ argv.push_back (const_cast <char *>(cmd.c_str ()));
40+ for (const auto & arg : args) {
41+ argv.push_back (const_cast <char *>(arg.c_str ()));
42+ }
43+ argv.push_back (nullptr );
5144
45+ int pipe_fd[3 ][2 ];
5246 /* 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 ;
47+ for (int i=0 ; i<3 ; i++) {
48+ if ( stdio_fd[i]==FDREDIR_PIPE && pipe (pipe_fd[i])!=0 ) return - 1 ;
5549 }
5650
51+ pid_t child_pid;
5752 switch ( child_pid = fork () ) {
5853 case -1 : /* error */
59- free (argv);
6054 return -1 ;
6155
6256 case 0 : /* child process */
6357 /* Connect pipes to command stdin/stdout/stderr and close unneeded fd's */
64- for (i=0 ; i<3 ; i++) {
58+ for (int i=0 ; i<3 ; i++) {
6559 if ( stdio_fd[i]==FDREDIR_PIPE ) {
6660 /* stdin must be connected to the pipe output,
6761 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 ;
62+ const int dir = (i==0 ? PIPE_OUT : PIPE_IN);
63+ if ( dup2 (pipe_fd[i][dir],def_stdio_fd[i])<0 ) return - 1 ;
64+ if ( close (pipe_fd[i][dir])!=0 ) return - 1 ;
65+ if ( close (pipe_fd[i][1 -dir])!=0 ) return - 1 ;
7266 }
7367 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 ;
68+ if ( dup2 (stdio_fd[i],def_stdio_fd[i])<0 ) return - 1 ;
69+ if ( close (stdio_fd[i])!=0 ) return - 1 ;
7670 }
7771 }
7872 /* Redirect stderr to stdout */
79- if ( err2out && dup2 (STDOUT_FILENO,STDERR_FILENO)<0 ) goto ret_error ;
73+ if ( err2out && dup2 (STDOUT_FILENO,STDERR_FILENO)<0 ) return - 1 ;
8074
8175 /* Replace child with command */
82- execvp (cmd, argv);
76+ execvp (cmd. c_str (), argv. data () );
8377 abort ();
8478
8579 default : /* parent process */
8680
87- free (argv);
88-
8981 /* Set and close file descriptors */
90- for (i=0 ; i<3 ; i++) {
82+ for (int i=0 ; i<3 ; i++) {
9183 if ( stdio_fd[i]==FDREDIR_PIPE ) {
9284 /* parent process output must connect to the input of
9385 the pipe to child, and vice versa for stdout/stderr: */
94- dir = (i==0 ? PIPE_IN : PIPE_OUT);
86+ const int dir = (i==0 ? PIPE_IN : PIPE_OUT);
9587 stdio_fd[i] = pipe_fd[i][dir];
9688 if ( close (pipe_fd[i][1 -dir])!=0 ) return -1 ;
9789 }
@@ -101,6 +93,8 @@ int execute(const char *cmd, const char **args, int nargs, int stdio_fd[3], int
10193 if ( redirect ) return child_pid;
10294
10395 /* Wait for the child command to finish */
96+ int status;
97+ pid_t pid;
10498 while ( (pid = wait (&status))!=-1 && pid!=child_pid );
10599 if ( pid!=child_pid ) return -1 ;
106100
@@ -115,21 +109,15 @@ int execute(const char *cmd, const char **args, int nargs, int stdio_fd[3], int
115109
116110 /* This should never be reached */
117111 return -2 ;
118-
119- /* Handle resources before returning on error */
120- ret_error:
121- free (argv);
122- return -1 ;
123112}
124113
125114
126115void version (const char *prog, const char *vers)
127116{
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);
117+ std::cout << prog << " -- part of DOMjudge version " << vers << std::endl
118+ << " Written by the DOMjudge developers" << std::endl << std::endl
119+ << " DOMjudge comes with ABSOLUTELY NO WARRANTY. This is free software, and you" << std::endl
120+ << " are welcome to redistribute it under certain conditions. See the GNU" << std::endl
121+ << " General Public Licence for details." << std::endl;
134122 exit (0 );
135- }
123+ }
0 commit comments