Do you remember the first time someone told you about fork()/exec() for Linux? Do you remember beeing completely confused? I do, and it’s an ongoing pain in the ass for me – every time I want to call something simple without blocking and without worrying about pipes or the structure of exec()/execl()/execlp() parameters, or the return of the fork() call.

Finally I had enough and wrote my own CreateProcess function. It will seem trivial for any Linux C programmer, but in my experience it’s not simple enough. This or something like it should have been part of the standard library, just like printf() is.

Feel free to use it for whatever you want, minding the GPL v2 licence:

/******************************************************************************
*   CreateProcess
*
*   Copyright (C) 2010 Andrew Smith
*
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, version 2 of the License only, not
*   any earlier or later version.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/******************************************************************************
*  CreateProcess function: a simple way for Linux/Unix to call programs
* without blocking and without the complications of fork()/exec() which
* normal people shouldn't need to understand :)
*
*  Usage example:

#include "CreateProcess.h"

int main(void)
{
    // Call it like this:
    CreateProcess("ls", "-a -l --sort=size");

    // Or like this:
    CreateProcess("date", NULL);

    // Note that the second call does not wait for the first to finish
    // as system() would

    return 0;
}

* Enjoy!
* - Andrew Smith
*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>

pid_t CreateProcess(const char* command, const char* parametersIn)
{
    const int maxNumArgs = 1024;
    const char* args[maxNumArgs];
    char* parameters = NULL;

    memset(args, 0, (sizeof(char*) * maxNumArgs));
    args[0] = command;

    if(parametersIn != NULL)
    {
        parameters = strdup(parametersIn);
        int strLen = strlen(parameters);

        int numParameters = 1;
        bool expectNextParam = true;
        int i;
        for(i = 0; i < strLen; i++)
        {
            if(parameters[i] == ' ' || parameters[i] == '\t' ||
               parameters[i] == '\n')
            {
                expectNextParam = true;
                parameters[i] = '\0';
            }
            else if(expectNextParam)
            {
                args[numParameters] = &(parameters[i]);
                numParameters++;
                expectNextParam = false;
            }
        }
    }

    pid_t pid = fork();
    if(pid == 0)
    {
        execvp(command, (char**)args);
        _exit(1);
    }

    if(parameters != NULL)
        free(parameters);

    return pid;
}