How to check for already running program?


N

Nick Sinclair

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);

}
 
Ad

Advertisements

E

eriwik

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.
 
A

Alex Fraser

[snip]
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 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
 
S

SM Ryan

#
# > 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);
 
Ad

Advertisements

N

Nick Sinclair

#
# > 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);

Sweet.
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Top