/* #Specification: pppwatch / principle To handle dedicated ppp connection (24/24 7/7), the utility pppwatch is called. It receives minimally two arguments. The first is the path of a control file and the others are the command and argument of a command used to establish a PPP link. Normally pppwatch is called this way # pppwatch /var/run/ppprestart.config netconf --connect config --fore # The control file is created by pppwatch. It executes the command until this file is erased (by anyone or linuxconf). For example to terminate a PPP connection, you would do # rm /var/run/ppprestart.config netconf --disconnect config # But netconf does it for you. pppwatch is very simple and could be written as a script. For efficiency (use much less memory), it is written in C++. Here is a sample script showing what it does # #!/bin/sh if [ $# = 0 ] ; then echo pppwatch control_file ppp connection command and args else ctrl=$1 shift touch $ctrl while [ -f $ctrl ] do $* done fi # Note that the pppwatch utility is called directly by linuxconf but the effective path may be overriden by the admin. The above script might be use as a start to customise this process, if needed. The control file is created as a symbolic link. The link simply hold the process ID of the current pppwatch. This is used to avoid some race condition where two pppwatch would be started for the same PPP configuration. */ #include #include #include #include #include #include #include #include #include #include /* Check if a PID file exist and the related process is running. */ static bool pppwatch_alive (const char *control) { bool ret = false; char path[PATH_MAX]; int nb = readlink(control,path,PATH_MAX); if (nb > 0){ path[nb] = '\0'; int pid = atoi (path); if (kill (pid,0)!=-1){ ret = true; } } return ret; } int main (int argc, char *argv[]) { int ret = -1; if (argc < 3){ fprintf (stderr,"pppwatch control_file command ...\n"); }else{ const char *control = argv[1]; if (pppwatch_alive(control)){ fprintf (stderr,"Another pppwatch is running for that PPP configuration\n"); }else{ signal (SIGCHLD,SIG_DFL); if (fork()==0){ char pidstr[20]; sprintf (pidstr,"%d",getpid()); unlink (control); if (symlink (pidstr,control)==-1){ fprintf (stderr,"Can't create control file %s (%s)\n" ,control,strerror(errno)); }else{ ret = 0; while (1){ // Make sure the control file is still there struct stat st; if (lstat(control,&st)==-1) break; pid_t pid = fork(); if (pid == 0){ execv (argv[2],(char **)argv+2); _exit (-1); }else if (pid == -1){ break; }else{ while (1){ int status; pid_t p = wait (&status); if (p == pid || p == -1) break; } } } _exit (0); } } } } return ret; }