///////////////////////////////////////////////////////////////////////////// // 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; }