home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / ios_src / ioslib.c < prev    next >
C/C++ Source or Header  |  1993-01-31  |  30KB  |  1,547 lines

  1. /*********************************************************************
  2.  
  3.                     IOS - lib routines
  4.                     
  5.     Program : IOSmail
  6.     Source  : free
  7.     Author  : Rinaldo Visscher
  8.     Date    : 1991
  9.  
  10.     Misc. routines.
  11. **********************************************************************/
  12.  
  13. #include        <stdio.h>
  14. #include        <stdlib.h>
  15. #include        <stdarg.h>
  16. #include        <aes.h>
  17. #include        <vdi.h>
  18. #if defined LATTICE
  19. #include        <sys/stat.h>
  20. #include        <dos.h>
  21. #else
  22. #include        <ext.h>
  23. #include        <tos.h>
  24. #endif
  25. #include        <string.h>
  26. #include        <time.h>
  27. #include        <ctype.h>
  28. #include        <errno.h>
  29.  
  30. #include        "portab.h"
  31. #include        "defs.h"
  32. #include        "ioslib.h"
  33. #include        "crc.h"
  34.  
  35. #include        "inmail.h"
  36. #include        "strutil.h"
  37. #include        "modules.h"
  38. #include        "lang.h"
  39.  
  40. #include        "vars.h"
  41.  
  42. #include        "compiler.h"
  43.  
  44. VOID freepktbuf(VOID);
  45. VOID freemsgbuf(VOID);
  46. VOID checkABC(VOID);
  47.  
  48. MLOCAL BYTE        *chars = "zCoHaJSu0.EikMm1BFchN4A tLvU3beInq29QGjyD5d6WTswlRg7PZfrxVp8YKOX";
  49. MLOCAL FILE        *LOG;
  50. MLOCAL BOOLEAN     isABCnode;
  51. MLOCAL BYTE        blink = 0;
  52. MLOCAL BYTE        bcount=0;
  53.  
  54. MLOCAL CONST BYTE    *werr[] = {    "Ok, no error",
  55.                                 "File permission denied",
  56.                                 "File not found",
  57.                                 "----",
  58.                                 "----",
  59.                                 "General I/O error",
  60.                                 "----",
  61.                                 "----",
  62.                                 "----",
  63.                                 "Invalid file handle",
  64.                                 "Illegal file specification",
  65.                                 "Invalid heap block",
  66.                                 "Heap overflow",
  67.                                 "File access mode error",
  68.                                 "----",
  69.                                 "----",
  70.                                 "----",
  71.                                 "File exists",
  72.                                 "Program load format",
  73.                                 "Device error",
  74.                                 "Path not found",        /*    20    */
  75.                                 "----",
  76.                                 "Invalid parameter",
  77.                                 "File table overflow",
  78.                                 "Too many files open",
  79.                                 "----",
  80.                                 "----",
  81.                                 "----",
  82.                                 "Disk full",
  83.                                 "Seek error",
  84.                                 "Read only device",        /*    30    */
  85.                                 "----",
  86.                                 "----",
  87.                                 "Domain error",
  88.                                 "Range error",
  89.                                 "No more matching files" };
  90.  
  91. EXTERN CONST BYTE *Copyright;
  92.  
  93. VOID terminate(WORD elevel)
  94. {
  95.     WORD    i;
  96.  
  97.     if (MTask == MULTIGEM) close_gem();
  98.     
  99.     for (i=0; i < LAST_MESSAGE; i++) free (Logmessage[i]);
  100.     
  101.     if (maxPRD)
  102.         for (i = 0; i < maxPRD; i++) free (PRDcode[i]);
  103.     
  104.     for (i=0; i < msgareas; i++)
  105.     {
  106.         free(Areaname[i]);
  107.         free(Areaorg[i]);
  108.         free(Areapath[i]);
  109.         if (Randorgfile[i])
  110.             free(Randorgfile[i]);
  111.         free(Tozone[i]);
  112.         free(Tonet[i]);
  113.         free(Tonode[i]);
  114.         free(Topoint[i]);
  115.         if (ROnode[i] != NULL) free (ROnode[i]);
  116.     }
  117.  
  118.     for(i=0 ; i < ncopyareas ; i++) {
  119.         free(Copyarea[i]);
  120.         free(Destarea[i]);
  121.         free(Copylegal[i]);
  122.     }
  123.     
  124.     for (i=0; i < nnodelist; i++) {
  125.         free (NODElist[i]);
  126.     }
  127.     
  128.     for (i=0; i < nfdbase; i++) free(ToBase[i]);
  129.     
  130.     for (i=0; i < nled; i++) free(Lareaname[i]);
  131.     
  132.     for(i=0; i < nkill; i++) free(Killfrom[i]);
  133.  
  134.     free_dupetrap();
  135.         
  136.     if (strlen(FDbase))        free(FDbase);
  137.     if (strlen(mailarea))    free(mailarea);
  138.     if (strlen(pkt_temp))    free(pkt_temp);
  139.     if (strlen(trasharea))    free(trasharea);
  140.     if (strlen(privatebox))    free(privatebox);
  141.     if (strlen(dupearea))    free(dupearea);
  142.     if (strlen(mailtemp))    free(mailtemp);
  143.     if (strlen(outbound))    free(outbound);
  144.     
  145.     if (doimport)
  146.         if (strlen(inbound))    free(inbound);
  147.     
  148.     if (strlen(Arch))        free(Arch);
  149.     if (strlen(Archcmdi))    free(Archcmdi);
  150.     if (strlen(Archcmdo))    free(Archcmdo);
  151.     if (strlen(Qbbslr))        free(Qbbslr);
  152.     if (strlen(Envpath))    free(Envpath);
  153.     if (strlen(logfile))    free(logfile);
  154.     
  155.     if (strlen(Lzh))         free(Lzh);
  156.     if (strlen(Zip))        free(Zip);
  157.     if (strlen(Arc))        free(Arc);
  158.     if (strlen(Arj))        free(Arj);
  159.     
  160.     if (strlen(LzheC))        free(LzheC);
  161.     if (strlen(ZipeC))        free(ZipeC);
  162.     if (strlen(ArceC))        free(ArceC);
  163.     if (strlen(ArjeC))        free(ArjeC);
  164.     
  165.     if (strlen(LzheA))        free(LzheA);
  166.     if (strlen(ZipeA))        free(ZipeA);
  167.     if (strlen(ArceA))        free(ArceA);
  168.     if (strlen(ArjeA))        free(ArjeA);
  169.     if (strlen(TRACKmsg))    free(TRACKmsg);
  170.     
  171.     if (strlen(Mainorg))    free(Mainorg);
  172.     
  173.     if(Areafix != NULL) {
  174.         if (strlen(Areafix))     free(Areafix);
  175.         if (strlen(Areafixcmd)) free(Areafixcmd);
  176.     }
  177.     
  178.     log_close();
  179.     
  180.     if (dowait)
  181.     {
  182.         if (MTask == MULTIGEM) {
  183.             v_curtext(vdi_handle,"\r\n--- Press KEY ---");
  184.             evnt_keybd();
  185.         }
  186.         else {
  187.             printf("\n--- \033pPress RETURN\033q ---");
  188.             getchar();
  189.         }
  190.     }
  191.     
  192.     exit(elevel);
  193. }
  194.  
  195. VOID w_error(BYTE *where)
  196. {
  197.     log_line(6,Logmessage[M__WRITE_ERROR], errno,
  198.         (errno <= ERANGE) ? werr[errno] : "Unknown", where);
  199.     
  200.     terminate(10);
  201. }
  202.  
  203. VOID *myalloc(size_t sp)
  204. {
  205.     BYTE    *tmp = malloc(sp);
  206.  
  207. #if defined EXTERNDEBUG
  208.     if (debugflag) {
  209.         log_line(6, ">%ld memory allocated", sp);
  210.     }
  211. #endif
  212.  
  213.     if (!tmp)
  214.     {
  215.         log_line(6,Logmessage[M__MEMORY_ERROR]);
  216. #if defined DEBUG
  217.         log_line(6,"?Memory allocation failed.");
  218. #endif
  219.         terminate(-39);
  220.     }
  221.     
  222.     return(tmp);
  223. }
  224.  
  225. BOOLEAN area_changed(WORD area)
  226. {
  227.     /*
  228.     **    Returns TRUE if area was changed and resets the archive
  229.     **    bit according to the TOS version
  230.     */
  231.     
  232.     BYTE    buffer[128];
  233.     WORD    attr;
  234.     
  235.     sprintf(buffer, "%s.HDR", Areapath[area]);
  236.     
  237.     attr = Fattrib(buffer, 0, -1);
  238.     giveTIMEslice();
  239.  
  240.     if (attr != -33 && attr != -34 && attr & FA_ARCHIVE)
  241.     {
  242.         if (intel(Sversion()) >= 0x0015U)
  243.             Fattrib(buffer, 1, 0);
  244.         else
  245.             Fattrib(buffer, 1, FA_ARCHIVE);
  246.         
  247.         return(TRUE);
  248.     }
  249.     
  250.     return(FALSE);
  251. }
  252.  
  253. WORD to_area(BYTE *msgtext)
  254. {
  255.     /*
  256.     **    Returns the area number to which a PrivateBox message
  257.     **    is destinated. If Netmail, it returns (-2)
  258.     **
  259.     **    If no AREA-Tag found, it returns (-1)
  260.     */
  261.     
  262.     BYTE    *p, *q, *z,
  263.             temp[80];
  264.     WORD    i;
  265.     
  266.     if ((p = strstr(msgtext, "\03AREA [")) == NULL)
  267.     {
  268.         log_line(3,Logmessage[M__NO_AREALINE]);
  269.         return (-1);
  270.     }
  271.     
  272.     z = p;
  273.     
  274.     while (*p != '[') p++;
  275.     p++;
  276.     
  277.     for(q = temp; *p && *p != ']'; *q++ = *p++);
  278.     *q = EOS;
  279.     
  280.     p = skip_to_blank(p);
  281.     strcpy(z, p);
  282.     
  283.     for(i=0; i < msgareas; i++)
  284.         if (!stricmp(temp, Areaname[i])) return(i);
  285.     
  286.     if (!strcmp(temp, "MAIL")) return(-2);
  287.     
  288.     return(-1);
  289. }
  290.  
  291. MLOCAL VOID swap_node(WORD first, WORD last)
  292. {
  293.     UWORD    h1, h2, h3, h4;
  294.     
  295.     h1 = Tz[first];
  296.     h2 = Tnt[first];
  297.     h3 = Tne[first];
  298.     h4 = Tp[first];
  299.     
  300.     Tz[first] = Tz[last];
  301.     Tnt[first] = Tnt[last];
  302.     Tne[first] = Tne[last];
  303.     Tp[first] = Tp[last];
  304.     
  305.     Tz[last] = h1;
  306.     Tnt[last] = h2;
  307.     Tne[last] = h3;
  308.     Tp[last] = h4;
  309. }
  310.  
  311. VOID sort_connected(WORD count, WORD start)
  312. {
  313.     WORD    i,
  314.             j;
  315.     
  316.     --count;
  317.     
  318.     if (count-1 <= 1) return;
  319.     
  320.     for (i = start; Tz[i] != (UWORD)(-1); i++)
  321.     {
  322.         for (j = i+1; Tz[j] != (UWORD)(-1); j++)
  323.         {
  324.             if (Tz[i] > Tz[j])
  325.             {
  326.                 swap_node(i, j);
  327.                 continue;
  328.             }
  329.             
  330.             if (Tz[i] == Tz[j] && Tnt[i] > Tnt[j])
  331.             {
  332.                 swap_node(i, j);
  333.                 continue;
  334.             }
  335.             
  336.             if (Tz[i] == Tz[j] && Tnt[i] == Tnt[j] && Tne[i] > Tne[j])
  337.             {
  338.                 swap_node(i,j);
  339.                 continue;
  340.             }
  341.             
  342.             if (Tz[i] == Tz[j] && Tnt[i] == Tnt[j] && Tne[i] == Tne[j] && Tp[i] > Tp[j])
  343.                 swap_node(i, j);
  344.         }
  345.     }
  346. }
  347.  
  348. BYTE *Remove_and_Add(BYTE *string, BYTE *msg) {
  349.     BYTE *rem,
  350.          *p,
  351.          line[100];
  352.     
  353.     strcpy (line, string);
  354.     
  355.     if (strstr(msg, line) != NULL) return (msg);
  356.     
  357.     msg = strip_line(msg, line);
  358.     strcpy (line, " ");
  359.     strcat (line, string);
  360.     msg = strip_line(msg,line);
  361.     
  362.     if ((p = strline(msg, "\01REPLY:")) == NULL &&
  363.         (p = strline(msg, "\01MSGID:")) == NULL) {
  364.         msg = add_a_line(string, G_VERSION, msg);
  365.         return (msg);
  366.     }
  367.     
  368.     p = skip_to_token (p, '\n');
  369.     
  370.     if (!*p) return (msg);
  371.     
  372.     rem = (BYTE *)myalloc(strlen(p) + 2);
  373.     
  374.     strcpy (rem, p);
  375.     
  376.     strcpy (p, string);
  377.     strcat (p, G_VERSION);
  378.     strcat (p, "\n");
  379.     strcat (p, rem);
  380.     
  381.     free (rem);
  382.     
  383.     return (msg);
  384. }
  385.  
  386. BYTE *change_msgid(BYTE *msgtext, MSGHEADER *hdr)
  387. {
  388.     /*
  389.     **    Changes the MSGID kludge to the address given in the
  390.     **    message header.
  391.     */
  392.     
  393.     BYTE    *temp, *p, s,
  394.     /*
  395.             *p = strline(msgtext, "\01MSGID:"),
  396.     */
  397.             bf[30],
  398.             tmp[40];
  399.  
  400.     WORD     i;
  401.     ULONG    j;
  402.     
  403. /*        
  404.     p = skip_to_token(p, '\n') - 2;
  405.     while (!isspace(*p) && *p) --p;
  406.     
  407.     if(*p)
  408.     {
  409.         p = skip_blanks(p);
  410.         for (temp = bf; *p && !isspace(*p); *temp++ = *p++);
  411.         *temp = EOS;
  412.     }
  413.     else
  414.     {
  415.         log_line(3,Logmessage[M__ILLEGAL_MSGID]);
  416.         return(msgtext);
  417.     }
  418.  
  419. */    
  420.     j = Random();
  421.     s = (BYTE) Random();
  422.     
  423.     sprintf (bf, "%02x%06lx" ,s ,j);
  424.     
  425.     msgtext = strip_line(msgtext, "\01MSGID:");
  426.     
  427.     p = (BYTE *) myalloc(MAXMSGLENGTH);
  428.     sprintf(p, "\01MSGID: %u:%u/%u ", hdr->Ozone, hdr->Onet, hdr->Onode);
  429.     
  430.     if (hdr->Opoint && !Npoint) {
  431.         sprintf(&p[strlen(p)-1], ".%u ", hdr->Opoint);
  432.     } else {
  433.         for (i=0; i < Npoint; i++) {
  434.             if (hdr->Ozone == Zpoint[i]) {
  435.                 break;
  436.             }
  437.         }
  438.         if (i >= Npoint && hdr->Opoint) {
  439.             sprintf(&p[strlen(p)-1], ".%u ", hdr->Opoint);
  440.         }
  441.     }
  442.     
  443.     if (!strlen (org_domain)) {
  444.         for (i=0; i < domain; i++) {
  445.             if (Appl[i].zone == hdr->Ozone) {
  446.                 if (strlen(Appl[i].domain)) {
  447.                     strncpy(tmp, Appl[i].domain, 39);
  448.                     if ((temp = strchr(tmp, '.')) != NULL) *temp = EOS;
  449.                     sprintf(&p[strlen(p)-1], "@%s ", tmp);
  450.                 }
  451.                 break;
  452.             }
  453.         }
  454.     } else {
  455.         sprintf (&p[strlen(p)-1], "@%s ", org_domain);
  456.     }
  457.     
  458.     sprintf(&p[strlen(p)], "%s\n", bf);
  459.     
  460.     strcat(p, msgtext);
  461.     strcpy(msgtext, p);
  462.     free(p);
  463.     return(msgtext);
  464. }
  465.  
  466. BYTE *add_a_line(BYTE *line, BYTE *addline, BYTE *msgtext)
  467. {
  468.     /*
  469.     **    Adds a line to the top of the message if such a line
  470.     **    is not already in the message text.
  471.     */
  472.     
  473.     BYTE    *p;
  474.     
  475.     if (strline(msgtext, line)) return(msgtext);
  476.     
  477.     if ((UWORD)(strlen(msgtext) + strlen(line) + strlen(addline)) >= MAXMSGLENGTH)
  478.     {
  479.         log_line(6,Logmessage[M__MSG_TO_BIG_TO_ADD], line);
  480.         return(msgtext);
  481.     }
  482.     
  483.     p = (BYTE *) myalloc(MAXMSGLENGTH);
  484.     
  485.     sprintf(p, "%s %s\n", line, addline);
  486.     strcpy(&p[strlen(p)], msgtext);
  487.     
  488.     strcpy(msgtext, p);
  489.     free(p);
  490.     
  491.     return(msgtext);
  492. }
  493.  
  494. BOOLEAN add_point(BYTE *msgtext, MSGHEADER *hdr)
  495. {
  496.     WORD    i;
  497.     BYTE    done_fmpt = FALSE,
  498.             done_topt = FALSE,
  499.             done_intl = FALSE;
  500.     
  501.     for (i = 0; i < nkey; i++)
  502.     {
  503.         if (hdr->Dzone == pwd[i].zone && hdr->Dnet == pwd[i].net &&
  504.             hdr->Dnode == pwd[i].node && hdr->Dpoint == pwd[i].point)
  505.         {
  506.             if (pwd[i].mtype == TYPE4d)
  507.             {
  508.                 sprintf(&msgtext[strlen(msgtext)], "\01INTL %u:%u/%u %u:%u/%u\n",
  509.                     hdr->Dzone, hdr->Dnet, hdr->Dnode, hdr->Ozone,
  510.                     hdr->Onet,hdr->Onode);
  511.                 
  512.                 done_intl++;
  513.                 
  514.                 if (hdr->Dpoint)
  515.                 {
  516.                     sprintf(&msgtext[strlen(msgtext)], "\01TOPT %u\n", hdr->Dpoint);
  517.                     done_topt++;
  518.                 }
  519.                 else
  520.                     if (hdr->Opoint)
  521.                     {
  522.                         sprintf(&msgtext[strlen(msgtext)], "\01FMPT %u\n", hdr->Opoint);
  523.                         done_fmpt++;
  524.                     }
  525.             }
  526.             
  527.             break;
  528.         }
  529.     }
  530.     
  531. #if defined EXTERNDEBUG
  532.     if (debugflag)
  533.     {
  534.         log_line(6,">Add kludged INTL etc. :");
  535.         log_line(6,">TOPT = %s", (done_topt) ? "Added" :"None");
  536.         log_line(6,">FMPT = %s", (done_fmpt) ? "Added" :"None");
  537.         log_line(6,">INTL = %s", (done_intl) ? "Added" :"None");
  538.     }
  539. #endif
  540.     
  541.     return((done_topt+done_fmpt+done_intl) ? TRUE : FALSE);
  542. }
  543.  
  544. BYTE *strline(BYTE *msgtext, BYTE *line)
  545. {
  546.     while (*msgtext)
  547.     {
  548.         if (!strncmp(msgtext, line, (WORD)strlen(line)))
  549.             return(msgtext);
  550.         
  551.         msgtext = skip_to_token(msgtext, '\n');
  552.         if (!*msgtext) break;
  553.     }
  554.     
  555.     return(NULL);
  556. }
  557.  
  558. BYTE *strip_those_lines(BYTE *msgtext, BYTE *line)
  559. {
  560.     while (strline(msgtext, line) != NULL)
  561.         msgtext = strip_line(msgtext, line);
  562.     
  563.     return(msgtext);
  564. }
  565.  
  566. WORD ARCtype(BYTE *ARCfile)
  567. {
  568.     /*
  569.     **    wwwMail: v.pomey 27 july 90
  570.     **    public domain - whatarc like
  571.     */
  572.     
  573.     WORD    amail;
  574.     UBYTE    c[4];
  575.     
  576.     amail = Fopen(ARCfile, FO_READ);
  577.     
  578.     if (amail < 0)
  579.     {
  580.         log_line(6,Logmessage[M__CANT_OPEN], ARCfile);
  581.         return(isUNKNOWN);
  582.     }
  583.     
  584.     Fread(amail, 4L, c);
  585.     Fclose(amail);
  586.     
  587.     giveTIMEslice();
  588.     
  589.     if (*c == 'P' && c[1] == 'K')    return(isZIPmail);
  590.     if (*c == 0x1a)                    return(isARCmail);
  591.     if (c[2] == '-' && c[3] == 'l')    return(isLZHmail);
  592.     if (*c == 0x60 && c[1] == 0xea)    return(isARJmail);
  593.     
  594.     return(isUNKNOWN);
  595. }
  596.  
  597. MLOCAL VOID rollchars(VOID)
  598. {
  599.     BYTE    charbuf = *chars;
  600.     
  601.     memcpy(chars, chars+1L, 63L);
  602.     chars[63] = charbuf;
  603. }
  604.  
  605. /*
  606. VOID decrypt(IOSKEY *key)
  607. {
  608.     WORD    i, j;
  609.     
  610.     key->year ^= DATE_XOR;
  611.     key->day ^= DATE_XOR;
  612.     key->month ^= DATE_XOR;
  613.     
  614.     key->start ^= START_XOR;
  615.     key->type  ^= KTYPE_XOR;
  616.     IOSKEY_zone = key->zone ^ START_XOR;
  617.     
  618.     while (*chars != key->start) rollchars();
  619.     
  620.     for (i=0; i < 36; i++)
  621.     {
  622.         key->name[i] ^= NAME_XOR;
  623.         
  624.         if (key->name[i] == -1)
  625.         {
  626.             key->name[i] = EOS;
  627.             break;
  628.         }
  629.         
  630.         for (j=0; j < key->name[i]; j++) rollchars();
  631.         
  632.         key->name[i] = *chars;
  633.     }
  634. }
  635. */
  636.  
  637. UWORD intel(UWORD x)
  638. {
  639.     return( ((x << 8) & 0xFF00) | ((x >> 8) & 0x00FF) );
  640. }
  641.  
  642. MLOCAL UWORD ztoi(BYTE *str, WORD len)
  643. {
  644.     UWORD    temp = 0;
  645.     
  646.     while (*str && len-- && isalnum(*str))
  647.     {
  648.         temp *= 36;
  649.         temp += isdigit(*str) ? *str-'0' : toupper(*str)-'A'+10;
  650.         str++;
  651.     }
  652.     
  653.     return(temp);
  654. }
  655.  
  656. VOID getTBaddress(BYTE *str, UWORD *zone, UWORD *net, UWORD *node)
  657. {
  658.     *zone = ztoi(str, 2);
  659.     *net = ztoi(str+2, 3);
  660.     *node = ztoi(str+5, 3);
  661. }
  662.  
  663. VOID getBTaddress(BYTE *str, UWORD *net, UWORD *node, UWORD *point)
  664. {
  665.     *net = ztoi(str, 3);
  666.     *node = ztoi(str+3, 3);
  667.     *point = ztoi(str+6, 2);
  668. }
  669.  
  670. VOID get4Daddress(BYTE *str, UWORD *zone, UWORD *net, UWORD *node, UWORD *point)
  671. {
  672.     *zone = ztoi(str, 2);
  673.     *net = ztoi(str+2, 3);
  674.     *node = ztoi(str+5, 3);
  675.     *point = ztoi(str+9, 2);
  676. }
  677.  
  678. BYTE *expand(BYTE *addr)
  679. {
  680.     LOCAL BYTE    dest[128];
  681.     /*BYTE        zone[6],
  682.                 net[6],
  683.                 node[6],
  684.                 point[6],
  685.                 *p = addr;*/
  686.     WORD        usealias = 0;
  687.     
  688.     
  689.     memset(dest, 0, 128L);
  690.     
  691.     if (addr[strlen(addr)-1] == '*')
  692.     {
  693.         strcpy(dest, addr);
  694.         return(dest);
  695.     }
  696.     
  697.     if (!strchr(addr, ':'))
  698.         sprintf(dest, "%u:", alias[0].zone);
  699.     else
  700.     {
  701.         strcpy(dest, addr);
  702.         if (!strchr(dest, '.')) strcat(dest, ".0");
  703.         
  704.         return(dest);
  705.     }
  706.     
  707.     if (!strchr(addr, '/'))
  708.         sprintf(dest+strlen(dest), "%u/", alias[usealias].net);
  709.     else
  710.     {
  711.         strcat(dest, addr);
  712.         if (!strchr(dest, '.')) strcat(dest, ".0");
  713.         return(dest);
  714.     }
  715.     
  716.     if (!strchr(addr, '.'))
  717.     {
  718.         strcat(dest, addr);
  719.         strcat(dest, ".0");
  720.         return(dest);
  721.     }
  722.     else if (*addr == '.')
  723.         sprintf(dest+strlen(dest), "%u", alias[usealias].node);
  724.     
  725.     strcat(dest, addr);
  726.     
  727.     return(dest);
  728. }
  729.  
  730. BYTE *address(BYTE *s, UWORD *zone, UWORD *net, UWORD *node,
  731.                 UWORD *point, UWORD *pnet, BYTE *domain)
  732. {
  733.     BYTE            *p = s,
  734.                     n[9],
  735.                     have = 0;
  736.     WORD            i = 0;
  737.     
  738.     if (!s) return(NULL);
  739.     
  740.     domain [0] = '\0';
  741.     
  742.     /*
  743.     **    First, give them all our numbers, if it's only .XX
  744.     */
  745.     
  746.     *zone = alias[0].zone;
  747.     *net = alias[0].net;
  748.     *node = alias[0].node;
  749.     *point = 0;
  750.     *pnet = alias[0].pointnet;
  751.     
  752.     if (*p == '.')        /* if it's a point */
  753.     {
  754.         *point = atoi(++p);
  755.         return(domain);
  756.     }
  757.     
  758.     do
  759.     {
  760.         while (*p != ':' && *p != '/' && *p != '.' && *p != EOS &&
  761.                 *p != ' ' && *p != '\t' && *p !='@') n[i++] = *p++;
  762.         
  763.         n[i] = EOS;
  764.         
  765.         if (!strlen(n))
  766.         {
  767.             if (*p == EOS) return (p);
  768.             log_line(6,Logmessage[M__CONFIG_ERROR_ADRES], s);
  769.             p = skip_blanks(++p);
  770.             continue;
  771.         }
  772.         
  773.         if (!isdigit (n[0])) {
  774.             log_line(6,Logmessage[M__CONFIG_ERROR_ADRES], s);
  775.             return (domain);
  776.         }
  777.         
  778.         if (!have && *p == ':')
  779.             *zone = atoi(n);
  780.         else if (have == 1 || *p == '/')
  781.         {
  782.             *net = atoi(n);
  783.             have = 1;
  784.         }
  785.         else if (have == 2) *node = atoi(n);
  786.         else if (have == 3) *point = atoi(n);
  787.         else if (have == 4) *pnet = atoi(n);
  788.         
  789.         have++;
  790.         
  791.         if (*p == EOS) return(NULL);
  792.                 
  793.         if (*p == '@') {
  794.             i = 0;
  795.             ++p;
  796.             do {
  797.                 if (*p == '.') break;
  798.                 domain[i++] = *p++;
  799.                 if (*p == EOS || *p == ' ') break;
  800.             } while (i < 10);
  801.             domain [i] = EOS;
  802.             
  803.             if (*p != ' ') p = skip_to_blank (p);
  804.             p = skip_blanks (p);
  805.             if (*p == EOS) return (NULL);
  806.             else {
  807.                 i = 0;
  808.                 continue;
  809.             }
  810.         } 
  811.         
  812.         p = skip_blanks(++p);
  813.         
  814.         i = 0;
  815.         
  816.     } while (*p != '\r', have < 5);
  817.     
  818.     return(domain);
  819. }
  820.  
  821. /*
  822. **    Screen buffering
  823. */
  824.  
  825. VOID instal_s_scr(VOID)
  826. {
  827.     BYTE    *help;
  828.     size_t    size;
  829.     
  830.     size = (size_t)_screen * 1024L;
  831.     help = (BYTE *) myalloc(size);
  832.     
  833.     oldestscr = scr1 = (LONG *) Physbase();
  834.     scr2 = (LONG *)((LONG) help + (512L - (LONG) help%512));
  835.     switch_it = (LONG)scr1 ^ (LONG)scr2;
  836. }
  837.  
  838. VOID dump_screen(VOID)
  839. {
  840.     WORD    i;
  841.     LONG    *dump_scr = scr2,
  842.             *old_scr = scr1;
  843.     
  844.     for (i=0; i < 8000; i++) *dump_scr++ = *old_scr++;
  845. }
  846.  
  847. VOID old_screen(VOID)
  848. {
  849.     WORD    i;
  850.     LONG    *dump_scr = scr2,
  851.             *old_scr = scr1;
  852.     
  853.     for (i=0; i < 8000; i++) *old_scr = *dump_scr++;
  854. }
  855.  
  856. VOID switch_screens(VOID)
  857. {
  858.     scr1 = (LONG *) ((LONG)scr1 ^ switch_it);
  859.     scr2 = (LONG *) ((LONG)scr2 ^ switch_it);
  860.     /*Setscreen(scr2, scr1, -1);*/
  861. }
  862.  
  863. VOID end_screen(VOID)
  864. {
  865.     Setscreen(oldestscr, oldestscr, -1);
  866. }
  867.  
  868. /*
  869. **    Logfile
  870. */
  871.  
  872. WORD log_open(VOID)
  873. {
  874.     if (dolog)
  875.         return(((LOG = fopen(logfile, "a")) != NULL) ? SUCCESS : FAILURE);
  876.     else
  877.         return(SUCCESS);
  878. }
  879.  
  880. VOID log_close(VOID)
  881. {
  882.     if (LOG)
  883.     {
  884.         fputs("\n", LOG);
  885.         fclose(LOG);
  886.     }
  887.     
  888.     LOG = NULL;
  889. }
  890.  
  891. VOID log_start(BYTE *program, BYTE *function)
  892. {
  893.     BYTE        startline[128];
  894.     time_t        unixtime;
  895.     struct tm    *tmptr;
  896.     
  897.     time(&unixtime);
  898.     tmptr = localtime(&unixtime);
  899.     if (strlen(Dateformat)) {
  900.         strftime(startline, 127L, Dateformat, tmptr);
  901.         strcat(startline, " IOS  ");
  902.         strcat(startline, program);
  903.     } else {
  904.         strcpy (startline, program);
  905.     }
  906.     
  907.     if (function)
  908.     {
  909.         strcat(startline, " execute ");
  910.         strcat(startline, function);
  911.     }
  912.     
  913.     strcat(startline, "\n");
  914.     
  915.     if (dolog) {
  916.         fputs("\n# ", LOG);
  917.         fputs(startline, LOG);
  918.     }
  919. }
  920.  
  921. WORD log_line(WORD level,BYTE *fmt, ...)
  922. {
  923.     BYTE        line[256],
  924.                 timestring[40],
  925.                 buffer[250];
  926.                 
  927.     WORD        cnt = 0,
  928.                 i;
  929.     time_t        unixtime;
  930.     struct tm    *tmptr;
  931.     va_list        argptr;
  932.     
  933.     
  934.     va_start(argptr, fmt);
  935.     
  936.     time(&unixtime);
  937.     tmptr = localtime(&unixtime);
  938.     
  939.     if (strlen(Dateformat))
  940.         strftime(timestring, 40, Dateformat, tmptr);
  941.     else timestring[0] = EOS;
  942.     
  943.     cnt += vsprintf(line, &fmt[1], argptr);
  944.     
  945.     if (dolog && strchr(logtypes, *fmt) && LOG && level >= loglevel)
  946.     {
  947. #if defined CONF_COMPILER
  948.         fprintf(LOG,"%c %s CCM  %s\n",*fmt,timestring,line);
  949. #else    
  950.         if (strlen(Dateformat))            
  951.             fprintf(LOG,"%c %s IOS  %s\n",*fmt,timestring,line);
  952.         else
  953.             fprintf(LOG,"%c %s\n",*fmt,line);
  954. #endif        
  955.         if ((i = ferror(LOG)) != 0)
  956.         {
  957.             fclose(LOG);
  958.             LOG = NULL;
  959.             cnt += printf ("Write error %d while writing LOG. Log closed.\n", i);
  960.             if (i == -1) {
  961.                 cnt += printf ("Disk FULL");
  962.                 terminate (10);
  963.             }
  964.             dolog = 0;
  965.         } else {
  966.             fflush(LOG);
  967.         }
  968.     }
  969.     
  970.     giveTIMEslice();
  971.     
  972.     if (strchr(disptypes, fmt[0]))
  973.         if (!doquit)
  974. #if defined CONF_COMP
  975.             cnt += printf("%c %s CCM  %s\n",*fmt,timestring,line);
  976. #else
  977.             if (MTask != MULTIGEM) {
  978.                 LOG_line ++;
  979.                 
  980.                 if (LOG_line >= 23) {
  981.                     LOG_line = 22;
  982.                     printf ("\033Y%c%c\033M", 7+' ', 0+' ');
  983.                 }
  984.                 printf ("\033Y%c%c", LOG_line+' ', 0+' ');
  985.                 
  986.                 if (strlen(Dateformat)) 
  987.                     cnt += printf("%c %s IOS  %s",*fmt,timestring,line);
  988.                 else
  989.                     cnt += printf("%c %s",*fmt,line);
  990.             } else {
  991.                 if (strlen(Dateformat))
  992.                     cnt += sprintf(buffer, "%c %s IOS  %s\n\r",*fmt,timestring,line);
  993.                 else
  994.                     cnt += sprintf(buffer, "%c %s\n\r",*fmt,line);
  995.                 
  996.                 v_curtext(vdi_handle, buffer);
  997.             }
  998. #endif
  999.     
  1000.     va_end(argptr);
  1001.     
  1002.     return(cnt);
  1003. }
  1004.  
  1005. /*
  1006. **    File I/O routines
  1007. */
  1008.  
  1009. VOID pktwrite(BYTE *str, UWORD len, FILE *fp)
  1010. {
  1011.     while (len--)
  1012.     {
  1013.         if (*str == '\n') putc('\r',fp);
  1014.         else putc(*str, fp);
  1015.         
  1016.         if (ferror(fp)) w_error("writing packet");
  1017.         
  1018.         str++;
  1019.     }
  1020.     
  1021.     putc(0, fp);
  1022.     
  1023.     giveTIMEslice();
  1024.     
  1025.     fflush(fp);
  1026.     
  1027.     if (ferror(fp)) w_error("writing packet");
  1028. }
  1029.  
  1030. VOID msgwrite(BYTE *str, size_t len, FILE *fp)
  1031. {
  1032.     while (len--)
  1033.     {
  1034.         putc(*str,fp);
  1035.         
  1036.         if (ferror(fp)) w_error("writing message");
  1037.         
  1038.         str++;
  1039.     }
  1040.     
  1041.     fflush(fp);
  1042.     
  1043.     giveTIMEslice();
  1044.     
  1045.     if (ferror(fp)) w_error("writing message");
  1046. }
  1047.  
  1048. VOID msgread(BYTE *str, size_t len, FILE *fp)
  1049. {
  1050.     BYTE    *p = str;
  1051.     
  1052.     while (len--) *p++ = (BYTE)getc(fp);
  1053.     
  1054.     *p = EOS;
  1055.     giveTIMEslice();
  1056. }
  1057.  
  1058. VOID hdrwrite(VOID *str, size_t len, FILE *fp)
  1059. {
  1060.     BYTE    *p = (BYTE *)str;
  1061.     
  1062.     while (len--)
  1063.     {
  1064.         putc(*p,fp);
  1065.         if (ferror(fp)) w_error("writing header");
  1066.         p++;
  1067.     }
  1068.     
  1069.     fflush(fp);
  1070.     
  1071.     giveTIMEslice();
  1072.     
  1073.     if (ferror(fp)) w_error("writing header");
  1074. }
  1075.  
  1076. VOID hdrread(VOID *str, size_t len, FILE *fp)
  1077. {
  1078.     BYTE    *p = (BYTE *)str;
  1079.     
  1080.     while (len--) *p++ = (BYTE)getc(fp);
  1081.     
  1082.     giveTIMEslice();
  1083. }
  1084.  
  1085. /*
  1086. **    Get used product code for the packetheader.
  1087. */
  1088.  
  1089. UBYTE Get_Code (UWORD zone, UWORD net, UWORD node, UWORD point)
  1090. {
  1091.     WORD i;
  1092.     
  1093.     if (point == (UWORD) -1) {
  1094.         for (i = 0; i < nalias; i++) {
  1095.             if (net == alias[i].pointnet) break;
  1096.         }
  1097.         if (i >= nalias)
  1098.             return (IOSPRDCODE);
  1099.         
  1100.         net = alias[i].net;
  1101.         point = node;
  1102.         node = alias[i].node;
  1103.     }
  1104.     
  1105.     for (i= 0 ; i < nkey; i++) {
  1106.         if (zone == pwd[i].zone && net == pwd[i].net &&
  1107.             node == pwd[i].node && point==pwd[i].point &&
  1108.             !strnicmp (pwd[i].Domain, dest_domain, 8)) {
  1109.             
  1110.             if (pwd[i]. TosScan == TRUE)
  1111.                 return (TOSSCANPRD);
  1112.             
  1113.             break;
  1114.         }
  1115.     }
  1116.     
  1117.     return (IOSPRDCODE);
  1118. }
  1119.  
  1120. /*
  1121. **    Packet header creation routines
  1122. */
  1123.  
  1124. VOID create_pkt_hdr(UWORD ozone, UWORD onet, UWORD onode, UWORD dzone, UWORD dnet, UWORD dnode, BYTE *pwd)
  1125. {
  1126.     UBYTE            PrdCode;
  1127.     
  1128.     struct date        d;
  1129.     struct time        t;
  1130.     
  1131.     getdate(&d);
  1132.     gettime(&t);
  1133.     
  1134.     PrdCode = Get_Code(dzone, dnet, dnode, -1);
  1135.     
  1136.     memset(&phdr, 0, sizeof(struct _pkthdr));
  1137.     
  1138.     phdr.ph_ozone = intel(ozone);
  1139.     phdr.ph_onet = intel(onet);
  1140.     phdr.ph_onode = intel(onode);
  1141.     
  1142.     phdr.ph_dzone = intel(dzone);
  1143.     phdr.ph_dnet = intel(dnet);
  1144.     phdr.ph_dnode = intel(dnode);
  1145.     
  1146.     strcpy(phdr.ph_pwd, pwd);
  1147.     
  1148. #if defined EXTERNDEBUG
  1149.     if (debugflag)
  1150.     {
  1151.         log_line(6,">Packet header :");
  1152.         log_line(6,">Origin %u:%u/%u -> %u:%u/%u", ozone, onet, onode, dzone, dnet, dnode);
  1153.     }
  1154. #endif
  1155.     
  1156.     phdr.ph_ver = intel(2);
  1157.     
  1158.     phdr.ph_capable = 0;                /*    Stone-Age    */
  1159.     phdr.ph_CWcopy = 0;
  1160.     
  1161.     phdr.ph_prod = PrdCode;
  1162.     
  1163.     phdr.ph_yr = intel(d.da_year);
  1164.     phdr.ph_mo = intel(d.da_mon - 1);
  1165.     phdr.ph_dy = intel(d.da_day);
  1166.     
  1167.     phdr.ph_hr = intel(t.ti_hour);
  1168.     phdr.ph_mn = intel(t.ti_min);
  1169.     phdr.ph_sc = intel(t.ti_sec);
  1170. }
  1171.  
  1172. VOID create_pkt_fnd(UWORD ozone, UWORD onet, UWORD onode, UWORD opoint, UWORD dzone, UWORD dnet, UWORD dnode, UWORD dpoint, BYTE *pwd)
  1173. {
  1174.     UBYTE            PrdCode;
  1175.     
  1176.     struct date        d;
  1177.     struct time        t;
  1178.     
  1179.     getdate(&d);
  1180.     gettime(&t);
  1181.     
  1182.     PrdCode = Get_Code(dzone, dnet, dnode, dpoint);
  1183.     
  1184.     memset(&phdr, 0, sizeof(struct _pkthdr));
  1185.     
  1186.     phdr.ph_ozone = phdr.ph_qozone = intel(ozone);
  1187.     phdr.ph_onet = intel(onet);
  1188.     phdr.ph_onode = intel(onode);
  1189.     phdr.ph_opoint = intel(opoint);
  1190.     
  1191.     /*if (opoint)
  1192.     {
  1193.         phdr.ph_auxnet = phdr.ph_onet;
  1194.         phdr.ph_onet = intel((UWORD)(-1));
  1195.     }*/
  1196.     
  1197.     phdr.ph_dzone = phdr.ph_qdzone = intel(dzone);
  1198.     phdr.ph_dnet = intel(dnet);
  1199.     phdr.ph_dnode = intel(dnode);
  1200.     phdr.ph_dpoint = intel(dpoint);
  1201.     
  1202.     strcpy(phdr.ph_pwd, pwd);
  1203.     
  1204.     phdr.ph_ver = intel(2);
  1205.     
  1206.     phdr.ph_capable = intel(1);            /*    Type 2+    */
  1207.     phdr.ph_CWcopy = 1;
  1208.     
  1209.     phdr.ph_prod = PrdCode;
  1210.     phdr.ph_rev = IOSMINOR;
  1211.     phdr.ph_revMin = IOSPKTVERS;
  1212.     
  1213.     phdr.ph_yr = intel(d.da_year);
  1214.     phdr.ph_mo = intel(d.da_mon - 1);
  1215.     phdr.ph_dy = intel(d.da_day);
  1216.     
  1217.     phdr.ph_hr = intel(t.ti_hour);
  1218.     phdr.ph_mn = intel(t.ti_min);
  1219.     phdr.ph_sc = intel(t.ti_sec);
  1220. }
  1221.  
  1222. VOID create_pkt_2_2(UWORD ozone, UWORD onet, UWORD onode, 
  1223.     UWORD opoint, UWORD dzone, UWORD dnet, UWORD dnode, 
  1224.     UWORD dpoint, BYTE *pwd, BYTE *Odomain, BYTE *Ddomain)
  1225. {
  1226.     WORD         i;
  1227.     BYTE         temp[20], *q;
  1228.     UBYTE        PrdCode;
  1229.     
  1230.     memset(&phdr2, 0, sizeof(struct _phdr2));
  1231.  
  1232.     strncpy(phdr2.ph_odomain, Odomain, 8);
  1233.  
  1234.     strncpy(phdr2.ph_ddomain, Ddomain, 8);
  1235.     
  1236.     PrdCode = Get_Code(dzone, dnet, dnode, dpoint);
  1237.     
  1238.     phdr2.ph_ozone = intel(ozone);
  1239.     phdr2.ph_onet = intel(onet);
  1240.     phdr2.ph_onode = intel(onode);
  1241.     phdr2.ph_opoint = intel(opoint);
  1242.     
  1243.     phdr2.ph_dzone = intel(dzone);
  1244.     phdr2.ph_dnet = intel(dnet);
  1245.     phdr2.ph_dnode = intel(dnode);
  1246.     phdr2.ph_dpoint = intel(dpoint);
  1247.     
  1248.     strcpy(phdr2.ph_pwd, pwd);
  1249.     
  1250.     phdr2.ph_ver = intel(2);
  1251.     
  1252.     phdr2.ph_sub = intel(2);            /*    Type 2.2    */
  1253.     
  1254.     phdr2.ph_prod = PrdCode;
  1255.     phdr2.ph_rev = IOSPKTVERS;
  1256.     
  1257.     phdr2.ph_spec_data[1] = IOSMINOR;
  1258.     phdr2.ph_spec_data[2] = IOSPRDCODE;
  1259.     
  1260.     memcpy(&phdr, &phdr2, sizeof(struct _phdr2));
  1261. }
  1262.  
  1263. VOID init_PKTS(VOID)
  1264. {
  1265.     WORD    i;
  1266.     
  1267.     memset(&PKTzone, 0, N_MAXPKT * 2);
  1268.     memset(&PKTnet, 0, N_MAXPKT * 2);
  1269.     memset(&PKTnode, 0, N_MAXPKT * 2);
  1270.     memset(&PKTpoint, 0, N_MAXPKT * 2);
  1271.     
  1272.     /*
  1273.     **    Netmail area
  1274.     */
  1275.     
  1276.     MMSG = NULL;
  1277.     MHDR = NULL;
  1278.     
  1279.     for (i=0; i < N_MAXPKT; i++) PKTchannel[i] = FILEclosed;
  1280.         
  1281.     for (i=0; i < N_MAXAREA; i++)
  1282.     {
  1283.         /*
  1284.         **    Local msgbase
  1285.         */
  1286.         
  1287.         LMSGfile[i] = FILEclosed;
  1288.         LHDRfile[i] = FILEclosed;
  1289.         lastareawritten[i] = -1;
  1290.     }
  1291.     
  1292.     /*
  1293.     **    Trasharea
  1294.     */
  1295.     
  1296.     MSGMSG = NULL;
  1297.     MSGHDR = NULL;
  1298. }
  1299.  
  1300. VOID close_PKTS(VOID)
  1301. {
  1302.     WORD    i, attr;
  1303.     BYTE    fbuf[128];
  1304.     UWORD    TO_AREAS, TO_PKTS;
  1305.     
  1306.     if (MMSG) fclose(MMSG);
  1307.     if (MHDR) fclose(MHDR);
  1308.     
  1309.     giveTIMEslice();
  1310.     
  1311.     if (MSGMSG) fclose(MSGMSG);
  1312.     if (MSGHDR) fclose(MSGHDR);
  1313.     
  1314.     giveTIMEslice();
  1315.  
  1316.     if (MTask == MULTITOS) {
  1317.         TO_PKTS = (UWORD) Files_to_open / 3;
  1318.         if (TO_PKTS > N_MAXPKT) TO_PKTS = N_MAXPKT;
  1319.         if (dofastimport == TRUE) TO_PKTS = N_PKTFILE / 2;
  1320.     } else {
  1321.         if (dofastimport) 
  1322.             TO_PKTS = N_PKTFILE / 2;
  1323.         else
  1324.             TO_PKTS = N_PKTFILE;
  1325.     }
  1326.     
  1327.     for (i=0; i < TO_PKTS; i++)
  1328.         if (PKTchannel[i] == FILEopen)
  1329.         {
  1330.             putc(0, PKTfile[i]);
  1331.             putc(0, PKTfile[i]);
  1332.             
  1333.             fclose(PKTfile[i]);
  1334.             giveTIMEslice();
  1335.         }
  1336.     
  1337.     if (MTask == MULTITOS) {
  1338.         TO_AREAS = (UWORD)Files_to_open / 5;
  1339.         if (TO_AREAS > N_MAXAREA) TO_AREAS = N_MAXAREA;
  1340.     }
  1341.     else
  1342.         TO_AREAS = N_AREAFILE;
  1343.  
  1344.     if (dofastimport == TRUE) {
  1345.         freemsgbuf();
  1346.         for (i = 0; i < N_FASTAREAS; i++) {
  1347.             lastareawritten[i] = -1;
  1348.         
  1349.             LHDRfile[i] = FILEclosed;
  1350.             LMSGfile[i] = FILEclosed;
  1351.         }
  1352.         
  1353.     } else {            
  1354.         for (i=0; i < TO_AREAS; i++)
  1355.         {
  1356.             if (LHDRfile[i] == FILEopen) fclose(LHDR[i]);
  1357.             giveTIMEslice();
  1358.             if (LMSGfile[i] == FILEopen) fclose(LMSG[i]);
  1359.             giveTIMEslice();
  1360.             
  1361.             if (LHDRfile[i] == FILEopen)
  1362.             {
  1363.                 sprintf(fbuf, "%s.HDR", Areapath[lastareawritten[i]]);
  1364.                 attr = Fattrib(fbuf, 0, -1);
  1365.                 if (attr != -33 && attr != -34 && attr & FA_ARCHIVE)
  1366.                 {
  1367.                     if (intel(Sversion()) >= 0x0015U)
  1368.                         Fattrib(fbuf, 1, 0);
  1369.                     else
  1370.                         Fattrib(fbuf, 1, FA_ARCHIVE);
  1371.                 }
  1372.             }
  1373.             
  1374.             lastareawritten[i] = -1;
  1375.             
  1376.             LHDRfile[i] = FILEclosed;
  1377.             LMSGfile[i] = FILEclosed;
  1378.         }
  1379.     }
  1380. }
  1381.  
  1382.  
  1383. BOOLEAN Not_allowed(BYTE *msgtext, WORD area) {
  1384.     WORD i;
  1385.     UWORD zone, net, node, point;
  1386.     BYTE Node[40];
  1387.     
  1388.     i = get_msgid(msgtext, &zone, &net, &node, &point);
  1389.     sprintf(Node, "%u:%u/%u.%u", zone, net, node ,point);
  1390.     if (i && newmatch(Node, ROnode[area] )) return (TRUE);
  1391.  
  1392.     return (FALSE);
  1393. }
  1394.  
  1395. VOID giveTIMEslice() {
  1396.     
  1397.     switch (MTask) {
  1398.         case MULTIGEM:
  1399.             evnt_timer(0, 0);
  1400.         break;
  1401.     }
  1402. /*    
  1403.     if (registered == UNR_VERS) {
  1404.         if (bcount ++ >= 10) {
  1405.             if (blink) {
  1406.                 printf("\033Y%c%c\033pRegister for Hfl 25-,\033q", 4+' ', 40+' ');
  1407.                 blink = 0;
  1408.             } else {
  1409.                 printf("\033Y%c%cRegister for Hfl 25-,", 4+' ', 40+' ');
  1410.                 blink = 1;
  1411.             }
  1412.             bcount =0;
  1413.         }
  1414.         delay (3);
  1415.     }
  1416. */
  1417.  
  1418. }
  1419.  
  1420. VOID install_gem () {
  1421.     WORD i;
  1422.     
  1423.     appl_init();
  1424.     
  1425.     for ( i = 1; i < 10; work_in[i++] = 1 ) {
  1426.         work_in[10] = 2;
  1427.          v_handle = graf_handle( &gl_wchar, &gl_hchar, &gl_wbox, &gl_hbox );
  1428.           work_in[0]  = vdi_handle = v_handle;
  1429.  
  1430.           v_opnvwk( work_in, &vdi_handle, work_out );
  1431.     }
  1432. }
  1433.  
  1434. VOID close_gem() {
  1435.    v_clsvwk( vdi_handle );
  1436.    appl_exit();
  1437. }
  1438.  
  1439. WORD hprintf(BYTE to, BYTE *fmt, ...)
  1440. {
  1441.     BYTE        line[256];
  1442.                 
  1443.     WORD        cnt = 0;
  1444.     va_list        argptr;
  1445.  
  1446.     va_start(argptr, fmt);
  1447.     
  1448.     cnt += vsprintf(line, fmt, argptr);
  1449.  
  1450.     if (MTask != MULTIGEM) {
  1451.         printf ("\033Y%c%cTime : %-05ld Secs.", ' ', 60+' ', time(NULL) - Ttest);
  1452.         switch (to) {
  1453.             case S_ALL:
  1454.                 printf("\033E\033Y%c%cArea     :", ' ', ' ');
  1455.                 printf("\033Y%c%cImported : %d", 1+ ' ', ' ', nimported);
  1456.                 printf("\033Y%c%cExported : %d", 2+ ' ', ' ', nechos);
  1457.                 printf("\033Y%c%cSysop    : %d", 3+ ' ', ' ', nprivate);
  1458.                 printf("\033Y%c%cNetmail  : %d", 4+ ' ', ' ', nnetmails);
  1459.                 printf("\033Y%c%cComments :", 5+' ', ' ');
  1460.                 printf("\033Y%c%cFrom        :", 1+' ', 16+' ');
  1461.                 printf("\033Y%c%cDestanation :", 2+' ', 16+' ');
  1462.                 printf("\033Y%c%cDeleted     : 0", 3+ ' ', 16+' ');
  1463.                 printf("\033Y%c%cTrashed     : %d", 4+' ', 16 +' ', ntrashed);
  1464.                 printf ("\033Y%c%c\033p", (S_START - 1)+' ', ' ');
  1465.                 printf ("%s    \033q", Copyright);
  1466.  
  1467.                 LOG_line = S_START;
  1468.                 break;
  1469.             case S_AREA:
  1470.                 printf("\033Y%c%c%-20s",   ' ', 11+' ', line);
  1471.             break;
  1472.             case S_IMP:
  1473.                 printf("\033Y%c%c%-04s", 1+' ', 11+' ', line);
  1474.             break;
  1475.             case S_EXP:
  1476.                 printf("\033Y%c%c%-04s", 2+' ', 11+' ', line);
  1477.             break;
  1478.             case S_SYSOP:
  1479.                 printf("\033Y%c%c%-04s", 3+' ', 11+' ', line);
  1480.             break;
  1481.             case S_NETMAIL:
  1482.                 printf("\033Y%c%c%-04s", 4+' ', 11+' ', line);
  1483.             break;
  1484.             case S_DELETED:
  1485.                 printf("\033Y%c%c%-04s", 3+' ', 30+' ', line);
  1486.             break;
  1487.             case S_FROM:
  1488.                 printf("\033Y%c%c%-25s", 1+' ', 30+' ', line);
  1489.             break;
  1490.             case S_DEST:
  1491.                 printf("\033Y%c%c%-25s", 2+' ', 30+' ', line);
  1492.             break;
  1493.             case S_COMMENT:
  1494.                 printf("\033Y%c%c%-50s", 5+' ', 11+' ', line);
  1495.             break;
  1496.             case S_TRASH:
  1497.                 printf("\033Y%c%c%-04s", 4+' ', 30+' ', line);
  1498.             break;
  1499.         }
  1500.     }
  1501.     else {
  1502.         va_end (argptr);
  1503.         return (0);
  1504.     }
  1505.     
  1506.     va_end(argptr);
  1507.     
  1508.     return (cnt);
  1509. }
  1510.  
  1511. WORD gprintf(BYTE *fmt, ...)
  1512. {
  1513.     BYTE        line[256];
  1514.                 
  1515.     WORD        cnt = 0;
  1516.     va_list        argptr;
  1517.  
  1518.     va_start(argptr, fmt);
  1519.     
  1520.     cnt += vsprintf(line, fmt, argptr);
  1521.  
  1522.     if (MTask != MULTIGEM) {
  1523.         LOG_line ++;
  1524.         
  1525.         if (LOG_line >= 23) {
  1526.             LOG_line = 22;
  1527.             printf ("\033Y%c%c\033M", S_START+' ', 0+' ');
  1528.         }
  1529.         printf ("\033Y%c%c", LOG_line+' ', 0+' ');
  1530.         if (line [strlen (line) - 1] == '\n')
  1531.             line[strlen(line) - 1] = EOS;
  1532.         printf("%s", line);
  1533.     }
  1534.     else {
  1535.         v_curtext(vdi_handle, line);
  1536.         if (line [strlen (line) - 1] == '\n')
  1537.             v_curtext (vdi_handle, "\r");
  1538.         else
  1539.             v_curtext (vdi_handle, " ");
  1540.     }
  1541.     
  1542.     va_end(argptr);
  1543.     
  1544.     return (cnt);
  1545. }
  1546.  
  1547.