/////////////////////////////////////////////////////////////////////////////
// Name: eviacamloader.c
// Purpose:
// Author: Cesar Mauri Loba (cesar at crea-si dot com)
// Modified by:
// Created: 09/06/2010
// Copyright: (C) 2010 Cesar Mauri Loba - CREA Software Systems
//
// 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, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
/////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include
#include
#include
/* check wait status to see if child process finished abnormaly */
int wait_status_correct (int status)
{
/* Doesn't take into account an abnormal exit status. Usually it means that eviacam has
finished due to a fatal error (e.g. camera not found or cancelled by the user) */
/*
if (WEXITSTATUS(status)!= 0) {
fprintf (stderr, "process finished abnormally. exit status: %d\n", WEXITSTATUS(status));
return 0;
}*/
if (WIFSIGNALED(status)) {
if (WCOREDUMP(status)) {
fprintf (stderr, "process finished abnormally. core dumped\n");
return 0;
}
int signum= WTERMSIG(status);
if (signum== SIGSEGV) {
fprintf (stderr, "process finished abnormally. segmentation fault\n");
return 0;
}
if (signum== SIGBUS) {
fprintf (stderr, "process finished abnormally. bus error\n");
return 0;
}
}
return 1;
}
int main (int argc, char **argv)
{
#ifndef NDEBUG
printf ("Use: %d, Group: %d. Eff. usr: %d, Eff. group: %d\n", getuid(), getgid(), geteuid(), getegid());
#endif
if (geteuid()== 0) {
/* running as root, change priority */
if (nice(-11)== -1) {
perror("nice");
return -1;
}
/* privileges revocation */
if (setgid (getgid())== -1 || setuid (getuid())== -1) {
perror("setgid/setuid");
return -1;
}
}
else
fprintf (stderr, "%s: this program needs root privileges. not renicing.\n", argv[0]);
/* run eviacam until normal exit */
for (;;) {
/* create child process to run eviacam */
pid_t pid= fork();
if (pid== -1) {
perror ("fork");
return -1;
}
else if (pid== 0) {
/* child process */
/*
workaround to enable sound on systems with pulseaudio
see [1] for more details
[1] https://sourceforge.net/tracker/?func=detail&aid=3095561&group_id=248049&atid=1199422
TODO: remove when this gets fixed
*/
/* check is padsp command can be run */
int padsp_command_available= 0;
struct stat stat_buf;
if (!stat("/usr/bin/padsp", &stat_buf)) padsp_command_available++;
if (padsp_command_available) {
if (execl ("/usr/bin/padsp", "eviacam", "/usr/local/bin/eviacam", NULL)== -1) {
perror("execl");
return -1;
}
}
else {
if (execl ("/usr/local/bin/eviacam", "eviacam", NULL)== -1) {
perror("execl");
return -1;
}
}
}
else
{
/* parent process */
int status;
if (wait(&status)== -1) {
perror ("wait");
return -1;
}
/* check whether the child process finished abnormaly */
if (!wait_status_correct(status)) {
fprintf (stderr, "%s: abnormal process termination, restarting\n", argv[0]);
sleep (1);
}
else break;
}
}
#ifndef NDEBUG
printf ("Use: %d, Group: %d. Eff. usr: %d, Eff. group: %d\n", getuid(), getgid(), geteuid(), getegid());
#endif
return 0;
}