Skip to content

Instantly share code, notes, and snippets.

@prasmussen
Created January 18, 2013 22:16
Show Gist options
  • Save prasmussen/4569123 to your computer and use it in GitHub Desktop.
Save prasmussen/4569123 to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#define CMD_OFFSET 2
#define MAX_CMD_LENGTH 2048
int strlen_total(char **str, int length) {
int i, total = 0;
for (i = 0; i < length; i++) {
total += strlen(str[i]);
}
return total;
}
void join(char *res, char **str, int length, char *sep) {
int i;
for (i = 0; i < length; i++) {
if (i > 0) {
strcat(res, sep);
}
strcat(res, str[i]);
}
}
int main(int argc, char **argv) {
if (argc <= CMD_OFFSET) {
fprintf(stderr, "%s ensures that only one instance of an application is running by creating an exclusive lockfile.\n\n", argv[0]);
fprintf(stderr, "Usage: %s <lockfile> <command> [arg ...]\n", argv[0]);
return 1;
}
// Grab name of lock file
char *lock_fname = argv[1];
// Grab a pointer to where the command starts - and the length
char **cmd = argv + CMD_OFFSET;
int length = argc - CMD_OFFSET;
// Calculate total length of the command, assuming there is a space after each argument (and \0 after the last argument)
int length_total = strlen_total(cmd, length) + length;
// Make sure that our buffer is large enough to hold the command
if (length_total > MAX_CMD_LENGTH) {
fprintf(stderr, "ERROR: Max command length is %d bytes, given command is %d bytes\n", MAX_CMD_LENGTH, length_total);
return 1;
}
// Build command string - separated by spaces
char cmd_str[MAX_CMD_LENGTH] = "";
join(cmd_str, cmd, length, " ");
// Try to create lockfile in exclusive mode (this is an atomic operation)
int lock_fd = open(lock_fname, O_CREAT|O_RDONLY|O_EXCL, 0600);
if (lock_fd == -1) {
fprintf(stderr, "ERROR: Failed to create exclusive lockfile: %s\n", lock_fname);
return 1;
}
// Execute command
int status = system(cmd_str);
if (status == -1) {
fprintf(stderr, "ERROR: Failed to execute command: '%s'\n", cmd_str);
}
// Delete lockfile
remove(lock_fname);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment