How to check for already running program?

Discussion in 'C Programming' started by Nick Sinclair, Jul 1, 2005.

  1. Hi all,
    I'm new to C.

    I have successfully written a small C program that acts as a "wrapper"
    around cgi scripts. These scripts perform admin tasks such as backing up
    etc. Obviously, The need for the "wrapper" was to get the scripts to run
    with "root" privileges. So far so good. I simply create a "URL shortcut"
    that some staff can double-click on to initiate the process.

    However, because I am creating these automated tasks for management staff
    of a company, I want to make sure that they don't go laucnching these tasks
    twice or similar (2 or more similtaneous backup processes to the same drive
    at the same time is not nice).

    I thought the bast way to address this was just to grab a "process listing"
    and use the available "regcomp and regexec" functions to check that there
    is not already and instance of the designated script running. If so, baulk
    and exit with a message.

    The thing I don't understand; is that when testing this, any attempts to
    run additional instances of the script using the c program don't work,
    because the "new instance" will wait until the old process finishes, and
    then start (which is not what I want).

    BTW: I call it like this
    http://some.internal.address/cgi-bin/nix_cgi_wrap?fw_backup.cgi

    Could someone please point me in the right direction?

    TIA


    /* This program was created to get around the problem */
    /* of having to do tasks that require root privileges */
    /* but aren't possible when run as a simple cgi script. */
    /* Set this binary to run suid and make sure it's owned */
    /* by root, and you're good to go. */
    /* Nick Sinclair 2005 GPL it's all yours. */

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <regex.h>
    #include <sys/types.h>
    #include <sys/wait.h>

    int main(int argc, char *argv[], int ac, char *av[]){

    /* Declare some variables */

    FILE *cgi_file;
    FILE *process_listing;

    char line[130];
    int counter = 0;

    pid_t pid;

    char *pattern = argv[1];

    int regex_result;
    regex_t re;

    /* Let's do some sanity checks on the cgi script name */

    /* Argument supplied at all? */

    if (argc==1)
    { printf("\nNo CGI script name supplied - Freaking out and
    exiting.\n\n");
    exit(172);
    }

    /* Too many arguments? */

    if (argc>2)
    { printf("\nToo many arguments supplied - Freaking out and
    exiting.\n\n");
    exit(172);
    }

    /* Does the file exist at all? */

    cgi_file = fopen(argv[1], "r");
    if (cgi_file==NULL)
    { printf("\nSupplied file cannot be read from or doesn't exist\n");
    printf(" - Freaking out and exiting -\n\n");
    exit(127);
    }

    /* Is the script already running - doh! */

    regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB);
    process_listing=popen("ps ax", "r");

    while ( fgets( line, sizeof line, process_listing))
    {
    regex_result=regexec(&re, line, (size_t) 0, NULL, 0);
    /* printf("Result = %d\n", regex_result); */

    if (regex_result==0)
    {
    /* printf("%s", line); */
    counter++;
    }

    }

    pclose(process_listing);
    regfree(&re);

    if (counter>1)
    {
    printf("Script already running! - Freaking out and exiting.\n\n");
    exit(172);
    }

    /* Set UID to 0 (root) */

    setuid(0);

    /* Now run the actual ".cgi" file */

    /* pid=getpid(); */
    execl("/usr/bin/bash", "bash", argv[1], (char *)0);

    }
     
    Nick Sinclair, Jul 1, 2005
    #1
    1. Advertisements

  2. Nick Sinclair

    eriwik Guest

    One quite simple way would be to open a socket at a specified port when
    the application starts. When the second instance starts and tries to
    open the same port it will fail. One has to take care however that no
    other application open the same port while the application is not
    running.

    A better way might be to create a appname.pid-file in /var/run/ when
    starting the application and check it one exists when starting. Problem
    with this is that if the application crashes before removing the the
    file can prevent it from starting again. To prevent this check the PID
    in the file and see if any running process has this PID.
     
    eriwik, Jul 1, 2005
    #2
    1. Advertisements

  3. Nick Sinclair

    Alex Fraser Guest

    [snip]
    I don't know of a reliable method within the scope of ANSI C, the topic of
    this newsgroup. On Unix systems, file locking can be used for mutual
    exclusion - you should ask about this in a platform-specific newsgroup,
    perhaps
    Also, you need to be particularly wary of security issues when you expose a
    means to invoke processes as root. Again, off-topic for this newsgroup.

    Alex
     
    Alex Fraser, Jul 1, 2005
    #3
  4. Nick Sinclair

    SM Ryan Guest

    #
    # > However, because I am creating these automated tasks for management staff
    # > of a company, I want to make sure that they don't go laucnching these
    # > tasks twice or similar (2 or more similtaneous backup processes to the
    # > same drive at the same time is not nice).

    Decide on some specific file path in the system.
    int fd = open(path,O_WRONLY|O_CREAT,0600);
    int rc = flock(fd,LOCK_EX|LOCK_NB);

    If rc==-1, another process is already in the critical section.

    If rc==0, this process has acquired the lock. If the process exits
    for any reason, the lock is released by the kernel. The process can
    also exit the critical section with
    flock(fd,LOCK_UN);
     
    SM Ryan, Jul 1, 2005
    #4
  5. Sweet.
     
    Nick Sinclair, Jul 4, 2005
    #5
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.