-3

I need to write a code in C for unix command that compliles and creates new file, but not allowed to use system() anywhere.

for example: gcc my_functions.c public_test.c -o my_functions.x I know it can be done in C simply calling system call such as

system("gcc my_functions.c public_test.c -o my_functions.x").

But I am not allowed to use system(). I have tried other functions execve,execlp but could not solve it. It would be very appreciable if someone can help me with this ? thank you

I have tried:

  • execlp("gcc","gcc","gcc my_functions.c public_test.c -o my_functions.x",0)

  • execlp("gcc","gcc","gcc", "my_functions.c", "public_test.c", "-o", "my_functions.x",0)

  • execlp("gcc","","gcc my_functions.c public_test.c -o my_functions.x",0)

  • execlp("","","gcc my_functions.c public_test.c -o my_functions.x",0)

None of these work and do not give any error message either. however it works when I call it using system().

MD XF
  • 7,860
  • 7
  • 40
  • 71
  • 2
    you can use exec(3) family of functions, fork, call exec in the child, waitpid in the parent – Ryan Nov 30 '16 at 04:46
  • "I have tried other functions execve,execlp but could not solve it". Well then show your attempt and ask about that. Don't ask about something else when it's clear that you know *what* to do but are having trouble with the *how*. – kaylum Nov 30 '16 at 04:52
  • If there is something you don't understand about `execlp` (for example), please ask a *specific* question, shiwing what you did and describing precisely what the result was and what you think it should have been. "I tried X and it didn't work" is not nearly enough information to provide a useful answer. [ask] – rici Nov 30 '16 at 04:53
  • "none of these work". Why are you randomly guessing instead of reading the [execlp man page](https://linux.die.net/man/3/execlp) and/or doing basic research to find the thousands of examples on how to correctly call the `execlp` function? For example: [I do not understand how execlp() works in Linux](http://stackoverflow.com/questions/21558937/i-do-not-understand-how-execlp-works-in-linux) – kaylum Nov 30 '16 at 05:07

1 Answers1

0

Sure, you can implement your own system function. Here's one from man7:

int
system(const char *command)
{
    sigset_t blockMask, origMask;
    struct sigaction saIgnore, saOrigQuit, saOrigInt, saDefault;
    pid_t childPid;
    int status, savedErrno;

    if (command == NULL)                /* Is a shell available? */
        return system(":") == 0;

    /* The parent process (the caller of system()) blocks SIGCHLD
       and ignore SIGINT and SIGQUIT while the child is executing.
       We must change the signal settings prior to forking, to avoid
       possible race conditions. This means that we must undo the
       effects of the following in the child after fork(). */

    sigemptyset(&blockMask);            /* Block SIGCHLD */
    sigaddset(&blockMask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &blockMask, &origMask);

    saIgnore.sa_handler = SIG_IGN;      /* Ignore SIGINT and SIGQUIT */
    saIgnore.sa_flags = 0;
    sigemptyset(&saIgnore.sa_mask);
    sigaction(SIGINT, &saIgnore, &saOrigInt);
    sigaction(SIGQUIT, &saIgnore, &saOrigQuit);

    switch (childPid = fork()) {
    case -1: /* fork() failed */
        status = -1;
        break;          /* Carry on to reset signal attributes */

    case 0: /* Child: exec command */

        /* We ignore possible error returns because the only specified error
           is for a failed exec(), and because errors in these calls can't
           affect the caller of system() (which is a separate process) */

        saDefault.sa_handler = SIG_DFL;
        saDefault.sa_flags = 0;
        sigemptyset(&saDefault.sa_mask);

        if (saOrigInt.sa_handler != SIG_IGN)
            sigaction(SIGINT, &saDefault, NULL);
        if (saOrigQuit.sa_handler != SIG_IGN)
            sigaction(SIGQUIT, &saDefault, NULL);

        sigprocmask(SIG_SETMASK, &origMask, NULL);

        execl("/bin/sh", "sh", "-c", command, (char *) NULL);
        _exit(127);                     /* We could not exec the shell */

    default: /* Parent: wait for our child to terminate */

        /* We must use waitpid() for this task; using wait() could inadvertently
           collect the status of one of the caller's other children */

        while (waitpid(childPid, &status, 0) == -1) {
            if (errno != EINTR) {       /* Error other than EINTR */
                status = -1;
                break;                  /* So exit loop */
            }
        }
        break;
    }

    /* Unblock SIGCHLD, restore dispositions of SIGINT and SIGQUIT */

    savedErrno = errno;                 /* The following may change 'errno' */

    sigprocmask(SIG_SETMASK, &origMask, NULL);
    sigaction(SIGINT, &saOrigInt, NULL);
    sigaction(SIGQUIT, &saOrigQuit, NULL);

    errno = savedErrno;

    return status;
}

Just don't #include <stdlib.h> or you will have conflicts.

MD XF
  • 7,860
  • 7
  • 40
  • 71