home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / uupoll068.lha / source / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-03  |  27.0 KB  |  828 lines

  1. /*            __
  2.      /  //  //__)_  / /
  3.     (__/(__//   (_)(_(_
  4.  
  5.     the UUCP polling server
  6.  
  7.     (c)Copyright 1991,92 Ralf S. Engelschall, All Rights Reserved.
  8.     (c)Copyright 1991,92 Cyvaned Systems,     All Rights Reserved.
  9.  
  10.     Genesis     : Fri Sep 20 23:26:29 1991
  11.     Last Change : Mon Aug  3 11:27:09 1992
  12.  
  13.     Developed and debugged with SAS/C Compiler V5.10a
  14.     running under AmigaOS 2.04 (37.175), Workbench 2.04 (37.67)
  15.     on an european PAL-Amiga 2000 B Rev 4.4
  16.     with 3MB RAM and 16KB runtime stack.
  17.  
  18.                                         Ralf S. Engelschall
  19.                                         rse@angle.sub.org
  20.                                                                     */
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <dos.h>
  26.  
  27. #include <proto/exec.h>
  28. #include <proto/dos.h>
  29. #include <dos/dos.h>
  30. #include <exec/types.h>
  31. #include <exec/nodes.h>
  32. #include <exec/tasks.h>
  33. #include <exec/ports.h>
  34. #include <devices/timer.h>
  35. #include <libraries/dos.h>
  36. #include <libraries/dosextens.h>
  37.  
  38. #include <clib/exec_protos.h>
  39. #include <clib/dos_protos.h>
  40. #include <pragmas/exec_pragmas.h>
  41. #include <pragmas/dos_pragmas.h>
  42.  
  43. #include "cus.h"
  44. #include "proto.h"
  45. #include "defines.h"
  46. #include "dbg.h"
  47. #include "rev.h"
  48. #include "stat.h"
  49.  
  50. #define DEFAULT_RETRIES          0
  51. #define DEFAULT_DELAY          0
  52. #define DEFAULT_RESTRICTION   0
  53. #define DEFAULT_PENDINGFILES  1
  54. #define DEFAULT_PENDINGKBYTES 10
  55. #define DEFAULT_ARGS          "-7"
  56. #define DEFAULT_NOTIFYUSER      "postmaster"
  57.  
  58. #define JOBCTL_NOTSPECIFIED 0
  59. #define JOBCTL_SWITCH       1
  60. #define JOBCTL_ENABLE       2
  61. #define JOBCTL_DISABLE      3
  62.  
  63. #define CHECK_NOTSPECIFIED 0
  64. #define CHECK_TOABORT      1
  65. #define CHECK_TOBREAK      2
  66. #define CHECK_TOBREAK_DELAY 20
  67.  
  68. #define SPOOLDIR    "uuspool:"
  69. #define LOG            "uuspool:logfile"
  70. #define MODEMSETUP    "uulib:modemsetup"
  71. #define LSYS        "uulib:l.sys"
  72. #define CONFIG        "uulib:config"
  73. #define FIELD        "DefaultNode"
  74.  
  75. #define DEFAULT_EXECCMND "uuxqt"
  76. #define UUCICO_DOSNAME     "uucico"
  77.  
  78. /* dependend return codes from uucico 115/115c/116/116a */
  79. #define UUCICORC_SUCCESS                        0
  80. #define UUCICORC_FAILURE-IN-CALL-OR-PROTOCOL    5
  81. #define UUCICORC_BREAK-OR-SOFTWARE-ERROR        10
  82.  
  83. #define TIMERMODE_RESTRICTION  1L
  84. #define TIMERMODE_SURVIVAL     TIMERMODE_RESTRICTION << 1
  85. #define TIMERMODE_DELAY        TIMERMODE_SURVIVAL << 1
  86.  
  87. #define SURVIVALMODE_WHOLESESSION    1L
  88. #define SURVIVALMODE_ABORTION        SURVIVALMODE_WHOLESESSION << 1
  89. #define SURVIVALTIME_WHOLESESSION    60*60*3    /*  3 hours   */
  90. #define SURVIVALTIME_ABORTION        60        /* 60 seconds */
  91.  
  92. struct timermsg {
  93.     struct timerequest tm_timereq;
  94.     UBYTE tm_timermode;
  95. };
  96.  
  97. static char caSystem[RANGE_6BIT];
  98. static char caCmnd[RANGE_7BIT];
  99. static char caTmp[RANGE_7BIT];
  100. static char *cpaArgv[RANGE_7BIT];
  101. static char caEnvname[RANGE_6BIT];
  102. static char caUucicoFile[RANGE_6BIT];
  103. static int fork_rc;
  104.  
  105. int main(int argc, char **argv)
  106. {
  107.     unsigned int nRetriesMax = DEFAULT_RETRIES;
  108.     unsigned int iRetries = 0;
  109.     unsigned int nDelay = DEFAULT_DELAY;
  110.     unsigned int nRestriction = DEFAULT_RESTRICTION;
  111.     signed   int nRestrictionTmp;
  112.     unsigned int wJobcontrol = JOBCTL_NOTSPECIFIED;
  113.     signed   int nPendingFiles = DEFAULT_PENDINGFILES;
  114.     signed   int nPendingKBytes = DEFAULT_PENDINGKBYTES;
  115.     unsigned int wCheck = CHECK_NOTSPECIFIED;
  116.     unsigned int wInfo = HOSTINFO_NO;
  117.  
  118.     char opt;
  119.     char *optarg;
  120.     char *optstr;
  121.     int optidx;
  122.  
  123.     char *cpConfig = CONFIG;
  124.     char *cpLsys = LSYS;
  125.     char *cpArgs = DEFAULT_ARGS;
  126.     char *cpExeccmndá= DEFAULT_EXECCMND;
  127.     char *cpLog = LOG;
  128.     char *cpField = FIELD;
  129.     char *cpSystemá= NULL;
  130.     char *cpModemsetup = MODEMSETUP;
  131.     char *cpEnvvar = NULL;
  132.     char *cpNotifyuser = DEFAULT_NOTIFYUSER;
  133.  
  134.     BOOL fModemsetupá= FALSE;
  135.     BOOL fAlways = FALSE;
  136.     BOOL fProfane = FALSE;
  137.     BOOL fExeccmnd = FALSE;
  138.     BOOL fRestriction = FALSE;
  139.     BOOL fPendingFiles = FALSE;
  140.     BOOL fPendingKBytes = FALSE;
  141.     BOOL fNotifyuser = FALSE;
  142.     BOOL fWebreaked = FALSE;
  143.  
  144.     extern char caSystem[];
  145.     extern char caCmnd[];
  146.     extern char caTmp[];
  147.  
  148.     struct MsgPort *timerport = NULL;
  149.     ULONG timerport_sigmask;
  150.     ULONG signals;
  151.     struct timermsg *timermsg_restriction = NULL;
  152.     struct timermsg *timermsg_survival = NULL;
  153.     struct timermsg *timermsg_delay = NULL;
  154.     struct timermsg *pMsg;
  155.     UBYTE timerdeviceflag_restriction = 0;
  156.     UBYTE timerdeviceflag_survival = 0;
  157.     UBYTE timerdeviceflag_delay = 0;
  158.     UBYTE active_timermsg = 0;
  159.     UBYTE survivalmode = 0;
  160.  
  161.     int fork_signum = -1;
  162.     ULONG fork_sigmask;
  163.     struct Process *fork_pid;
  164.     BPTR lock;
  165.  
  166.     struct Library *CheckBase = NULL;
  167.     struct Process *PID;
  168.     char *cpProgname;
  169.     char *cp;
  170.     int rc = DOSRC_SUCCESS;
  171.  
  172.  
  173.     cpProgname = strupr(argv[0]);
  174.     if (    (cp = strrchr(cpProgname, '/')) != NULL
  175.          ||    (cp = strrchr(cpProgname, ':')) != NULL    )
  176.         cpProgname = ++cp;
  177.  
  178.     if ((CheckBase = OpenLibrary(DOSNAME, 37L)) == NULL) {
  179.         printf("%s R%d.%d needs AmigaOS 2.04 (37.xx) or higher.\n", cpProgname, ProgVersion, ProgRevision);
  180.         printf("Before OS2.04 you should take %s R0.67 or lower.\n", cpProgname);
  181.         cu(DOSRC_FAIL);
  182.     }
  183.     cpProgname = strlwr(cpProgname);
  184.  
  185.     PID = (struct Process *)FindTask(NULL);
  186.     ulog(cpLog, cpProgname, "-", "Startup Release %d.%d %s [pid=%02d]",
  187.         ProgVersion, ProgRevision, ProgDate, PID->pr_TaskNum);
  188.  
  189.  
  190.     dbg(2, "processing argument line\n");
  191.     optidx = 1;
  192.     optstr = "sSrdtuneEpPcjx";
  193.     for ( ; (optarg = argopt(argc, argv, optstr, &optidx, &opt)) != NULL; ) {
  194.         switch(opt) {
  195.             case 's':    fProfane = FALSE;
  196.                         dbg(3, "fProfane = FALSE\n");
  197.                         if (*optarg != NUL) {
  198.                             cpSystem = strlwr(strcvt(optarg));
  199.                             dbg(3, "cpSystem = \"%s\"\n", cpSystem);
  200.                         }
  201.                         break;
  202.  
  203.             case 'S':    fProfane = TRUE;
  204.                         dbg(3, "fProfane = TRUE\n");
  205.                         if (*optarg != NUL) {
  206.                             cpSystem = strlwr(strcvt(optarg));
  207.                             dbg(3, "cpSystem = \"%s\"\n", cpSystem);
  208.                         }
  209.                         break;
  210.  
  211.             case 'r':    nRetriesMax = abs(atoi(optarg));
  212.                         dbg(3, "nRetriesMax = %d\n", nRetriesMax);
  213.                         break;
  214.  
  215.             case 'd':    nDelay = abs(atoi(optarg));
  216.                         dbg(3, "nDelay = %d\n", nDelay);
  217.                         break;
  218.  
  219.             case 't':    nRestriction = abs(atoi(optarg));
  220.                         fRestriction = TRUE;
  221.                         dbg(3, "nRestriction = %d\n", nRestriction);
  222.                         break;
  223.  
  224.             case 'u':    cpArgs = strcvt(optarg);
  225.                         dbg(3, "cpArgs = \"%s\"\n", cpArgs);
  226.                         break;
  227.  
  228.             case 'm':    fModemsetup= TRUE;
  229.                         dbg(3, "fModemsetup = TRUE\n");
  230.                         break;
  231.  
  232.             case 'n':    fNotifyuser = TRUE;
  233.                         dbg(3, "fNotifyuser = TRUE\n");
  234.                         if (*optarg != NUL) {
  235.                             cpNotifyuser = strcvt(optarg);
  236.                             dbg(3, "cpNotifyuser = \"%s\"\n", cpNotifyuser);
  237.                         }
  238.                         break;
  239.  
  240.             case 'e':    fExeccmnd = FALSE;
  241.                         dbg(3, "fExeccmnd = FALSE\n");
  242.                         cpExeccmnd = strcvt(optarg);
  243.                         dbg(3, "cpExeccmnd = \"%s\"\n", cpExeccmnd);
  244.                         break;
  245.  
  246.             case 'E':    fExeccmnd = TRUE;
  247.                         dbg(3, "fExeccmnd = TRUE\n");
  248.                         if (*optarg != NUL) {
  249.                             cpExeccmnd = strcvt(optarg);
  250.                             dbg(3, "cpExeccmnd = \"%s\"\n", cpExeccmnd);
  251.                         }
  252.                         break;
  253.  
  254.             case 'p':    fPendingFiles = TRUE;
  255.                         dbg(3, "fPendingFiles = TRUE\n");
  256.                         if (*optarg != NUL) {
  257.                             nPendingFiles = atoi(optarg);
  258.                             dbg(3, "nPendingFiles = %d\n", nPendingFiles);
  259.                         }
  260.                         break;
  261.  
  262.             case 'P':    fPendingKBytes = TRUE;
  263.                         dbg(3, "fPendingKBytes = TRUE\n");
  264.                         if (*optarg != NUL) {
  265.                             nPendingKBytes = atoi(optarg);
  266.                             dbg(3, "nPendingKBytes = %d\n", nPendingKBytes);
  267.                         }
  268.                         break;
  269.  
  270.             case 'a':    fAlways = TRUE;
  271.                         dbg(3, "fAlways = TRUE\n");
  272.                         break;
  273.  
  274.             case 'c':    if (*optarg != NUL && abs(atoi(optarg)) == 1) {
  275.                             wCheck = CHECK_TOBREAK;
  276.                             dbg(3, "wCheck = CHECK_TOBREAK\n");
  277.                         }
  278.                         else {
  279.                             wCheck = CHECK_TOABORT;
  280.                             dbg(3, "wCheck = CHECK_TOABORT\n");
  281.                         }
  282.                         break;
  283.  
  284.             case 'j':    if (*optarg != NUL) {
  285.                             if (abs(atoi(optarg)) == 0) {
  286.                                 wJobcontrol = JOBCTL_DISABLE;
  287.                                 dbg(3, "wJobcontrol = JOBCTL_DISABLE\n");
  288.                             }
  289.                             else {
  290.                                 wJobcontrol = JOBCTL_ENABLE;
  291.                                 dbg(3, "wJobcontrol = JOBCTL_ENABLE\n");
  292.                             }
  293.                         }
  294.                         else {
  295.                             wJobcontrol = JOBCTL_SWITCH;
  296.                             dbg(3, "wJobcontrol = JOBCTL_SWITCH\n");
  297.                         }
  298.                         break;
  299.  
  300.             case 'i':    wInfo = HOSTINFO_SHORT;
  301.                         dbg(3, "wInfo = HOSTINFO_SHORT\n");
  302.                         break;
  303.  
  304.             case 'I':    wInfo = HOSTINFO_LONG;
  305.                         dbg(3, "wInfo = HOSTINFO_LONG\n");
  306.                         break;
  307.  
  308.             case 'x':    dbglevel = abs(atoi(optarg));
  309.                         break;
  310.  
  311.             case 'v':    dbg(2, "giving version info\n");
  312.                         giveversioninfo(cpProgname);
  313.                         cu(DOSRC_SUCCESS);
  314.  
  315.             case '?':    dbg(2, "giving usage info\n");
  316.                         giveusage(cpProgname);
  317.                         cu(DOSRC_SUCCESS);
  318.  
  319.             default :    ulog(cpLog, cpProgname, "-", "Ignored bad option '%c'", opt);
  320.         }
  321.     }
  322.     for ( ; optidx < argc; optidx++)
  323.         ulog(cpLog, cpProgname, "-", "Ignored arg '%s'", argv[optidx]);
  324.  
  325.     if (cpSystem == NULL) {
  326.         dbg(2, "getting default system name\n");
  327.         if ((cpSystem = getfield(cpConfig, cpField, caSystem)) == NULL) {
  328.             ulog(cpLog, cpProgname, "-", "Failed because cannot get default hostname from '%s' field of '%s'", cpField, cpConfig);
  329.             cu(DOSRC_FAIL);
  330.         }
  331.         truncdomain(cpSystem);
  332.         dbg(2, "cpSystem = \"%s\"\n", cpSystem);
  333.     }
  334.  
  335.     if (!inlsys(cpLsys, cpSystem)) {
  336.         ulog(cpLog, cpProgname, "-", "Failed due to invalid hostname: %s", cpSystem);
  337.         cu(DOSRC_FAIL);
  338.     }
  339.  
  340.     if (wInfo != HOSTINFO_NO) {
  341.         dbg(2, "giving info about current status\n");
  342.         hostinfo(cpProgname, cpLsys, cpConfig, cpSystem, wInfo);
  343.         cu(DOSRC_SUCCESS);
  344.     }
  345.  
  346.     sprintf(caEnvname, "%s.JOBCTL", cpProgname);
  347.     if ((cpEnvvar = getenv(caEnvname)) == NULL) {
  348.         ulog(cpLog, cpProgname, "-", "Failed to get job control enviroment %s", caEnvname);
  349.             sprintf(caEnvname, "%s.JOBCTL=ENABLE", cpProgname);
  350.             strupr(caEnvname);
  351.             if (putenv(caEnvname) != 0)
  352.                 ulog(cpLog, cpProgname, cpSystem, "Failed to set new job control enviroment %s", caEnvname);
  353.     }
  354.  
  355.     if (wJobcontrol != JOBCTL_NOTSPECIFIED) {
  356.         switch(wJobcontrol) {
  357.             case JOBCTL_SWITCH :    if (strcmp(cpEnvvar, "DISABLE") == 0)
  358.                                         strcpy(caTmp, "ENABLE");
  359.                                     else
  360.                                         strcpy(caTmp, "DISABLE");
  361.                                     break;
  362.             case JOBCTL_ENABLE :    strcpy(caTmp, "ENABLE");
  363.                                     break;
  364.             case JOBCTL_DISABLE :    strcpy(caTmp, "DISABLE");
  365.                                     break;
  366.         }
  367.         sprintf(caEnvname, "%s.JOBCTL=%s", cpProgname, caTmp);
  368.         strupr(caEnvname);
  369.         if (putenv(caEnvname) != 0)
  370.             ulog(cpLog, cpProgname, cpSystem, "Failed to set new job control enviroment %s", caEnvname);
  371.         cu(DOSRC_SUCCESS);
  372.     }
  373.  
  374.     if (strcmp(cpEnvvar, "DISABLE") == 0) {
  375.         ulog(cpLog, cpProgname, "-", "Abort because we are currently disabled");
  376.         cu(DOSRC_SUCCESS);
  377.     }
  378.  
  379.     if (wCheck != CHECK_NOTSPECIFIED) {
  380.         if (IsProcRunning(UUCICO_DOSNAME)) {
  381.             switch(wCheck) {
  382.                 case CHECK_TOABORT :
  383.                     ulog(cpLog, cpProgname, cpSystem, "abort due to `check' option and a already running uucico process");
  384.                     cu(DOSRC_SUCCESS);
  385.                 case CHECK_TOBREAK :
  386.                     ulog(cpLog, cpProgname, cpSystem, "sending break signal to still running uucico process due to `check' option");
  387.                     BreakProc(UUCICO_DOSNAME);
  388.                     ulog(cpLog, cpProgname, cpSystem, "waiting %d seconds sending break signal to still running uucico process due to `check' option", CHECK_TOBREAK_DELAY);
  389.                     Delay(50*CHECK_TOBREAK_DELAY);
  390.                     break;
  391.             }
  392.         }
  393.     }
  394.  
  395.     if (!fProfane) {
  396.         dbg(2, "calculating restriction time\n");
  397.         if ((nRestrictionTmp = timerestriction(cpLsys, cpSystem)) == -1) {
  398.             printf("polling time violation for host %s\n", cpSystem);
  399.             ulog(cpLog, cpProgname, cpSystem, "Failed due to polling time violation for host %s", cpSystem);
  400.             cu(DOSRC_FAIL);
  401.         } else {
  402.             if (nRestriction == 0)
  403.                 nRestriction = nRestrictionTmp;
  404.             dbg(2, "nRestriction = %d\n", nRestriction);
  405.         }
  406.     } else {
  407.         if (!fRestriction) {
  408.             dbg(2, "setting restriction time to zero due to left option and profanation\n");
  409.             nRestriction = 0;
  410.         }
  411.     }
  412.  
  413.     if (fAlways) {
  414.         dbg(2, "setting enviroment of system \"%s\" to 'FAILED' because of 'always' option\n", cpSystem);
  415.         sprintf(caEnvname, "%s.STAT.%s=FAILED", cpProgname, cpSystem);
  416.         strupr(caEnvname);
  417.         if (putenv(caEnvname) != 0) {
  418.             ulog(cpLog, cpProgname, cpSystem, "Failed to set enviroment %s", caEnvname);
  419.         }
  420.     } else {
  421.         dbg(2, "getting enviroment of system \"%s\"\n", cpSystem);
  422.         sprintf(caEnvname, "%s.STAT.%s", cpProgname, cpSystem);
  423.         if ((cpEnvvar = getenv(caEnvname)) == NULL) {
  424.             ulog(cpLog, cpProgname, cpSystem, "Failed to get enviroment %s", caEnvname);
  425.             sprintf(caEnvname, "%s.STAT.%s=FAILED", cpProgname, cpSystem);
  426.             strupr(caEnvname);
  427.             if (putenv(caEnvname) != 0)
  428.                 ulog(cpLog, cpProgname, cpSystem, "Failed to set new enviroment %s", caEnvname);
  429.         } else {
  430.             if ((fPendingFiles && nPendingFiles != 0) || (fPendingKBytes && nPendingKBytes != 0)) {
  431.                 if (fPendingKBytes && nPendingKBytes != 0) {
  432.                     if (!PendingKBytes(SPOOLDIR, cpSystem, nPendingKBytes)) {
  433.                         ulog(cpLog, cpProgname, cpSystem, "Abort because not more/less or equal pending KBytes for host %s", cpSystem);
  434.                         cu(DOSRC_SUCCESS);
  435.                     }
  436.                 }
  437.                 if (fPendingFiles && nPendingFiles != 0) {
  438.                     if (!PendingFiles(SPOOLDIR, cpSystem, nPendingFiles)) {
  439.                         ulog(cpLog, cpProgname, cpSystem, "Abort because not more/less or equal pending Files for host %s", cpSystem);
  440.                         cu(DOSRC_SUCCESS);
  441.                     }
  442.                 }
  443.             }
  444.             else {
  445.                 if (strcmp(cpEnvvar, "SUCCESSFUL") == 0) {
  446.                     ulog(cpLog, cpProgname, cpSystem, "Abort because last time we had polled already successful");
  447.                     cu(DOSRC_SUCCESS);
  448.                 }
  449.             }
  450.         }
  451.     }
  452.  
  453.     ulog(cpLog, cpProgname, cpSystem, "OK Startup");
  454.  
  455.  
  456.     dbg(2, "create env of timers\n");
  457.     dbg(3, "create timer msgport\n");
  458.     if ((timerport = CreatePort(0, 0)) == NULL)
  459.         cu(DOSRC_FAIL);
  460.  
  461.     dbg(3, "create IORequest struct for restriction timer\n");
  462.     if ((timermsg_restriction = (struct timermsg *)CreateExtIO(timerport, sizeof(struct timermsg))) == NULL)
  463.         cu(DOSRC_FAIL);
  464.     dbg(3, "open timer.device for restriction timer\n");
  465.     if ((timerdeviceflag_restriction = OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)timermsg_restriction, 0)) != NULL)
  466.         cu(DOSRC_FAIL);
  467.  
  468.     dbg(3, "create IORequest struct for survival timer\n");
  469.     if ((timermsg_survival = (struct timermsg *)CreateExtIO(timerport, sizeof(struct timermsg))) == NULL)
  470.         cu(DOSRC_FAIL);
  471.     dbg(3, "open timer.device for survival timer\n");
  472.     if ((timerdeviceflag_survival = OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)timermsg_survival, 0)) != NULL)
  473.         cu(DOSRC_FAIL);
  474.  
  475.     dbg(3, "create IORequest struct for delay timer\n");
  476.     if ((timermsg_delay = (struct timermsg *)CreateExtIO(timerport, sizeof(struct timermsg))) == NULL)
  477.         cu(DOSRC_FAIL);
  478.     dbg(3, "open timer.device for delay timer\n");
  479.     if ((timerdeviceflag_delay = OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)timermsg_delay, 0)) != NULL)
  480.         cu(DOSRC_FAIL);
  481.  
  482.  
  483.     if (nRestriction) {
  484.         timermsg_restriction->tm_timereq.tr_node.io_Command = TR_ADDREQUEST;
  485.         timermsg_restriction->tm_timereq.tr_time.tv_secs = nRestriction * 60 - (fRestriction ? 0 : 30);
  486.         timermsg_restriction->tm_timereq.tr_time.tv_micro = 0;
  487.         timermsg_restriction->tm_timermode = TIMERMODE_RESTRICTION;
  488.         dbg(2, "starting restriction timer with %d seconds\n", timermsg_restriction->tm_timereq.tr_time.tv_secs);
  489.         SendIO((struct IORequest *)timermsg_restriction);
  490.         active_timermsg = active_timermsg | TIMERMODE_RESTRICTION;
  491.     }
  492.  
  493.     timermsg_survival->tm_timereq.tr_node.io_Command = TR_ADDREQUEST;
  494.     timermsg_survival->tm_timereq.tr_time.tv_secs = SURVIVALTIME_WHOLESESSION;
  495.     timermsg_survival->tm_timereq.tr_time.tv_micro = 0;
  496.     timermsg_survival->tm_timermode = TIMERMODE_SURVIVAL;
  497.     dbg(2, "starting survival timer with %d seconds\n", timermsg_survival->tm_timereq.tr_time.tv_secs);
  498.     SendIO((struct IORequest *)timermsg_survival);
  499.     active_timermsg = active_timermsg | TIMERMODE_SURVIVAL;
  500.     survivalmode = SURVIVALMODE_WHOLESESSION;
  501.  
  502.     if (fModemsetup) {
  503.         dbg(2, "setting up modem\n");
  504.         if (!setupmodem(cpModemsetup, cpLsys, cpSystem)) {
  505.             ulog(cpLog, cpProgname, cpSystem, "Modem setup failed");
  506.             cu(DOSRC_FAIL);
  507.         }
  508.         ulog(cpLog, cpProgname, cpSystem, "Modem setup successful");
  509.     }
  510.  
  511.     dbg(3, "alloc signal for forking\n");
  512.     if ((fork_signum = AllocSignal(-1)) == -1)
  513.         cu(DOSRC_FAIL);
  514.  
  515.     dbg(3, "locating uucico executable\n");
  516.     if ((lock = GetProgramDir()) != NULL) {
  517.         if (NameFromLock(lock, caTmp, 256) != 0) {
  518.             if (caTmp[strlen(caTmp)-1] != ':' && caTmp[strlen(caTmp)-1] != '/') {
  519.                 caTmp[strlen(caTmp)]   = '/';
  520.                 caTmp[strlen(caTmp)+2] = NUL;
  521.             }
  522.         }
  523.     }
  524.     else
  525.         caTmp[0] = NUL;
  526.     sprintf(caUucicoFile, "%s%s", caTmp, UUCICO_DOSNAME);
  527.  
  528.     for ( ; ; ) {
  529.         dbg(2, "(re)entering outer loop (fork loop)\n");
  530.  
  531.         if (iRetries == 0)
  532.             ulog(cpLog, cpProgname, cpSystem, "Trying to poll host");
  533.         else
  534.             ulog(cpLog, cpProgname, cpSystem, "Retrying (#%d) to poll host", iRetries);
  535.  
  536.         sprintf(caCmnd, "-%s%s %s", (fProfane) ? "S" : "s", cpSystem, cpArgs);
  537.         dbg(2, "forking: %s %s\n", UUCICO_DOSNAME, caCmnd);
  538.         if ((fork_pid = fork(caUucicoFile, caCmnd, &fork_rc, fork_signum)) == NULL) {
  539.             ulog(cpLog, cpProgname, cpSystem, "FAILED because cannot fork %s %s", UUCICO_DOSNAME, caCmnd);
  540.             cu(DOSRC_FAIL);
  541.         }
  542.  
  543.         for ( ; ; ) {
  544.             dbg(2, "(re)entering inner loop (wait loop)\n");
  545.  
  546.             dbg(2, "go sleeping until wakeup\n");
  547.             timerport_sigmask = 1L << timerport->mp_SigBit;
  548.             fork_sigmask = 1L << fork_signum;
  549.             signals = Wait((ULONG)(fork_sigmask | timerport_sigmask | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D));
  550.  
  551.             if (signals & timerport_sigmask) {
  552.                 dbg(2, "awakened through timer interrupt\n");
  553.                 if (pMsg = (struct timermsg *)GetMsg(timerport)) {
  554.  
  555.                     if (pMsg->tm_timermode == TIMERMODE_SURVIVAL) {
  556.                         active_timermsg = active_timermsg & ~(TIMERMODE_SURVIVAL);
  557.  
  558.                         if (survivalmode == SURVIVALMODE_ABORTION) {
  559.                             ulog(cpLog, cpProgname, cpSystem, "interupted due to survival timeout for uucico abortion");
  560.                             survivalmode = survivalmode & ~(SURVIVALMODE_ABORTION);
  561.                             cu(DOSRC_FAIL);
  562.                         }
  563.                         if (survivalmode == SURVIVALMODE_WHOLESESSION) {
  564.                             ulog(cpLog, cpProgname, cpSystem, "interupted due to survival timeout for whole session");
  565.                             survivalmode = survivalmode & ~(SURVIVALMODE_WHOLESESSION);
  566.                             cu(DOSRC_FAIL);
  567.                         }
  568.                         continue;
  569.                     }
  570.  
  571.                     if (pMsg->tm_timermode == TIMERMODE_RESTRICTION) {
  572.  
  573.                         ulog(cpLog, cpProgname, cpSystem, "interupted due to restriction timeout of %d minute%s", nRestriction, (nRestriction != 1) ? "s" : "" );
  574.                         ulog(cpLog, cpProgname, cpSystem, "sending break signal to abort uucico process");
  575.                         Signal((struct Task *)fork_pid, SIGBREAKF_CTRL_C);
  576.                         fWebreaked = TRUE;
  577.  
  578.                         dbg(2, "cancelling currently active survival timer\n");
  579.                         AbortIO((struct IORequest *)timermsg_survival);
  580.                         WaitIO((struct IORequest *)timermsg_survival);
  581.                         timermsg_survival->tm_timereq.tr_node.io_Command = TR_ADDREQUEST;
  582.                         timermsg_survival->tm_timereq.tr_time.tv_secs = SURVIVALTIME_ABORTION;
  583.                         timermsg_survival->tm_timereq.tr_time.tv_micro = 0;
  584.                         timermsg_survival->tm_timermode = TIMERMODE_SURVIVAL;
  585.                         dbg(2, "starting survival timer with %d seconds for abortion process\n", timermsg_survival->tm_timereq.tr_time.tv_secs);
  586.                         SendIO((struct IORequest *)timermsg_survival);
  587.                         active_timermsg = active_timermsg | TIMERMODE_SURVIVAL;
  588.                         survivalmode = SURVIVALMODE_ABORTION;
  589.  
  590.                         fExeccmnd = TRUE;
  591.                         dbg(3, "fExeccmnd = TRUE\n");
  592.                         continue;
  593.                     }
  594.  
  595.                     if (pMsg->tm_timermode == TIMERMODE_DELAY) {
  596.  
  597.                         ulog(cpLog, cpProgname, cpSystem, "interupted due to delay timer of %d second%s", nDelay, (nDelay != 1) ? "s" : "" );
  598.                         active_timermsg = active_timermsg & ~(TIMERMODE_DELAY);
  599.                         break;
  600.                     }
  601.  
  602.                 }
  603.             }
  604.  
  605.             if (signals & SIGBREAKF_CTRL_C) {
  606.                 dbg(2, "awakened through ctrl-c signal\n");
  607.                 ulog(cpLog, cpProgname, cpSystem, "interupted due to ctrl-c signal");
  608.  
  609.                 if (active_timermsg & TIMERMODE_DELAY) {
  610.                     dbg(2, "aborting delay timer\n");
  611.                     AbortIO((struct IORequest *)timermsg_delay);
  612.                     WaitIO((struct IORequest *)timermsg_delay);
  613.                     active_timermsg = active_timermsg & ~(TIMERMODE_DELAY);
  614.                     dbg(2, "cancelling currently active survival timer\n");
  615.                     AbortIO((struct IORequest *)timermsg_survival);
  616.                     WaitIO((struct IORequest *)timermsg_survival);
  617.                     cu(DOSRC_FAIL);
  618.                 }
  619.                 else {
  620.                     ulog(cpLog, cpProgname, cpSystem, "sending break signal to abort uucico process");
  621.                     Signal((struct Task *)fork_pid, SIGBREAKF_CTRL_C);
  622.  
  623.                     dbg(2, "cancelling currently active survival timer\n");
  624.                     AbortIO((struct IORequest *)timermsg_survival);
  625.                     WaitIO((struct IORequest *)timermsg_survival);
  626.                     timermsg_survival->tm_timereq.tr_node.io_Command = TR_ADDREQUEST;
  627.                     timermsg_survival->tm_timereq.tr_time.tv_secs = SURVIVALTIME_ABORTION;
  628.                     timermsg_survival->tm_timereq.tr_time.tv_micro = 0;
  629.                     timermsg_survival->tm_timermode = TIMERMODE_SURVIVAL;
  630.                     dbg(2, "starting survival timer with %d seconds for abortion process\n", timermsg_survival->tm_timereq.tr_time.tv_secs);
  631.                     SendIO((struct IORequest *)timermsg_survival);
  632.                     active_timermsg = active_timermsg | TIMERMODE_SURVIVAL;
  633.                     survivalmode = survivalmode | SURVIVALMODE_ABORTION;
  634.  
  635.                     fExeccmnd = TRUE;
  636.                     dbg(3, "fExeccmnd = TRUE\n");
  637.                     continue;
  638.                 }
  639.             }
  640.  
  641.             if (signals & SIGBREAKF_CTRL_D) {
  642.                 dbg(2, "awakened through ctrl-d signal\n");
  643.                 ulog(cpLog, cpProgname, cpSystem, "interupted due to ctrl-d signal");
  644.  
  645.                 if (active_timermsg & TIMERMODE_DELAY) {
  646.                     dbg(2, "aborting delay timer\n");
  647.                     AbortIO((struct IORequest *)timermsg_delay);
  648.                     WaitIO((struct IORequest *)timermsg_delay);
  649.                     active_timermsg = active_timermsg & ~(TIMERMODE_DELAY);
  650.                     dbg(2, "cancelling currently active survival timer\n");
  651.                     AbortIO((struct IORequest *)timermsg_survival);
  652.                     WaitIO((struct IORequest *)timermsg_survival);
  653.                 }
  654.                 else {
  655.                     ulog(cpLog, cpProgname, cpSystem, "sending break signal to abort uucico process");
  656.                     Signal((struct Task *)fork_pid, SIGBREAKF_CTRL_C);
  657.  
  658.                     dbg(2, "cancelling currently active survival timer\n");
  659.                     AbortIO((struct IORequest *)timermsg_survival);
  660.                     WaitIO((struct IORequest *)timermsg_survival);
  661.                     timermsg_survival->tm_timereq.tr_node.io_Command = TR_ADDREQUEST;
  662.                     timermsg_survival->tm_timereq.tr_time.tv_secs = SURVIVALTIME_ABORTION;
  663.                     timermsg_survival->tm_timereq.tr_time.tv_micro = 0;
  664.                     timermsg_survival->tm_timermode = TIMERMODE_SURVIVAL;
  665.                     dbg(2, "starting survival timer with %d seconds for abortion process\n", timermsg_survival->tm_timereq.tr_time.tv_secs);
  666.                     SendIO((struct IORequest *)timermsg_survival);
  667.                     active_timermsg = active_timermsg | TIMERMODE_SURVIVAL;
  668.                     survivalmode = survivalmode | SURVIVALMODE_ABORTION;
  669.                 }
  670.                 cu(DOSRC_FAIL);
  671.             }
  672.  
  673.             if (signals & fork_sigmask) {
  674.                 dbg(2, "awakened through fork termination\n");
  675.  
  676.                 if (fork_rc == 0) {
  677.                     dbg(2, "uucico was succesfull\n");
  678.                     ulog(cpLog, cpProgname, cpSystem, "finished (polling was successful)");
  679.  
  680.                     dbg(2, "setting enviroment to 'SUCCESSFUL'\n");
  681.                     sprintf(caEnvname, "%s.STAT.%s=SUCCESSFUL", cpProgname, cpSystem);
  682.                     strupr(caEnvname);
  683.                     if (putenv(caEnvname) != 0)
  684.                         ulog(cpLog, cpProgname, cpSystem, "Failed to set enviroment %s", caEnvname);
  685.  
  686.                     fExeccmnd = TRUE;
  687.                     dbg(3, "fExeccmnd = TRUE\n");
  688.                     cu(DOSRC_SUCCESS);
  689.                 }
  690.  
  691.                 if (fork_rc == 5) {
  692.                     dbg(2, "uucico failure in call and/or protocol\n");
  693.                     iRetries++;
  694.                     if (iRetries > nRetriesMax) {
  695.                         if (nRetriesMax != 0)
  696.                             ulog(cpLog, cpProgname, cpSystem, "stopped due to max retries of %d", nRetriesMax);
  697.                         dbg(2, "setting enviroment to 'FAILED'\n");
  698.                         sprintf(caEnvname, "%s.STAT.%s=FAILED", cpProgname, cpSystem);
  699.                         strupr(caEnvname);
  700.                         if (putenv(caEnvname) != 0)
  701.                             ulog(cpLog, cpProgname, cpSystem, "Failed to set enviroment %s", caEnvname);
  702.  
  703.                         if (fNotifyuser) {
  704.                             ulog(cpLog, cpProgname, cpSystem, "notifying user `%s' about this failed session", cpNotifyuser);
  705.                             sprintf(caTmp, "session stopped due to max retries of %d", nRetriesMax);
  706.                             NotifyOnFailure(cpNotifyuser, cpSystem, caTmp);
  707.                         }
  708.                         cu(DOSRC_FAIL);
  709.                     }
  710.  
  711.                     if (nDelay) {
  712.                         timermsg_delay->tm_timereq.tr_node.io_Command = TR_ADDREQUEST;
  713.                         timermsg_delay->tm_timereq.tr_time.tv_secs = nDelay;
  714.                         timermsg_delay->tm_timereq.tr_time.tv_micro = 0;
  715.                         timermsg_delay->tm_timermode = TIMERMODE_DELAY;
  716.                         dbg(2, "starting delay timer with %d seconds for retry procedure\n", timermsg_delay->tm_timereq.tr_time.tv_secs);
  717.                         SendIO((struct IORequest *)timermsg_delay);
  718.                         active_timermsg = active_timermsg | TIMERMODE_DELAY;
  719.                         continue;
  720.                     }
  721.                     break;
  722.                 }
  723.  
  724.                 dbg(2, "uucico break/software failure\n");
  725.  
  726.                 if (survivalmode == SURVIVALMODE_ABORTION) {
  727.                     dbg(2, "cancelling currently active survival timer\n");
  728.                     AbortIO((struct IORequest *)timermsg_survival);
  729.                     WaitIO((struct IORequest *)timermsg_survival);
  730.                     survivalmode = survivalmode & ~(SURVIVALMODE_ABORTION);
  731.                 }
  732.  
  733.                 dbg(2, "setting enviroment to 'FAILED'\n");
  734.                 sprintf(caEnvname, "%s.STAT.%s=FAILED", cpProgname, cpSystem);
  735.                 strupr(caEnvname);
  736.                 if (putenv(caEnvname) != 0)
  737.                     ulog(cpLog, cpProgname, cpSystem, "Failed to set enviroment %s", caEnvname);
  738.  
  739.                 if (fNotifyuser) {
  740.                     if (fWebreaked) {
  741.                         ulog(cpLog, cpProgname, cpSystem, "notifying user `%s' about this failed session", cpNotifyuser);
  742.                         sprintf(caTmp, "session stopped due to restriction timeout of %d minute%s", nRestriction, (nRestriction != 1) ? "s" : "");
  743.                         NotifyOnFailure(cpNotifyuser, cpSystem, caTmp);
  744.                     }
  745.                 }
  746.  
  747.                 fExeccmnd = TRUE;
  748.                 dbg(3, "fExeccmnd = TRUE\n");
  749.                 cu(DOSRC_FAIL);
  750.             }
  751.  
  752.         }
  753.     }
  754.  
  755.     cus:
  756.  
  757.     if (fork_signum != -1) {
  758.         dbg(2, "freeing signal of forking\n");
  759.         FreeSignal(fork_signum);
  760.     }
  761.  
  762.     if (active_timermsg & TIMERMODE_DELAY) {
  763.         dbg(2, "aborting delay timer\n");
  764.         AbortIO((struct IORequest *)timermsg_delay);
  765.         WaitIO((struct IORequest *)timermsg_delay);
  766.         active_timermsg = active_timermsg & ~(TIMERMODE_DELAY);
  767.     }
  768.  
  769.     if (active_timermsg & TIMERMODE_RESTRICTION) {
  770.         dbg(2, "aborting restriction timer\n");
  771.         AbortIO((struct IORequest *)timermsg_restriction);
  772.         WaitIO((struct IORequest *)timermsg_restriction);
  773.         active_timermsg = active_timermsg & ~(TIMERMODE_RESTRICTION);
  774.     }
  775.  
  776.     if (active_timermsg & TIMERMODE_SURVIVAL) {
  777.         dbg(2, "aborting survival timer\n");
  778.         AbortIO((struct IORequest *)timermsg_survival);
  779.         WaitIO((struct IORequest *)timermsg_survival);
  780.         active_timermsg = active_timermsg & ~(TIMERMODE_SURVIVAL);
  781.     }
  782.  
  783.     dbg(2, "delete env of timers\n");
  784.     if (timerdeviceflag_delay) {
  785.         dbg(3, "closing timer.device of delay timer\n");
  786.         CloseDevice((struct IORequest *)timermsg_delay);
  787.     }
  788.     if (timerdeviceflag_restriction) {
  789.         dbg(3, "closing timer.device of restriction timer\n");
  790.         CloseDevice((struct IORequest *)timermsg_restriction);
  791.     }
  792.     if (timerdeviceflag_survival) {
  793.         dbg(3, "closing timer.device of survival timer\n");
  794.         CloseDevice((struct IORequest *)timermsg_survival);
  795.     }
  796.     if (timerport) {
  797.         dbg(3, "delete timer msgport\n");
  798.         DeletePort(timerport);
  799.     }
  800.     if (timermsg_delay) {
  801.         dbg(3, "delete IORequest struct of delay timer\n");
  802.         DeleteExtIO((struct IORequest *)timermsg_delay);
  803.     }
  804.     if (timermsg_restriction) {
  805.         dbg(3, "delete IORequest struct of restriction timer\n");
  806.         DeleteExtIO((struct IORequest *)timermsg_restriction);
  807.     }
  808.     if (timermsg_survival) {
  809.         dbg(3, "delete IORequest struct of surval timer\n");
  810.         DeleteExtIO((struct IORequest *)timermsg_survival);
  811.     }
  812.  
  813.     if (fExeccmnd && strlen(cpExeccmnd) > 0) {
  814.         ulog(cpLog, cpProgname, cpSystem, "Executing %s", cpExeccmnd);
  815.         if (SystemCmndAsync(cpExeccmnd) == -1)
  816.             ulog(cpLog, cpProgname, cpSystem, "Error executing %s", cpExeccmnd);
  817.     }
  818.  
  819.     if (CheckBase)
  820.         CloseLibrary(CheckBase);
  821.  
  822.     ulog(cpLog, cpProgname, (cpSystem) ? cpSystem : "-", "OK Exit");
  823.     dbg(3, "rc = %d\n", rc);
  824.     dbg(2, "exit\n");
  825.     return rc;
  826. }
  827.  
  828.