static char * plugin_get_hostname (SCPluginIfcfg *plugin) { shvarFile *network; char *hostname; gboolean ignore_localhost; if (g_file_get_contents (HOSTNAME_FILE, &hostname, NULL, NULL)) { g_strchomp (hostname); return hostname; } network = svOpenFile (SC_NETWORK_FILE, NULL); if (!network) { _LOGW ("Could not get hostname: failed to read " SC_NETWORK_FILE); return NULL; } hostname = svGetValue (network, "HOSTNAME", FALSE); ignore_localhost = svTrueValue (network, "NM_IGNORE_HOSTNAME_LOCALHOST", FALSE); if (ignore_localhost) { /* Ignore a default hostname ('localhost[6]' or 'localhost[6].localdomain[6]') * to preserve 'network' service behavior. */ if (hostname && !nm_utils_is_specific_hostname (hostname)) { g_free (hostname); hostname = NULL; } } svCloseFile (network); return hostname; }
int main(int argc, char **argv) { int status; pid_t waited; char *device, *real_device, *physicalDevice = NULL; char *boot = NULL; shvarFile *ifcfg; sigset_t blockedsigs, unblockedsigs; int pppdPid = 0; int timeout = 30; char *temp; gboolean dying = FALSE; int sendsig; gboolean connectedOnce = FALSE; int maxfail = 0; // MAXFAIL Patch <*****@*****.**> if (argc < 2) { fprintf (stderr, "usage: ppp-watch <interface-name> [boot]\n"); exit(30); } if (strncmp(argv[1], "ifcfg-", 6) == 0) { device = argv[1] + 6; } else { device = argv[1]; } detach(device); /* Prepare a child process to monitor pppd. When we return, we'll be in the child. */ if ((argc > 2) && (strcmp("boot", argv[2]) == 0)) { boot = argv[2]; } ifcfg = shvarfilesGet(device); if (ifcfg == NULL) failureExit(28); real_device = svGetValue(ifcfg, "DEVICE"); if (real_device == NULL) real_device = device; doPidFile(real_device); /* We'll want to know which signal interrupted our sleep below, so * attach a signal handler to these. */ set_signal(SIGTERM, signal_tracker); set_signal(SIGINT, signal_tracker); set_signal(SIGHUP, signal_tracker); set_signal(SIGIO, signal_tracker); set_signal(SIGCHLD, signal_tracker); /* We time out only if we're being run at boot-time. */ if (boot) { temp = svGetValue(ifcfg, "BOOTTIMEOUT"); if (temp) { timeout = atoi(temp); if (timeout < 1) timeout = 1; free(temp); } else { timeout = 30; } set_signal(SIGALRM, signal_tracker); alarm(timeout); } /* Register us to get a signal when something changes. Yes, that's vague. */ fork_exec(TRUE, "/sbin/netreport", NULL, NULL, NULL); /* Reset theSigchld, which should have been triggered by netreport. */ theSigchld = 0; /* We don't set up the procmask until after we have received the netreport * signal. Do so now. */ sigemptyset(&blockedsigs); sigaddset(&blockedsigs, SIGTERM); sigaddset(&blockedsigs, SIGINT); sigaddset(&blockedsigs, SIGHUP); sigaddset(&blockedsigs, SIGIO); sigaddset(&blockedsigs, SIGCHLD); if (boot) { sigaddset(&blockedsigs, SIGALRM); } sigprocmask(SIG_BLOCK, &blockedsigs, NULL); sigfillset(&unblockedsigs); sigdelset(&unblockedsigs, SIGTERM); sigdelset(&unblockedsigs, SIGINT); sigdelset(&unblockedsigs, SIGHUP); sigdelset(&unblockedsigs, SIGIO); sigdelset(&unblockedsigs, SIGCHLD); if (boot) { sigdelset(&unblockedsigs, SIGALRM); } sigprocmask(SIG_UNBLOCK, &unblockedsigs, NULL); /* Initialize the retry timeout using the RETRYTIMEOUT setting. */ temp = svGetValue(ifcfg, "RETRYTIMEOUT"); if (temp) { timeout = atoi(temp); free(temp); } else { timeout = 30; } /* Start trying to bring the interface up. */ fork_exec(FALSE, IFUP_PPP, "daemon", device, boot); while (TRUE) { /* Wait for a signal. */ if (!theSigterm && !theSigint && !theSighup && !theSigio && !theSigchld && !theSigalrm) { sigsuspend(&unblockedsigs); } /* If we got SIGTERM or SIGINT, give up and hang up. */ if (theSigterm || theSigint) { theSigterm = theSigint = 0; /* If we've already tried to exit this way, use SIGKILL instead * of SIGTERM, because pppd's just being stubborn. */ if (dying) { sendsig = SIGKILL; } else { sendsig = SIGTERM; } dying = TRUE; /* Get the pid of our child pppd. */ pppLogicalToPhysical(&pppdPid, device, NULL); /* We don't know what our child pid is. This is very confusing. */ if (!pppdPid) { failureExit(35); } /* Die, pppd, die. */ kill(pppdPid, sendsig); if (sendsig == SIGKILL) { kill(-pppdPid, SIGTERM); /* Give it a chance to die nicely, then kill its whole process group. */ usleep(2500000); kill(-pppdPid, sendsig); hangup(ifcfg); failureExit(32); } } /* If we got SIGHUP, reload and redial. */ if (theSighup) { theSighup = 0; /* Free and reload the configuration structure. */ if (ifcfg->parent) svCloseFile(ifcfg->parent); svCloseFile(ifcfg); ifcfg = shvarfilesGet(device); /* Get the PID of our child pppd. */ pppLogicalToPhysical(&pppdPid, device, NULL); kill(pppdPid, SIGTERM); /* We'll redial when the SIGCHLD arrives, even if PERSIST is * not set (the latter handled by clearing the "we've connected * at least once" flag). */ connectedOnce = FALSE; /* We don't want to delay before redialing, either, so cut * the retry timeout to zero. */ timeout = 0; } /* If we got a SIGIO (from netreport, presumably), check if the * interface is up and return zero (via our parent) if it is. */ if (theSigio) { theSigio = 0; pppLogicalToPhysical(NULL, device, &physicalDevice); if (physicalDevice) { if (interfaceIsUp(physicalDevice)) { /* The interface is up, so report a success to a parent if * we have one. Any errors after this we just swallow. */ relay_exitcode(0); connectedOnce = TRUE; alarm(0); } free(physicalDevice); } } /* If we got a SIGCHLD, then pppd died (possibly because we killed it), * and we need to restart it after timeout seconds. */ if (theSigchld) { theSigchld = 0; /* Find its pid, which is also its process group ID. */ waited = waitpid(-1, &status, 0); if (waited == -1) { continue; } /* Now, we need to kill any children of pppd still in pppd's * process group, in case they are hanging around. * pppd is dead (we just waited for it) but there is no * guarantee that its children are dead, and they will * hold the modem if we do not get rid of them. * We have kept the old pid/pgrp around in pppdPid. */ if (pppdPid) { kill(-pppdPid, SIGTERM); /* give it a chance to die nicely */ usleep(2500000); kill(-pppdPid, SIGKILL); hangup(ifcfg); } pppdPid = 0; /* Bail if the child exitted abnormally or we were already * signalled to kill it. */ if (!WIFEXITED(status)) { failureExit(29); } if (dying) { failureExit(WEXITSTATUS(status)); } /* Error conditions from which we do not expect to recover * without user intervention -- do not fill up the logs. */ switch (WEXITSTATUS(status)) { case 1: case 2: case 3: case 4: case 6: case 7: case 9: case 14: case 17: failureExit(WEXITSTATUS(status)); break; default: break; } /* PGB 08/20/02: We no longer retry connecting MAXFAIL times on a failed connect script unless RETRYCONNECT is true. */ if ((WEXITSTATUS(status) == 8) && !svTrueValue(ifcfg, "RETRYCONNECT", FALSE)) { failureExit(WEXITSTATUS(status)); } /* If we've never connected, or PERSIST is set, dial again, up * to MAXFAIL times. */ if ((WEXITSTATUS(status) == 8) || !connectedOnce || svTrueValue(ifcfg, "PERSIST", FALSE)) { /* If we've been connected (i.e., if we didn't force a redial, * but the connection went down) wait for DISCONNECTTIMEOUT * seconds before redialing. */ if (connectedOnce) { connectedOnce = FALSE; temp = svGetValue(ifcfg, "DISCONNECTTIMEOUT"); if (temp) { timeout = atoi(temp); free(temp); } else { timeout = 2; } } sigprocmask(SIG_UNBLOCK, &blockedsigs, NULL); sleep(timeout); sigprocmask(SIG_BLOCK, &blockedsigs, NULL); if (!theSigterm && !theSigint && !theSighup && !theSigio && !theSigchld && !theSigalrm) { fork_exec(FALSE, IFUP_PPP, "daemon", device, boot); } /* Reinitialize the retry timeout. */ temp = svGetValue(ifcfg, "RETRYTIMEOUT"); if (temp) { timeout = atoi(temp); free(temp); } else { timeout = 30; } // Scott Sharkey <*****@*****.**> // MAXFAIL Patch... temp = svGetValue(ifcfg, "MAXFAIL"); if (temp) { maxfail = atoi(temp); free(temp); } else { maxfail = 0; } if ( maxfail != 0 ) { dialCount++; if ( dialCount >= maxfail ) failureExit(WEXITSTATUS(status)); } } else { failureExit(WEXITSTATUS(status)); } } /* We timed out, and we're running at boot-time. */ if (theSigalrm) { failureExit(34); } } }