head 1.3; access; symbols; locks alexis:1.3; strict; comment @ * @; 1.3 date 97.01.31.14.43.34; author alexis; state Exp; branches; next 1.2; 1.2 date 97.01.31.10.22.48; author alexis; state Exp; branches; next 1.1; 1.1 date 97.01.22.10.34.43; author alexis; state Exp; branches; next ; desc @@ 1.3 log @MILEPOST - MAY NOT WORK @ text @#define MAIN static char *rcs_id = "$Id$"; /* * System includes with reasons */ #include #include /* for printf and NULL */ #include /* for strrchr(), strtok() */ #include /* for SIGINT, SIG_IGN etc */ #include /* for wait() par types */ #include /* for time() */ #include /* for stat() */ #include /* for stat() */ /* * Local includes with reasons */ #include "pppld_msgids.h" /* for interprocess message codes */ #include "pppld_utils.h" /* for basename(), and various error fncs */ #include "pppld_ipc.h" /* for forward refs */ #include "pppld.h" /* for delayq definitions */ #include "patchlevel.h" /* * Local defines */ #define TRUE (0 == 0) #define FALSE (0 != 0) #define MSGSZ 128 #define DELAYQ_SIZ 8 #define LOCK_DIR "/tmp" #define PPPD_LOCK_FILE "/var/run/ppp0.pid" #define MASTER_CONFIG_FILE "master.cfg" /* * Forward refs for functions defined externally */ /* * Forward refs for static functions */ extern int mhf_exec_pppd(); extern int mhf_got_good_conn(); extern int mhf_ok_pppd(); extern int mhf_nok_pppd(); extern int mhf_set_quit(); extern int mhf_set_donews(); extern int mhf_set_idlecheck(); extern int mhf_set_qualitycheck_interval(int *); extern int mhf_unset_donews(); extern int mhf_unset_idlecheck(); extern int mhf_unset_qualitycheck_interval(); extern int mhf_exec_ipup(); extern int mhf_hangup(); extern int mhf_exec_qtest(); extern int mhf_ok_qtest(); extern int mhf_nok_qtest(); extern int mhf_exec_sndmail(); extern int mhf_ok_sndmail(); extern int mhf_nok_sndmail(); extern int mhf_exec_sndnews(); extern int mhf_ok_sndnews(); extern int mhf_nok_sndnews(); extern int mhf_exec_getmail(); extern int mhf_ok_getmail(); extern int mhf_nok_getmail(); extern int mhf_exec_getnews(); extern int mhf_ok_getnews(); extern int mhf_nok_getnews(); extern int mhf_exec_idle(); extern int mhf_ok_idle(); extern int mhf_nok_idle(); extern int mhf_noaction(); extern int mhf_exec_ipdown(); extern int mhf_redial(); extern int mhf_info(); extern int mhf_load_config(); extern int mhf_set_debug(); static int make_lock(int); static int unmake_lock(void); void sigalrm_handler(int); int delaysendmsg(time_t, int, int *); /* * Global variables - config related data */ char pppd_cmd[128]; char chat_cmd[128]; char announce_cmd[128]; char port[16]; char netmask[32]; int speed; char login[16]; char password[16]; char telno[32]; char chatfile[64]; char qualitycheck_remhost[32]; int qualitycheck_interval; int qualitycheck_minquality; int idlecheck_interval; int idlecheck_timeout; /* * Global variables - state data */ int state_curr; /* are we connected right now? */ int state_cfgok; int state_want; /* do we want to be connected? */ int state_done; /* have we been connected? */ int state_inipup; /* are we running post connection sequence? */ int state_donenx; /* used to assess if ipup is finished */ int state_donemx; /* used to assess if ipup is finished */ int state_quit; /* * Global data - the delayed message queue */ struct delaymsgrec delayq[DELAYQ_SIZ]; /* for delayed messages and activation times */ int delayq_top; /* how many elements in that array? */ /* * Global data - server message handling function lookup table */ struct mhflkuprec svrmhflkupdat[] = { { MSGID_EXEC_PPPD, mhf_exec_pppd }, { MSGID_OK_PPPD, mhf_ok_pppd }, { MSGID_NOK_PPPD, mhf_nok_pppd }, { MSGID_SET_QUIT, mhf_set_quit }, { MSGID_EXEC_IPUP, mhf_exec_ipup }, { MSGID_HANGUP, mhf_hangup }, { MSGID_REDIAL, mhf_redial }, { MSGID_EXEC_QTEST, mhf_exec_qtest }, { MSGID_OK_QTEST, mhf_ok_qtest }, { MSGID_NOK_QTEST, mhf_nok_qtest }, { MSGID_EXEC_SNDMAIL, mhf_exec_sndmail }, { MSGID_OK_SNDMAIL, mhf_ok_sndmail }, { MSGID_NOK_SNDMAIL, mhf_nok_sndmail }, { MSGID_EXEC_SNDNEWS, mhf_exec_sndnews }, { MSGID_OK_SNDNEWS, mhf_ok_sndnews }, { MSGID_NOK_SNDNEWS, mhf_nok_sndnews }, { MSGID_EXEC_GETMAIL, mhf_exec_getmail }, { MSGID_OK_GETMAIL, mhf_ok_getmail }, { MSGID_NOK_GETMAIL, mhf_nok_getmail }, { MSGID_EXEC_GETNEWS, mhf_exec_getnews }, { MSGID_OK_GETNEWS, mhf_ok_getnews }, { MSGID_NOK_GETNEWS, mhf_nok_getnews }, { MSGID_EXEC_IDLECHECK, mhf_exec_idle }, { MSGID_OK_IDLECHECK, mhf_ok_idle }, { MSGID_NOK_IDLECHECK, mhf_nok_idle }, { MSGID_EXEC_IPDOWN, mhf_exec_ipdown }, { MSGID_NOACTION, mhf_noaction }, { MSGID_INFO, mhf_info }, { MSGID_SET_QUALITYCHECK, mhf_set_qualitycheck_interval }, { MSGID_SET_DEBUG, mhf_set_debug }, { MSGID_SET_DONEWS, mhf_set_donews }, { MSGID_SET_IDLECHECK, mhf_set_idlecheck }, { MSGID_UNSET_QUALITYCHECK, mhf_unset_qualitycheck_interval }, { MSGID_UNSET_DONEWS, mhf_unset_donews }, { MSGID_LOAD_CONFIG, mhf_load_config }, { MSGID_UNSET_IDLECHECK, mhf_unset_idlecheck } }; int do_xfer_news_flag; extern struct msginfrec svrmsginfdat[]; /* * Functions! */ void sigint_handler( int unknown) { debug(DBG_FUNCS, "sigint_handler: sof"); info("exiting on SIGINT"); if (state_cfgok) unlink(chatfile); unmake_lock(); exit(0); } void sigterm_handler( int unknown) { debug(DBG_FUNCS, "sigterm_handler: sof"); info("exiting on SIGTERM"); if (state_cfgok) unlink(chatfile); unmake_lock(); exit(0); } void sigchld_handler( int unknown) { signal(SIGCHLD, SIG_IGN); debug(DBG_FUNCS, "sigchld_handler: sof"); wait(NULL); debug(DBG_SIGS, "sigchld_handler: done wait()"); signal(SIGCHLD, sigchld_handler); } int make_lock( int attempt) { char lock_file[128]; char tmp_lock_file[128]; int locking_pid; FILE *fp; struct stat statbuf; char procbuf[16]; debug(DBG_FUNCS, "make_lock: sof"); if (attempt >= 2) return(1); sprintf(lock_file, "%s/%s.pid", LOCK_DIR, progname); sprintf(tmp_lock_file, "%s/%s.pid.%d", LOCK_DIR, progname, getpid()); /* create temporary lock_file */ if ((fp=fopen(tmp_lock_file, "w")) == (FILE *) NULL) { perror("fopen (1)"); exit(1); } fprintf(fp, "%d\n", getpid()); fclose(fp); /* slide lock into place */ if (link(tmp_lock_file, lock_file) == 0) { unlink(tmp_lock_file); return(0); } /* if blocked examine the existing lock */ if ((fp=fopen(lock_file, "r")) == (FILE *) NULL) { perror("fopen (2)"); exit(1); } if (fscanf(fp, "%d", &locking_pid) != 1) { perror("fscanf"); exit(1); } fclose(fp); /* assume locks are stale - horrible on Suns */ sprintf(procbuf, "/proc/%d", locking_pid); if (stat(procbuf, &statbuf) == 0) { info("locked already (pid=%d)", locking_pid); return(1); } info("stale lock %s removed (pid=%d)", lock_file, locking_pid); unlink(lock_file); return(make_lock(attempt+1)); } int unmake_lock() { char lock_file[128]; debug(DBG_FUNCS, "unmake_lock: sof"); sprintf(lock_file, "%s/%s.pid", LOCK_DIR, progname); unlink(lock_file); } int kill_pppd() { FILE *fp; int pppd_pid; debug(DBG_FUNCS, "kill_pppd: sof"); if ((fp=fopen(PPPD_LOCK_FILE, "r")) == NULL) { warning("pppd appears not to be running"); return(1); } fscanf(fp, "%d", &pppd_pid); fclose(fp); printf("%s: sending process %d signal 15\n", progname, pppd_pid); return(kill(pppd_pid, 15)); } usage() { debug(DBG_FUNCS, "usage: sof"); fprintf(stderr, "Usage: %s\n", progname); exit(1); } main( int argc, char *argv[]) { pid_t pid; int msgidx; int msgid; int detach_flag; char buf[MAX_MSG_SIZ]; int par; progname = basename(argv[0]); delayq_top = 0; /* debug_level = 5; */ do_xfer_news_flag = 1; detach_flag = 1; while (argc>1 && argv[1][0] == '-') { if (strcmp(argv[1], "-nn") == 0) do_xfer_news_flag = 0; else if (strcmp(argv[1], "-nf") == 0) detach_flag = 0; else if (strcmp(argv[1], "-d") == 0) { (argc<3 || sscanf(argv[2], "%ld", &debug_level)!=1) && usage(); argc--; argv++; } else usage(); argv++; argc--; } if (argc != 1) usage(); fork() && exit(0); debug(DBG_LOCKS, "main: before make_lock"); if (make_lock(0) != 0) error("locking problem"); pppld_ipc_server_shutdown(); if (pppld_ipc_server_init()) { unmake_lock(); exit(1); } /* * The server should reap zombies but not be bothered about return codes, * which will be handled by the wrapper. INT and TERM should be handled * gracefully. */ debug(DBG_SIGS, "main: setting up signal handlers"); signal(SIGCHLD, sigchld_handler); signal(SIGINT, sigint_handler); signal(SIGTERM, sigterm_handler); /* * The current state could be ascertained rather than assumed?, and the * others derived from it, this would allow the server at least to be * killed and restarted while pppd is running would that be useful? */ state_curr = 0; state_cfgok = 0; state_want = 0; state_done = 0; state_inipup = 0; state_quit = 0; /* * Load config files, though failure to do so is not a terminal error. * We just note the return code and prevent pppd being run if it fails. * The user may have another go at loading it up again later. */ state_cfgok = load_config(MASTER_CONFIG_FILE, 0) ? 0 : 1; /* * Main loop. Just read messages and call handler functions until either * the quit flag is set or there is a message read error. */ info("ready"); while (!state_quit) { if ((argc=pppld_ipc_read_msg(svrmsginfdat, MSGTO_SVR, svrmhflkupdat)) < 0) { if (state_cfgok) unlink(chatfile); unmake_lock(); exit(1); } } /* * Graceful exit code */ pppld_ipc_server_shutdown(); if (state_cfgok) unlink(chatfile); unmake_lock(); exit(0); } forkandsend( char *cmdstr, int okmsgid, int nokmsgid) { int pid; /* used to hold process ids temporarily */ int cmdrc; /* return code of the exec'd command */ int statsup; /* for ascertaining the exit code of the exec'd program */ int old_statsup; /* for ascertaining the exit code of the exec'd program */ int inquotes, inword, moveon; char *argv[64]; int i; char *cp; debug(DBG_FUNCS, "forkandsend: sof"); /* * Let the server go on with what it was doing - possibly dealing with * more messages and signals. */ if ((pid=fork()) < 0) { perror("fork"); } else if (pid > 0) { debug(DBG_EXECS, "forkandsend-caller: returning straight away after successful fork"); return; } /* * Wrapper signal handlers are a bit different to normal. INT and QUIT * are ignored in order to ensure that the OK/NOK message will get issued * signalling that the wrapped program has exited. And CHLD is waited * for. Can't remember why I can't just ignore it - maybe because I do * want to wait for the child. */ signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGCHLD, SIG_DFL); debug(DBG_EXECS, "forkandsend-wrapper: running (pid=%d), about to fork and wait", getpid()); if ((pid=fork()) < 0) { perror("fork"); } else if (pid == 0) { /* * The wrapped process should use default handlers, as it it were * being run from the shell. */ signal(SIGTERM, SIG_DFL); signal(SIGINT, SIG_DFL); debug(DBG_SPECIAL1, "forkandsend-execer: processing command string: %s", cmdstr); inword=0; inquotes=0; moveon=1; for (i=0,cp=cmdstr; *cp; moveon && cp++) { moveon = 1; /* *after* quotes we're always in a word */ if (!inword && inquotes) { debug(DBG_SPECIAL1, "quoted start of word [%s]", cp); argv[i++] = cp; inword = 1; /* start of normal word */ } else if (!inword && *cp != ' ' && *cp != '\t' && *cp != '"') { debug(DBG_SPECIAL1, "unquoted start of word [%s]", cp); argv[i++] = cp; inword = 1; /* encountering quaotes while not in a word, means the next char is the start of a word - left to be picked up next time round */ } else if (!inquotes && *cp == '"') { debug(DBG_SPECIAL1, "opening quotes while not in word ... [%s]", cp); inquotes = 1; /* but we do need to shuffle everything after this up one */ strmove(cp, cp+1); debug(DBG_SPECIAL1, "... shuffled up [%s]", cp); moveon = 0; /* normal end of word */ } else if (!inquotes && (*cp == ' ' || *cp == '\t')) { debug(DBG_SPECIAL1, "unquoted end of word [%s]", cp); *cp = '\0'; inword = 0; /* encountering end quotes does not mean end of word ("hell"o) */ } else if (inquotes && *cp == '"') { debug(DBG_SPECIAL1, "closing quotes ... [%s]", cp); inquotes = 0; /* *cp = '\0'; */ inword = 0; /* but we do need to shuffle everything after this up one */ strmove(cp, cp+1); debug(DBG_SPECIAL1, "... shuffled up [%s]", cp); moveon = 0; } sleep(1); } argv[i] = NULL; argv[0] = basename(argv[0]); for (i=0; argv[i]!=NULL; i++) debug(DBG_SPECIAL1, "forkandsend: argv[%d] = %s", i, argv[i]); execv(cmdstr, argv); perror("exec"); exit(1); } debug(DBG_SIGS, "forkandsend-wrapper: waiting for all children"); old_statsup = -1; while (wait(&statsup) != -1) { debug(DBG_SIGS, "forkandsend-wrapper: caught a child with wait"); old_statsup = statsup; } debug(DBG_SIGS, "forkandsend-wrapper: done waiting for all children"); if (old_statsup == -1) internal("(%s,%d)", __FILE__, __LINE__); else if (old_statsup & 0x7f == 0x7f) debug(DBG_SIGS, "child stopped on signal %d", old_statsup >> 8); else if (old_statsup & 0x7f) debug(DBG_SIGS, "child exited on signal %d", old_statsup & 0x7f); else { cmdrc = old_statsup >> 8; debug(DBG_EXECS, "child exited with exit %d", cmdrc); } pppld_ipc_send_msg(svrmsginfdat, MSGTO_SVR, (cmdrc == 0) ? okmsgid : nokmsgid, NULL); exit(0); } delaysendmsg( time_t dotime, int msgid, int *parp) { int i, j; time_t tmptime; int *tmpparp; int tmpid; int tmpen; time_t interval; /* we don't really want to be messing with the queue and get interrupted */ signal(SIGALRM, SIG_IGN); debug(DBG_FUNCS, "delaysendmsg: sof"); if (delayq_top == DELAYQ_SIZ) error("delay queue is full!"); delayq[delayq_top].time = dotime; delayq[delayq_top].id = msgid; delayq[delayq_top].en = 1; delayq[delayq_top].parp = parp; delayq_top++; debug(DBG_DELAYQ, "delaysendmsg: added (%ld,%d)", dotime, msgid); for (i=0; i delayq[j+1].time) { tmptime = delayq[j].time; delayq[j].time = delayq[j+1].time; delayq[j+1].time = tmptime; tmpparp = delayq[j].parp; delayq[j].parp = delayq[j+1].parp; delayq[j+1].parp = tmpparp; tmpid = delayq[j].id; delayq[j].id = delayq[j+1].id; delayq[j+1].id = tmpid; tmpen = delayq[j].en; delayq[j].en = delayq[j+1].en; delayq[j+1].en = tmpen; } } } for (i=0; i 0 && time(NULL) >= delayq[0].time) { if (delayq[0].en) { debug(DBG_DELAYQ, "sigalrm_handler: now sending delayed message %d", delayq[0].id); pppld_ipc_send_msg(svrmsginfdat, MSGTO_SVR, delayq[0].id, delayq[0].parp); if (delayq[0].parp != NULL) free(delayq[0].parp); } else debug(DBG_DELAYQ, "sigalrm_handler: dequeueing a disabled item"); for (i=0; i 0) { debug(DBG_DELAYQ|DBG_SIGS, "sigalrm_handler: resetting alarm"); signal(SIGALRM, sigalrm_handler); alarm(delayq[0].time - time(NULL)); } else { /* don't bother setting the signal handler, or the alarm - there is no alarm to set, and delaymsgsend() will set the handler next time */ debug(DBG_DELAYQ, "sigalrm_handler: queue now empty"); } } @ 1.2 log @WORKING MILESTONE @ text @d1 3 d24 2 a35 6 #define REASON_UP 0 #define REASON_QUALITY 1 #define REASON_IDLE 2 #define REASON_HANGUP 3 #define REASON_REDIAL 4 a41 17 #define QTEST_CMD "/home/alexis/dev/ppp/qtest" #define SNDMAIL_CMD "/home/alexis/dev/ppp/sndmail" #define GETMAIL_CMD "/home/alexis/dev/ppp/getmail" #define SNDNEWS_CMD "/home/alexis/dev/ppp/sndnews" #define GETNEWS_CMD "/home/alexis/dev/ppp/getnews" /* * Structure and type definitions */ struct delaymsgrec { time_t time; /* dequeue time */ int id; /* message id */ int en; /* flag to indicate if enabled */ int *parp; }; d50 37 a86 36 int mhf_exec_pppd(); int mhf_got_good_conn(); int mhf_ok_pppd(); int mhf_nok_pppd(); int mhf_set_quit(); int mhf_set_donews(); int mhf_set_idlecheck(); int mhf_set_qualitycheck_interval(int *); int mhf_unset_donews(); int mhf_unset_idlecheck(); int mhf_unset_qualitycheck_interval(); int mhf_exec_ipup(); int mhf_hangup(); int mhf_exec_qtest(); int mhf_ok_qtest(); int mhf_nok_qtest(); int mhf_exec_sndmail(); int mhf_ok_sndmail(); int mhf_nok_sndmail(); int mhf_exec_sndnews(); int mhf_ok_sndnews(); int mhf_nok_sndnews(); int mhf_exec_getmail(); int mhf_ok_getmail(); int mhf_nok_getmail(); int mhf_exec_getnews(); int mhf_ok_getnews(); int mhf_nok_getnews(); int mhf_exec_idle(); int mhf_ok_idle(); int mhf_nok_idle(); int mhf_noaction(); int mhf_exec_ipdown(); int mhf_redial(); int mhf_info(); int mhf_load_config(); d94 1 d127 2 a128 2 int state_donenx; /* used to assess if ipup is finished */ int state_donemx; /* used to assess if ipup is finished */ a131 7 * Global data - idle check info */ int idlecheck_oldusecnt = -1; unsigned long idlecheck_oldusetim = 0; /* d172 1 a180 1 int reason_down; d192 1 d202 1 d212 4 a216 3 debug(DBG_SIGS, "sigchld_handler: waiting ..."); wait(NULL); debug(DBG_SIGS, "sigchld_handler: waiting done"); d229 1 d276 2 a278 1 d287 2 d291 1 a291 1 return; a292 1 d295 1 d297 1 a297 1 kill(pppd_pid, 15); d302 2 d322 2 a323 1 debug_level = 5; d334 1 a334 1 (argc<3 || sscanf(argv[2], "%d", &debug_level)!=1) && usage(); d347 2 d350 1 a350 3 if (make_lock(0) != 0) { debug(DBG_LOCKS, "locking problem"); a351 2 exit(1); } d359 5 a363 1 debug(DBG_SIGS, "main: before signal setup"); d365 2 a368 3 /* the server should reap zombies but not be bothered about return codes, which will be handled by the wrapper */ signal(SIGCHLD, sigchld_handler); d370 5 a374 3 /* the current state could be ascertained rather than assumed?, and the others derived from it */ /* this would allow the server at least to be killed and restarted while pppd is running */ /* would that be useful? */ d383 6 a388 1 /* load config files - and derive a few other things */ d391 5 a396 1 d405 4 d425 1 a425 1 int inquotes, inword; d430 2 d440 1 a440 1 debug(DBG_OTHER, "server: returning straight away after successful fork"); d444 8 d455 2 a456 1 debug(DBG_OTHER, "wrapper: running (pid=%d) will fork and wait for: %s", getpid(), cmdstr); d461 6 a468 7 debug(DBG_EXECS, "execer: execing: %s", cmdstr); /* for (i=0,cp=strtok(cmdstr, " "); cp!=NULL; i++,cp=strtok(NULL, " ")) argv[i] = cp; */ inword=0; inquotes=0; for (i=0,cp=cmdstr; *cp; cp++) { d470 4 d476 1 a476 1 debug(DBG_EXECS, "quoted start of word [%s]", cp); d482 1 a482 1 debug(DBG_EXECS, "unquoted start of word [%s]", cp); d490 1 a490 1 debug(DBG_EXECS, "opening quotes while not in word ... [%s]", cp); d493 3 a495 2 /* strmove(cp, cp+1); debug(DBG_EXECS, "... shuffled up [%s]", cp); */ d499 1 a499 1 debug(DBG_EXECS, "unquoted end of word [%s]", cp); d505 1 a505 1 debug(DBG_EXECS, "closing quotes ... [%s]", cp); d507 1 a507 1 *cp = '\0'; d510 3 a512 2 /* strmove(cp, cp+1); debug(DBG_EXECS, "... shuffled up [%s]", cp); */ d514 1 d520 1 a520 1 debug(DBG_EXECS, "forkandsend: argv[%d] = %s", i, argv[i]); d526 1 a526 1 debug(DBG_SIGS, "wrapper: waiting for all children"); d529 1 a529 1 debug(DBG_SIGS, "wrapper: caught a child with wait"); d532 1 a532 1 debug(DBG_SIGS, "wrapper: done waiting for all children"); d535 1 a535 1 debug(DBG_OTHER, "problem"); d537 1 a537 1 debug(DBG_EXECS, "child stopped on signal %d", old_statsup >> 8); d539 1 a539 1 debug(DBG_EXECS, "child exited on signal %d", old_statsup & 0x7f); a548 484 mhf_load_config() { state_cfgok = load_config("master.cfg", 0) ? 0 : 1; } mhf_info() { int i; long t = time(NULL); info("STATES"); info("state_cfgok: %d", state_cfgok); info("state_curr: %d", state_curr); info("state_want: %d", state_want); info("state_done: %d", state_done); info("state_inipup: %d", state_inipup); info("state_donenx: %d", state_donenx); info("state_donemx: %d", state_donemx); info("state_quit: %d", state_quit); info("QUEUES"); info("delayq_top: %d", delayq_top); for (i=0; i idlecheck_oldusetim + idlecheck_timeout) { debug(DBG_OTHER, "mhf_exec_idle: idle and time limit expired!"); state_idle = 1; } else if (use == idlecheck_oldusecnt) { debug(DBG_OTHER, "mhf_exec_idle: idle"); } else { debug(DBG_OTHER, "mhf_exec_idle: not idle, saving current usage levels"); idlecheck_oldusetim = time(NULL); idlecheck_oldusecnt = use; } /* * Send a message to be acted on according to whether we have been idle * long enough or not. The code called could be incorporated here since * *this* function is so quick, but why bother? */ pppld_ipc_send_msg(svrmsginfdat, MSGTO_SVR, state_idle ? MSGID_NOK_IDLECHECK : MSGID_OK_IDLECHECK, NULL); } mhf_ok_idle() { debug(DBG_OTHER, "mhf_ok_idle: sof, timeout is %d", idlecheck_timeout); if (idlecheck_timeout && state_curr) { debug(DBG_OTHER, "mhf_ok_idle: requeuing idle check for %d secs", idlecheck_interval); delaysendmsg(time(NULL)+idlecheck_interval, MSGID_EXEC_IDLECHECK, NULL); } else debug(DBG_OTHER, "mhf_ok_idle: NOT requeuing idle check"); } mhf_nok_idle() { /* no need to requeue the check message ... just let the idle process die */ state_want = 0; reason_down = REASON_IDLE; kill_pppd(); } mhf_unset_qualitycheck_interval() { int q; q = 0; /* * That variable may be automatic since pppld_ipc_send_msg() really * has finished with the memory it's in when it exits. (It constructs * a text string from the args and dispatches the message. */ pppld_ipc_send_msg(svrmsginfdat, MSGTO_SVR, MSGID_SET_QUALITYCHECK, &q); } mhf_set_qualitycheck_interval( int *new_qualitycheck_intervalp) { int old_qualitycheck_interval = qualitycheck_interval; int i; qualitycheck_interval = *new_qualitycheck_intervalp; /* * if we require a positive quality and we have a positive interval but * didn't have one already! ... and of course we're connected and * want to be ... */ if (qualitycheck_interval && !old_qualitycheck_interval && qualitycheck_minquality) { if (state_curr && state_want) pppld_ipc_send_msg(svrmsginfdat, MSGTO_SVR, MSGID_EXEC_QTEST, NULL); /* * if it is the toggling of the quality interval that should deactivate * the delayed queued quality checks then cancel them now */ } else if (qualitycheck_minquality) /* dequeuing could go here, instead od being in a separate function */ for (i=0; i /* for strrchr() */ d31 1 d41 1 a42 3 #define ANNUP_CMD "/home/alexis/dev/ppp/annup" #define ANNDOWN_CMD "/home/alexis/dev/ppp/anndown" #define PPPD_CMD "/home/alexis/dev/ppp/pppd" a52 5 struct msgid2fncrec { int id; int (*fnc)(); }; d57 1 d69 1 d72 7 a78 3 int mhf_toggle_quit(); int mhf_toggle_idlecheck(); int mhf_toggle_qcheck(); d103 1 d109 1 d112 24 a135 1 * Global variables d139 1 d142 16 a157 1 int state_in_ipup; /* are we running post connection sequence? */ a159 2 int done_xfer_news_flag; /* used to assess if ipup is finished */ int done_xfer_mail_flag; /* used to assess if ipup is finished */ d161 40 a200 31 struct msgid2fncrec msgid2fncdat[] = { { MSGID_EXEC_PPPD, mhf_exec_pppd }, { MSGID_OK_PPPD, mhf_ok_pppd }, { MSGID_NOK_PPPD, mhf_nok_pppd }, { MSGID_TOGGLE_QUIT, mhf_toggle_quit }, { MSGID_EXEC_IPUP, mhf_exec_ipup }, { MSGID_HANGUP, mhf_hangup }, { MSGID_REDIAL, mhf_redial }, { MSGID_EXEC_QTEST, mhf_exec_qtest }, { MSGID_OK_QTEST, mhf_ok_qtest }, { MSGID_NOK_QTEST, mhf_nok_qtest }, { MSGID_EXEC_SNDMAIL, mhf_exec_sndmail }, { MSGID_OK_SNDMAIL, mhf_ok_sndmail }, { MSGID_NOK_SNDMAIL, mhf_nok_sndmail }, { MSGID_EXEC_SNDNEWS, mhf_exec_sndnews }, { MSGID_OK_SNDNEWS, mhf_ok_sndnews }, { MSGID_NOK_SNDNEWS, mhf_nok_sndnews }, { MSGID_EXEC_GETMAIL, mhf_exec_getmail }, { MSGID_OK_GETMAIL, mhf_ok_getmail }, { MSGID_NOK_GETMAIL, mhf_nok_getmail }, { MSGID_EXEC_GETNEWS, mhf_exec_getnews }, { MSGID_OK_GETNEWS, mhf_ok_getnews }, { MSGID_NOK_GETNEWS, mhf_nok_getnews }, { MSGID_EXEC_IDLECHECK, mhf_exec_idle }, { MSGID_OK_IDLECHECK, mhf_ok_idle }, { MSGID_NOK_IDLECHECK, mhf_nok_idle }, { MSGID_EXEC_IPDOWN, mhf_exec_ipdown }, { MSGID_NOACTION, mhf_noaction }, { MSGID_TOGGLE_QCHECK, mhf_toggle_qcheck }, { MSGID_INFO, mhf_info }, { MSGID_TOGGLE_IDLECHECK, mhf_toggle_idlecheck } a202 23 /* * 0?? command start requests and exit codes * 00? pppd commands * 01? ipup commands * 02? qtest commands * 03? sndmail commands * 04? sndnews commands * 05? getmail commands * 06? getnews commands * 07? idle commands * 08? ipdown commands * 1?? flag changes * 2?? weird ones :-) */ int quit_flag; int idlecheck_flag; int qcheck_flag; int qcheck_interval; int qcheck_minquality; int idlecheck_interval; int idlecheck_timeout; int qcheck_interval; d204 3 d216 1 d225 1 d256 1 a256 1 perror("fopen"); d270 1 a270 1 perror("fopen"); d306 2 a307 2 perror("fopen"); exit(1); d329 1 d331 1 a333 1 debug_level = 5; d336 3 d340 7 a346 1 if (strcmp(argv[1], "-d") == 0) { d387 1 d390 5 a394 1 state_in_ipup = 0; d398 3 a400 16 quit_flag = 0; idlecheck_flag = 1; qcheck_flag = 1; /* this will be controlled by config */ qcheck_minquality = 50; /* this will be controlled by config */ idlecheck_timeout = 300; /* check the level every quarter of that interval - so a max idle of 1.25 * 300 - 1/inf idlecheck_interval = idlecheck_timeout / 4; /* idle checks must fit entirely inside the quality check interval since the quality check alters the usage count */ qcheck_interval = 2 * idlecheck_timeout; while (!quit_flag) { if (pppld_ipc_read_msg(MSGTO_SVR, buf, sizeof(buf)) < 0) { a403 14 if ((msgid=msgtxt2id(buf)) < 0) { warning("unhandlable message received and ignored: %s", buf); continue; } /* if we now have the message id, then look up that id in the id:fnc map */ for (msgidx=0; msgidx