head 1.25; access; symbols new_system:1.14 old_system:1.13; locks ahuxley:1.25; strict; comment @ * @; 1.25 date 2000.01.09.10.59.50; author ahuxley; state Exp; branches; next 1.24; 1.24 date 99.05.07.14.40.48; author alexis; state Exp; branches; next 1.23; 1.23 date 99.05.06.08.43.09; author alexis; state Exp; branches; next 1.22; 1.22 date 99.04.28.09.45.34; author alexis; state Exp; branches; next 1.21; 1.21 date 99.04.26.16.14.48; author alexis; state Exp; branches; next 1.20; 1.20 date 99.01.07.13.08.41; author alexis; state Exp; branches; next 1.19; 1.19 date 98.10.17.12.55.46; author alexis; state Exp; branches; next 1.18; 1.18 date 98.10.07.16.37.08; author alexis; state Exp; branches; next 1.17; 1.17 date 98.08.31.12.40.37; author alexis; state Exp; branches; next 1.16; 1.16 date 98.08.28.17.39.26; author alexis; state Exp; branches; next 1.15; 1.15 date 98.08.28.13.11.19; author alexis; state Exp; branches; next 1.14; 1.14 date 98.08.08.09.47.47; author alexis; state Exp; branches; next 1.13; 1.13 date 98.08.07.11.28.42; author alexis; state Exp; branches; next 1.12; 1.12 date 98.03.01.22.29.29; author alexis; state Exp; branches; next 1.11; 1.11 date 97.11.11.11.54.41; author alexis; state Exp; branches; next 1.10; 1.10 date 97.10.26.12.12.29; author alexis; state Exp; branches; next 1.9; 1.9 date 97.10.20.17.30.40; author alexis; state Exp; branches; next 1.8; 1.8 date 97.10.20.16.58.17; author alexis; state Exp; branches; next 1.7; 1.7 date 97.09.22.18.01.23; author alexis; state Exp; branches; next 1.6; 1.6 date 97.02.21.17.12.10; author alexis; state Exp; branches; next 1.5; 1.5 date 97.02.16.14.42.28; author alexis; state Exp; branches; next 1.4; 1.4 date 97.02.16.12.39.36; author alexis; state Exp; branches; next 1.3; 1.3 date 97.02.15.11.12.52; author alexis; state Exp; branches; next 1.2; 1.2 date 97.02.09.16.00.50; author alexis; state Exp; branches; next 1.1; 1.1 date 97.02.01.21.52.17; author alexis; state Exp; branches; next ; desc @MILEPOST - WORKS @ 1.25 log @Added start of variable definition code - NOTE THIS MAKES PPPLCD UNUSABLE AT THE MOMENT! @ text @/*@@unused@@*/ static char *ppplcd_c_rcs_id = "$Header: /diskb/home/alexis/dev/supported/ppplc/bin/RCS/ppplcd.c,v 1.24 1999/05/07 14:40:48 alexis Exp alexis $"; /******************************************************************************* * * System Includes * *******************************************************************************/ #include #include /* for NULL */ #include /* for strrchr(), strtok() */ #include /* for SIGINT, SIG_IGN etc */ #include /* for wait() par types */ #include /* for time() */ #include /* for setpgrp() */ #include /* for errno in strerror() */ #include /* for exit() */ #include /* for va_lists */ #include /* for calloc(), atoi() */ #include /* for getpwnam() */ #include /* for getgrnam() */ #include /* for umask() */ /******************************************************************************* * * Application Includes * *******************************************************************************/ #include "utils.h" /* for mybasename() and error fncs */ #include "ppplc.h" /* for c queue definitions */ #include "patchlevel.h" #include "sm.h" #include "ppplc_msgids.h" /* for message ids */ /******************************************************************************* * * Symbol Definitions * *******************************************************************************/ #define HUPID_UNSET -1 #define HUPID_QUALITY 1 #define HUPID_IDLE 2 #define HUPID_HANGUP 3 #define ANNID_UP 0 #define ANNID_DOWN_QUALITY_REDIAL 1 #define ANNID_DOWN_QUALITY_NOREDIAL 2 #define ANNID_DOWN_REMOTE_REDIAL 3 #define ANNID_DOWN_REMOTE_NOREDIAL 4 #define ANNID_DOWN_IDLE_NOREDIAL 5 #define ANNID_DOWN_HANGUP_NOREDIAL 6 #define IFNO_UNSET -1 #define INFID_RESERVED -1000 #define PPPD_LOCK_FILE_FMTSTR "/var/run/ppp%d.pid" #define PPPLCD_MAXSTRLEN 256 #define KW_COMMAND_UNIX_PPPD "command-unix-pppd" #define KW_COMMAND_UNIX_CHAT "command-unix-chat" #define KW_COMMAND_PPPLCD_ANNOUNCE "command-ppplcd-announce" #define KW_COMMAND_PPPLCD_WANNABECHANGED "command-ppplcd-wannabechanged" #define KW_SETTING_PPPD_DEBUG "setting-pppd-debug" #define KW_SETTING_PPPD_KDEBUG "setting-pppd-kdebug" #define KW_INCLUDE "include" #define KW_SETTING_MISC_TIMEOUT_IDLE "setting-misc-timeout-idle" #define KW_COMMAND_PPPLCD_QUALITYTEST "command-ppplcd-qualitytest" #define KW_COMMAND_PPPLCD_USECOUNT "command-ppplcd-usecount" #define KW_COMMAND_PPPLCD_XFER_NEWS "command-ppplcd-xfer-news" #define KW_COMMAND_PPPLCD_XFER_MAIL "command-ppplcd-xfer-mail" #define KW_SETTING_CONNECT_LOGIN "setting-connect-login" #define KW_SETTING_CONNECT_PASSWORD "setting-connect-password" #define KW_SETTING_CONNECT_PHONENUMBER "setting-connect-phonenumber" #define KW_SETTING_MISC_AUTORECONNECT "setting-misc-autoreconnect" #define KW_SETTING_IP_NETMASK "setting-ip-netmask" #define KW_SETTING_IP_MTU "setting-ip-mtu" #define KW_SETTING_IP_MRU "setting-ip-mru" #define KW_SETTING_IPC_MODE "setting-ipc-mode" #define KW_SETTING_IPC_OWNER "setting-ipc-owner" #define KW_SETTING_IPC_GROUP "setting-ipc-group" #define KW_SETTING_DEVICE_MODEM_DEVICE "setting-device-modem-device" #define KW_SETTING_DEVICE_MODEM_SPEED "setting-device-modem-speed" #define KW_SETTING_MISC_QUALITY "setting-misc-quality" #define KW_CHATLINE "chatline" #define KW_COMMAND_PPPLCD_MISC "command-ppplcd-misc" #define KW_ASSIGN "assign" #define KWN_UNSET -1 /* unset numeric keyword */ /******************************************************************************* * * Structure Definitions * *******************************************************************************/ struct strchnrec { /* generic string chain */ char *str; /* the string */ struct strchnrec *nxt; /* the link */ }; /******************************************************************************* * * Static Functions Forward Declarations * *******************************************************************************/ static int gen_lockfile_name(char *, char *); static void sigchld_handler(int); static void sigterm_handler(int); static int ipup_part1(void); static int ipup_part2(void); static int ipup_part3(void); static int ipup_part4(void); static int mhf_load_config(int *); static int mhf_gen_config(int *); static int mhf_set_autoreconnect(int *); static int mhf_unset_autoreconnect(int *); static int mhf_info_request(int *); static int mhf_exec_pppd(int *); static int mhf_ok_pppd(int *); static int mhf_nok_pppd(int *); static int mhf_exec_ipup(int *); static int mhf_exec_wannabe_changed(int *); static int mhf_ok_wannabe_changed(int *); static int mhf_nok_wannabe_changed(int *); static int kill_pppd(int); static int mhf_exec_announce(int *); static int mhf_exec_qtest(int *); static int mhf_ok_qtest(int *); static int mhf_nok_qtest(int *); static int mhf_qtest_response(int *); static int mhf_exec_mail(int *); static int mhf_exec_misc(int *); static int mhf_nok_mail(int *); static int mhf_ok_mail(int *); static int mhf_exec_news(int *); static int mhf_nok_news(int *); static int mhf_ok_news(int *); static int mhf_exec_usecnt(int *); static int mhf_ok_usecnt(int *); static int mhf_nok_usecnt(int *); static int mhf_usecnt_response(int *); static int mhf_set_debug(int *); static int mhf_set_quality(int *); static int mhf_set_idlepars(int *); static int mhf_set_quit(int *); static int mhf_set_donews(int *); static int mhf_unset_donews(int *); static int mhf_hangup(int *); static int mhf_exec_ipdown(int *); static int mhf_noaction(int *); static void init_config(void); static int gen_config(void); static int load_config(char *, int); static int assmf_init(char *, uid_t *, gid_t *, int *); static int usage(void); /******************************************************************************* * * Static Data Definitions * *******************************************************************************/ static char *lock_dir = NULL; /* locks dir, dflt if null */ static char **global_argvp; /* for funcs to change cmdln */ static int global_argc; /* for funcs to change cmdln */ static int reason_down = HUPID_UNSET; static int idle_oldusecnt = -1; static unsigned long idle_oldusetim = 0; static int ppp_interface_no; static char pppd_cmd[PPPLCD_MAXSTRLEN]; static char chat_cmd[PPPLCD_MAXSTRLEN]; static char announce_cmd[PPPLCD_MAXSTRLEN]; static char wannabe_changed_cmd[PPPLCD_MAXSTRLEN]; static char chatfile[PPPLCD_MAXSTRLEN]; static char qtest_cmd[PPPLCD_MAXSTRLEN]; static char usecnt_cmd[PPPLCD_MAXSTRLEN]; static char news_cmd[PPPLCD_MAXSTRLEN]; static char misc_cmd[PPPLCD_MAXSTRLEN]; static char mail_cmd[PPPLCD_MAXSTRLEN]; static int pppd_debug = 0; static int pppd_kdebug = 0; static char port[16]; static char netmask[32]; static int speed; static int mtu; static int mru; static char login[16]; static char password[16]; static char telno[32]; static char *master_config_file; static int quality_interval; static int quality_minlevel; static int idle_timeout; static int state_cfgok; static int flag_officially_up; /* have we been connected? */ static int flag_wannabe_up; /* have we been connected? */ static int state_inipup; /* in post conn sequence? */ static int flag_exit_when_you_become_interruptable_again; static int flag_in_connect_sequence; static struct strchnrec *strchnroot = NULL; /* chain of chat lines */ static int do_xfer_news_flag; static int flag_autoreconnect; static int state_inipup; /* in post conn sequence? */ static int state_donenx; /* to assess if ipup finished */ static int state_donemx; /* to assess if ipup finished */ static uid_t ipc_owner; static gid_t ipc_group; static int ipc_mode; static struct mhflkuprec svrmhf_data[] = { { 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_EXEC_QTEST, mhf_exec_qtest }, { MSGID_OK_QTEST, mhf_ok_qtest }, { MSGID_NOK_QTEST, mhf_nok_qtest }, { MSGID_EXEC_MAIL, mhf_exec_mail }, { MSGID_OK_MAIL, mhf_ok_mail }, { MSGID_NOK_MAIL, mhf_nok_mail }, { MSGID_EXEC_NEWS, mhf_exec_news }, { MSGID_OK_NEWS, mhf_ok_news }, { MSGID_NOK_NEWS, mhf_nok_news }, { MSGID_EXEC_IPDOWN, mhf_exec_ipdown }, { MSGID_NOACTION, mhf_noaction }, { MSGID_INFO_REQ, mhf_info_request }, { MSGID_SET_QUALITY, mhf_set_quality }, { MSGID_SET_DEBUG, mhf_set_debug }, { MSGID_SET_DONEWS, mhf_set_donews }, { MSGID_SET_IDLEPARS, mhf_set_idlepars }, { MSGID_EXEC_USECNT, mhf_exec_usecnt }, { MSGID_OK_USECNT, mhf_ok_usecnt }, { MSGID_NOK_USECNT, mhf_nok_usecnt }, { MSGID_EXEC_QTEST, mhf_exec_qtest }, { MSGID_OK_QTEST, mhf_ok_qtest }, { MSGID_NOK_QTEST, mhf_nok_qtest }, { MSGID_UNSET_DONEWS, mhf_unset_donews }, { MSGID_LOAD_CONFIG, mhf_load_config }, { MSGID_GEN_CONFIG, mhf_gen_config }, { MSGID_SET_AUTORECONNECT, mhf_set_autoreconnect }, { MSGID_UNSET_AUTORECONNECT, mhf_unset_autoreconnect }, { MSGID_QTEST_RESPONSE, mhf_qtest_response }, { MSGID_EXEC_MISC, mhf_exec_misc }, { MSGID_EXEC_ANNOUNCE, mhf_exec_announce }, { MSGID_EXEC_WANNABE_CHANGED, mhf_exec_wannabe_changed }, { MSGID_OK_WANNABE_CHANGED, mhf_ok_wannabe_changed }, { MSGID_NOK_WANNABE_CHANGED, mhf_nok_wannabe_changed }, { MSGID_USECNT_RESPONSE, mhf_usecnt_response }, { MSGID_PSEUDO_LAST, NULL } }; static struct varspcrec *ppplcd_varspc = NULL; /******************************************************************************* * * Global Data Definitions * *******************************************************************************/ /******************************************************************************* * * Functions: main() and usage() and gen_lockfile_name() * *******************************************************************************/ /* * We make usage() return an int in the declaration, although it actually * returns nothing, so that callers can use a construct like: * * (argc == 3) || usage(); * * which would otherwise return an error. */ static int usage() { debug(DBG_FUNCS, "usage: sof"); fprintf(stderr, "Usage: %s [ -v | -d ] [ -n ] [ -i ] [ -V ] \n", progname); exit(EXIT_FAILURE); } main( int argc, char *argv[]) { pid_t pid; pid_t locking_pid; int rc; int detach_flag; char *cp; /* * save argv into global var, so that functions can modify the command * line displayed by 'ps' etc. */ global_argvp = &argv[0]; global_argc = argc; progname = mybasename(argv[0], ""); detach_flag = 1; ppp_interface_no = IFNO_UNSET; while (argc>1 && argv[1][0] == '-') { if (strcmp(argv[1], "-n") == 0) detach_flag = 0; else if (strcmp(argv[1], "-V") ==0) { printf("%s version %s\n", progname, patchlevel); exit(EXIT_SUCCESS); } else if (strcmp(argv[1], "-d") == 0) { (argc<3) && usage(); (sscanf(argv[2], "%lu", &debug_level)!=1) && usage(); argc--; argv++; } else if (strcmp(argv[1], "-i") == 0) { (argc<3) && usage(); (sscanf(argv[2], "%d", &ppp_interface_no)!=1) && usage(); argc--; argv++; } else (void) usage(); argv++; argc--; } if (argc != 2) (void) usage(); if (!detach_flag) info("process not detached"); else if ((pid=fork()) < 0) error(strerror(errno)); else if (pid > 0) exit(EXIT_SUCCESS); else { i_am_a_daemon = TRUE; putenv("I_AM_A_DAEMON=true"); /* for child scripts */ } /* ensure shell breaks don't kill us */ /*@@-unrecog@@*/ setpgrp(); /*@@=unrecog@@*/ debug(DBG_FUNCS, "main: sof (proper)"); /* * 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. Note signal handlers should be set up *BEFORE* calling * the my_lock() function. */ debug(DBG_SIGEXEC, "main: setting up signal handlers"); signal(SIGCHLD, sigchld_handler); signal(SIGINT, genericsighandler); signal(SIGTERM, genericsighandler); if ((locking_pid=my_lock(NULL, gen_lockfile_name)) > 0) error("running already (pid=%d)", locking_pid); else if (locking_pid < 0) error("can't create lockfile: %s", strerror(errno)); smf_shutdown(); /* * 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. * Note that the config must be loaded to get the ipc perms etc before * the mesage queue is created. But that the ownership of an existing * message queue will not be affected if the config is reloaded. */ if ((rc=smf_init(SMS_MCMODE_SERVER|SMS_MCMODE_CLIENT, assmf_init, argv[1]))) error("state machine initialisation failed (errcode=%d)", rc); /* TEST!!! */ if ((cp=lookup(ppplcd_varspc, "VAR2")) == NULL) warning("variable not found"); else info("var has value %s", cp); info("ready"); smf_engine(MSGTO_PPPLCD, svrmsginfo_data, svrmhf_data); /* * Graceful exit code */ smf_shutdown(); my_unlock(NULL, gen_lockfile_name); exit(EXIT_SUCCESS); } int gen_lockfile_name( char *lockfile, char *lockwhat) { /* lockwhat is set to NULL */ sprintf(lockfile, "%s/%s.pid", LOCK_DIR, progname); return(0); } /******************************************************************************* * * Functions: Signal Handlers * *******************************************************************************/ static void sigchld_handler( /*@@unused@@*/ int signumber) { signal(SIGCHLD, SIG_IGN); debug(DBG_FUNCS, "sigchld_handler: sof"); (void) wait(NULL); debug(DBG_SIGEXEC, "sigchld_handler: done wait()"); signal(SIGCHLD, sigchld_handler); } /****************************************************************************** * * Functions: Message Handlers * ******************************************************************************/ static int mhf_load_config( int *notusedp) { debug(DBG_FUNCS, "mhf_load_config: sof"); load_config("master.cfg", 0); } static int mhf_gen_config( int *notusedp) { debug(DBG_FUNCS, "mhf_gen_config: sof"); gen_config(); } static int mhf_set_autoreconnect( int *notusedp) { flag_autoreconnect = TRUE; } static int mhf_unset_autoreconnect( int *notusedp) { flag_autoreconnect = FALSE; } static int mhf_info_request( int *parp) { int info_requester = *parp; int parcnt; int *mp; int rc; debug(DBG_FUNCS, "mhf_info_request: sof"); parcnt = (svrmsginfo_data+smf_msginfo(svrmsginfo_data, MSGID_INFO_DATA))->argc; if (parcnt == 0) { internal("mhf_info_request: lookup says MSGID_INFO_DATA has no pars"); } else if ((mp=(int *) calloc(sizeof(int), parcnt)) == NULL) error("calloc: %s", strerror(errno)); /* * Read/Write parameters */ *(mp+0) = flag_wannabe_up; *(mp+1) = smf_setquit(SMS_VAR_READ); *(mp+2) = do_xfer_news_flag; *(mp+3) = flag_autoreconnect; *(mp+4) = debug_level; *(mp+5) = idle_timeout; *(mp+6) = quality_minlevel; *(mp+7) = quality_interval; *(mp+8) = INFID_RESERVED; *(mp+9) = INFID_RESERVED; *(mp+10) = INFID_RESERVED; *(mp+11) = INFID_RESERVED; *(mp+12) = INFID_RESERVED; *(mp+13) = INFID_RESERVED; *(mp+14) = INFID_RESERVED; *(mp+15) = INFID_RESERVED; *(mp+16) = INFID_RESERVED; *(mp+17) = INFID_RESERVED; *(mp+18) = INFID_RESERVED; *(mp+19) = INFID_RESERVED; /* * Read-only parameters */ *(mp+20) = flag_officially_up; *(mp+21) = state_cfgok; *(mp+22) = state_donemx; *(mp+23) = state_donenx; *(mp+24) = state_inipup; *(mp+25) = ipc_mode; *(mp+26) = ipc_owner; *(mp+27) = ipc_group; *(mp+28) = INFID_RESERVED; *(mp+29) = INFID_RESERVED; *(mp+30) = INFID_RESERVED; *(mp+31) = INFID_RESERVED; *(mp+32) = INFID_RESERVED; *(mp+33) = INFID_RESERVED; *(mp+34) = INFID_RESERVED; *(mp+35) = INFID_RESERVED; *(mp+36) = INFID_RESERVED; *(mp+37) = INFID_RESERVED; *(mp+38) = INFID_RESERVED; *(mp+39) = INFID_RESERVED; if (rc=smf_submit(svrmsginfo_data, info_requester, time(NULL), MSGID_INFO_DATA, mp, SMS_SUBMIT_QUEUE)) error("IPC queue submit failed"); free(mp); } static int mhf_exec_pppd( int *notusedp) { char cmdbuf[512]; int *intp; debug(DBG_FUNCS, "mhf_exec_pppd: sof"); if (flag_in_connect_sequence) { warning("internal lock set"); return(1); } else flag_in_connect_sequence = TRUE; if (!state_cfgok) { warning("config has not yet been successfully loaded"); flag_in_connect_sequence = FALSE; return; } if (!flag_wannabe_up) { flag_wannabe_up = TRUE; if (*wannabe_changed_cmd != '\0') { if ((intp = (int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *intp = 1; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_WANNABE_CHANGED, intp, SMS_SUBMIT_DIRECT); } } flag_exit_when_you_become_interruptable_again = FALSE; /* sprintf(cmdbuf, "%s %s %d connect \"%s -v -f %s\" call %s crtscts defaultroute lock netmask %s noipdefault asyncmap 0x00000000 mru %d mtu %d lcp-echo-interval 180 -detach lcp-echo-interval 0 kdebug %d%s", pppd_cmd, port, speed, chat_cmd, chatfile, "eso-dial", netmask, mru, mtu, pppd_kdebug, pppd_debug ? " debug" : ""); */ substitute(cmdbuf, lookup(ppplcd_varspc, "pppd2"), ppplcd_varspc); reason_down = HUPID_UNSET; smf_fkwsmrc(cmdbuf, MSGTO_PPPLCD, MSGID_OK_PPPD, MSGID_NOK_PPPD, svrmsginfo_data); } static int mhf_exec_wannabe_changed( int *statusp) { char envbuf[16]; sprintf(envbuf, "%d", *statusp); setenv("PPPLCD_WANNABE", envbuf, TRUE); smf_fkwsmrc(wannabe_changed_cmd, MSGTO_PPPLCD, MSGID_OK_WANNABE_CHANGED, MSGID_NOK_WANNABE_CHANGED, svrmsginfo_data); } static int mhf_ok_wannabe_changed( int *notusedp) { debug(DBG_FUNCS, "mhf_ok_wannabe_changed: sof"); } static int mhf_nok_wannabe_changed( int *notusedp) { debug(DBG_FUNCS, "mhf_nok_wannabe_changed: sof"); mhf_ok_wannabe_changed(notusedp); } static int mhf_exec_announce( int *annidp) { char cmdbuf[512]; sprintf(cmdbuf, "%s %d", announce_cmd, *annidp); smf_fkwsmrc(cmdbuf, MSGTO_PPPLCD, MSGID_NOACTION, MSGID_NOACTION, svrmsginfo_data); } static int mhf_ok_pppd( int *notusedp) { int announce_id; int *mp; int *intp; debug(DBG_FUNCS, "mhf_ok_pppd: sof"); /* * In the event that the 'HANGUP' message was sent at a time when * pppd *was* interruptable, then this variable will have been set * (how was the killer supposed to know it wasn't uninterruptable?) * and not cleared yet. This is the earliest place to clear it. */ flag_exit_when_you_become_interruptable_again = FALSE; /* * Same goes for these. */ ppp_interface_no = IFNO_UNSET; state_inipup = 0; /* * Delete pending use count checks */ if ((mp=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *mp = MSGID_EXEC_USECNT; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_DEL_MSGID, mp, SMS_SUBMIT_DIRECT); /* * Delete pending quality checks */ if ((mp=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *mp = MSGID_EXEC_QTEST; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_DEL_MSGID, mp, SMS_SUBMIT_DIRECT); if (flag_officially_up) { flag_officially_up = FALSE; /* * Work out if we should try to reconnect */ switch (reason_down) { case HUPID_UNSET: /* remote hangup */ flag_wannabe_up = flag_autoreconnect; break; case HUPID_QUALITY: /* locally detected bad quality */ flag_wannabe_up = flag_autoreconnect; break; case HUPID_HANGUP: /* local hangup */ flag_wannabe_up = 0; break; case HUPID_IDLE: /* locally detected idle */ flag_wannabe_up = 0; break; } /* * Announce down only (we'd only be inside the above 'if', if we * had announced being up. Note that announce_id depends on * the flag_wannabe_up we have just worked out, so the flag_wannabe_up * calculation must come *before* the announce_id calculation. */ switch (reason_down) { case HUPID_UNSET: /* remote hangup */ announce_id = (flag_wannabe_up) ? ANNID_DOWN_REMOTE_REDIAL : ANNID_DOWN_REMOTE_NOREDIAL; break; case HUPID_QUALITY: /* locally detected bad quality */ announce_id = (flag_wannabe_up) ? ANNID_DOWN_QUALITY_REDIAL : ANNID_DOWN_QUALITY_NOREDIAL; break; case HUPID_HANGUP: /* local hangup */ announce_id = ANNID_DOWN_HANGUP_NOREDIAL; break; case HUPID_IDLE: /* locally detected idle */ announce_id = ANNID_DOWN_IDLE_NOREDIAL; break; default: internal("(%s,%d) unexpected down reason: %d", __FILE__, __LINE__, reason_down); break; } if ((mp=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *mp = announce_id; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_ANNOUNCE, mp, SMS_SUBMIT_DIRECT); } if (!flag_wannabe_up && *wannabe_changed_cmd != '\0') { if ((intp = (int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *intp = 0; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_WANNABE_CHANGED, intp, SMS_SUBMIT_DIRECT); } /* * If we do want to reconnect then go ahead and do it! */ flag_in_connect_sequence = FALSE; if (flag_wannabe_up) smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_PPPD, NULL, SMS_SUBMIT_DIRECT); } static int mhf_nok_pppd( int *notusedp) { debug(DBG_FUNCS, "mhf_nok_pppd: sof"); mhf_ok_pppd(notusedp); } static int mhf_exec_ipup( int *ifnop) { debug(DBG_FUNCS, "mhf_exec_ipup: sof"); ppp_interface_no = *ifnop; /* note interface number */ if (flag_exit_when_you_become_interruptable_again) { flag_exit_when_you_become_interruptable_again = FALSE; return(kill_pppd(ppp_interface_no)); } state_inipup = 1; return(ipup_part1()); } static int mhf_exec_qtest( int *notusedp) { char cmdbuf[PPPLCD_MAXSTRLEN]; debug(DBG_FUNCS, "mhf_exec_qtest: sof"); smf_fkwsmrc(qtest_cmd, MSGTO_PPPLCD, MSGID_OK_QTEST, MSGID_NOK_QTEST, svrmsginfo_data); } static int mhf_ok_qtest( int *notusedp) { debug(DBG_FUNCS, "mhf_ok_qtest: sof"); /* * qualitycheck_flag is likely to be on, hey!, or why would we be here in * the first place? but it could have been turned off while the test was * running, so we check again. */ if (quality_interval && quality_minlevel && flag_officially_up && flag_wannabe_up) { debug(DBG_QUALIDLE, "mhf_ok_qtest: requeuing qtest check for %d secs", quality_interval); smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL)+quality_interval, MSGID_EXEC_QTEST, NULL, SMS_SUBMIT_DIRECT); } else debug(DBG_QUALIDLE, "mhf_ok_qtest: NOT requeuing qtest"); } static int mhf_nok_qtest( int *notusedp) { debug(DBG_FUNCS, "mhf_nok_qtest: sof"); mhf_ok_qtest(notusedp); } static int mhf_qtest_response( int *qualityp) { if (*qualityp < quality_minlevel) { reason_down = HUPID_QUALITY; return(kill_pppd(ppp_interface_no)); } else if (state_inipup && !flag_officially_up) return(ipup_part3()); } static int mhf_exec_mail( int *notusedp) { debug(DBG_FUNCS|DBG_SPECIAL1, "mhf_exec_mail: sof"); smf_fkwsmrc(mail_cmd, MSGTO_PPPLCD, MSGID_OK_MAIL, MSGID_NOK_MAIL, svrmsginfo_data); } static int mhf_nok_mail( int *notusedp) { debug(DBG_FUNCS, "mhf_nok_mail: sof"); mhf_ok_mail(notusedp); } static int mhf_ok_mail( int *notusedp) { debug(DBG_FUNCS, "mhf_ok_mail: sof"); if (!state_inipup) return; state_donemx = 1; ipup_part4(); } static int mhf_exec_misc( int *notusedp) { debug(DBG_FUNCS, "mhf_exec_misc: sof"); smf_fkwsmrc(misc_cmd, MSGTO_PPPLCD, MSGID_NOACTION, MSGID_NOACTION, svrmsginfo_data); } static int mhf_exec_news( int *notusedp) { debug(DBG_FUNCS, "mhf_exec_news: sof"); smf_fkwsmrc(news_cmd, MSGTO_PPPLCD, MSGID_OK_NEWS, MSGID_NOK_NEWS, svrmsginfo_data); } static int mhf_nok_news( int *notusedp) { debug(DBG_FUNCS, "mhf_nok_news: sof"); mhf_ok_news(notusedp); } static int mhf_ok_news( int *notusedp) { debug(DBG_FUNCS, "mhf_ok_news: sof"); if (!state_inipup) return; state_donenx = 1; ipup_part4(); } static int mhf_exec_usecnt( int *parp) { char cmdbuf[512]; debug(DBG_FUNCS, "mhf_exec_usecnt: sof"); sprintf(cmdbuf, "%s ppp%d", usecnt_cmd, *parp); smf_fkwsmrc(cmdbuf, MSGTO_PPPLCD, MSGID_OK_USECNT, MSGID_NOK_USECNT, svrmsginfo_data); } static int mhf_ok_usecnt( int *notusedp) { int *ifnop; debug(DBG_FUNCS, "mhf_ok_usecnt: sof"); if (idle_timeout && flag_officially_up && flag_wannabe_up) { debug(DBG_QUALIDLE, "mhf_ok_usecnt: requeuing idle check for %d secs", idle_timeout/4); if ((ifnop=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *ifnop = ppp_interface_no; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL)+idle_timeout/4, MSGID_EXEC_USECNT, ifnop, SMS_SUBMIT_DIRECT); } else debug(DBG_QUALIDLE, "mhf_ok_usecnt: NOT requeuing idle check"); } static int mhf_nok_usecnt( int *notusedp) { debug(DBG_FUNCS, "mhf_nok_usecnt: sof"); mhf_ok_usecnt(notusedp); } static int mhf_usecnt_response( int *usecountp) { /* * countrisen !countrisen * ----------------------------------- * expired | update last count kill with announce * !expired | update last count do nothing */ if (*usecountp == idle_oldusecnt && time(NULL) > idle_oldusetim + idle_timeout) { debug(DBG_QUALIDLE, "mhf_exec_usecnt: idle and limit expired"); reason_down = HUPID_IDLE; return(kill_pppd(ppp_interface_no)); } else if (*usecountp == idle_oldusecnt) { debug(DBG_QUALIDLE, "mhf_exec_usecnt: idle but limit not expired yet"); return(0); } else { debug(DBG_QUALIDLE, "mhf_exec_usecnt: not idle"); idle_oldusetim = time(NULL); idle_oldusecnt = *usecountp; return(0); } } static int mhf_set_debug( int *debug_levelp) { debug(DBG_FUNCS, "mhf_set_debug: sof"); /* * Note that the mhf functions currently take integers as parameters * and that debug_level is a long. Really the parameter should be the * address of a union of int, unsigned long and char *. And the * mhf functions should extract the bit they want. But we'll leave * that for the time being. */ debug_level = (unsigned long) *debug_levelp; } static int mhf_set_quality( int *new_qualityp) { int *mp; debug(DBG_FUNCS, "mhf_set_quality: sof"); /* * Delete pending quality checks */ if ((mp=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *mp = MSGID_EXEC_QTEST; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_DEL_MSGID, mp, SMS_SUBMIT_DIRECT); quality_minlevel = *new_qualityp; quality_interval = *(new_qualityp+1); if (quality_minlevel > 0 && quality_interval > 0 && flag_officially_up && flag_wannabe_up) smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_QTEST, NULL, SMS_SUBMIT_DIRECT); } static int mhf_set_idlepars( int *idle_timeoutp) { int i; int *ifnop; int *mp; debug(DBG_FUNCS, "mhf_set_idlepars: sof"); /* * Delete pending use count checks */ if ((mp=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *mp = MSGID_EXEC_USECNT; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_DEL_MSGID, mp, SMS_SUBMIT_DIRECT); if (*idle_timeoutp > 0 && idle_timeout == 0) { idle_oldusecnt = -1; idle_oldusetim = 0; } idle_timeout = *idle_timeoutp; if (idle_timeout > 0 && flag_officially_up && flag_wannabe_up) { if ((ifnop=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *ifnop = ppp_interface_no; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_USECNT, ifnop, SMS_SUBMIT_DIRECT); } } static int mhf_set_quit( int *notusedp) { debug(DBG_FUNCS, "mhf_set_quit: sof"); smf_setquit(SMS_VAR_TOGGLE); } static int mhf_set_donews( int *notusedp) { debug(DBG_FUNCS, "mhf_set_donews: sof"); do_xfer_news_flag = 1; } static int mhf_unset_donews( int *notusedp) { debug(DBG_FUNCS, "mhf_unset_donews: sof"); do_xfer_news_flag = 0; } static int mhf_hangup( int *notusedp) { debug(DBG_FUNCS, "mhf_hangup: sof"); flag_exit_when_you_become_interruptable_again = TRUE; flag_wannabe_up = FALSE; if (flag_officially_up) { reason_down = HUPID_HANGUP; return(kill_pppd(ppp_interface_no)); } return(0); } static int mhf_exec_ipdown( int *notusedp) { debug(DBG_FUNCS, "mhf_exec_ipdown: sof"); /* * note ppp_interface_no is cleared when pppd exits - it's more certain * to be done there than here (e.g. kill -9 on running pppd will not * result in this function getting called. */ } static int mhf_noaction( int *notusedp) { debug(DBG_FUNCS, "mhf_noaction: sof"); } /****************************************************************************** * * 'QUICK' FUNCTIONS * *******************************************************************************/ static int ipup_part1() { int *intp; debug(DBG_FUNCS, "ipup_part1 (placeholder): sof"); return(ipup_part2()); } static int ipup_part2() { debug(DBG_FUNCS, "ipup_part2 (quality tester): sof"); if (quality_interval && quality_minlevel) return(smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_QTEST, NULL, SMS_SUBMIT_DIRECT)); else return(ipup_part3()); } static int ipup_part3() { char cmdbuf[PPPLCD_MAXSTRLEN]; int *mp; int *ifnop; debug(DBG_FUNCS, "ipup_part3 (announce, news, mail, misc): sof"); /* * Announce it's up! */ if ((mp=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *mp = ANNID_UP; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_ANNOUNCE, mp, SMS_SUBMIT_DIRECT); flag_officially_up = TRUE; /* * Do mail, news, misc and idle checks concurrently */ if (*misc_cmd != '\0') smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_MISC, NULL, SMS_SUBMIT_DIRECT); if (idle_timeout) { idle_oldusecnt = -1; idle_oldusetim = 0; if ((ifnop=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *ifnop = ppp_interface_no; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_USECNT, ifnop, SMS_SUBMIT_DIRECT); } state_donenx = state_donemx = 0; if (*mail_cmd == '\0' && (*news_cmd == '\0' || !do_xfer_news_flag)) ipup_part4(); else { if (*news_cmd != '\0' && do_xfer_news_flag) smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_NEWS, NULL, SMS_SUBMIT_DIRECT); if (*mail_cmd != '\0') smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_MAIL, NULL, SMS_SUBMIT_DIRECT); } } static int ipup_part4() { debug(DBG_FUNCS|DBG_SPECIAL1, "ipup_part4 (news & mail exit union): sof"); if ((*mail_cmd != '\0' && !state_donemx) || (*news_cmd != '\0' && do_xfer_news_flag && !state_donenx)) return; debug(DBG_FUNCS|DBG_SPECIAL1, "ipup_part4 (placeholder): post-exclusions"); state_inipup = 0; } /****************************************************************************** * * APPLICATION-SPECIFIC STATE-MACHINE INTERFACE FUNCTIONS * ******************************************************************************/ /* * Application specific state machine initialisation function */ static int assmf_init( char *master_config_file, uid_t *ipc_owner_p, gid_t *ipc_group_p, int *ipc_mode_p) { do_xfer_news_flag = 1; state_inipup = 0; state_cfgok = 0; if (ppp_interface_no == IFNO_UNSET) { flag_officially_up = FALSE; flag_wannabe_up = FALSE; flag_in_connect_sequence = FALSE; } else { flag_officially_up = TRUE; flag_wannabe_up = TRUE; flag_in_connect_sequence = TRUE; } /* * Code removed: we can no longer derive flag_officially_up and * flag_wannabe_up. But we could have a command to mean "I'm telling you, * the connection is currently UP." */ if (load_config(master_config_file, 0) != 0) { warning("config file load failed"); return(1); } if (gen_config() != 0) { warning("config file generate failed"); return(2); } *ipc_owner_p = ipc_owner; *ipc_group_p = ipc_group; *ipc_mode_p = ipc_mode; return(0); } static void init_config() { struct strchnrec *linkaddr, *tmp; debug(DBG_FUNCS, "init_config: sof"); sprintf(chatfile, "%s/%s.%d.chat", TMP_DIR, progname, (int) getpid()); /* * These are all the things that are necessary! Optional ones should * be set in main before the options. they are tested below in * gen_config(). */ *pppd_cmd = '\0'; *chat_cmd = '\0'; idle_timeout = KWN_UNSET; flag_autoreconnect = KWN_UNSET; quality_interval = KWN_UNSET; quality_minlevel = KWN_UNSET; *announce_cmd = '\0'; *wannabe_changed_cmd = '\0'; *qtest_cmd = '\0'; *usecnt_cmd = '\0'; *news_cmd = '\0'; *misc_cmd = '\0'; *mail_cmd = '\0'; *port = '\0'; *netmask = '\0'; speed = KWN_UNSET; mtu = KWN_UNSET; mru = KWN_UNSET; ipc_mode = KWN_UNSET; ipc_owner = KWN_UNSET; ipc_group = KWN_UNSET; *login = '\0'; *password = '\0'; *telno = '\0'; debug(DBG_IGNORE, "init_config: removing old chatlines"); /*@@-compdestroy@@*/ for (linkaddr=strchnroot; linkaddr!=NULL; linkaddr=tmp) { free(linkaddr->str); tmp = linkaddr->nxt; free(linkaddr); } /*@@=compdestroy@@*/ strchnroot = NULL; state_cfgok = 0; } static int load_config( char *fname, int level) { FILE *fp; char linebuf[PPPLCD_MAXSTRLEN]; int lineno; int rc; char *endcp, *valcp, *colcp, *cmdcp; struct strchnrec **linkaddrp; struct passwd *pwp; /*@@-mustfree@@*/ struct group *grpp; char *val, *var; debug(DBG_FUNCS, "load_config: sof"); /* * Free up old storage of chatlines */ if (level == 0) init_config(); if ((fp=fopen(fname, "r")) == NULL) { warning("can't open %s", fname); return(1); } for (lineno=1; fgets(linebuf, (int) sizeof(linebuf), fp) != NULL; lineno++) { /* find the proper beginning of the line */ for (cmdcp=linebuf; *cmdcp && (*cmdcp=='\t' || *cmdcp==' '); cmdcp++) ; if (!*cmdcp) { continue; } else if (*cmdcp == '\n') { continue; } else if (*cmdcp == '#') { continue; } /* terminate the first word */ for (endcp=cmdcp; *endcp && *endcp!='\n' && *endcp!=':' && *endcp!=' ' && *endcp!='\t'; endcp++) ; if (*endcp == '\n' || !*endcp) { warning("no colon in line %d of file %s", lineno, fname); (void) fclose(fp); return(2); } else if (endcp == cmdcp) { warning("no command in line %d of file %s", lineno, fname); (void) fclose(fp); return(3); } /* but locate the colon first, 'cos terminating the first word may overwrite the colon and then we've lost it! */ for (colcp=endcp; *colcp && *colcp !=':'; colcp++) ; if (!*colcp) { warning("no colon in line %d of file %s", lineno, fname); (void) fclose(fp); return(4); } /* now go back and terminate the word */ *endcp = '\0'; /* find the first letter of the value */ for (valcp=colcp+1; *valcp && (*valcp=='\n' || *valcp=='\t' || *valcp==' '); valcp++) ; if (!*valcp) { warning("command without value at line %d of file %s", lineno, fname); (void) fclose(fp); return(5); } /* finally remove any trailing whitespace */ for (endcp=valcp+strlen(valcp)-1; endcp>valcp && (*endcp==' ' || *endcp=='\t' || *endcp=='\n'); endcp--) { ; } *(endcp+1) = '\0'; /* * Here list all optional and required config file entries */ if (strcmp(cmdcp, KW_INCLUDE) == 0) { if ((rc=load_config(valcp, level+1)) != 0) { (void) fclose(fp); return(rc); } } else if (strcmp(cmdcp, KW_COMMAND_UNIX_PPPD) == 0) { strcpy(pppd_cmd, valcp); } else if (strcmp(cmdcp, KW_COMMAND_UNIX_CHAT) == 0) { strcpy(chat_cmd, valcp); } else if (strcmp(cmdcp, KW_SETTING_PPPD_DEBUG) == 0) { pppd_debug = atoi(valcp); } else if (strcmp(cmdcp, KW_SETTING_PPPD_KDEBUG) == 0) { pppd_kdebug = atoi(valcp); } else if (strcmp(cmdcp, KW_SETTING_MISC_TIMEOUT_IDLE) == 0) { idle_timeout = atoi(valcp); } else if (strcmp(cmdcp, KW_COMMAND_PPPLCD_ANNOUNCE) == 0) { strcpy(announce_cmd, valcp); } else if (strcmp(cmdcp, KW_COMMAND_PPPLCD_WANNABECHANGED) == 0) { strcpy(wannabe_changed_cmd, valcp); } else if (strcmp(cmdcp, KW_COMMAND_PPPLCD_QUALITYTEST) == 0) { strcpy(qtest_cmd, valcp); } else if (strcmp(cmdcp, KW_COMMAND_PPPLCD_USECOUNT) == 0) { strcpy(usecnt_cmd, valcp); } else if (strcmp(cmdcp, KW_COMMAND_PPPLCD_MISC) == 0) { strcpy(misc_cmd, valcp); } else if (strcmp(cmdcp, KW_COMMAND_PPPLCD_XFER_NEWS) == 0) { strcpy(news_cmd, valcp); } else if (strcmp(cmdcp, KW_COMMAND_PPPLCD_XFER_MAIL) == 0) { strcpy(mail_cmd, valcp); } else if (strcmp(cmdcp, KW_SETTING_CONNECT_LOGIN) == 0) { strcpy(login, valcp); } else if (strcmp(cmdcp, KW_SETTING_CONNECT_PASSWORD) == 0) { strcpy(password, valcp); } else if (strcmp(cmdcp, KW_SETTING_CONNECT_PHONENUMBER) == 0) { strcpy(telno, valcp); } else if (strcmp(cmdcp, KW_SETTING_IP_NETMASK) == 0) { strcpy(netmask, valcp); } else if (strcmp(cmdcp, KW_ASSIGN) == 0) { var=strtok(valcp, " \t"); val=strtok(NULL, " \t"); debug(DBG_VARSPC, "load_config: found assign in config file (%s=%s)", var, val); if (assign(&ppplcd_varspc, var, val) != 0) error("assignment failed"); } else if (strcmp(cmdcp, KW_SETTING_IPC_MODE) == 0) { if (sscanf(valcp, "%i", &ipc_mode) != 1) { warning("%s: definition invalid", KW_SETTING_IPC_MODE); (void) fclose(fp); return(10); } } else if (strcmp(cmdcp, KW_SETTING_IPC_OWNER) == 0) { if ((pwp=getpwnam(valcp)) != NULL) ipc_owner = pwp->pw_uid; } else if (strcmp(cmdcp, KW_SETTING_IPC_GROUP) == 0) { /* getgrnam(3) doesn't document if pointer needs user-freeing */ if ((grpp=getgrnam(valcp)) != NULL) ipc_group = grpp->gr_gid; } else if (strcmp(cmdcp, KW_SETTING_MISC_QUALITY) == 0) { if (sscanf(valcp, "%d %d", &quality_minlevel, &quality_interval) != 2) { warning("%s: definition invalid", KW_SETTING_MISC_QUALITY); (void) fclose(fp); return(10); } } else if (strcmp(cmdcp, KW_SETTING_DEVICE_MODEM_DEVICE) == 0) { strcpy(port, valcp); } else if (strcmp(cmdcp, KW_SETTING_DEVICE_MODEM_SPEED) == 0) { speed = atoi(valcp); } else if (strcmp(cmdcp, KW_SETTING_IP_MTU) == 0) { mtu = atoi(valcp); } else if (strcmp(cmdcp, KW_SETTING_IP_MRU) == 0) { mru = atoi(valcp); } else if (strcmp(cmdcp, KW_SETTING_MISC_AUTORECONNECT) == 0) { flag_autoreconnect = atoi(valcp); } else if (strcmp(cmdcp, KW_CHATLINE) == 0) { for (linkaddrp=&strchnroot; *linkaddrp!=NULL; linkaddrp=&(*linkaddrp)->nxt) ; if ((*linkaddrp=(struct strchnrec *) malloc(sizeof(struct strchnrec))) == NULL) internal("(%s,%d) malloc failed"); /*@@-unrecog@@*/ if (((*linkaddrp)->str = strdup(valcp)) == NULL) /*@@=unrecog@@*/ internal("(%s,%d) malloc failed"); (*linkaddrp)->nxt = NULL; } else { warning("invalid command '%s' at line %d of file %s", cmdcp, lineno, fname); (void) fclose(fp); return(6); } } (void) fclose(fp); return(0); } static int gen_config() { static FILE *chat_fp; struct strchnrec *linkaddr; char valbuf[PPPLCD_MAXSTRLEN]; char *cp; mode_t old_umask; debug(DBG_FUNCS, "gen_config: sof"); state_cfgok = 0; old_umask = (mode_t) umask(077); delonexit(chatfile); if ((chat_fp=fopen(chatfile, "w")) == NULL) { warning("can't open %s: %s", chatfile, strerror(errno)); return(1); } (void) umask(old_umask); /* * Here check all required pars, set to special values in init_config() */ if (!*pppd_cmd) { warning("%s: not defined", KW_COMMAND_UNIX_PPPD); return(1); } else if (!*chat_cmd) { warning("%s: not defined", KW_COMMAND_UNIX_CHAT); return(1); } if (idle_timeout == KWN_UNSET) { warning("%s: not defined", KW_SETTING_MISC_TIMEOUT_IDLE); return(1); } else if (!*qtest_cmd) { warning("%s: not defined", KW_COMMAND_PPPLCD_QUALITYTEST); return(1); } else if (!*usecnt_cmd) { warning("%s: not defined", KW_COMMAND_PPPLCD_USECOUNT); return(1); } else if (!*announce_cmd) { warning("%s: not defined", KW_COMMAND_PPPLCD_ANNOUNCE); return(1); } else if (!*netmask) { warning("%s: not defined", KW_SETTING_IP_NETMASK); return(1); } else if (!*port) { warning("%s: not defined", KW_SETTING_DEVICE_MODEM_DEVICE); return(1); } else if (speed == KWN_UNSET) { warning("%s: not defined", KW_SETTING_DEVICE_MODEM_SPEED); return(1); } else if (!*telno) { warning("%s: not defined", KW_SETTING_CONNECT_PHONENUMBER); return(1); } else if (!*password) { warning("%s: not defined", KW_SETTING_CONNECT_PASSWORD); return(1); } else if (!*login) { warning("%s: not defined", KW_SETTING_CONNECT_LOGIN); return(1); } else if (pppd_kdebug < 0 || pppd_kdebug > 7) { warning("%s: out of range", KW_SETTING_PPPD_KDEBUG); return(1); } else if (pppd_debug < 0 || pppd_debug > 1) { warning("%s: out of range", KW_SETTING_PPPD_DEBUG); return(1); } else if (quality_minlevel == KWN_UNSET || quality_interval == KWN_UNSET) { warning("%s: not defined", KW_SETTING_MISC_QUALITY); return(1); } else if (strchnroot == NULL) { warning("no chat lines defined in config files"); return(1); } /* * Here generate the chat script */ for (linkaddr=strchnroot; linkaddr!=NULL; linkaddr=linkaddr->nxt) { debug(DBG_IGNORE, "gen_config: examining the chat strings"); strcpy(valbuf, linkaddr->str); if ((cp=strstr(valbuf, "%T")) != NULL && !*telno) { warning("chatline using %T with no telephone number defined yet"); (void) fclose(chat_fp); return(1); } else if (cp != NULL) { *(cp+1) = 's'; fprintf(chat_fp, valbuf, telno); } else if ((cp=strstr(valbuf, "%I")) != NULL && idle_timeout == KWN_UNSET) { warning("chatline using %I with no idle timeout defined yet"); (void) fclose(chat_fp); return(1); } else if (cp != NULL) { *(cp+1) = 'd'; fprintf(chat_fp, valbuf, idle_timeout); } else if ((cp=strstr(valbuf, "%L")) != NULL && !*login) { warning("chatline using %L with no login defined yet"); (void) fclose(chat_fp); return(1); } else if (cp != NULL) { *(cp+1) = 's'; fprintf(chat_fp, valbuf, login); } else if ((cp=strstr(valbuf, "%P")) != NULL && !*password) { warning("chatline using %P with no password defined yet"); (void) fclose(chat_fp); return(1); } else if (cp != NULL) { *(cp+1) = 's'; fprintf(chat_fp, valbuf, password); } else { fprintf(chat_fp, valbuf); } fprintf(chat_fp, "\n"); } (void) fclose(chat_fp); /* * Here we insert other '%' things into the appropriate command strings. */ /* * Here make any adjustments to values and give any warnings about * ranges etc. */ if (ipc_mode == KWN_UNSET) { warning("%s: not defined, defaulting to 0700", KW_SETTING_IPC_MODE); ipc_mode = 0700; } if (ipc_owner == KWN_UNSET) { warning("%s: not defined, defaulting to root", KW_SETTING_IPC_OWNER); ipc_owner = 0; } if (ipc_group == KWN_UNSET) { warning("%s: not defined, defaulting to root", KW_SETTING_IPC_GROUP); ipc_group = 0; } if (mtu == KWN_UNSET) { warning("%s: not defined, defaulting to 576", KW_SETTING_IP_MTU); mtu = 576; } if (mru == KWN_UNSET) { warning("%s: not defined, defaulting to 576", KW_SETTING_IP_MRU); mru = 576; } if (flag_autoreconnect == KWN_UNSET) { warning("%s: not defined, defaulting", KW_SETTING_MISC_AUTORECONNECT); flag_autoreconnect = FALSE; } if (!*misc_cmd) warning("%s: not defined", KW_COMMAND_PPPLCD_MISC); if (!*news_cmd) warning("%s: not defined", KW_COMMAND_PPPLCD_XFER_NEWS); if (!*mail_cmd) warning("%s: not defined", KW_COMMAND_PPPLCD_XFER_MAIL); if (!*wannabe_changed_cmd) warning("%s: not defined", KW_COMMAND_PPPLCD_WANNABECHANGED); if (pppd_kdebug && !pppd_debug) { warning("pppd-kdebug is set, setting ppp-debug too"); pppd_debug = 1; } /* * Flag that config has been successfully loaded - we may go ahead and * connect if we wish. */ state_cfgok = 1; return(0); } static int kill_pppd( int ifno) { FILE *fp; pid_t pppd_pid; char pppd_lock_file[PPPLCD_MAXSTRLEN]; debug(DBG_FUNCS, "kill_pppd: sof"); sprintf(pppd_lock_file, PPPD_LOCK_FILE_FMTSTR, ifno); if ((fp=fopen(pppd_lock_file, "r")) == NULL) { warning("unexpectedly no pppd lock file for ppp%d was found", ifno); return(1); } if (fscanf(fp, "%d", (int *) &pppd_pid) != 1) { warning("invalid text in lock file for ppp%d", ifno); return(1); } (void) fclose(fp); return(kill(pppd_pid, 15)); } @ 1.24 log @using IFNO_UNSET instead of '-1' internal symbol names for config file keywords all shortened SIGALM handler moved to inside sm.c SIGINT and SIGTERM handlers superflous - generic's are acceptable All references to 'named' now changed to 'wannabe_changed' second RCS id removed state_curr and state_want changed to flag_officially_up and flag_wannabe_up -nf is now -n added -i to allow attachement to an already up PPP interface locking, signal handler installation and initialisation rearranged made use of smf_init() return code lookup_msginfo() is now smf_msginfo() fork_and_submit_rc_ipc_msg() is now smf_fkwsmrc() named/wannabe state change handler now receives environment var, not cmdline par named/wannabe state change handler now doesn't remember previous state - this repetition avoidance was built in around calls to this function mhf_pppd_ok() code reorder to clarity @ text @d2 1 a2 1 static char *ppplcd_c_rcs_id = "$Header: /diskb/home/alexis/dev/supported/ppplc/bin/RCS/ppplcd.c,v 1.23 1999/05/06 08:43:09 alexis Exp alexis $"; d88 1 d254 1 d293 1 d384 7 d563 3 a565 2 sprintf(cmdbuf, "%s %s %d connect \"%s -v -f %s\" crtscts defaultroute lock netmask %s noipdefault asyncmap 0x00000000 mru %d mtu %d lcp-echo-interval 180 -detach lcp-echo-interval 0 kdebug %d%s", pppd_cmd, port, speed, chat_cmd, chatfile, netmask, mru, mtu, pppd_kdebug, pppd_debug ? " debug" : ""); d1225 1 d1351 7 @ 1.23 log @removed a superfluous symbol added a few comments about structure definitions moved nsswitcher code to state_want change time, not state_curr. added flag flag_exit_when_you_become_interruptable_again specifically to handle MSGID_HANGUP being sent when pppd is in IO locked signal deafness pppd-exit code clarified @ text @d2 1 a2 1 static char *ppplcd_c_rcs_id = "$Header: /diskb/home/alexis/dev/supported/ppplc/bin/RCS/ppplcd.c,v 1.22 1999/04/28 09:45:34 alexis Exp alexis $"; d56 1 d61 28 a88 27 #define PPPLCD_CONF_KW_COMMAND_UNIX_PPPD "command-unix-pppd" #define PPPLCD_CONF_KW_COMMAND_UNIX_CHAT "command-unix-chat" #define PPPLCD_CONF_KW_COMMAND_PPPLCD_ANNOUNCE "command-ppplcd-announce" #define PPPLCD_CONF_KW_COMMAND_PPPLCD_NSSWITCH "command-ppplcd-nsswitcher" #define PPPLCD_CONF_KW_SETTING_PPPD_DEBUG "setting-pppd-debug" #define PPPLCD_CONF_KW_SETTING_PPPD_KDEBUG "setting-pppd-kdebug" #define PPPLCD_CONF_KW_INCLUDE "include" #define PPPLCD_CONF_KW_SETTING_MISC_TIMEOUT_IDLE "setting-misc-timeout-idle" #define PPPLCD_CONF_KW_COMMAND_PPPLCD_QUALITYTEST "command-ppplcd-qualitytest" #define PPPLCD_CONF_KW_COMMAND_PPPLCD_USECOUNT "command-ppplcd-usecount" #define PPPLCD_CONF_KW_COMMAND_PPPLCD_XFER_NEWS "command-ppplcd-xfer-news" #define PPPLCD_CONF_KW_COMMAND_PPPLCD_XFER_MAIL "command-ppplcd-xfer-mail" #define PPPLCD_CONF_KW_SETTING_CONNECT_LOGIN "setting-connect-login" #define PPPLCD_CONF_KW_SETTING_CONNECT_PASSWORD "setting-connect-password" #define PPPLCD_CONF_KW_SETTING_CONNECT_PHONENUMBER "setting-connect-phonenumber" #define PPPLCD_CONF_KW_SETTING_MISC_AUTORECONNECT "setting-misc-autoreconnect" #define PPPLCD_CONF_KW_SETTING_IP_NETMASK "setting-ip-netmask" #define PPPLCD_CONF_KW_SETTING_IP_MTU "setting-ip-mtu" #define PPPLCD_CONF_KW_SETTING_IP_MRU "setting-ip-mru" #define PPPLCD_CONF_KW_SETTING_IPC_MODE "setting-ipc-mode" #define PPPLCD_CONF_KW_SETTING_IPC_OWNER "setting-ipc-owner" #define PPPLCD_CONF_KW_SETTING_IPC_GROUP "setting-ipc-group" #define PPPLCD_CONF_KW_SETTING_DEVICE_MODEM_DEVICE "setting-device-modem-device" #define PPPLCD_CONF_KW_SETTING_DEVICE_MODEM_SPEED "setting-device-modem-speed" #define PPPLCD_CONF_KW_SETTING_MISC_QUALITY "setting-misc-quality" #define PPPLCD_CONF_KW_CHATLINE "chatline" #define PPPLCD_CONF_KW_COMMAND_PPPLCD_MISC "command-ppplcd-misc" a107 1 static void sigalrm_handler(int); a109 1 static void sigint_handler(int); d123 3 a125 3 static int mhf_exec_named(int *); static int mhf_ok_named(int *); static int mhf_nok_named(int *); a167 1 static char *rcs_id = "$Header: /diskb/home/alexis/dev/supported/ppplc/bin/RCS/ppplcd.c,v 1.22 1999/04/28 09:45:34 alexis Exp alexis $"; d170 1 a170 1 static int ppp_interface_no = -1; d174 1 a174 1 static char named_modifier_cmd[PPPLCD_MAXSTRLEN]; d196 2 a197 2 static int state_curr; /* have we been connected? */ static int state_want; /* have we been connected? */ d200 1 d203 1 a203 1 static int autoreconnect_flag; d247 3 a249 3 { MSGID_EXEC_NAMED, mhf_exec_named }, { MSGID_OK_NAMED, mhf_ok_named }, { MSGID_NOK_NAMED, mhf_nok_named }, d279 1 a279 1 fprintf(stderr, "Usage: %s [ -d ] [ -nf ] [ -V ] \n", progname); d303 2 d306 1 a306 1 if (strcmp(argv[1], "-nf") == 0) d318 5 d339 4 a349 6 if ((locking_pid=my_lock(NULL, gen_lockfile_name)) > 0) error("running already (pid=%d)", locking_pid); else if (locking_pid < 0) error("can't create lockfile: %s", strerror(errno)); smf_shutdown(); d354 2 a355 1 * gracefully. d360 9 a368 2 signal(SIGINT, sigint_handler); signal(SIGTERM, sigterm_handler); d379 2 a380 24 smf_init(SMS_MCMODE_SERVER|SMS_MCMODE_CLIENT, assmf_init, argv[1]); /* * IMPORTANT NOTE: * In this program SIGALRM is a way to say "a job that was already * present on the C job queue is now due for servicing". * However, processing the queue in the signal handler can * get *very* sticky, because the processing can *itself* modify the * queue. Far safer is to let the SIGALRM cause the wait on the IPC * queue to break out, and the main loop to simply cycle round to checking * the C queue. This way we don't get terribly recursive. So, the handler * does *nothing*. And this is the critical bit: IGNORING SIGALRM IS NOT * THE SAME AS HAVING A HANDLER WHICH DOES NOTHING! THIS IS CRITICAL TO * THE FUNCTIONING OF THIS LOOP! If SIGALRM is ignored, then msgrcv() * simply goes on waiting forever and the (possibly overdue) message in * the C queue is never processed. If SIGALRM is left at its default * behaviour then the whole program aborts. However, if any handler is * specified, then msgrcv() exits with error code EINTR. We can test for * this. So the alarm handler *really* does nothing. It is just there * so that this signal() call can ensure that msgrcv() will exit when * the SIGALRM is generated. */ signal(SIGALRM, sigalrm_handler); a381 5 if (detach_flag) { i_am_a_daemon = TRUE; putenv("I_AM_A_DAEMON=true"); /* for child scripts */ } a407 25 static void sigalrm_handler( /*@@unused@@*/ int signumber) { debug(DBG_FUNCS, "sigalrm_handler: sof"); } static void sigint_handler( /*@@unused@@*/ int signumber) { debug(DBG_FUNCS, "sigint_handler: sof"); info("exiting on SIGINT"); exit(EXIT_FAILURE); } static void sigterm_handler( /*@@unused@@*/ int signumber) { debug(DBG_FUNCS, "sigterm_handler: sof"); info("exiting on SIGTERM"); exit(EXIT_FAILURE); } d442 1 a442 1 autoreconnect_flag = 1; d448 1 a448 1 autoreconnect_flag = 0; d461 1 a461 1 parcnt = (svrmsginfo_data+lookup_msginfo(svrmsginfo_data, MSGID_INFO_DATA))->argc; d471 1 a471 1 *(mp+0) = state_want; d474 1 a474 1 *(mp+3) = autoreconnect_flag; d496 1 a496 1 *(mp+20) = state_curr; d529 6 a534 20 /* * what about regenning the chat file? should that do here? no - another * step is needed - so that ppp-on results in MSGID_EXEC_PREPPPD getting * queued, and then this checks doregen_flag, if it's set - which the * server does at startup - then the file get's regenerated by a fork * and send sort of thing - perhaps not forking - and the flag gets * cleared, either way, the next step should be to queueu MSGID_EXEC_PPPD * - either in mhf_exec_prepppd - which would be the non-forking function * mentioned above - or should it fork? could be slow? - note that it * would be queued from there only if the regen was *not* necessary, * otherwise it would be queed from mhf_ok_prepppd(). */ if (state_curr) { warning("already connected!"); return; } /* how to detect currently running pppd that hasn't yet set state_curr? */ d538 1 d542 3 a544 11 if (state_want != 1) { state_want = 1; /* * Note that named restart has been moved to where state_want is * switched, rather than state_curr. This makes named settled and * ready to serve sendmail which will make requests as soon as the * connection is up (with Demon ISP). */ if (*named_modifier_cmd != '\0') { d548 1 a548 1 smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_NAMED, intp, SMS_SUBMIT_DIRECT); d552 1 a552 1 flag_exit_when_you_become_interruptable_again = 0; d556 1 a556 1 fork_and_submit_rc_ipc_msg(cmdbuf, MSGTO_PPPLCD, MSGID_OK_PPPD, MSGID_NOK_PPPD, svrmsginfo_data); d559 1 a559 1 static int mhf_exec_named( d562 5 a566 8 static int last_request = -1; char cmdbuf[512]; if (*statusp != last_request) { sprintf(cmdbuf, "%s %d", named_modifier_cmd, *statusp); fork_and_submit_rc_ipc_msg(cmdbuf, MSGTO_PPPLCD, MSGID_OK_NAMED, MSGID_NOK_NAMED, svrmsginfo_data); last_request = *statusp; } d569 1 a569 1 static int mhf_ok_named( d572 1 a572 1 debug(DBG_FUNCS, "mhf_ok_named: sof"); d575 1 a575 1 static int mhf_nok_named( d578 2 a579 2 debug(DBG_FUNCS, "mhf_nok_named: sof"); mhf_ok_named(notusedp); d588 1 a588 1 fork_and_submit_rc_ipc_msg(cmdbuf, MSGTO_PPPLCD, MSGID_NOACTION, MSGID_NOACTION, svrmsginfo_data); d607 1 a607 1 flag_exit_when_you_become_interruptable_again = 0; d613 1 a613 1 ppp_interface_no = -1; d634 2 a635 2 if (state_curr) { state_curr = 0; d643 1 a643 1 state_want = autoreconnect_flag; d646 1 a646 1 state_want = autoreconnect_flag; d649 1 a649 1 state_want = 0; d652 1 a652 1 state_want = 0; d657 3 a659 3 * Announce down only if we announced it was up (state_curr means * "we have announced it is up.") Note that announce_id depends on * the state_want we have just worked out, so the state_want d665 1 a665 1 announce_id = (state_want) ? ANNID_DOWN_REMOTE_REDIAL : d669 1 a669 1 announce_id = (state_want) ? ANNID_DOWN_QUALITY_REDIAL : d690 1 a690 6 /* * If we're not going to attempt reconnection, then switch named * back to non-internet mode. */ if (!state_want && *named_modifier_cmd != '\0') { d694 1 a694 1 smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_NAMED, intp, SMS_SUBMIT_DIRECT); d701 2 a702 1 if (state_want) d719 1 a719 1 flag_exit_when_you_become_interruptable_again = 0; d732 1 a732 1 fork_and_submit_rc_ipc_msg(qtest_cmd, MSGTO_PPPLCD, MSGID_OK_QTEST, MSGID_NOK_QTEST, svrmsginfo_data); d746 1 a746 1 if (quality_interval && quality_minlevel && state_curr && state_want) { d767 1 a767 1 } else if (state_inipup && !state_curr) d775 1 a775 1 fork_and_submit_rc_ipc_msg(mail_cmd, MSGTO_PPPLCD, MSGID_OK_MAIL, MSGID_NOK_MAIL, svrmsginfo_data); d799 1 a799 1 fork_and_submit_rc_ipc_msg(misc_cmd, MSGTO_PPPLCD, MSGID_NOACTION, MSGID_NOACTION, svrmsginfo_data); d806 1 a806 1 fork_and_submit_rc_ipc_msg(news_cmd, MSGTO_PPPLCD, MSGID_OK_NEWS, MSGID_NOK_NEWS, svrmsginfo_data); d833 1 a833 1 fork_and_submit_rc_ipc_msg(cmdbuf, MSGTO_PPPLCD, MSGID_OK_USECNT, MSGID_NOK_USECNT, svrmsginfo_data); d843 1 a843 1 if (idle_timeout && state_curr && state_want) { d923 1 a923 1 if (quality_minlevel > 0 && quality_interval > 0 && state_curr && state_want) d952 1 a952 1 if (idle_timeout > 0 && state_curr && state_want) { d989 2 a990 2 flag_exit_when_you_become_interruptable_again = 1; state_want = 0; d992 1 a992 1 if (state_curr) { d1060 1 a1060 1 state_curr = 1; a1115 3 autoreconnect_flag = 0; state_curr = 0; state_want = 0; d1119 10 d1130 3 a1132 3 * Code removed: we can no longer derive state_curr and state_want. * But we could have a command to mean "I'm telling you, the connection * is currently UP." d1168 4 a1171 4 idle_timeout = -1; autoreconnect_flag = -1; quality_interval = -1; quality_minlevel = -1; d1173 1 a1173 1 *named_modifier_cmd = '\0'; d1181 6 a1186 6 speed = -1; mtu = -1; mru = -1; ipc_mode = -1; ipc_owner = -1; ipc_group = -1; d1286 1 a1286 1 if (strcmp(cmdcp, PPPLCD_CONF_KW_INCLUDE) == 0) { d1292 1 a1292 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_COMMAND_UNIX_PPPD) == 0) { d1295 1 a1295 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_COMMAND_UNIX_CHAT) == 0) { d1298 1 a1298 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_PPPD_DEBUG) == 0) { d1301 1 a1301 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_PPPD_KDEBUG) == 0) { d1304 1 a1304 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_MISC_TIMEOUT_IDLE) == 0) { d1307 1 a1307 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_COMMAND_PPPLCD_ANNOUNCE) == 0) { d1310 2 a1311 2 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_COMMAND_PPPLCD_NSSWITCH) == 0) { strcpy(named_modifier_cmd, valcp); d1313 1 a1313 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_COMMAND_PPPLCD_QUALITYTEST) == 0) { d1316 1 a1316 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_COMMAND_PPPLCD_USECOUNT) == 0) { d1319 1 a1319 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_COMMAND_PPPLCD_MISC) == 0) { d1322 1 a1322 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_COMMAND_PPPLCD_XFER_NEWS) == 0) { d1325 1 a1325 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_COMMAND_PPPLCD_XFER_MAIL) == 0) { d1328 1 a1328 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_CONNECT_LOGIN) == 0) { d1331 1 a1331 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_CONNECT_PASSWORD) == 0) { d1334 1 a1334 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_CONNECT_PHONENUMBER) == 0) { d1337 1 a1337 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_IP_NETMASK) == 0) { d1340 1 a1340 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_IPC_MODE) == 0) { d1342 1 a1342 1 warning("%s: definition invalid", PPPLCD_CONF_KW_SETTING_IPC_MODE); d1347 1 a1347 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_IPC_OWNER) == 0) { d1351 1 a1351 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_IPC_GROUP) == 0) { d1357 1 a1357 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_MISC_QUALITY) == 0) { d1359 1 a1359 1 warning("%s: definition invalid", PPPLCD_CONF_KW_SETTING_MISC_QUALITY); d1364 1 a1364 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_DEVICE_MODEM_DEVICE) == 0) { d1367 1 a1367 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_DEVICE_MODEM_SPEED) == 0) { d1370 1 a1370 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_IP_MTU) == 0) { d1373 1 a1373 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_IP_MRU) == 0) { d1376 2 a1377 2 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_SETTING_MISC_AUTORECONNECT) == 0) { autoreconnect_flag = atoi(valcp); d1379 1 a1379 1 } else if (strcmp(cmdcp, PPPLCD_CONF_KW_CHATLINE) == 0) { d1426 1 a1426 1 warning("%s: not defined", PPPLCD_CONF_KW_COMMAND_UNIX_PPPD); d1429 1 a1429 1 warning("%s: not defined", PPPLCD_CONF_KW_COMMAND_UNIX_CHAT); d1431 4 a1434 5 } else if (autoreconnect_flag == -1) { warning("%s: not defined", PPPLCD_CONF_KW_SETTING_MISC_AUTORECONNECT); return(1); } else if (idle_timeout == -1) { warning("%s: not defined", PPPLCD_CONF_KW_SETTING_MISC_TIMEOUT_IDLE); d1437 1 a1437 1 warning("%s: not defined", PPPLCD_CONF_KW_COMMAND_PPPLCD_QUALITYTEST); d1440 1 a1440 1 warning("%s: not defined", PPPLCD_CONF_KW_COMMAND_PPPLCD_USECOUNT); d1443 1 a1443 1 warning("%s: not defined", PPPLCD_CONF_KW_COMMAND_PPPLCD_ANNOUNCE); d1446 1 a1446 1 warning("%s: not defined", PPPLCD_CONF_KW_SETTING_IP_NETMASK); d1449 1 a1449 1 warning("%s: not defined", PPPLCD_CONF_KW_SETTING_DEVICE_MODEM_DEVICE); d1451 2 a1452 2 } else if (speed == -1) { warning("%s: not defined", PPPLCD_CONF_KW_SETTING_DEVICE_MODEM_SPEED); d1455 1 a1455 1 warning("%s: not defined", PPPLCD_CONF_KW_SETTING_CONNECT_PHONENUMBER); d1458 1 a1458 1 warning("%s: not defined", PPPLCD_CONF_KW_SETTING_CONNECT_PASSWORD); d1461 1 a1461 1 warning("%s: not defined", PPPLCD_CONF_KW_SETTING_CONNECT_LOGIN); d1464 1 a1464 1 warning("%s: out of range", PPPLCD_CONF_KW_SETTING_PPPD_KDEBUG); d1467 1 a1467 1 warning("%s: out of range", PPPLCD_CONF_KW_SETTING_PPPD_DEBUG); d1469 2 a1470 2 } else if (quality_minlevel == -1 || quality_interval == -1) { warning("%s: not defined", PPPLCD_CONF_KW_SETTING_MISC_QUALITY); d1491 1 a1491 1 } else if ((cp=strstr(valbuf, "%I")) != NULL && idle_timeout == -1) { d1529 2 a1530 2 if (ipc_mode == -1) { warning("%s: not defined, defaulting to 0700", PPPLCD_CONF_KW_SETTING_IPC_MODE); d1533 2 a1534 2 if (ipc_owner == -1) { warning("%s: not defined, defaulting to root ownership", PPPLCD_CONF_KW_SETTING_IPC_OWNER); d1537 2 a1538 2 if (ipc_group == -1) { warning("%s: not defined, defaulting to root groupship", PPPLCD_CONF_KW_SETTING_IPC_GROUP); d1541 2 a1542 2 if (mtu == -1) { warning("%s: not defined, defaulting to 576", PPPLCD_CONF_KW_SETTING_IP_MTU); d1545 2 a1546 2 if (mru == -1) { warning("%s: not defined, defaulting to 576", PPPLCD_CONF_KW_SETTING_IP_MRU); d1549 5 d1555 1 a1555 1 warning("%s: not defined", PPPLCD_CONF_KW_COMMAND_PPPLCD_MISC); d1557 1 a1557 1 warning("%s: not defined", PPPLCD_CONF_KW_COMMAND_PPPLCD_XFER_NEWS); d1559 3 a1561 3 warning("%s: not defined", PPPLCD_CONF_KW_COMMAND_PPPLCD_XFER_MAIL); if (!*named_modifier_cmd) warning("%s: not defined", PPPLCD_CONF_KW_COMMAND_PPPLCD_NSSWITCH); a1585 3 if (ifno < 0) internal("(%s,%d): kill_pppd passed %d", __FILE__, __LINE__, ifno); a1601 1 @ 1.22 log @./dhuy.shpp ./sm_msgids.shpp ./utils.c ./sndmsg.c ./patchlevel.c ./patchlevel.h ./ppplc.h ./ppplc_msgids.c ./ppplcc.shpp ./xppplcc.shpp ./sm.h.shpp ./getmsg.c ./gep.sh.shpp ./sm.c ./ppplc_msgids.shpp ./ppplc_msgids.h.shpp @ text @d2 1 a2 1 static char *ppplcd_c_rcs_id = "$Header: /diskb/home/alexis/dev/supported/ppplc/bin/RCS/ppplcd.c,v 1.21 1999/04/26 16:14:48 alexis Exp alexis $"; a24 1 a30 1 d47 1 d55 1 d57 3 a59 1 #define PPPLCD_MHF_MAXSTRLEN 256 a86 2 #define PPPD_LOCK_FILE_FMTSTR "/var/run/ppp%d.pid" #define PPPLCD_MAXSTRLEN 256 d94 3 a96 3 struct strchnrec { char *str; struct strchnrec *nxt; d105 1 a105 1 static int gen_lockfile_name(char *, char *); /* write filename into buffer */ d155 1 a155 1 static int assmf_init(char *, uid_t *, gid_t *, int *); /* appspec state mc init fnc */ d168 1 a168 1 static char *rcs_id = "$Header: /diskb/home/alexis/dev/supported/ppplc/bin/RCS/ppplcd_mhf.c,v 1.21 1999/04/26 16:18:44 alexis Exp alexis $"; d200 2 a201 1 static struct strchnrec *strchnroot = NULL; a368 4 * Code removed; we can no longer derive state_curr and state_want. */ /* d565 1 d583 1 a583 1 warning("already connected or attempt in progress!"); d587 2 d594 19 a612 1 state_want = 1; d635 1 a635 1 if (state_inipup) ipup_part2(); d641 1 d663 11 a673 4 /* * This first paragraph is a list of things that have to be done * very very urgently, they match 1 to 1 with stuff done in * mhf_exec_ipup() before link tests. a677 6 if (*named_modifier_cmd != '\0') { if ((intp = (int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *intp = 0; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_NAMED, intp, SMS_SUBMIT_DIRECT); } d680 10 a689 1 * Normal stuff follows. d692 5 d699 5 d705 1 a705 8 /* * If the remote end hangs up either because of idle or bad line * or whatever then we take the decision to redial or not on * what the user has specified for this situation. */ case HUPID_UNSET: a706 1 announce_id = (state_want) ? ANNID_DOWN_REMOTE_REDIAL : ANNID_DOWN_REMOTE_NOREDIAL; d708 1 a708 1 case HUPID_QUALITY: a709 1 announce_id = (state_want) ? ANNID_DOWN_QUALITY_REDIAL : ANNID_DOWN_QUALITY_NOREDIAL; d711 1 a711 1 case HUPID_HANGUP: d713 23 d738 1 a738 2 case HUPID_IDLE: state_want = 0; d742 2 a743 1 internal("(%s,%d) unexpected down reason: %d", __FILE__, __LINE__, reason_down); d745 1 a745 5 } /* * Announce the connect is down for whatever reason */ d751 6 d758 2 a759 5 /* * Delete pending use count checks */ if ((mp=(int *) calloc(sizeof(int), 1)) == NULL) d761 3 a763 2 *mp = MSGID_EXEC_USECNT; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_DEL_MSGID, mp, SMS_SUBMIT_DIRECT); d765 3 a767 9 /* * Delete pending quality checks */ if ((mp=(int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *mp = MSGID_EXEC_QTEST; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_DEL_MSGID, mp, SMS_SUBMIT_DIRECT); } d785 4 d790 1 a790 1 ipup_part1(); d796 1 a796 1 char cmdbuf[PPPLCD_MHF_MAXSTRLEN]; d830 3 a832 6 /* * goodqual !goodqual * ----------------------------------- * ininup | do main ipup kill without announce * !inipup | do nothing kill with announce */ d834 2 a835 13 if (*qualityp < quality_minlevel) if (!state_curr && state_inipup) /* up but unannounced pending tests */ kill_pppd(ppp_interface_no); else { reason_down = HUPID_QUALITY; kill_pppd(ppp_interface_no); } else if (!state_curr && state_inipup) ipup_part3(); else ; d937 2 a938 1 if (*usecountp == idle_oldusecnt && time(NULL) > idle_oldusetim + idle_timeout) { d941 2 a942 1 kill_pppd(ppp_interface_no); d945 2 d951 1 d1055 2 d1058 1 d1061 1 a1061 1 kill_pppd(ppp_interface_no); d1063 2 d1096 1 a1096 2 debug(DBG_FUNCS, "ipup_part1 (nsswitcher): sof"); if (!state_want) return(kill_pppd(ppp_interface_no)); d1098 1 a1098 7 if (*named_modifier_cmd != '\0') { if ((intp = (int *) calloc(sizeof(int), 1)) == NULL) error("calloc: %s", strerror(errno)); *intp = 1; smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_NAMED, intp, SMS_SUBMIT_DIRECT); } else ipup_part2(); a1103 1 if (!state_want) return(kill_pppd(ppp_interface_no)); d1106 1 a1106 1 smf_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), MSGID_EXEC_QTEST, NULL, SMS_SUBMIT_DIRECT); d1108 1 a1108 1 ipup_part3(); d1113 1 a1113 1 char cmdbuf[PPPLCD_MHF_MAXSTRLEN]; d1118 4 a1121 1 if (!state_want) return(kill_pppd(ppp_interface_no)); d1158 1 a1158 1 debug(DBG_FUNCS|DBG_SPECIAL1, "ipup_part4 (placeholder): sof"); d1172 4 d1189 6 @ 1.21 log @changed size of fgets buffers @ text @a0 1 #define MAIN d2 1 a2 1 static char *ppplcd_c_rcs_id = "$Header: /diskb/home/alexis/dev/supported/ppplc/bin/RCS/ppplcd.c,v 1.20 1999/01/07 13:08:41 alexis Exp alexis $"; d4 5 a8 3 /* * System includes with reasons */ d11 20 a30 8 #include /* for printf and NULL */ #include /* for strrchr(), strtok(), strerror() */ #include /* for SIGINT, SIG_IGN etc */ #include /* for wait() par types */ #include /* for time() */ #include /* for setpgrp() */ #include /* for errno in strerror() */ #include /* for exit() */ a31 3 /* * Local includes with reasons */ a32 2 #include "ppplcd_msgids.h" /* for interprocess message codes */ #include "ppplcd_mhf.h" /* for msg handling fnc names only */ d34 1 a34 2 #include "ppplcd_ipc.h" /* for forward refs */ #include "ppplcd.h" /* for c queue definitions */ d36 2 a37 8 #include "ppplcd_cfg.h" /* for chatfile[] */ /* * Local defines */ #define TRUE (0 == 0) #define FALSE (0 != 0) d39 58 a96 14 #define MSGSZ 128 #define C_QUEUE_SIZE 8 #define PPPD_LOCK_FILE_FMTSTR "/var/run/ppp%d.pid" /* * Structures used by static functions and statuc and automatic data */ struct c_queue_rec { time_t time; /* dequeue time */ int id; /* message id */ int *parp; /* parameter block pointer */ d99 5 a103 3 /* * Forward refs for functions defined externally */ a104 5 /* * Forward refs for static functions */ static void c_queue_process(void); d106 57 d164 46 a209 34 /* * Global variables */ char pppd_cmd[PPPLCD_MAXSTRLEN]; char chat_cmd[PPPLCD_MAXSTRLEN]; char announce_cmd[PPPLCD_MAXSTRLEN]; char named_modifier_cmd[PPPLCD_MAXSTRLEN]; char port[16]; uid_t ipc_owner; gid_t ipc_group; int ipc_mode; char netmask[32]; int speed; int mtu; int mru; char login[16]; char password[16]; char telno[32]; char *master_config_file; int quality_interval; int quality_minlevel; int idle_timeout; int state_cfgok; int state_curr; /* have we been connected? */ int state_want; /* have we been connected? */ int state_inipup; /* in post conn sequence? */ int state_donenx; /* to assess if ipup finished */ int state_donemx; /* to assess if ipup finished */ int state_quit; int do_xfer_news_flag; int autoreconnect_flag; struct mhflkuprec svrmhf_data[] = { a244 2 { MSGID_SUB_MSGID, mhf_sub_msgids }, { MSGID_DEL_MSGID, mhf_del_msgid }, d249 2 a250 1 { MSGID_USECNT_RESPONSE, mhf_usecnt_response } d253 11 a263 10 /* * Static data */ static struct c_queue_rec c_queue[C_QUEUE_SIZE];/* for delayed messages */ static int c_queue_top; /* how many in that array? */ static char *lock_dir = NULL; /* locks dir, dflt if null */ static char **global_argvp; /* for funcs to change cmdln */ static int global_argc; /* for funcs to change cmdln */ d266 6 a271 1 * Functions! a273 65 void sigalrm_handler( /*@@unused@@*/ int signumber) { debug(DBG_FUNCS, "sigalrm_handler: sof"); } void sigint_handler( /*@@unused@@*/ int signumber) { debug(DBG_FUNCS, "sigint_handler: sof"); info("exiting on SIGINT"); exit(EXIT_FAILURE); } void sigterm_handler( /*@@unused@@*/ int signumber) { debug(DBG_FUNCS, "sigterm_handler: sof"); info("exiting on SIGTERM"); exit(EXIT_FAILURE); } void sigchld_handler( /*@@unused@@*/ int signumber) { signal(SIGCHLD, SIG_IGN); debug(DBG_FUNCS, "sigchld_handler: sof"); (void) wait(NULL); debug(DBG_SIGEXEC, "sigchld_handler: done wait()"); signal(SIGCHLD, sigchld_handler); } int kill_pppd( int ifno) { FILE *fp; pid_t pppd_pid; char pppd_lock_file[PPPLCD_MAXSTRLEN]; debug(DBG_FUNCS, "kill_pppd: sof"); if (ifno < 0) internal("(%s,%d): kill_pppd passed %d", __FILE__, __LINE__, ifno); sprintf(pppd_lock_file, PPPD_LOCK_FILE_FMTSTR, ifno); if ((fp=fopen(pppd_lock_file, "r")) == NULL) { warning("unexpectedly no pppd lock file for ppp%d was found", ifno); return(1); } if (fscanf(fp, "%d", (int *) &pppd_pid) != 1) { warning("invalid text in lock file for ppp%d", ifno); return(1); } (void) fclose(fp); return(kill(pppd_pid, 15)); } a299 1 c_queue_top = 0; a300 2 do_xfer_news_flag = 1; autoreconnect_flag = 0; a323 1 master_config_file = argv[1]; d343 1 a343 1 (void) ppplcd_ipc_server_shutdown(); a355 10 /* * Initialise state info */ state_curr = 0; state_want = 0; state_inipup = 0; state_quit = 0; state_cfgok = 0; d365 1 a365 7 if (load_config(master_config_file, 0) != 0) warning("config file load failed"); else if (gen_config() != 0) warning("config file generate failed"); if (ppplcd_ipc_server_init(ipc_owner, ipc_group, ipc_mode) != 0) error("failed to locate message queue"); a392 1 c_queue_top = 0; d399 1 a399 27 while (!state_quit) { /* * Try to read the IPC message queue. If an error occurs then abort. * If we get an interrupted system call then this should be becuase * an alarm has gone off, but since we can't be sure it's best to * to cancel any pending alarm anyway. (It will get set in the queue * processing code anyway.) */ rc = ipc_queue_process(svrmsginfo_data, MSGTO_PPPLCD, c_queue_submit); if (rc < 0) error("read error on ipc msg"); else if (rc == EINTR) (void) alarm(0); /* * Process the C queue. This may or may not set an alarm which * *should* interrupt the IPC read after we loop round. Note that * this should come *after* the IPC read in the loop, in order * that state_quit gets tested before the IPC read, otherwise * we can send a quit message, and the system doesn't quit until * any other message is recieved. */ c_queue_process(); } d405 1 a405 1 (void) ppplcd_ipc_server_shutdown(); d419 80 a498 13 int fork_and_submit_rc_ipc_msg( char *cmdstr, int okmsgid, int nokmsgid) { pid_t pid; /* used to hold process ids */ int cmdrc; /* return code of the exec'd command */ int statsup; /* for ascertaining rc of exec'd prg */ int old_statsup; /* for ascertaining rc of exec'd prg */ int inquotes, inword, moveon; char *argv[64]; int i; char *cp; d501 32 a532 1 debug(DBG_FUNCS, "fork_and_submit_rc_ipc_msg: sof"); d535 1 a535 2 * do some very very quick tests on the string to check there's * nothing really daft going on. d538 32 a569 4 if (cmdstr == NULL || *cmdstr == '\0') { debug(DBG_SPECIAL1, "fork_and_submit_rc_ipc_msg: invalid cmdstr"); return(-1); } d572 10 a581 2 * Let the server go on with what it was doing - possibly dealing with * more messages and signals. d584 27 a610 5 if ((pid=fork()) < 0) error(strerror(errno)); else if (pid > 0) { debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg: returning after fork"); return(0); d612 46 d660 1 a660 5 * 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. d663 98 a760 3 signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGCHLD, SIG_DFL); d762 6 a767 5 debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg-rc_rptr: about to fork execer and wait"); if ((pid=fork()) < 0) error(strerror(errno)); else if (pid == 0) { d769 6 a774 4 /* * The execer process should use default handlers, as it it were * being run from the shell. */ d776 9 a784 2 signal(SIGTERM, SIG_DFL); signal(SIGINT, SIG_DFL); d786 7 a792 36 inword=0; inquotes=0; moveon=1; for (i=0,cp=cmdstr; *cp != '\0'; moveon && cp++) { moveon = 1; /* *after* quotes we're always in a word */ if (!inword && inquotes) { argv[i++] = cp; inword = 1; /* start of normal word */ } else if (!inword && *cp != ' ' && *cp != '\t' && *cp != '"') { argv[i++] = cp; inword = 1; /* encountering quotes 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 == '"') { inquotes = 1; /* but we do need to shuffle everything after this up one */ (void) strmove(cp, cp+1); moveon = 0; /* normal end of word */ } else if (!inquotes && (*cp == ' ' || *cp == '\t')) { *cp = '\0'; inword = 0; /* encountering end quotes does not mean end of word ("hell"o) */ } else if (inquotes && *cp == '"') { inquotes = 0; /* *cp = '\0'; */ inword = 0; /* but we do need to shuffle everything after this up one */ (void) strmove(cp, cp+1); moveon = 0; } d794 13 d808 44 a851 7 argv[i] = NULL; /*@@-onlytrans@@*/ argv[0] = mybasename(argv[0], ""); /*@@=onlytrans@@*/ (void) execv(cmdstr, argv); error(strerror(errno)); } d853 1 a853 30 debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg-rc_rptr: waiting for all children"); old_statsup = -1; while (wait(&statsup) != -1) { debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg-rc_rptr: caught a child with wait"); old_statsup = statsup; } debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg-rc_rptr: done waiting for all children"); if (old_statsup == -1) internal("(%s,%d)", __FILE__, __LINE__); else if (old_statsup & 0x7f == 0x7f) internal("don't know how to handle child stopping on signal %d (%s,%d)", (unsigned) old_statsup >> 8, __FILE__, __LINE__); else if (old_statsup & 0x7f) internal("don't know how to handle child exiting on signal %d (%s,%d)", old_statsup & 0x7f, __FILE__, __LINE__); cmdrc = (int) ((unsigned) old_statsup >> 8); debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg-rc_rptr: child exited with exit %d", cmdrc); /* * Note we can't use c_queue_submit here because it would go to the * return-code-reporter's C queue - NOT - the C-queue-processor's * C queue. We *must* use IPC. */ debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg-rc_rptr: sending rc"); /*@@-evalorder@@*/ if ((rc=ipc_queue_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), (cmdrc == 0) ? okmsgid : nokmsgid, NULL)) != 0) /*@@=evalorder@@*/ error("can't queue message (%d)", rc); exit(EXIT_SUCCESS); d856 1 a856 3 int c_queue_submit( time_t dotime, int msgid, d859 51 a909 11 int i, j; time_t tmptime; int *tmpparp; int tmpid; time_t timenow; debug(DBG_FUNCS, "c_queue_submit: sof"); if (c_queue_top == C_QUEUE_SIZE) { warning("c queue is full, submit ignored"); return(1); d911 1 d913 4 a916 19 c_queue[c_queue_top].time = dotime; c_queue[c_queue_top].id = msgid; /*@@-temptrans@@*/ c_queue[c_queue_top].parp = parp; /*@@=temptrans@@*/ c_queue_top++; debug(DBG_MSGQ, "c_queue_submit: submitted: time %ld, id %d", dotime, msgid); for (i=0; i c_queue[j+1].time) { tmptime = c_queue[j].time; c_queue[j].time = c_queue[j+1].time; c_queue[j+1].time = tmptime; /*@@-kepttrans -mustfree@@*/ tmpparp = c_queue[j].parp; c_queue[j].parp = c_queue[j+1].parp; c_queue[j+1].parp = tmpparp; /*@@=kepttrans =mustfree@@*/ tmpid = c_queue[j].id; c_queue[j].id = c_queue[j+1].id; c_queue[j+1].id = tmpid; } } } d918 7 a924 2 for (timenow=time(NULL), i=0; i 0 && (timenow=time(NULL)) >= c_queue[0].time) { debug(DBG_MSGQ, "c_queue_process: dequeuing message %d", c_queue[0].id); d977 23 a999 4 /* * Under the new system it is vital to dequeue the entry *before* * executing it. Otherwise we can easily get into infinite loops. */ d1001 4 a1004 9 tmp_id = c_queue[0].id; tmp_parp = c_queue[0].parp; for (i=0; i 0) { debug(DBG_FUNCS, "c_queue_process: setting c queue process time"); (void) alarm((unsigned) c_queue[0].time - timenow); } else debug(DBG_FUNCS, "c_queue_process: no jobs on c queue, no alarm"); debug(DBG_FUNCS, "c_queue_process: eof"); d1114 1 a1114 2 int c_queue_del_msgid( int msgid) d1116 7 a1122 1 int s, d; d1124 23 a1146 1 debug(DBG_FUNCS, "c_queue_del_msgid: sof"); d1148 9 a1156 13 for (s=0,d=0; s 0) error("locked already (pid=%d)", (int) locking_pid); d295 1 a295 1 error("locking problem"); d334 1 a334 2 if (ppplcd_ipc_server_init(ipc_owner, ipc_group, ipc_mode) != 0) { cleanup(); a335 1 } d365 5 d381 1 a381 2 if (rc < 0) { cleanup(); d383 1 a383 1 } else if (rc == EINTR) d403 1 a403 1 cleanup(); d407 8 d553 1 a553 1 if ((rc=ipc_queue_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), (cmdrc == 0) ? okmsgid : nokmsgid, NULL)) != 0) { a554 1 cleanup(); a555 1 } @ 1.18 log @delinted abstracted ppp interface number - preparatory to per-interface servers added nsswitcher support removed unused variables removed ppplcdexit() - part of functionality taken on cleanup @ text @d3 1 a3 1 static char *rcs_id = "$Id: ppplcd.c,v 1.17 1998/08/31 12:40:37 alexis Exp alexis $"; d430 10 @ 1.17 log @added function to delete messages from queue @ text @d2 2 a3 1 static char *rcs_id = "$Id: ppplcd.c,v 1.16 1998/08/28 17:39:26 alexis Exp alexis $"; d42 1 a42 1 #define PPPD_LOCK_FILE "/var/run/ppp0.pid" d71 1 d74 2 a75 2 int ipc_owner; int ipc_group; d108 1 a108 1 { MSGID_EXEC_MAIL, mhf_exec_mail }, d137 3 a146 1 static int c_queue_lock = 0; d158 1 a158 2 void ppplcdexit( int rc) d160 3 a162 4 if (*chatfile) unlink(chatfile); my_lock(progname, lock_dir); exit(rc); d166 2 a167 1 int unknown) d173 2 a174 1 int unknown) d178 2 a179 1 ppplcdexit(0); d183 2 a184 1 int unknown) d188 2 a189 1 ppplcdexit(0); d193 2 a194 1 int unknown) d198 1 a198 1 wait(NULL); d203 2 a204 1 int kill_pppd() d207 2 a208 1 int pppd_pid; d212 7 a218 2 if ((fp=fopen(PPPD_LOCK_FILE, "r")) == NULL) { warning("pppd is not running or not up yet"); d221 7 a227 2 fscanf(fp, "%d", &pppd_pid); fclose(fp); d232 1 a232 1 usage() d237 1 a237 1 exit(1); d245 1 a245 5 int msgidx; int msgid; char buf[MAX_MSG_SIZ]; int par; int locking_pid; a246 1 FILE *fp; d269 1 a269 1 exit(0); d273 1 a273 1 (sscanf(argv[2], "%ld", &debug_level)!=1) && usage(); d277 1 a277 1 usage(); d284 1 a284 1 usage(); d288 5 a292 5 ; else if ((rc=fork()) < 0) error(exit, 1, strerror(errno)); else if (rc > 0) exit(0); d295 1 d297 1 d301 1 a301 1 error(exit, 1, "locked already (pid=%d)", locking_pid); d303 1 a303 1 error(exit, 1, "locking problem"); d305 1 a305 1 ppplcd_ipc_server_shutdown(); d319 1 a319 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? d337 1 a337 3 if (load_config(master_config_file, 0) == 0) gen_config(); else d339 2 d342 3 a344 12 if (ppplcd_ipc_server_init(ipc_owner, ipc_group, ipc_mode)) error(ppplcdexit, 1, "failed to locate message queue"); /* * Take state_curr from whether ppp0 interface is up */ if ((fp=fopen("/proc/net/route", "r")) == NULL) error(ppplcdexit, 1, "fopen: ", strerror[errno]); while (fgets(buf, sizeof(buf), fp) != NULL) { if (strncmp(buf, "ppp0", 4) == 0) state_curr = 1; a345 1 fclose(fp); d348 1 a348 1 * Assume state_done and state_want are the same as state_curr a350 2 state_want = state_curr; d386 5 a390 4 if (rc < 0) error(ppplcdexit, 1, "read error on ipc msg"); else if (rc == EINTR) alarm(0); d408 3 a410 2 ppplcd_ipc_server_shutdown(); ppplcdexit(0); d414 1 a414 1 fork_and_submit_rc_ipc_msg( d419 1 a419 1 int pid; /* used to hold process ids */ d437 1 a437 1 error(ppplcdexit, 1, strerror(errno)); d440 1 a440 1 return; d458 1 a458 1 error(exit, 1, strerror(errno)); d470 1 a470 1 for (i=0,cp=cmdstr; *cp; moveon && cp++) { d488 1 a488 1 strmove(cp, cp+1); d502 1 a502 1 strmove(cp, cp+1); d508 1 d510 3 a512 2 execv(cmdstr, argv); error(exit, 1, strerror(errno)); a514 4 /* sprintf(*(global_argvp+0), "%.*s", strlen(*(global_argvp+0)), "child"); for (i=1; i> 8); d528 4 a531 5 debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg-rc_rptr: child exited on signal %d", old_statsup & 0x7f); else { cmdrc = old_statsup >> 8; debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg-rc_rptr: child exited with exit %d", cmdrc); } d539 8 a546 4 debug(DBG_SIGEXEC, "fork_and_submit_rc_ipc_msg-rc_rptr: sending rc"); if (rc=ipc_queue_submit(svrmsginfo_data, MSGTO_PPPLCD, time(NULL), (cmdrc == 0) ? okmsgid : nokmsgid, NULL)) error(ppplcdexit, 1, "can't queue message (%d)", rc); exit(0); a557 1 time_t interval; d564 1 a564 1 return; d569 1 d571 1 d579 1 d581 1 d591 1 d637 1 a637 1 (svrmhf_data[msgidx].fnc)(tmp_parp); d654 1 a654 1 alarm(c_queue[0].time - timenow); a679 1 c_queue_info(); d681 1 d702 1 a702 12 } c_queue_info() { int i; time_t timenow = time(NULL); debug(DBG_FUNCS, "c_queue_info: sof"); for (i=0; i> 8); d530 1 a530 1 debug(DBG_SIGEXEC, "forkandsend-child: child exited on signal %d", old_statsup & 0x7f); d533 1 a533 1 debug(DBG_SIGEXEC, "forkandsend-child: child exited with exit %d", cmdrc); d536 9 a544 5 #if OLD_SYSTEM ppplcd_ipc_send_msg(svrmsginfdat, MSGTO_SVR, (cmdrc == 0) ? okmsgid : nokmsgid, NULL); #else delayqueue_send(time(NULL), (cmdrc == 0) ? okmsgid : nokmsgid, NULL); #endif d548 1 a548 1 delayqueue_send( d558 1 d560 1 a560 2 debug(DBG_FUNCS, "delayqueue_send: sof"); delayqueue_lock(); d562 4 a565 2 if (delayq_top == DELAYQ_SIZ) error(ppplcdexit, 1, "delay queue is full!"); d567 12 a578 12 delayq[delayq_top].time = dotime; delayq[delayq_top].id = msgid; delayq[delayq_top].parp = parp; delayq_top++; debug(DBG_MSGQ, "delayqueue_send: delay-queued (%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; d583 2 a584 2 for (i=0; i 0 && time(NULL) >= delayq[0].time) { debug(DBG_MSGQ, "sigalrm_handler: now sending delayed message %d", delayq[0].id); #if OLD_SYSTEM ppplcd_ipc_send_msg(svrmsginfdat, MSGTO_SVR, delayq[0].id, delayq[0].parp); for (i=0; i 0) { interval = delayq[0].time - time(NULL); if (interval > 0) { signal(SIGALRM, sigalrm_handler); debug(DBG_MSGQ, "delayqueue_unlock: %d second interval - setting alarm", interval); alarm(interval); } else { signal(SIGALRM, sigalrm_handler); debug(DBG_MSGQ, "delayqueue_unlock: zero interval - setting alarm for one second"); alarm(1); } } debug(DBG_FUNCS, "delayqueue_unlock: eof"); a707 1 #endif @ 1.13 log @milepost - seems to work ok, though few messages seem wrong @ text @d2 4 a5 1 static char *rcs_id = "$Id: ppplcd.c,v 1.12 1998/03/01 22:29:29 alexis Exp alexis $"; a48 4 /* * Forward refs for static functions */ d62 1 d75 1 d96 3 a98 2 void sigalrm_handler(int); int delaysendmsg(time_t, int, int *); d100 4 d148 17 a164 2 struct delaymsgrec delayq[DELAYQ_SIZ]; /* for delayed messages and activation times */ int delayq_top; /* how many elements in that array? */ d180 1 d193 1 d436 4 d442 1 a442 1 if ((argc=ppplcd_ipc_read_msg(svrmsginfdat, MSGTO_SVR, svrmhflkupdat)) < 0) d575 1 d577 3 d583 1 a583 1 delaysendmsg( d594 2 a595 4 /* we don't really want to be messing with the queue and get interrupted */ signal(SIGALRM, SIG_IGN); debug(DBG_FUNCS, "delaysendmsg: sof"); d604 1 a604 1 debug(DBG_MSGQ, "delaysendmsg: delay-queued (%ld,%d)", dotime, msgid); d617 1 a617 1 debug(DBG_MSGQ, "delaysendmsg: rank %d, time %ld, id %d", i, delayq[i].time, delayq[i].id); d619 2 a620 5 interval = delayq[0].time - time(NULL); debug(DBG_MSGQ, "delaysendmsg: setting alarm for %d seconds", interval); signal(SIGALRM, sigalrm_handler); alarm(interval); d623 1 a623 1 void sigalrm_handler( d627 3 a637 1 signal(SIGALRM, SIG_IGN); d639 1 d648 3 d652 9 d662 9 a673 1 delayq[i].en = delayq[i+1].en; d677 9 d693 38 a730 1 debug(DBG_MSGQ, "sigalrm_handler: rank %d, time %ld, id %d, en %d", i, delayq[i].time, delayq[i].id, delayq[i].en); d732 10 a741 5 /* * If there are messages in the queue then set the alarm for the * wakeup time of the first job. If not then there's no need to * set the alarm. (It will be set when a job is added.) */ d743 1 d745 10 a754 3 debug(DBG_MSGQ|DBG_SIGEXEC, "sigalrm_handler: setting alarm"); signal(SIGALRM, sigalrm_handler); alarm(delayq[0].time - time(NULL)); d756 1 d758 1 @ 1.12 log @added name of function in some debug calls @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.11 1997/11/11 11:54:41 alexis Exp alexis $"; d23 1 a23 1 #include "utils.h" /* for basename(), and various error fncs */ d55 2 a56 2 extern int mhf_set_idlecheck(); extern int mhf_set_qualitycheck_interval(int *); a57 2 extern int mhf_unset_idlecheck(); extern int mhf_unset_qualitycheck_interval(); d75 9 a83 3 extern int mhf_exec_idle(); extern int mhf_ok_idle(); extern int mhf_nok_idle(); d90 4 a93 2 extern int mhf_set_redial_on_hangup(); extern int mhf_unset_redial_on_hangup(); d121 3 a123 4 int qualitycheck_interval; int idlecheck_interval; int idlecheck_timeout; d171 6 a176 3 { MSGID_EXEC_IDLECHECK, mhf_exec_idle }, { MSGID_OK_IDLECHECK, mhf_ok_idle }, { MSGID_NOK_IDLECHECK, mhf_nok_idle }, d180 1 a180 1 { MSGID_SET_QUALITYCHECK, mhf_set_qualitycheck_interval }, d183 7 a189 2 { MSGID_SET_IDLECHECK, mhf_set_idlecheck }, { MSGID_UNSET_QUALITYCHECK, mhf_unset_qualitycheck_interval }, d193 4 a196 3 { MSGID_SET_REDIAL_ON_HANGUP, mhf_set_redial_on_hangup }, { MSGID_UNSET_REDIAL_ON_HANGUP, mhf_unset_redial_on_hangup }, { MSGID_UNSET_IDLECHECK, mhf_unset_idlecheck } d200 1 a200 1 int on_remote_hangup_do_redial; d243 1 a243 1 debug(DBG_SIGS, "sigchld_handler: done wait()"); d268 1 a268 1 fprintf(stderr, "Usage: %s [ -d ] [ -r | -nr ] [ -nn ] [ -nf ] [ -V ] config_file\n", progname); d294 1 a294 1 progname = basename(argv[0], ""); d298 1 a298 1 on_remote_hangup_do_redial = 0; d301 1 a301 4 if (strcmp(argv[1], "-nn") == 0) do_xfer_news_flag = 0; else if (strcmp(argv[1], "-nf") == 0) a303 6 else if (strcmp(argv[1], "-r") == 0) on_remote_hangup_do_redial = 1; else if (strcmp(argv[1], "-nr") == 0) on_remote_hangup_do_redial = 0; a317 5 } else if (strcmp(argv[1], "-dl") == 0) { (argc<3) && usage(); lock_dir = argv[2]; argc--; argv++; d339 1 a339 1 debug(DBG_LOCKS, "main: before make_lock"); d353 1 a353 1 debug(DBG_SIGS, "main: setting up signal handlers"); d451 1 a451 1 debug(DBG_EXECS, "forkandsend-caller: returning straight away after successful fork"); d467 1 a467 1 debug(DBG_EXECS, "forkandsend-wrapper: running (pid=%d), about to fork and wait", getpid()); d520 1 a520 1 argv[0] = basename(argv[0], ""); d525 1 a525 1 sprintf(*(global_argvp+0), "%.*s", strlen(*(global_argvp+0)), "wrapper"); d529 1 a529 1 debug(DBG_SIGS, "forkandsend-wrapper: waiting for all children"); d532 1 a532 1 debug(DBG_SIGS, "forkandsend-wrapper: caught a child with wait"); d535 1 a535 1 debug(DBG_SIGS, "forkandsend-wrapper: done waiting for all children"); d540 1 a540 1 debug(DBG_SIGS, "forkandsend-wrapper: child stopped on signal %d", old_statsup >> 8); d542 1 a542 1 debug(DBG_SIGS, "forkandsend-wrapper: child exited on signal %d", old_statsup & 0x7f); d545 1 a545 1 debug(DBG_EXECS, "forkandsend-wrapper: child exited with exit %d", cmdrc); a560 1 int tmpen; a572 1 delayq[delayq_top].en = 1; d575 1 a575 1 debug(DBG_DELAYQ, "delaysendmsg: added (%ld,%d)", dotime, msgid); a582 1 tmpen = delayq[j].en; delayq[j].en = delayq[j+1].en; delayq[j+1].en = tmpen; d588 1 a588 1 debug(DBG_DELAYQ, "delaysendmsg: rank %d, time %ld, id %d, en %d", i, delayq[i].time, delayq[i].id, delayq[i].en); d591 1 a591 1 debug(DBG_DELAYQ, "delaysendmsg: setting alarm for %d seconds", interval); d602 7 a608 2 /* we don't want to get interrupted - not that we should since there is only one alarm clock! */ d610 1 d612 4 a615 1 debug(DBG_FUNCS, "sigalrm_handler: sof"); d618 2 a619 7 if (delayq[0].en) { debug(DBG_DELAYQ, "sigalrm_handler: now sending delayed message %d", delayq[0].id); ppplcd_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"); d630 4 d635 7 a641 1 debug(DBG_DELAYQ, "sigalrm_handler: rank %d, time %ld, id %d, en %d", i, delayq[i].time, delayq[i].id, delayq[i].en); d644 1 a644 1 debug(DBG_DELAYQ|DBG_SIGS, "sigalrm_handler: resetting alarm"); a646 5 } 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.11 log @ppplcd_utils.h renamed added support for config-defined newshost, mtu, mru ditched quality check remote host and acceptable level - now must be spec'd on quality testing command's command line created global argc, argv to be modified in the same way sendmail does for process listings lock functions renamed added code to detect development versions (as opposed to releases) @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.10 1997/10/26 12:12:29 alexis Exp alexis $"; d540 1 a540 1 debug(DBG_SIGS, "child stopped on signal %d", old_statsup >> 8); d542 1 a542 1 debug(DBG_SIGS, "child exited on signal %d", old_statsup & 0x7f); d545 1 a545 1 debug(DBG_EXECS, "child exited with exit %d", cmdrc); @ 1.10 log @stamped for release 1.0.6 @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.9 1997/10/20 17:30:40 alexis Exp alexis $"; d23 1 a23 1 #include "ppplcd_utils.h" /* for basename(), and various error fncs */ d102 1 d108 2 a114 1 char qualitycheck_remhost[32]; a115 1 int qualitycheck_minquality; d189 2 d203 1 a203 1 unmake_lock(progname, lock_dir); d270 9 d300 7 a306 2 printf("%s version %s\n", progname, patchlevel); exit(0); d340 1 a340 1 if ((locking_pid=make_lock(progname, lock_dir)) > 0) d494 1 a494 1 /* encountering quaotes while not in a word, means the next d524 4 @ 1.9 log @version info now just printf'd @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.8 1997/10/20 16:58:17 alexis Exp alexis $"; @ 1.8 log @modified basename function to take a second parameter to strip @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.7 1997/09/22 18:01:23 alexis Exp $"; d288 1 a288 2 debug_level |= DBG_INFO; info("version %s", patchlevel); @ 1.7 log @LOCK_DIR abstracted lock_dir (command line lock directory specification) added detach_flag moved to ppplcd_utils.c as it's used by messaging funcs and sndmsg blows up if it's not available for it also @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.6 1997/02/21 17:12:10 alexis Exp alexis $"; d268 1 a268 1 progname = basename(argv[0]); d504 1 a504 1 argv[0] = basename(argv[0]); @ 1.6 log @New vars for ipc ownership. group perms table indentation corrected - cosmetic locking function return code examined for error or existing lock msg queue init relocated to after loading of config files (need ipc owner etc) @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.5 1997/02/16 14:42:28 alexis Exp alexis $"; d187 2 d200 1 a200 1 unmake_lock(progname); a261 1 int detach_flag; a270 2 /* debug_level = 5; */ d293 7 a299 1 (argc<3 || sscanf(argv[2], "%ld", &debug_level)!=1) && usage(); d313 3 a315 1 if ((rc=fork()) < 0) d324 1 a324 1 if ((locking_pid=make_lock(progname)) > 0) @ 1.5 log @states moved back here. and now evaluated rather than assumed. @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.4 1997/02/16 12:39:36 alexis Exp alexis $"; d102 3 d144 38 a181 38 { 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_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_GEN_CONFIG, mhf_gen_config }, { MSGID_SET_REDIAL_ON_HANGUP, mhf_set_redial_on_hangup }, { MSGID_UNSET_REDIAL_ON_HANGUP, mhf_unset_redial_on_hangup }, { MSGID_UNSET_IDLECHECK, mhf_unset_idlecheck } d317 1 a317 1 if ((locking_pid=make_lock(progname)) != 0) d319 2 a322 2 if (ppplcd_ipc_server_init()) error(ppplcdexit, 1, "failed to locate message queue"); d341 3 a343 3 state_curr = 0; state_want = 0; state_done = 0; d345 2 a346 2 state_quit = 0; state_cfgok = 0; d352 3 d361 3 @ 1.4 log @added -V option @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.3 1997/02/15 11:12:52 alexis Exp alexis $"; d122 2 d246 1 a246 1 fprintf(stderr, "Usage: %s [ -d ] [ -r | -nr ] [ -nn ] [ -nf ]\n", progname); d262 1 d338 2 d355 20 @ 1.3 log @master config file must now be supplied on command line. usage message correct now. @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.2 1997/02/09 16:00:50 alexis Exp alexis $"; d282 6 a287 1 else if (strcmp(argv[1], "-d") == 0) { @ 1.2 log @More changes ... now works. @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.1 1997/02/01 21:52:17 alexis Exp alexis $"; a40 1 #define MASTER_CONFIG_FILE "/home/alexis/dev/ppp/master.cfg" d107 1 d244 1 a244 1 fprintf(stderr, "Usage: %s\n", progname); d293 1 a293 1 if (argc != 1) d295 1 d341 1 a341 1 if (load_config(MASTER_CONFIG_FILE, 0) == 0) @ 1.1 log @Initial revision @ text @d2 1 a2 1 static char *rcs_id = "$Id: ppplcd.c,v 1.3 1997/01/31 14:43:34 alexis Exp alexis $"; d10 1 a10 1 #include /* for strrchr(), strtok() */ d15 2 d27 1 a51 1 extern int mhf_got_good_conn(); a107 1 char chatfile[64]; d188 9 d202 1 a202 2 unmake_lock(progname); exit(0); d210 1 a210 2 unmake_lock(progname); exit(0); d259 1 d296 5 a300 1 fork() && exit(0); d306 1 a306 1 error("locked already (pid=%d)", locking_pid); d309 2 a310 4 if (ppplcd_ipc_server_init()) { unmake_lock(progname); exit(1); } d351 3 a353 6 while (!state_quit) { if ((argc=ppplcd_ipc_read_msg(svrmsginfdat, MSGTO_SVR, svrmhflkupdat)) < 0) { unmake_lock(progname); exit(1); } } d360 1 a360 2 unmake_lock(progname); exit(0); d385 3 a387 3 if ((pid=fork()) < 0) { perror("fork"); } else if (pid > 0) { d406 3 a408 3 if ((pid=fork()) < 0) { perror("fork"); } else if (pid == 0) { d459 1 a459 2 perror("exec"); exit(1); d503 1 a503 1 error("delay queue is full!"); @