ckuus4.c
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:380k
源码类别:

通讯/手机编程

开发平台:

Windows_Unix

  1.       case TN_NG_RF: printf( "u, refused;   " ); break;
  2.       case TN_NG_RQ: printf( "u, requested; "); break;
  3.       case TN_NG_MU: printf( "u, required;  "); break;
  4.     }
  5.     switch (TELOPT_ME_MODE(TELOPT_BINARY)) {
  6.       case TN_NG_AC: printf( "me, accepted; " ); break ;
  7.       case TN_NG_RF: printf( "me, refused; " ); break;
  8.       case TN_NG_RQ: printf( "me, requested; "); break;
  9.       case TN_NG_MU: printf( "me, required;  "); break;
  10.     }
  11.     printf("u, %s; me, %sn",
  12.            TELOPT_U(TELOPT_BINARY) ? "BINARY" : "NVT",
  13.            TELOPT_ME(TELOPT_BINARY) ? "BINARY" : "NVT"
  14.            );
  15.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  16.     printf(" binary-transfer-mode: %sn",showoff(tn_b_xfer));
  17.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  18.     printf(" bug binary-me-means-u-too: %sn",showoff(tn_b_meu));
  19.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  20.     printf(" bug binary-u-means-me-too: %sn",showoff(tn_b_ume));
  21.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  22.     printf(" bug sb-implies-will-do: %sn",showoff(tn_sb_bug));
  23.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  24.     printf(" terminal-type: ");
  25.     if (tn_term) {
  26.         printf("%sn",tn_term);
  27.     } else {
  28.         char *p;
  29. #ifdef OS2
  30.         p = (tt_type >= 0 && tt_type <= max_tt) ?
  31.           tt_info[tt_type].x_name :
  32.             "UNKNOWN";
  33. #else
  34.         p = getenv("TERM");
  35. #endif /* OS2 */
  36.         if (p)
  37.           printf("none (%s will be used)n",p);
  38.         else printf("nonen");
  39.     }
  40.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  41. #ifdef CK_ENVIRONMENT
  42.     printf(" environment: %sn", showoff(tn_env_flg));
  43.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  44.     printf("   account: %sn",tn_env_acct);
  45.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  46.     printf("   display: %sn",tn_env_disp);
  47.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  48.     printf("   job    : %sn",tn_env_job);
  49.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  50.     printf("   printer: %sn",tn_env_prnt);
  51.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  52. #ifndef NOSPL
  53.     printf("   user   : %sn",uidbuf);
  54.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  55. #endif /* NOSPL */
  56.     printf("   system : %sn",tn_env_sys);
  57.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  58. #endif /* CK_ENVIRONMENT */
  59. #ifdef CK_SNDLOC
  60.     printf(" location: %sn", tn_loc ? tn_loc : "(none)");
  61.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  62. #endif /* CK_SNDLOC */
  63.     return(n);
  64. }
  65. #endif /* TNCODE */
  66. #ifdef CK_NETBIOS
  67. static int
  68. shonb(n) int n; {
  69.     printf("NETBIOS parameters:n");
  70.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  71.     printf(" API       : %sn",
  72.            NetbeuiAPI ?
  73.            "NETAPI.DLL - IBM Extended Services or Novell Netware Requester"
  74.            : "ACSNETB.DLL - IBM Network Transport Services/2" ) ;
  75.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  76.     printf(" Local Name: [%s]n", NetBiosName);
  77.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  78.     printf(" Adapter   : %dn", NetBiosAdapter);
  79.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  80.     if (NetBiosLSN > 0xFF) {
  81.         printf(" Session   : %dn", NetBiosLSN);
  82.     } else {
  83.         printf(" Session   : none activen");
  84.     }
  85.     if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
  86.     return(n);
  87. }
  88. #endif /* CK_NETBIOS */
  89. #ifndef NONET
  90. int
  91. shonet() {
  92. #ifndef NETCONN
  93.     printf("nNo networks are supported in this version of C-Kermitn");
  94. #else
  95. #ifdef NOLOCAL
  96.     printf("nNo networks are supported in this version of C-Kermitn");
  97. #else /* rest of this routine */
  98.     int i, n = 4;
  99. #ifndef NODIAL
  100.     if (nnetdir <= 1) {
  101.         printf("nNetwork directory: %sn",netdir[0] ? netdir[0] : "(none)");
  102.         n++;
  103.     } else {
  104.         int i;
  105.         printf("nNetwork directories:n");
  106.         for (i = 0; i < nnetdir; i++) {
  107.             printf("%2d. %sn",i,netdir[i]);
  108.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  109.         }
  110.     }
  111. #endif /* NODIAL */
  112. #ifdef OS2
  113.     printf("nNetwork availability:n");
  114. #else
  115.     printf("nSupported networks:n");
  116. #endif /* OS2 */
  117.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  118. #ifdef VMS
  119. #ifdef TCPWARE
  120.     printf(" Process Software Corporation TCPware for OpenVMS");
  121. #else
  122. #ifdef MULTINET
  123.     printf(" TGV MultiNet TCP/IP");
  124. #else
  125. #ifdef WINTCP
  126.     printf(" WOLLONGONG WIN/TCP");
  127. #else
  128. #ifdef DEC_TCPIP
  129.     {
  130.         static $DESCRIPTOR(tcp_desc,"_TCP0:");
  131.         int status;
  132.         long devclass;
  133.         static int itmcod = DVI$_DEVCLASS;
  134. #ifdef COMMENT
  135.         status = LIB$GETDVI(&itmcod, 0, &tcp_desc, &devclass);
  136. #else
  137.         /* Martin Zinser 9/96 */
  138.         status = lib$getdvi(&itmcod, 0, &tcp_desc, &devclass);
  139. #endif /* COMMENT */
  140.         if ((status & 1) && (devclass == DC$_SCOM))
  141.           printf(" Process Software Corporation TCPware for OpenVMS");
  142.         else
  143. #ifdef UCX50
  144.           printf(" DEC TCP/IP Services for (Open)VMS 5.0");
  145. #else
  146.           printf(" DEC TCP/IP Services for (Open)VMS");
  147. #endif /* UCX50 */
  148.     }
  149. #else
  150. #ifdef CMU_TCPIP
  151.     printf(" CMU-OpenVMS/IP");
  152. #else
  153.     printf(" None");
  154. #endif /* CMU_TCPIP */
  155. #endif /* DEC_TCPIP */
  156. #endif /* WINTCP */
  157. #endif /* MULTINET */
  158. #endif /* TCPWARE */
  159.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  160. #ifdef TNCODE
  161.     printf(", TELNET protocolnn");
  162.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  163.     n = shotel(n);
  164.     if (n < 0) return(0);
  165.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  166. #endif /* TNCODE */
  167.     printf("n");
  168.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  169. #else /* Not VMS */
  170. #ifdef SUNX25
  171.     printf(" SunLink X.25n");
  172.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  173. #endif /* SUNX25 */
  174. #ifdef STRATUSX25
  175.     printf(" Stratus VOS X.25n");
  176.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  177. #endif /* STRATUSX25 */
  178. #ifdef IBMX25
  179.     printf(" IBM AIX X.25n");
  180.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  181. #endif /* IBMX25 */
  182. #ifdef HPX25
  183.     printf(" HP-UX X.25n");
  184.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  185. #endif /* HPX25 */
  186. #ifdef DECNET
  187. #ifdef OS2
  188. #ifdef NT
  189.     if (dnet_avail)
  190.       printf(" DECnet, LAT and CTERM protocolsn");
  191.     else
  192.       printf(" DECnet, LAT and CTERM protocols - not availablen");
  193.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  194. #else /* NT */
  195.     if (dnet_avail)
  196.       printf(" DECnet, LAT protocoln");
  197.     else
  198.       printf(" DECnet, LAT protocol - not availablen");
  199.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  200. #endif /* NT */
  201. #else
  202.     printf(" DECnetn");
  203.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  204. #endif /* OS2 */
  205. #endif /* DECNET */
  206. #ifdef NPIPE
  207.     printf(" Named Pipesn");
  208.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  209. #endif /* NPIPE */
  210. #ifdef CK_NETBIOS
  211.     if (netbiosAvail)
  212.       printf(" NETBIOSn");
  213.     else
  214.       printf(" NETBIOS - not availablen");
  215.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  216. #endif /* CK_NETBIOS */
  217. #ifdef SUPERLAT
  218.     if (slat_avail)
  219.       printf(" SuperLATn");
  220.     else
  221.       printf(" SuperLAT - not availablen") ;
  222.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  223. #endif /* SUPERLAT */
  224. #ifdef TCPSOCKET
  225.     if (
  226. #ifdef OS2
  227.         tcp_avail
  228. #else
  229.         1
  230. #endif /* OS2 */
  231.         ) {
  232.         char ipaddr[16];
  233.         if (getlocalipaddrs(ipaddr,16,0) < 0) {
  234. #ifdef OS2ONLY
  235.             printf(" TCP/IP via %sn", tcpname);
  236. #else
  237.             printf(" TCP/IPn");
  238. #endif /* OS2ONLY */
  239.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  240.         } else {
  241.             int i = 1;
  242. #ifdef OS2ONLY
  243.           printf(" TCP/IP [%16s] via %sn", ipaddr, tcpname);
  244. #else
  245.           printf(" TCP/IP [%16s]n",ipaddr);
  246. #endif /* OS2ONLY */
  247.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  248.             while (getlocalipaddrs(ipaddr,16,i++) >= 0) {
  249.                 printf("        [%16s]n",ipaddr);
  250.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  251.             }
  252.         }
  253. #ifdef TNCODE
  254.         if (nettype == NET_TCPB) {
  255.             printf("n");
  256.             n = shotel(++n);
  257.             if (n < 0) return(0);
  258.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  259.         }
  260. #endif /* TNCODE */
  261. #ifdef OS2
  262.     } else {
  263.         printf(" TCP/IP - not available%sn",tcpname[0] ? tcpname : "" );
  264.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  265. #endif /* OS2 */
  266.     }
  267. #endif /* TCPSOCKET */
  268. #ifdef CK_NETBIOS
  269.     if (netbiosAvail && nettype == NET_BIOS) {
  270.        printf("n") ;
  271.        if ((n = shonb(++n)) < 0) return(0);
  272.        if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  273.     }
  274. #endif /* CK_NETBIOS */
  275. #endif /* VMS */
  276.     printf("nActive network connection:n");
  277.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  278.     if (network) {
  279.         printf(" Host: %s",ttname);
  280.         if ((nettype == NET_TCPA || nettype == NET_TCPB) && *ipaddr)
  281.           printf(" [%s]",ipaddr);
  282.     } else
  283.       printf(" Host: none");
  284.     printf(", via: ");
  285.     if (nettype == NET_TCPA || nettype == NET_TCPB)
  286.       printf("tcp/ipn");
  287.     else if (nettype == NET_SX25)
  288.       printf("SunLink X.25n");
  289.     else if (nettype == NET_VX25)
  290.       printf("Stratus VOS X.25n");
  291.     else if (nettype == NET_IX25)
  292.       printf("IBM AIX X.25n");
  293.     else if (nettype == NET_HX25)
  294.       printf("HP-UX X.25n");
  295.     else if (nettype == NET_DEC) {
  296.         if ( ttnproto == NP_LAT )
  297.           printf("DECnet LATn");
  298.         else if ( ttnproto == NP_CTERM )
  299.           printf("DECnet CTERMn");
  300.         else
  301.           printf("DECnetn");
  302.     } else if (nettype == NET_PIPE)
  303.       printf("Named Pipesn");
  304.     else if (nettype == NET_BIOS)
  305.       printf("NetBIOSn");
  306.     else if (nettype == NET_SLAT)
  307.       printf("SuperLATn");
  308. #ifdef NETFILE
  309.     else if ( nettype == NET_FILE )
  310.       printf("local filen");
  311. #endif /* NETFILE */
  312. #ifdef NETCMD
  313.     else if ( nettype == NET_CMD )
  314.       printf("pipen");
  315. #endif /* NETCMD */
  316. #ifdef NETPTY
  317.     else if ( nettype == NET_PTY )
  318.         printf("psuedoterminaln");
  319. #endif /* NETPTY */
  320. #ifdef NETDLL
  321.     else if ( nettype == NET_DLL )
  322.       printf("dynamic link libraryn");
  323. #endif /* NETDLL */
  324. #ifdef SSH
  325.     else if ( nettype == NET_SSH )
  326.       printf("Secure Shelln");
  327. #endif /* SSH */
  328.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  329. #ifdef ANYX25
  330.     if ((nettype == NET_SX25) ||
  331.         (nettype == NET_VX25) ||
  332.         (nettype == NET_IX25))
  333.       if ((n = shox25(n)) < 0) return(0);
  334. #endif /* ANYX25 */
  335. #ifdef TCPSOCKET
  336.     if (nettype == NET_TCPA || nettype == NET_TCPB) {
  337.         printf(" Reverse DNS lookup: %sn", showooa(tcp_rdns));
  338.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  339. #ifdef CK_DNS_SRV
  340.         printf(" DNS Service Records lookup: %sn", showooa(tcp_dns_srv));
  341.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  342. #endif /* CK_DNS_SRV */
  343. #ifndef NOTCPOPTS
  344. #ifdef SOL_SOCKET
  345. #ifdef SO_KEEPALIVE
  346.         printf(" Keepalive: %sn", showoff(tcp_keepalive));
  347.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  348. #endif /* SO_KEEPALIVE */
  349. #ifdef SO_LINGER
  350.         printf(" Linger: %s", tcp_linger ? "on, " : "offn" );
  351.         if (tcp_linger) {
  352.             if (tcp_linger_tmo)
  353.               printf("%d x 10 millisecondsn",tcp_linger_tmo);
  354.             else
  355.               printf("no timeoutn");
  356.         }
  357.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  358. #endif /* SO_LINGER */
  359. #ifdef SO_DONTROUTE
  360.         printf(" DontRoute: %sn", tcp_dontroute ? "on" : "off" );
  361.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  362. #endif /* SO_DONTROUTE */
  363. #ifdef TCP_NODELAY
  364.         printf(" Nodelay: %sn", showoff(tcp_nodelay));
  365.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  366. #endif /* TCP_NODELAY */
  367. #ifdef SO_SNDBUF
  368.         if (tcp_sendbuf <= 0)
  369.           printf(" Send buffer: (default size)n");
  370.         else
  371.           printf(" Send buffer: %d bytesn", tcp_sendbuf);
  372.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  373. #endif /* SO_SNDBUF */
  374. #ifdef SO_RCVBUF
  375.         if (tcp_recvbuf <= 0)
  376.           printf(" Receive buffer: (default size)n");
  377.         else
  378.           printf(" Receive buffer: %d bytesn", tcp_recvbuf);
  379.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  380. #endif /* SO_RCVBUF */
  381. #endif /* SOL_SOCKET */
  382. #endif /* NOTCPOPTS */
  383.     }
  384. #ifdef RLOGCODE
  385.     if (ttnproto == NP_RLOGIN) {
  386.         printf(" LOGIN (rlogin) protocoln");
  387.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  388.     }
  389. #ifdef CK_KERBEROS
  390.     else if (ttnproto == NP_K4LOGIN) {
  391.         printf(" Kerberos 4 LOGIN (klogin) protocoln");
  392.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  393.     }
  394.     else if (ttnproto == NP_EK4LOGIN) {
  395.         printf(" Encrypted Kerberos 4 LOGIN (eklogin) protocoln");
  396.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  397.     }
  398.     else if (ttnproto == NP_K5LOGIN) {
  399.         printf(" Kerberos 5 LOGIN (klogin) protocoln");
  400.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  401.     }
  402.     else if (ttnproto == NP_EK5LOGIN) {
  403.         printf(" Encrypted Kerberos 5 LOGIN (eklogin) protocoln");
  404.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  405.     }
  406. #endif /* CK_KERBEROS */
  407. #endif /* RLOGCODE */
  408. #ifdef TNCODE
  409.     if (ttnproto == NP_TELNET) {
  410.         printf(" TELNET protocoln");
  411.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  412.         printf(" Echoing is currently %sn",duplex ? "local" : "remote");
  413.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  414.     }
  415. #endif /* TNCODE */
  416.     if (ttnproto == NP_TCPRAW) {
  417.         printf(" Raw TCP socketn");
  418.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  419.     }
  420. #endif /* TCPSOCKET */
  421.     printf("n");
  422. #endif /* NOLOCAL */
  423. #endif /* NETCONN */
  424.     return(0);
  425. }
  426. #endif /* NONET */
  427. #ifndef NODIAL
  428. VOID
  429. shodial() {
  430.     if (mdmtyp >= 0 || local != 0) doshodial();
  431. }
  432. VOID
  433. shods(s) char *s; {                     /* Show a dial-related string */
  434.     char c;
  435.     if (s == NULL || !(*s)) {           /* Empty? */
  436.         printf("(none)n");
  437.     } else {                            /* Not empty. */
  438.         while (c = *s++)                /* Can contain controls */
  439.           if (c == '\')                /* a backslash */
  440.             printf("\\");
  441.           else if (c > 31 && c < 127) {
  442.               putchar(c);
  443.           } else
  444.             printf("\{%d}",c);
  445.         printf("n");
  446.     }
  447. }
  448. int
  449. doshodial() {
  450.     int i, n = 2;
  451.     printf(" Dial status:  %d", dialsta);
  452. #ifdef BIGBUFOK
  453.     if (dialsta > 90)
  454.       printf(" = Unknown error");
  455.     else if (dialsta < 0)
  456.       printf(" = (none)");
  457.     else if (dialsta < 30 && dialmsg[dialsta])
  458.       printf(" = %s", dialmsg[dialsta]);
  459. #endif /* BIGBUFOK */
  460.     n++;
  461.     if (ndialdir <= 1) {
  462.         printf("n Dial directory: %sn",dialdir[0] ? dialdir[0] : "(none)");
  463.     } else {
  464.         int i;
  465.         printf("n Dial directories:n");
  466.         for (i = 0; i < ndialdir; i++)
  467.           printf("%2d. %sn",i+1,dialdir[i]);
  468.         n += ndialdir;
  469.     }
  470.     printf(" Dial method:  ");
  471.     if      (dialmauto)         printf("auto   ");
  472.     else if (dialmth == XYDM_D) printf("default");
  473.     else if (dialmth == XYDM_P) printf("pulse  ");
  474.     else if (dialmth == XYDM_T) printf("tone   ");
  475.     printf("         Dial sort: %sn",dialsrt ? "on" : "off");
  476.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  477.     printf(" Dial hangup:  %s             Dial display: %sn",
  478.            dialhng ? "on " : "off", dialdpy ? "on" : "off");
  479.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  480.     if (dialrtr > 0) {
  481.         printf(" Dial retries: %-6d          Dial interval: %dn",
  482.                dialrtr, dialint);
  483.     } else {
  484.         printf(" Dial retries: (auto)          Dial interval: %dn", dialint);
  485.     }
  486.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  487.     printf(" Dial timeout: ");
  488. #ifdef CK_TAPI
  489.     if (tttapi && !tapipass)
  490.         printf("(tapi)");
  491.     else
  492. #endif /* CK_TAPI */
  493.     if (dialtmo > 0)
  494.       printf("%4d sec", dialtmo);
  495.     else
  496.       printf("0 (auto)");
  497.     printf("        Redial number: %sn",dialnum ? dialnum : "(none)");
  498.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  499.     printf(" Dial confirmation: %s        Dial convert-directory: %sn",
  500.            dialcnf ? "on " : "off",
  501.            dialcvt ? ((dialcvt == 1) ? "on" : "ask") : "off");
  502.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  503.     printf(" Dial ignore-dialtone: %s", dialidt ? "on " : "off");
  504.     printf("     Dial pacing: %dn",dialpace);
  505.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  506.     printf(
  507. " Dial prefix:                  %sn", dialnpr ? dialnpr : "(none)");
  508.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  509.     printf(
  510. " Dial suffix:                  %sn", dialsfx ? dialsfx : "(none)");
  511.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  512.     printf(
  513. " Dial country-code:            %-12s", diallcc ? diallcc : "(none)");
  514.     printf("Dial connect:  %s", dialcon ? ((dialcon == 1) ? "on" : "auto")
  515.            : "off");
  516.     if (dialcon != CAR_OFF)
  517.       printf(" %s", dialcq ? "quiet" : "verbose");
  518.     printf(
  519. "n Dial area-code:               %-12s", diallac ? diallac : "(none)");
  520.     n++;
  521.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  522.     printf("Dial restrict: ");
  523.     if (dialrstr == 5) printf("internationaln");
  524.     else if (dialrstr == 4) printf("long-distancen");
  525.     else if (dialrstr == 2) printf("localn");
  526.     else if (dialrstr == 6) printf("nonen");
  527.     else printf("?n");
  528.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  529.     printf(" Dial lc-area-codes:           ");
  530.     if (nlocalac == 0)
  531.       printf("(none)");
  532.     else
  533.       for (i = 0; i < nlocalac; i++)
  534.         printf("%s ", diallcac[i]);
  535.     printf(
  536. "n Dial lc-prefix:               %sn", diallcp ? diallcp : "(none)");
  537.     n++;
  538.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  539.     printf(
  540. " Dial lc-suffix:               %sn", diallcs ? diallcs : "(none)");
  541.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  542.     printf(
  543. " Dial ld-prefix:               %sn", dialldp ? dialldp : "(none)");
  544.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  545.     printf(
  546. " Dial ld-suffix:               %sn", diallds ? diallds : "(none)");
  547.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  548.     printf(
  549. " Dial force-long-distance      %sn", showoff(dialfld));
  550.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  551.     printf(
  552. " Dial intl-prefix:             %sn", dialixp ? dialixp : "(none)");
  553.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  554.     printf(
  555. " Dial intl-suffix:             %sn", dialixs ? dialixs : "(none)");
  556.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  557.     printf(
  558. " Dial toll-free-area-code:     ");
  559.     if (ntollfree == 0)
  560.       printf("(none)");
  561.     else
  562.       for (i = 0; i < ntollfree; i++)
  563.         printf("%s ", dialtfc[i]);
  564.     printf("n");
  565.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  566.     printf(
  567. " Dial pulse-countries:         ");
  568.     if (ndialpucc == 0)
  569.       printf("(none)");
  570.     else
  571.       for (i = 0; i < ndialpucc; i++)
  572.         printf("%s ", dialpucc[i]);
  573.     printf("n");
  574.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  575.     printf(
  576. " Dial tone-countries:          ");
  577.     if (ndialtocc == 0)
  578.       printf("(none)");
  579.     else
  580.       for (i = 0; i < ndialtocc; i++)
  581.         printf("%s ", dialtocc[i]);
  582.     printf("n");
  583.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  584.     printf(
  585. " Dial toll-free-prefix:        %sn",
  586.            dialtfp ? dialtfp :
  587.           (dialldp ? dialldp : "(none)")
  588.           );
  589.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  590.     printf(
  591. #ifdef COMMENT
  592. " Dial pbx-exchange:            %sn", dialpxx ? dialpxx : "(none)");
  593. #else
  594. " Dial pbx-exchange:            ");
  595.     if (ndialpxx == 0)
  596.       printf("(none)");
  597.     else
  598.       for (i = 0; i < ndialpxx; i++)
  599.         printf("%s ", dialpxx[i]);
  600.     printf("n");
  601. #endif /* COMMENT */
  602.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  603.     printf(
  604. " Dial pbx-inside-prefix:       %sn", dialpxi ? dialpxi : "(none)");
  605.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  606.     printf(
  607. " Dial pbx-outside-prefix:      %sn", dialpxo ? dialpxo : "(none)");
  608.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  609.     printf(
  610. " Dial macro:                   %sn", dialmac ? dialmac : "(none)");
  611.     return(0);
  612. }
  613. #endif /* NODIAL */
  614. #endif /* NOLOCAL */
  615. /*  Show File Parameters */
  616. static char *
  617. pathval(x) int x; {
  618.     switch (x) {
  619.       case PATH_OFF:  return("off");
  620.       case PATH_ABS:  return("absolute");
  621.       case PATH_REL:  return("relative");
  622.       case PATH_AUTO: return("auto");
  623.       default: return("unknown");
  624.     }
  625. }
  626. VOID
  627. shofil() {
  628.     char *s; int i = 0, n = 1;
  629.     extern char * ifdnam[];
  630. #ifdef UNIX
  631.     extern int wildxpand;
  632. #endif /* UNIX */
  633.     extern char * snd_move, * snd_rename, * rcv_move, * rcv_rename;
  634. #ifdef PATTERNS
  635.     extern int patterns;
  636. #endif /* PATTERNS */
  637.     extern char * rfspec, * sfspec;
  638. #ifdef UNIX
  639.     extern int zobufsize, zofbuffer, zofblock;
  640. #endif /* UNIX */
  641. #ifdef CK_CTRLZ
  642.     extern int eofmethod;
  643. #endif /* CK_CTRLZ */
  644.     printf("n");
  645. #ifdef VMS
  646.     printf(" File record-Length:      %5dn",frecl);
  647.     n++;
  648. #endif /* VMS */
  649. #ifndef NOXFER
  650.     printf(" Transfer mode:           %sn",
  651.            xfermode == XMODE_A ?
  652.            "automatic" :
  653.            "manual"
  654.            );
  655.     n++;
  656. #ifdef PATTERNS
  657.     printf(" File patterns:           %s", showooa(patterns));
  658.     if (xfermode == XMODE_M && patterns)
  659.       printf(" (but disabled by TRANSFER-MODE MANUAL)");
  660.     else if (patterns)
  661.       printf(" (SHOW PATTERNS for list)");
  662.     printf("n");
  663.     n++;
  664. #endif /* PATTERNS */
  665.     if (xfermode == XMODE_A)
  666.       printf(" Default file type:       %sn",shoxm());
  667.     else
  668.       printf(" File type:               %sn",shoxm());
  669.     n++;
  670.     if (fncnv == XYFN_L)
  671.       s = "literal";
  672.     else if (fncnv == XYFN_C)
  673.       s = "converted";
  674.     else
  675.       s = "(unknown)";
  676.     printf(" File names:              %sn",s);
  677.     n++;
  678.     printf(" Send pathnames:          %sn", pathval(fnspath));
  679.     n++;
  680.     printf(" Receive pathnames:       %sn", pathval(fnrpath));
  681.     n++;
  682. #ifdef UNIXOROSK
  683.     printf(" Match dot files:         %sn", matchdot ? "yes" : "no");
  684.     n++;
  685. #ifdef UNIX
  686.     printf(" Wildcard-expansion:      %sn", wildxpand ? "shell" : "kermit");
  687.     n++;
  688. #endif /* UNIX */
  689. #endif /* UNIXOROSK */
  690.     printf(" File collision:          ");
  691.     for (i = 0; i < ncolx; i++)
  692.       if (colxtab[i].kwval == fncact) break;
  693.     printf("%sn", (i == ncolx) ? "unknown" : colxtab[i].kwd);
  694.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  695.     printf(" File destination:        %sn",
  696.            (dest == DEST_D) ? "disk" :
  697.            ((dest == DEST_S) ? "screen" :
  698.             ((dest == DEST_N) ? "nowhere" :
  699.             "printer"))
  700.            );
  701.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  702.     s = (keep >= 0 && keep <= 2) ? ifdnam[keep] : "keep";
  703.     printf(" File incomplete:         %sn",s);
  704.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  705.     printf(" File bytesize:           %dn",(fmask == 0177) ? 7 : 8);
  706.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  707. #ifndef NOCSETS
  708.     printf(" File character-set:      %sn",fcsinfo[fcharset].keyword);
  709.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  710. #ifdef UNICODE
  711.     printf(" File UCS bom:            %sn",showoff(ucsbom));
  712.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  713.     printf(" File UCS byte-order:     %s-endiann",
  714.            ucsorder ? "little" : "big");
  715.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  716.     printf(" Computer byteorder:      %s-endiann",
  717.            byteorder ? "little" : "big");
  718.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  719. #endif /* UNICODE */
  720. #endif /* NOCSETS */
  721.     printf(" File end-of-line:        ");
  722.     i = feol;
  723.     switch (feol) {
  724.       case XYFA_C: printf("%sn","cr"); break;
  725.       case XYFA_L: printf("%sn","lf"); break;
  726.       case XYFA_2: printf("%sn","crlf"); break;
  727.       default: printf("%dn",i);
  728.     }
  729. #endif /* NOXFER */
  730.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  731. #ifdef CK_CTRLZ
  732.     printf(" File eof:                %sn", eofmethod ? "ctrl-z" : "length");
  733.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  734. #endif /* CK_CTRLZ */
  735. #ifndef NOXFER
  736. #ifdef CK_TMPDIR
  737.     printf(" File download-directory: %sn", dldir ? dldir : "(none)");
  738.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  739. #ifdef COMMENT
  740.     i = 256;
  741.     s = line;
  742.     zzstring("\v(tmpdir)",&s,&i);
  743.     printf(" Temporary directory:     %sn", line);
  744.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  745. #endif /* COMMENT */
  746. #endif /* CK_TMPDIR */
  747. #ifdef VMS
  748.     {
  749. extern int vmssversions, vmsrversions;
  750. printf(" Send version-numbers:    %sn",showoff(vmssversions));
  751. if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  752. printf(" Receive version-numbers: %sn",showoff(vmsrversions));
  753. if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  754.     }
  755. #endif /* VMS */
  756.     printf(" Send move-to:            %sn",
  757.            snd_move ? snd_move : "(none)");
  758.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  759.     printf(" Send rename-to:          %sn",
  760.            snd_rename ? snd_rename : "(none)");
  761.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  762.     printf(" Receive move-to:         %sn",
  763.            rcv_move ? rcv_move : "(none)");
  764.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  765.     printf(" Receive rename-to:       %sn",
  766.            rcv_rename ? rcv_rename : "(none)");
  767.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  768. #endif /* NOXFER */
  769. #ifdef KERMRC
  770.     printf(" Initialization file:     %sn", noinit ? "(none)" :
  771. #ifdef CK_SYSINI
  772.            CK_SYSINI
  773. #else
  774.            kermrc
  775. #endif /* CK_SYSINI */
  776.            );
  777. #endif /* KERMRC */
  778.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  779.     if (k_info_dir) {
  780.         printf(" Kermit doc files:        %sn", k_info_dir);
  781.         if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  782.     }
  783. #ifdef UNIX
  784.     printf(" Disk output buffer:      %d (writes are %s, %s)n",
  785.            zobufsize,
  786.            zofbuffer ? "buffered" : "unbuffered",
  787.            zofblock ? "blocking" : "nonblocking"
  788.            );
  789.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  790. #endif /* UNIX */
  791. #ifdef OS2ORUNIX
  792.     printf(" Longest filename:        %dn", maxnam);
  793.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  794.     printf(" Longest pathname:        %dn", maxpath);
  795.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  796. #endif /* OS2ORUNIX */
  797.     printf(" Last file sent:          %sn", sfspec ? sfspec : "(none)");
  798.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  799.     printf(" Last file received:      %sn", rfspec ? rfspec : "(none)");
  800.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  801.     printf("n Also see:n");
  802.     n++;
  803.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  804.     printf(" SHOW PROTOCOL, SHOW XFER");
  805. #ifdef CK_LABELED
  806.     printf(", SHOW LABELED");
  807. #endif /* CK_LABELED */
  808. #ifdef PATTERNS
  809.     printf(", SHOW PATTERNS");
  810. #endif /* PATTERNS */
  811. #ifdef STREAMING
  812.     printf(", SHOW STREAMING");
  813. #endif /* STREAMING */
  814. #ifndef NOCSETS
  815.     printf(", SHOW CHARACTER-SETS");
  816. #endif /* NOCSETS */
  817.     printf("nn");
  818. }
  819. #ifndef NOXFER
  820. VOID
  821. shoparp() {                             /* Protocol */
  822.     extern int docrc, skipbup;
  823.     char *s;
  824. #ifdef CK_TIMERS
  825.     extern int rttflg;
  826. #endif /* CK_TIMERS */
  827.     printf("Protocol: %sn",ptab[protocol].p_name);
  828.     if (protocol == PROTO_K) {
  829.         printf("nProtocol Parameters:   Send    Receive");
  830.         if (timef)
  831.           printf("n Timeout (used=%2d):%7d*%8d ", timint, rtimo, pkttim);
  832.         else
  833.           printf("n Timeout (used=%2d):%7d%9d ",  timint, rtimo, pkttim);
  834. #ifdef XFRCAN
  835.         printf("       Cancellation:    %s",showoff(xfrcan));
  836.         if (xfrcan)
  837.           printf(" %d %d", xfrchr, xfrnum);
  838. #endif /* XFRCAN */
  839.         printf("n Padding:      %11d%9d", npad,   mypadn);
  840.         if (bctr == 4)
  841.           printf("        Block Check: blank-free-2n");
  842.         else
  843.           printf("        Block Check: %6dn",bctr);
  844.         printf(  " Pad Character:%11d%9d", padch,  mypadc);
  845.         printf("        Delay:       %6dn",ckdelay);
  846.         printf(  " Pause:        %11d%9d", pktpaus, pktpaus);
  847.         printf("        Attributes:      %sn",showoff(atcapr));
  848.         printf(  " Packet Start: %11d%9d", mystch, stchr);
  849.         printf("        Max Retries: %6dn",maxtry);
  850.         printf(  " Packet End:   %11d%9d", seol,   eol);
  851.         if (ebqflg)
  852.           printf("        8th-Bit Prefix: '%c'",ebq);
  853.         else
  854.           printf("        8th-Bit Prefix: ('%c' but not used)",ebq);
  855.         printf(  "n Packet Length:%11d ", spmax);
  856.         printf("%8d     ",  urpsiz);
  857.         if (rptflg)
  858.           printf("   Repeat Prefix:  '%c'",rptq);
  859.         else
  860.           printf("   Repeat Prefix:  ('%c' but not used)",rptq);
  861.         printf(  "n Maximum Length: %9d%9d", maxsps, maxrps);
  862.         printf("        Window Size:%7d set, %d usedn",wslotr,wmax);
  863.         printf(    " Buffer Size:  %11d%9d", bigsbsiz, bigrbsiz);
  864.         printf("        Locking-Shift:    ");
  865.         if (lscapu == 2) {
  866.             printf("forced");
  867.         } else {
  868.             printf("%s", (lscapr ? "enabled" : "disabled"));
  869.             if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
  870.         }
  871.         printf("nn");
  872.         if (!(s = ptab[protocol].h_b_init)) s = "";
  873.         printf(" Auto-upload command (binary): %sn", *s ? s : "(none)");
  874.         if (!(s = ptab[protocol].h_t_init)) s = "";
  875.         printf(" Auto-upload command (text):   %sn", *s ? s : "(none)");
  876.         if (!(s = ptab[protocol].h_x_init)) s = "";
  877.         printf(" Auto-server command:          %sn", *s ? s : "(none)");
  878.         tmpbuf[0] = NUL;
  879. #ifdef CK_TIMERS
  880.         if (rttflg) {
  881.             extern int mintime, maxtime;
  882.             sprintf(tmpbuf," Packet timeouts: dynamic %d:%d",
  883.                     mintime,
  884.                     maxtime);
  885.         } else {
  886.             sprintf(tmpbuf," Packet timeouts: fixed");
  887.         }
  888. #endif /* CK_TIMERS */
  889.         if (tmpbuf[0])
  890.           printf("%-31s",tmpbuf);
  891.         printf("Send backup: %sn",showoff(!skipbup));
  892.         printf(" Transfer mode:   %s", xfermode == XMODE_A ?
  893.                "automatic   " :
  894.                "manual      "
  895.                );
  896.         printf(" Transfer slow-start: %s, crc: %sn",
  897.                showoff(slostart),
  898.                showoff(docrc)
  899.                );
  900. #ifdef PIPESEND
  901.         {
  902.             extern int usepipes;
  903.             printf(" Transfer pipes:  %s         ",usepipes ? "on " : "off");
  904.         }
  905. #endif /* PIPESEND */
  906. #ifndef NOCSETS
  907.         printf(" Transfer character-set: ");
  908.         if (tcharset == TC_TRANSP)
  909.           printf("transparentn");
  910.         else
  911.           printf("%sn", tcsinfo[tcharset].keyword );
  912. #endif /* NOCSETS */
  913. #ifdef PIPESEND
  914.         {
  915.             extern char * sndfilter, * rcvfilter;
  916.             printf(" Send filter:     %sn", sndfilter ? sndfilter : "(none)");
  917.             printf(" Receive filter:  %sn", rcvfilter ? rcvfilter : "(none)");
  918.         }
  919. #endif /* PIPESEND */
  920.         printf("nAlso see:n");
  921.         printf(" SHOW FILE, SHOW XFER");
  922. #ifdef CK_LABELED
  923.         printf(", SHOW LABELED");
  924. #endif /* CK_LABELED */
  925. #ifdef PATTERNS
  926.         printf(", SHOW PATTERNS");
  927. #endif /* PATTERNS */
  928. #ifdef STREAMING
  929.         printf(", SHOW STREAMING");
  930. #endif /* STREAMING */
  931. #ifndef NOCSETS
  932.         printf(", SHOW CHARACTER-SETS");
  933. #endif /* NOCSETS */
  934.     }
  935. #ifdef CK_XYZ
  936. #ifdef XYZ_INTERNAL
  937.     if (protocol != PROTO_K) {
  938.         int i;
  939.         int x;
  940.         printf(" File type: %sn", binary ? "binary" : "text");
  941.         if (protocol == PROTO_Z) {              /* Zmodem */
  942.             printf(" Window size:   ");
  943.             if (ptab[protocol].winsize < 1)
  944.               printf("nonen");
  945.             else
  946.               printf("%dn",wslotr);
  947. #ifdef COMMENT
  948.             printf(" Packet (frame) length: ");
  949.             if (ptab[protocol].spktlen < 0)
  950.               printf("nonen");
  951.             else
  952.               printf("%dn",spmax);
  953. #endif /* COMMENT */
  954.         } else {
  955.             if (ptab[protocol].spktlen >= 1000)
  956.               printf(" 1K packetsn");
  957.             else
  958.               printf(" 128-byte packetsn");
  959.         }
  960.         printf(" Pathname stripping when sending:   %sn",
  961.                showoff(ptab[protocol].fnsp)
  962.                );
  963.         printf(" Pathname stripping when receiving: %sn",
  964.                showoff(ptab[protocol].fnrp)
  965.                );
  966.         printf(" Filename collision action:         ");
  967.         for (i = 0; i < ncolx; i++)
  968.           if (colxtab[i].kwval == fncact) break;
  969.         printf("%-12s", (i == ncolx) ? "unknown" : colxtab[i].kwd);
  970.         printf("n Escape control characters:          ");
  971.         x = ptab[protocol].prefix;
  972.         if (x == PX_ALL)
  973.           printf("alln");
  974.         else if (x == PX_CAU || x==PX_WIL)
  975.           printf("minimaln");
  976.         else
  977.           printf("nonen");
  978.         if (!(s = ptab[protocol].h_b_init))
  979.           s = "";
  980.         printf(" Autoreceive command (binary): %sn", *s ? s : "(none)");
  981.         if (!(s = ptab[protocol].h_t_init))
  982.           s = "";
  983.         printf(" Autoreceive command (text):   %sn", *s ? s : "(none)");
  984.     }
  985. #else
  986.     if (protocol != PROTO_K) {
  987.         printf("nExecuted by external commands:nn");
  988.         s = ptab[protocol].p_b_scmd;
  989.         if (!s) s = "";
  990.         printf(" SEND command (binary):        %sn", *s ? s : "(none)");
  991.         s = ptab[protocol].p_t_scmd;
  992.         if (!s) s = "";
  993.         printf(" SEND command (text):          %sn", *s ? s : "(none)");
  994.         s = ptab[protocol].p_b_rcmd;
  995.         if (!s) s = "";
  996.         printf(" RECEIVE command (binary):     %sn", *s ? s : "(none)");
  997.         s = ptab[protocol].p_t_rcmd;
  998.         if (!s) s = "";
  999.         printf(" RECEIVE command (text):       %sn", *s ? s : "(none)");
  1000.         s = ptab[protocol].h_b_init;
  1001.         if (!s) s = "";
  1002.         printf(" Autoreceive command (binary): %sn", *s ? s : "(none)");
  1003.         s = ptab[protocol].h_t_init;
  1004.         if (!s) s = "";
  1005.         printf(" Autoreceive command (text):   %sn", *s ? s : "(none)");
  1006.     }
  1007. #endif /* XYZ_INTERNAL */
  1008. #endif /* CK_XYZ */
  1009. }
  1010. #endif /* NOXFER */
  1011. #ifndef NOCSETS
  1012. /* Character-set items */
  1013. extern int s_cset, r_cset, axcset[], afcset[];
  1014. extern struct keytab xfrmtab[];
  1015. VOID
  1016. shoparl() {
  1017. #ifdef COMMENT
  1018.     int i;
  1019. /* Misleading... */
  1020.     printf("nAvailable Languages:n");
  1021.     for (i = 0; i < MAXLANG; i++) {
  1022.         printf(" %sn",langs[i].description);
  1023.     }
  1024. #else
  1025.     printf("nLanguage-specific translation rules: %sn",
  1026.            language == L_USASCII ? "none" : langs[language].description);
  1027.     shocharset();
  1028.     printf("nn");
  1029. #endif /* COMMENT */
  1030. }
  1031. VOID
  1032. shocharset() {
  1033.     int x;
  1034.     char * s = "Unknown";
  1035.     extern int xlatype;
  1036.     debug(F101,"SHOW FILE CHAR","",fcharset);
  1037.     printf("n File Character-Set: %s (%s), ",
  1038.            fcsinfo[fcharset].keyword,
  1039.            fcsinfo[fcharset].name
  1040.            );
  1041.     if ((x = fcsinfo[fcharset].size) == 128)
  1042.       printf("7-bit");
  1043.     else if (x == 256)
  1044.       printf("8-bit");
  1045.     else
  1046.       printf("multibyte");
  1047.     printf("n Transfer Character-Set");
  1048. #ifdef COMMENT
  1049.     if (tslevel == TS_L2)
  1050.       printf(": (international)");
  1051.     else
  1052. #endif /* COMMENT */
  1053.     if (tcharset == TC_TRANSP)
  1054.       printf(": Transparent");
  1055.     else
  1056.       printf(": %s (%s)",tcsinfo[tcharset].keyword, tcsinfo[tcharset].name);
  1057.     printf("n");
  1058. #ifdef COMMENT
  1059.     switch (xlatype) {
  1060.       case XLA_NONE: s = "None"; break;
  1061.       case XLA_BYTE: s = "Byte"; break;
  1062.       case XLA_JAPAN: s = "Japanese"; break;
  1063.       case XLA_UNICODE: s = "Unicode"; break;
  1064.     }
  1065.     printf("n Translation type: %sn",s);
  1066. #endif /* COMMENT */
  1067.     printf(" SEND character-set-selection: %sn",xfrmtab[s_cset].kwd);
  1068.     printf(" RECEIVE character-set-selection: %sn",xfrmtab[r_cset].kwd);
  1069.     if (s_cset == XMODE_A || r_cset == XMODE_A)
  1070.       printf(
  1071.       " (Use SHOW ASSOCIATIONS to list automatic character-set selections.)n"
  1072.              );
  1073. }
  1074. VOID
  1075. showassoc() {
  1076.     int i, k, n = 4;
  1077.     char * s;
  1078.     printf("nFor incoming files:nn");
  1079.     printf("Transfer Character-Set   File Character-Setn");
  1080.     for (i = 1; i <= MAXTCSETS; i++) {
  1081.         k = axcset[i];
  1082.         if (k < 0 || k > MAXFCSETS)
  1083.           s = "(none)";
  1084.         else
  1085.           s = fcsinfo[k].keyword;
  1086.         if (!s) s = "";
  1087.         if (!*s) s = "(none)";
  1088.         printf(" %-25s%sn",tcsinfo[i].keyword,s);
  1089.         if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  1090.     }
  1091.     printf("nFor outbound files:nn");
  1092.     n += 2;
  1093.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  1094.     printf("File Character-Set       Transfer Character-Setn");
  1095.     if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  1096.     for (i = 0; i <= MAXFCSETS; i++) {
  1097.         k = afcset[i];
  1098.         if (k < 0 || k > MAXTCSETS)
  1099.           s = "(none)";
  1100.         else
  1101.           s = tcsinfo[k].keyword;
  1102.         if (!s) s = "";
  1103.         if (!*s) s = "(none)";
  1104.         printf(" %-25s%sn",fcsinfo[i].keyword,s);
  1105.         if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
  1106.     }
  1107. }
  1108. #endif /* NOCSETS */
  1109. VOID
  1110. shopar() {
  1111.     printf("Show what?  (Type "show ?" for a list of possiblities.)n");
  1112. }
  1113. #endif /* NOSHOW */
  1114. #ifndef NOXFER
  1115. /*  D O S T A T  --  Display file transfer statistics.  */
  1116. int
  1117. dostat(brief) int brief; {
  1118.     extern long filrej, peakcps;
  1119.     extern int lastspmax, streamed, cleared, streamok;
  1120.     extern char whoareu[];
  1121.     int n = 0;
  1122.     extern int docrc, interrupted, fatalio;
  1123. #ifdef CK_TTGWSIZ
  1124. #ifdef OS2
  1125.     if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
  1126.       ttgwsiz();
  1127. #else /* OS2 */
  1128.     if (ttgwsiz() > 0) {
  1129.         if (tt_rows > 0 && tt_cols > 0) {
  1130.             cmd_rows = tt_rows;
  1131.             cmd_cols = tt_cols;
  1132.         }
  1133.     }
  1134. #endif /* OS2 */
  1135. #endif /* CK_TTGWSIZ */
  1136.     debug(F101,"dostat xferstat","",xferstat);
  1137.     if (xferstat < 0) {
  1138.         printf(" No file transfers yet.n");
  1139.         return(1);
  1140.     }
  1141.     if (brief) printf("n");
  1142.     n = 1;
  1143.     printf(" status                 : ");
  1144.     if (xferstat) printf("SUCCESSn");
  1145.     else if (interrupted) printf("FAILURE (interrupted)n");
  1146.     else if (fatalio) printf("FAILURE (i/o error)n");
  1147.     else printf("FAILUREn");
  1148.     n++;
  1149.     if (xferstat > 0) {
  1150.         if (docrc)
  1151.           printf(" crc-16 of file(s)      : %ldn", crc16);
  1152.         else
  1153.           printf(" crc-16 of file(s)      : (disabled)n");
  1154.         n++;
  1155.     }
  1156.     if (!xferstat && *epktmsg) {
  1157.         printf(" reason                 : %sn", epktmsg);
  1158.         n++;
  1159.     }
  1160.     if (!brief) {
  1161.         if (whoareu[0]) {
  1162.             printf(" remote system type     : %sn",
  1163.                    getsysid((char *)whoareu));
  1164.             n++;
  1165.         }
  1166.         printf(" files transferred      : %ldn",filcnt - filrej);
  1167.         printf(" files not transferred  : %ldn",filrej);
  1168.         printf(" characters last file   : %ldn",ffc);
  1169.         printf(" total file characters  : %ldn",tfc);
  1170.         printf(" communication line in  : %ldn",tlci);
  1171.         printf(" communication line out : %ldn",tlco);
  1172.         printf(" packets sent           : %dn", spackets);
  1173.         printf(" packets received       : %dn", rpackets);
  1174.         n += 8;
  1175.     }
  1176.     printf(" damaged packets rec'd  : %dn", crunched);
  1177.     printf(" timeouts               : %dn", timeouts);
  1178.     printf(" retransmissions        : %dn", retrans);
  1179.     n += 3;
  1180.     if (!brief) {
  1181.         if (filcnt > 0) {
  1182.             printf(" parity                 : %s",parnam((char)parity));
  1183.             n++;
  1184.             if (autopar) { printf(" (detected automatically)"); n++; }
  1185.             printf(
  1186.                  "n control characters     : %ld prefixed, %ld unprefixedn",
  1187.                    ccp, ccu);
  1188.             n++;
  1189.             printf(" 8th bit prefixing      : ");
  1190.             n++;
  1191.             if (ebqflg) printf("yes [%c]n",ebq); else printf("non");
  1192.             n++;
  1193.             printf(" locking shifts         : %sn", lscapu ? "yes" : "no");
  1194.             n++;
  1195.         }
  1196.     }
  1197.     if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
  1198.     if (streamed > 0)
  1199.       printf(" window slots used      : (streaming)n");
  1200.     else
  1201.       printf(" window slots used      : %d of %dn", wmax, wslotr);
  1202.     if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
  1203.     printf(" reliable:              : %s%sn",
  1204.            streamok ? "" : "not ", "negotiated");
  1205.     if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
  1206.     printf(" clearchannel:          : %s%sn",
  1207.            cleared  ? "" : "not ", "negotiated");
  1208.     if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
  1209.     if (!brief) {
  1210.         printf(" packet length          : %d (send), %d (receive)n",
  1211.                lastspmax, urpsiz);
  1212.         if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
  1213.         printf(" compression            : ");
  1214.         if (rptflg)
  1215.           printf("yes [%c] (%ld)n",(char) rptq,rptn);
  1216.         else
  1217.           printf("non");
  1218.         if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
  1219.         if (bctu == 4)
  1220.           printf(" block check type used  : blank-free-2n");
  1221.         else
  1222.           printf(" block check type used  : %dn",bctu);
  1223.         if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
  1224.     }
  1225. #ifdef GFTIMER
  1226. #ifdef COMMENT
  1227.     printf(" elapsed time           : %0.3f sec, %sn", fptsecs,hhmmss(tsecs));
  1228. #endif /* COMMENT */
  1229.     printf(" elapsed time           : %s (%0.3f sec)n",
  1230.            hhmmss((long)(fptsecs + 0.5)),fptsecs);
  1231. #else
  1232. #ifdef COMMENT
  1233.     printf(" elapsed time           : %s (%d sec)n",hhmmss(tsecs),tsecs);
  1234. #endif /* COMMENT */
  1235.     printf(" elapsed time           : %d sec, %sn",tsecs,hhmmss(tsecs));
  1236. #endif /* GFTIMER */
  1237.     if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
  1238.     if (local && !network && !brief) {
  1239.         if (speed <= 0L) speed = ttgspd();
  1240.         if (speed > 0L) {
  1241.             if (speed == 8880)
  1242.               printf(" transmission rate      : 75/1200 bpsn");
  1243.             else
  1244.               printf(" transmission rate      : %ld bpsn",speed);
  1245.             if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
  1246.         }
  1247.     }
  1248.     if (local && !network &&    /* Only makes sense for */
  1249.         mdmtyp == 0 &&          /* direct serial connections */
  1250.         speed > 99L &&          /* when we really know the speed */
  1251.         speed != 8880L
  1252.         ) {
  1253.         int eff;
  1254.         eff = (((tfcps * 100L) / (speed / 100L)) + 5L) / 10L;
  1255.         printf(" effective data rate    : %ld cps (%d%%)n",tfcps,eff);
  1256.     } else
  1257.       printf(" effective data rate    : %ld cpsn", tfcps);
  1258.     if (peakcps > 0L && peakcps > tfcps)
  1259.       printf(" peak data rate         : %ld cpsn", peakcps);
  1260.     if (brief)
  1261.       printf("nUse STATISTICS /VERBOSE for greater detail.nn");
  1262.     return(1);
  1263. }
  1264. #endif /* NOXFER */
  1265. #ifndef NOSPL
  1266. /* The INPUT command */
  1267. /*
  1268.   NOTE: An INPUT timeout of 0 means to perform a nonblocking read of the
  1269.   material that has already arrived and is waiting to be read, and perform
  1270.   matches against it, without doing any further reads.  It should succeed
  1271.   or fail instantaneously.
  1272. */
  1273. /* Output buffering for "doinput" */
  1274. #ifdef pdp11
  1275. #define MAXBURST 16             /* Maximum size of input burst */
  1276. #else
  1277. #define MAXBURST 1024
  1278. #endif /* pdp11 */
  1279. #ifdef OSK
  1280. static CHAR *conbuf;            /* Buffer to hold output for console */
  1281. #else
  1282. static CHAR conbuf[MAXBURST];   /* Buffer to hold output for console */
  1283. #endif /* OSK */
  1284. static int concnt = 0;          /* Number of characters buffered */
  1285. #ifdef OSK
  1286. static CHAR *sesbuf;            /* Buffer to hold output for session log */
  1287. #else
  1288. static CHAR sesbuf[MAXBURST];   /* Buffer to hold output for session log */
  1289. #endif /* OSK */
  1290. static int sescnt = 0;          /* Number of characters buffered */
  1291. static VOID                             /* Flush INPUT echoing */
  1292. myflsh() {                              /* and session log output. */
  1293.     if (concnt > 0) {
  1294.         conxo(concnt, (char *) conbuf);
  1295.         concnt = 0;
  1296.     }
  1297.     if (sescnt > 0) {
  1298.         logstr((char *) sesbuf, sescnt);
  1299.         sescnt = 0;
  1300.     }
  1301. }
  1302. /* Execute the INPUT and MINPUT commands */
  1303. int instatus = -1;
  1304. long inetime = -1L;
  1305. int inwait = 0;
  1306. /* For returning the input sequence that matched */
  1307. #ifdef BIGBUFOK
  1308. #define MATCHBUFSIZ 8191
  1309. #else
  1310. #define MATCHBUFSIZ 1023
  1311. #endif /* BIGBUFOK */
  1312. static char * matchbuf = NULL;
  1313. static int matchindex = 0;
  1314. /*
  1315.   timo = How long to wait:
  1316.          < 0 = Wait forever
  1317.            0 = Don't wait
  1318.          > 0 = Wait this many seconds
  1319.   ms   = Array of strings to wait for.
  1320.   mp   = Array of flags.
  1321.          If mp[i] == 0, ms[i] is literal, else it's a pattern.
  1322. */
  1323. int
  1324. doinput(timo,ms,mp) int timo; char *ms[]; int mp[]; {
  1325.     extern int inintr;
  1326. #ifdef CK_AUTODL
  1327.     extern int inautodl;
  1328. #endif /* CK_AUTODL */
  1329.     int x, y, i, t, rt, icn, anychar, mi[MINPMAX];
  1330. #ifdef GFTIMER
  1331.     CKFLOAT fpt = 0.0;
  1332. #endif /* GFTIMER */
  1333.     int lastchar = 0;
  1334.     int waiting = 0;
  1335.     char ch, *xp, *s;
  1336.     CHAR c;
  1337. #ifdef OS2
  1338.     extern int term_io;
  1339.     int term_io_save;
  1340. #endif /* OS2 */
  1341. #ifdef TNCODE
  1342.     static int cr = 0;
  1343. #endif /* TNCODE */
  1344.     int is_tn = 0;
  1345.     int wrapped = 0;
  1346. #define CK_BURST
  1347. /*
  1348.   This enables the INPUT speedup code, which depends on ttchk() returning
  1349.   accurate information.  If INPUT fails with this code enabled, change the
  1350.   above "#define" to "#undef".
  1351. */
  1352. #ifdef CK_BURST
  1353.     int burst = 0;                      /* Chars remaining in input burst */
  1354. #endif /* CK_BURST */
  1355.     inwait = timo;                      /* For v(inwait) */
  1356.     makestr(&inpmatch,NULL);
  1357.     if (!matchbuf)
  1358.       matchbuf = malloc(MATCHBUFSIZ+1);
  1359.     matchindex = 0;
  1360.     is_tn =
  1361. #ifdef TNCODE
  1362.         (local && network && ttnproto == NP_TELNET) || (!local && sstelnet)
  1363. #else
  1364.          0
  1365. #endif /* TNCODE */
  1366.           ;
  1367.     instatus = INP_IE;                  /* 3 = internal error */
  1368.     kbchar = 0;
  1369. #ifdef OSK
  1370.     if (conbuf == NULL) {
  1371.         if ((conbuf = (CHAR *)malloc(MAXBURST*2)) == NULL) {
  1372.             return(0);
  1373.         }
  1374.         sesbuf = conbuf + MAXBURST;
  1375.     }
  1376. #endif /* OSK */
  1377. #ifndef NOLOCAL
  1378.     if (local) {                        /* In local mode... */
  1379.         if ((waiting = ttchk()) < 0) {  /* check that connection is open */
  1380.             printf("?Connection %s %s is not open.n",
  1381.                    network ? "to" : "on",
  1382.                    ttname
  1383.                    );
  1384.             instatus = INP_IO;
  1385.             return(0);
  1386.         }
  1387.         debug(F101,"doinput waiting","",waiting);
  1388.         y = ttvt(speed,flow);           /* Put line in "ttvt" mode */
  1389.         if (y < 0) {
  1390.             printf("?INPUT initialization errorn");
  1391.             instatus = INP_IO;
  1392.             return(0);                  /* Watch out for failure. */
  1393.         }
  1394.     }
  1395. #endif /* NOLOCAL */
  1396.     if (!ms[0]) {                       /* If we were passed a NULL pointer */
  1397.         anychar = 1;                    /*  ... */
  1398.     } else {
  1399.         y = (int)strlen(ms[0]);         /* Or if search string is empty */
  1400.         anychar = (y < 1);              /* any input character will do. */
  1401.     }
  1402.     if (!anychar && waiting == 0 && timo == 0)
  1403.       return(0);
  1404. #ifndef NODEBUG
  1405.     if (deblog) {
  1406.         char xbuf[24];
  1407.         debug(F101,"doinput anychar","",anychar);
  1408.         debug(F101,"doinput timo","",timo);
  1409.         debug(F101,"doinput echo","",inecho);
  1410.         debug(F101,"doinput burst","",burst);
  1411.         y = -1;
  1412.         while (ms[++y]) {
  1413.             sprintf(xbuf,"doinput string %2d",y);
  1414.             debug(F111,xbuf,ms[y],mp[y]);
  1415.         }
  1416.     }
  1417. #endif /* NODEBUG */
  1418. #ifdef IKS_OPTION
  1419.     if (is_tn) {
  1420.         /* If the remote side is in a state of IKS START-SERVER    */
  1421.         /* we request that the state be changed.  We will detect   */
  1422.         /* a failure to adhere to the request when we call ttinc() */
  1423.         if (TELOPT_U(TELOPT_KERMIT) &&
  1424.             TELOPT_SB(TELOPT_KERMIT).kermit.u_start)
  1425.           iks_wait(KERMIT_REQ_STOP,0);  /* Send Request-Stop */
  1426. #ifdef CK_AUTODL
  1427.         /* If we are processing packets during INPUT and we have not */
  1428.         /* sent a START message, do so now.                          */
  1429.         if (inautodl && !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
  1430.             tn_siks(KERMIT_START);      /* Send Kermit-Server Start */
  1431.         }
  1432. #endif /* CK_AUTODL */
  1433.     }
  1434. #endif /* IKS_OPTION */
  1435.     x = 0;                              /* Return code, assume failure */
  1436.     instatus = INP_TO;                  /* Status, assume timeout */
  1437.     for (y = 0; y < MINPMAX; y++)
  1438.       mi[y] = 0;                        /* String pattern match position */
  1439.     if (!inpcas[cmdlvl]) {              /* INPUT CASE = IGNORE?  */
  1440.         y = -1;
  1441.         while(xp = ms[++y]) {
  1442.             while (*xp) {               /* Convert to lowercase */
  1443.                 if (isupper(*xp)) *xp = (char) tolower(*xp);
  1444.                 xp++;
  1445.             }
  1446.         }
  1447.     }
  1448.     rtimer();                           /* Reset timer. */
  1449. #ifdef GFTIMER
  1450.     rftimer();                          /* Floating-point timer too. */
  1451. #endif /* GFTIMER */
  1452.     inetime = -1L;                      /* Initialize elapsed time. */
  1453.     t = 0;                              /* Time now is 0. */
  1454.     m_found = 0;                        /* Default to timed-out */
  1455.     incount = 0;                        /* Character counter */
  1456.     rt = (timo == 0) ? 0 : 1;           /* Character-read timeout interval */
  1457. #ifdef OS2
  1458.     term_io_save = term_io;             /* Disable I/O by emulator */
  1459.     term_io = 0;
  1460. #endif /* OS2 */
  1461.     while (1) {                         /* Character-getting loop */
  1462. #ifdef CK_APC
  1463.         /* Check to see if there is an Autodown or other APC command */
  1464.         if (apcactive == APC_LOCAL ||
  1465.             (apcactive == APC_REMOTE && apcstatus != APC_OFF)) {
  1466.             if (mlook(mactab,"_apc_commands",nmac) == -1) {
  1467.                 debug(F110,"doinput about to execute APC",apcbuf,0);
  1468.                 domac("_apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
  1469.                 delmac("_apc_commands");
  1470.                 apcactive = APC_INACTIVE;
  1471. #ifdef DEBUG
  1472.             } else {
  1473.                 debug(F100,"doinput APC in progress","",0);
  1474. #endif /* DEBUG */
  1475.             }
  1476.         }
  1477. #endif /* CK_APC */
  1478.         if (timo == 0 && waiting < 1) { /* Special exit criterion */
  1479.             instatus = INP_TO;          /* for timeout == 0 */
  1480.             break;
  1481.         }
  1482.         if (local) {                    /* One case for local */
  1483.             y = ttinc(rt);              /* Get character from comm device */
  1484.             debug(F101,"input ttinc(rt) returns","",y);
  1485.             if (y < -1) {               /* Connection failed. */
  1486.                 instatus = INP_IO;      /* Status = i/o error */
  1487. #ifdef OS2
  1488.                 term_io = term_io_save;
  1489. #endif /* OS2 */
  1490.                 switch (y) {
  1491.                   case -2:              /* Connection lost */
  1492.                     if (local && !network && carrier != CAR_OFF) {
  1493. #ifdef CKLOGDIAL
  1494.                         dologend();
  1495. #endif /* CKLOGDIAL */
  1496.                         printf("Connection closed.n");
  1497.                         ttclos(1);
  1498.                     }
  1499.                     break;
  1500.                   case -3:
  1501. #ifdef CKLOGDIAL
  1502.                     dologend();
  1503. #endif /* CKLOGDIAL */
  1504.                     printf("Session Limit exceeded - closing connection.n");
  1505.                     ttclos(1);
  1506.                   default:
  1507.                     break;
  1508.                 }
  1509.                 return(0);
  1510.             }
  1511.             if (inintr) {
  1512.                 if ((icn = conchk()) > 0) { /* Interrupted from keyboard? */
  1513.                     kbchar = coninc(0);
  1514.                     debug(F101,"input interrupted from keyboard","",icn);
  1515.                     while (--icn > 0) {
  1516.                         debug(F110,"doinput","absorbing",0);
  1517.                         coninc(0);      /* Yes, absorb what was typed. */
  1518.                     }
  1519.                     instatus = INP_UI;  /* Fail and remember why. */
  1520.                     break;
  1521.                 }
  1522.             }
  1523.         } else {                        /* Another for remote */
  1524.             y = coninc(rt);
  1525.             debug(F101,"input coninc(rt) returns","",y);
  1526.         }
  1527.         if (y > -1) {                   /* A character arrived */
  1528.             if (timo == 0)
  1529.               waiting--;
  1530. #ifndef OS2
  1531. #ifdef TNCODE
  1532.             /* Check for telnet protocol negotiation */
  1533.             if (is_tn) {
  1534.                 switch (y & 0xff) {
  1535.                   case IAC:
  1536.                     cr = 0;
  1537.                     myflsh();   /* Break from input burst for tn_doop() */
  1538. #ifdef CK_BURST
  1539.                     burst = 0;
  1540. #endif /* CK_BURST */
  1541.                     waiting -= 2;       /* (not necessarily...) */
  1542.                     switch (tn_doop((CHAR)(y & 0xff),duplex,ttinc)) {
  1543.                       case 2: duplex = 0; continue;
  1544.                       case 1: duplex = 1; continue;
  1545. #ifdef IKS_OPTION
  1546.                       case 4:
  1547.                         if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
  1548.                              !tcp_incoming) {
  1549.                             instatus = INP_IKS;
  1550.                             printf(
  1551. " Internet Kermit Service in SERVER mode.n Please use REMOTE commands.n"
  1552.                                    );
  1553.                             break;
  1554.                         }
  1555.                         continue;
  1556. #endif /* IKS_OPTION */
  1557.                       case 6:           /* TELNET DO LOGOUT received */
  1558.                       default: continue;
  1559.                     }
  1560.                   case CR:
  1561.                     cr = 1;
  1562.                     break;
  1563.                   case NUL:
  1564.                     if (!TELOPT_U(TELOPT_BINARY) && cr) {
  1565.                         cr = 0;
  1566.                         continue;
  1567.                     }
  1568.                     cr = 0;
  1569.                     break;
  1570.                   default:
  1571.                     cr = 0;
  1572.                 }
  1573.                 /* I'm echoing remote chars */
  1574.                 if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
  1575.                   ttoc((char)y);
  1576.             }
  1577. #endif /* TNCODE */
  1578. #ifdef CK_AUTODL
  1579.             /* Check for file transfer packets */
  1580.             if (inautodl) autodown(y);
  1581. #endif /* CK_AUTODL */
  1582. #else  /* OS2 */
  1583. #ifdef TNCODE
  1584.             /* Check for telnet protocol negotiation */
  1585.             if (is_tn) {
  1586.                 int tx;
  1587.                 switch (y & 0xff) {
  1588.                   case IAC:
  1589.                     myflsh();   /* Break from input burst for tn_doop() */
  1590. #ifdef CK_BURST
  1591.                     burst = 0;
  1592. #endif /* CK_BURST */
  1593. #ifdef IKS_OPTION
  1594.                     tx = scriptwrtbuf((USHORT)y);
  1595.                     if (tx == 4) {
  1596.                         if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
  1597.                             !tcp_incoming
  1598.                             ) {
  1599.                             instatus = INP_IKS;
  1600.                             printf(
  1601.   " Internet Kermit Service in SERVER mode.n Please use REMOTE commands.n"
  1602.                                    );
  1603.                             break;
  1604.                         }
  1605.                     } else if (tx == 6) {
  1606.                         /* TELNET DO LOGOUT received */
  1607.                     }
  1608. #else /* IKS_OPTION */
  1609.                     /* Handles Telnet negotiations */
  1610.                     tx = scriptwrtbuf((USHORT)y);
  1611.                     if (tx == 6) {
  1612.                         /* TELNET DO LOGOUT received */
  1613.                     }
  1614. #endif /* IKS_OPTION */
  1615.                     waiting -= 2;       /* (not necessarily...) */
  1616.                     cr = 0;
  1617.                     continue;           /* and autodownload check */
  1618.                   case CR:
  1619.                     cr = 1;
  1620.                     tx = scriptwrtbuf((USHORT)y);
  1621.                     if (tx == 6) {
  1622.                         /* TELNET DO LOGOUT received */
  1623.                     }
  1624.                     break;
  1625.                   case NUL:
  1626.                     cr = 0;
  1627.                     if (!TELOPT_U(TELOPT_BINARY) && cr)
  1628.                       continue;
  1629.                     tx = scriptwrtbuf((USHORT)y);
  1630.                     if (tx == 6) {
  1631.                         /* TELNET DO LOGOUT received */
  1632.                     }
  1633.                     break;
  1634.                   default:
  1635.                     cr = 0;
  1636.                     tx = scriptwrtbuf((USHORT)y);
  1637.                     if (tx == 6) {
  1638.                         /* TELNET DO LOGOUT received */
  1639.                     }
  1640.                 }
  1641.                 /* I'm echoing remote chars */
  1642.                 if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
  1643.                   ttoc((CHAR)y);
  1644.             } else
  1645. #endif /* TNCODE */
  1646.               /* Handles terminal emulation responses */
  1647.               scriptwrtbuf((USHORT)y);
  1648. #endif /* OS2 */
  1649.             /* Real input character to be checked */
  1650. #ifdef CK_BURST
  1651.             burst--;                    /* One less character waiting */
  1652.             debug(F101,"doinput burst","",burst);
  1653. #endif /* CK_BURST */
  1654.             c = (CHAR) (cmask & (CHAR) y); /* Mask off parity */
  1655.             inchar[0] = c;              /* Remember character for v(inchar) */
  1656. #ifdef COMMENT
  1657. #ifdef CK_BURST
  1658.             /* Update "lastchar" time only once during input burst */
  1659.             if (burst <= 0)
  1660. #endif /* CK_BURST */
  1661. #endif /* COMMENT */
  1662.               lastchar = gtimer();      /* Remember when it came */
  1663.             if (c == '') {            /* NUL, we can't use it */
  1664.                 if (anychar) {          /* Except if any character will do? */
  1665.                     x = 1;              /* Yes, done. */
  1666.                     incount = 1;        /* This must be the first and only. */
  1667.                     break;
  1668.                 } else goto refill;     /* Otherwise continue INPUTting */
  1669.             }
  1670.             *inpbp++ = c;               /* Store char in circular buffer */
  1671.             incount++;                  /* Count it for v(incount) */
  1672.             /* Don't NUL-terminate here - it's a circular buffer. */
  1673.             if (inpbp >= inpbuf + inbufsize) { /* Time to wrap around? */
  1674.                 wrapped++;
  1675.                 *inpbp = NUL ;          /* Make it null-terminated */
  1676.                 inpbp = inpbuf;         /* Yes. */
  1677.             }
  1678.             if (matchbuf) {
  1679.                 if (matchindex < MATCHBUFSIZ) {
  1680.                     matchbuf[matchindex++] = c;
  1681.                     matchbuf[matchindex] = NUL;
  1682.                 }
  1683.             }
  1684. #ifdef MAC
  1685.             {
  1686.                 extern char *ttermw;    /* fake pointer cast */
  1687.                 if (inecho) {
  1688.                     outchar(ttermw, c); /* echo to terminal window */
  1689.                     /* this might be too much overhead to do here ? */
  1690.                     updatecommand(ttermw);
  1691.                 }
  1692.             }
  1693. #else /* Not MAC */
  1694.             if (inecho) conbuf[concnt++] = c; /* Buffer console output */
  1695. #endif /* MAC */
  1696. #ifndef OS2
  1697.             if (seslog) {
  1698. #ifdef UNIX
  1699.                 if (sessft != 0 || c != 'r')
  1700. #else
  1701. #ifdef OSK
  1702.                 if (sessft != 0 || c != '12')
  1703. #endif /* OSK */
  1704. #endif /* UNIX */
  1705.                   sesbuf[sescnt++] = c; /* Buffer session log output */
  1706.             }
  1707. #endif /* OS2 */
  1708.             if (anychar) {              /* Any character will do? */
  1709.                 x = 1;
  1710.                 break;
  1711.             }
  1712.             if (!inpcas[cmdlvl]) {      /* Ignore alphabetic case? */
  1713.                 if (isupper(c))         /* Yes, convert input char to lower */
  1714.                   c = (CHAR) tolower(c);
  1715.             }
  1716.             debug(F000,"doinput char","",c);
  1717.             /* Here is the matching section */
  1718.             y = -1;                     /* Loop thru search strings */
  1719.             while (s = ms[++y]) {       /* ...as many as we have. */
  1720.                 if (mp[y]) {            /* Pattern match? */
  1721.                     int j;
  1722.                     /* This is gross but it works... */
  1723.                     /* We could just as easily have prepended '*' to the  */
  1724.                     /* pattern and skipped the loop, except then we would */
  1725.                     /* not have any way to identify the matching string.  */
  1726.                     for (j = 0; j < matchindex; j++) {
  1727.                         if (ckmatch(s,&matchbuf[j],1,0)) {
  1728.                             matchindex = j;
  1729.                             x = 1;
  1730.                             break;
  1731.                         }
  1732.                     }
  1733.                     if (x > 0)
  1734.                       break;
  1735.                     continue;
  1736.                 }                       /* Literal match. */
  1737.                 i = mi[y];              /* Match-position in search string. */
  1738.                 debug(F000,"compare char","",(CHAR)s[i]);
  1739.                 if (c == (CHAR) s[i]) { /* Check for match */
  1740.                     i++;                /* Got one, go to next character */
  1741.                 } else {                /* Don't have a match */
  1742.                     int j;
  1743.                     for (j = i; i > 0; ) { /* Back up in search string */
  1744.                         i--; /* (Do this here to prevent compiler foulup) */
  1745.                         /* j is the length of the substring that matched */
  1746.                         if (c == (CHAR) s[i]) {
  1747.                             if (!strncmp(s,&s[j-i],i)) {
  1748.                                 i++;          /* c actually matches -- cfk */
  1749.                                 break;
  1750.                             }
  1751.                         }
  1752.                     }
  1753.                 }
  1754.                 if ((CHAR) s[i] == (CHAR) '') { /* Matched to end? */
  1755.                     ckstrncpy(matchbuf,ms[y],MATCHBUFSIZ);
  1756.                     matchindex = 0;
  1757.                     x = 1;              /* Yes, */
  1758.                     break;              /* done. */
  1759.                 }
  1760.                 mi[y] = i;              /* No, remember match-position */
  1761.             }
  1762.             if (x == 1) {               /* Set v(minput) result */
  1763.                 m_found = y + 1;
  1764.                 break;
  1765.             }
  1766.         }
  1767. #ifdef CK_BURST
  1768.         else if (y <= -1 && burst > 0) {
  1769.             debug(F111,"doinput (y<=-1&&burst>0)","burst",burst);
  1770.                                         /* a timo occurred so there can't   */
  1771.             burst = 0;                  /* be data waiting; must check timo */
  1772.         }
  1773.       refill:
  1774.         if (burst <= 0) {               /* No buffered chars remaining... */
  1775.             myflsh();                   /* Flush buffered output */
  1776.             if (local) {                /* Get size of next input burst */
  1777.                 burst = ttchk();
  1778.                 if (burst < 0) {        /* ttchk() says connection is closed */
  1779.                     instatus = INP_IO;  /* Status = i/o error */
  1780. #ifdef OS2
  1781.                     term_io = term_io_save;
  1782. #endif /* OS2 */
  1783.                     printf("Fatal error - disconnected.n");
  1784.                     ttclos(1);
  1785.                     break;
  1786.                 }
  1787.                 if (inintr) {
  1788.                     if ((icn = conchk()) > 0) { /* Interrupt from keyboard? */
  1789.                         kbchar = coninc(0);
  1790.                         debug(F101,"input interrupted from keyboard","",icn);
  1791.                         while (--icn > 0) coninc(0); /* Yes, absorb chars. */
  1792.                         break;          /* And fail. */
  1793.                     }
  1794.                 }
  1795.             } else {
  1796.                 burst = conchk();
  1797.             }
  1798.             debug(F101,"doinput burst","",burst);
  1799.             /* Prevent overflow of "conbuf" and "sesbuf" */
  1800.             if (burst > MAXBURST)
  1801.               burst = MAXBURST;
  1802.             /* Did not match, timer exceeded? */
  1803.             t = gtimer();
  1804.             debug(F111,"doinput gtimer","burst",t);
  1805.             debug(F101,"doinput timo","",timo);
  1806.             if ((t >= timo) && (timo > 0))
  1807.               break;
  1808.             else if (insilence > 0 && (t - lastchar) > insilence)
  1809.               break;
  1810.         } else {
  1811.             debug(F111,"doinput (burst > 0)","burst",burst);
  1812.         }
  1813. #else
  1814.         myflsh();                       /* Flush buffered output */
  1815.         /* Did not match, timer exceeded? */
  1816.         t = gtimer();
  1817.         debug(F111,"doinput gtimer","no burst",t);
  1818.         debug(F101,"doinput timo","",timo);
  1819.         if ((t >= timo) && (timo > -1))
  1820.           break;
  1821.         else if (insilence > 0 && (t - lastchar) > insilence)
  1822.           break;
  1823. #endif /* CK_BURST */
  1824.     }                                   /* Still have time left, continue. */
  1825.     myflsh();                           /* Flush buffered output. */
  1826.     if (x > 0)
  1827.       instatus = 0;
  1828. #ifdef OS2
  1829.     term_io = term_io_save;
  1830. #endif /* OS2 */
  1831. #ifdef COMMENT
  1832. #ifdef IKS_OPTION
  1833. #ifdef CK_AUTODL
  1834.     if (is_tn && TELOPT_ME(TELOPT_KERMIT) && inautodl) {
  1835.         tn_siks(KERMIT_STOP);           /* Send Kermit-Server Stop */
  1836.     }
  1837. #endif /* CK_AUTODL */
  1838. #endif /* IKS_OPTION */
  1839. #endif /* COMMENT */
  1840. #ifdef GFTIMER
  1841.     fpt = gftimer();                    /* Get elapsed time */
  1842. /* If a long is 32 bits, it would take about 50 days for this to overflow. */
  1843.     inetime = (int)(fpt * (CKFLOAT)1000.0);
  1844. #else
  1845.     inetime = (int)(gtimer() * 1000);
  1846. #endif /* GFTIMER */
  1847.     makestr(&inpmatch,&matchbuf[matchindex]); /* v(inmatch) */
  1848.     return(x);                          /* Return the return code. */
  1849. }
  1850. #endif /* NOSPL */
  1851. #ifndef NOSPL
  1852. /* REINPUT Command */
  1853. /*
  1854.   Note, the timeout parameter is required, but ignored.  Syntax is compatible
  1855.   with MS-DOS Kermit except timeout can't be omitted.  This function only
  1856.   looks at the characters already received and does not read any new
  1857.   characters from the connection.
  1858. */
  1859. int
  1860. doreinp(timo,s,pat) int timo; char *s; int pat; {
  1861.     int x, y, i;
  1862.     char *xx, *xp, *xq = (char *)0;
  1863.     CHAR c;
  1864.     if (!s) s = "";
  1865.     debug(F101,"doreinput pat","",pat);
  1866.     y = (int)strlen(s);
  1867.     debug(F111,"doreinput search",s,y);
  1868.     if (y > inbufsize) {                /* If search string longer than */
  1869.         debug(F101,"doreinput inbufsize","",inbufsize);
  1870.         return(0);                      /* input buffer, fail. */
  1871.     }
  1872.     makestr(&inpmatch,NULL);
  1873.     if (!matchbuf)
  1874.       matchbuf = malloc(MATCHBUFSIZ+1);
  1875.     matchindex = 0;
  1876.     x = 0;                              /* Return code, assume failure */
  1877.     i = 0;                              /* String pattern match position */
  1878.     if (!inpcas[cmdlvl]) {              /* INPUT CASE = IGNORE?  */
  1879.         xp = malloc(y+2);               /* Make a separate copy of the */
  1880.         if (!xp) {                      /* search string. */
  1881.             printf("?malloc error 6n");
  1882.             return(x);
  1883.         } else xq = xp;                 /* Keep pointer to beginning. */
  1884.         while (*s) {                    /* Yes, convert to lowercase */
  1885.             *xp = *s;
  1886.             if (isupper(*xp)) *xp = (char) tolower(*xp);
  1887.             xp++; s++;
  1888.         }
  1889.         *xp = NUL;                      /* Terminate it! */
  1890.         s = xq;                         /* Move search pointer to it. */
  1891.     }
  1892.     xx = *inpbp ? inpbp : inpbuf;       /* Current INPUT buffer pointer */
  1893.     do {
  1894.         c = *xx++;                      /* Get next character */
  1895.         debug(F000,"XXX","",c);
  1896.         if (!c) break;
  1897.         if (xx >= inpbuf + inbufsize)   /* Wrap around if necessary */
  1898.           xx = inpbuf;
  1899.         if (!inpcas[cmdlvl]) {          /* Ignore alphabetic case? */
  1900.             if (isupper(c)) c = (CHAR) tolower(c); /* Yes */
  1901.         }
  1902.         if (pat) {
  1903.             int j;
  1904.             if (matchbuf) {
  1905.                 if (matchindex < MATCHBUFSIZ) {
  1906.                     matchbuf[matchindex++] = c;
  1907.                     matchbuf[matchindex] = NUL;
  1908.                     debug(F111,"XXX",matchbuf,matchindex);
  1909.                 }
  1910.                 for (j = 0; j < matchindex; j++) { /* Gross but effective */
  1911.                     if (ckmatch(s,&matchbuf[j],1,0)) {
  1912.                         debug(F101,"GOT IT","",j);
  1913.                         matchindex = j;
  1914.                         x = 1;
  1915.                         break;
  1916.                     }
  1917.                 }
  1918.             }
  1919.             if (x > 0)
  1920.               break;
  1921.             continue;
  1922.         }
  1923.         debug(F000,"doreinp char","",c);
  1924.         debug(F000,"compare char","",(CHAR) s[i]);
  1925.         if (((char) c) == ((char) s[i])) { /* Check for match */
  1926.             i++;                        /* Got one, go to next character */
  1927.         } else {                        /* Don't have a match */
  1928.             int j;
  1929.             for (j = i; i > 0; ) {      /* [jrs] search backwards for it  */
  1930.                 i--;
  1931.                 if (((char) c) == ((char) s[i])) {
  1932.                     if (!strncmp(s,&s[j-i],i)) {
  1933.                         i++;
  1934.                         break;
  1935.                     }
  1936.                 }
  1937.             }
  1938.         }                               /* [jrs] or return to zero from -1 */
  1939.         if (s[i] == '') {             /* Matched all the way to end? */
  1940.             ckstrncpy(matchbuf,s,MATCHBUFSIZ);
  1941.             matchindex = 0;
  1942.             x = 1;                      /* Yes, */
  1943.             break;                      /* done. */
  1944.         }
  1945.     } while (xx != inpbp && x < 1);     /* Until back where we started. */
  1946.     if (!inpcas[cmdlvl]) if (xq) free(xq); /* Free this if it was malloc'd. */
  1947.     makestr(&inpmatch,&matchbuf[matchindex]); /* v(inmatch) */
  1948.     return(x);                          /* Return search result. */
  1949. }
  1950. /*  X X S T R I N G  --  Interpret strings containing backslash escapes  */
  1951. /*  Z Z S T R I N G  --  (new name...)  */
  1952. /*
  1953.  Copies result to new string.
  1954.   strips enclosing braces or doublequotes.
  1955.   interprets backslash escapes.
  1956.   returns 0 on success, nonzero on failure.
  1957.   tries to be compatible with MS-DOS Kermit.
  1958.  Syntax of input string:
  1959.   string = chars | "chars" | {chars}
  1960.   chars = (c*e*)*
  1961.   where c = any printable character, ascii 32-126
  1962.   and e = a backslash escape
  1963.   and * means 0 or more repetitions of preceding quantity
  1964.   backslash escape = operand
  1965.   operand = {number} | number | fname(operand) | v(name) | $(name) | m(name)
  1966.   number = [r]n[n[n]]], i.e. an optional radix code followed by 1-3 digits
  1967.   radix code is oO (octal), xX (hex), dD or none (decimal) (see xxesc()).
  1968. */
  1969. #ifndef NOFRILLS
  1970. int
  1971. yystring(s,s2) char *s; char **s2; {    /* Reverse a string */
  1972.     int x;
  1973.     static char *new;
  1974.     new = *s2;
  1975.     if (!s || !new) return(-1);         /* Watch out for null pointers. */
  1976.     if ((x = (int)strlen(s)) == 0) {    /* Recursion done. */
  1977.         *new = '';
  1978.         return(0);
  1979.     }
  1980.     x--;                                /* Otherwise, call self */
  1981.     *new++ = s[x];                      /* to reverse rest of string. */
  1982.     s[x] = 0;
  1983.     return(yystring(s,&new));
  1984. }
  1985. #endif /* NOFRILLS */
  1986. static char ipabuf[16] = { NUL };       /* IP address buffer */
  1987. static char *
  1988. getip(s) char *s; {
  1989.     char c=NUL;                         /* Workers... */
  1990.     int i=0, p=0, d=0;
  1991.     int state = 0;                      /* State of 2-state FSA */
  1992.     while (c = *s++) {
  1993.         switch(state) {
  1994.           case 0:                       /* Find first digit */
  1995.             i = 0;                      /* Output buffer index */
  1996.             ipabuf[i] = NUL;            /* Initialize output buffer */
  1997.             p = 0;                      /* Period counter */
  1998.             d = 0;                      /* Digit counter */
  1999.             if (isdigit(c)) {           /* Have first digit */
  2000.                 d = 1;                  /* Count it */
  2001.                 ipabuf[i++] = c;        /* Copy it */
  2002.                 state = 1;              /* Change state */
  2003.             }
  2004.             break;
  2005.           case 1:                       /* In numeric field */
  2006.             if (isdigit(c)) {           /* Have digit */
  2007.                 if (++d > 3)            /* Too many */
  2008.                   state = 0;            /* Start over */
  2009.                 else                    /* Not too many */
  2010.                   ipabuf[i++] = c;      /* Keep it */
  2011.             } else if (c == '.' && p < 3) { /* Have a period */
  2012.                 p++;                    /* Count it */
  2013.                 if (d == 0)             /* Not preceded by a digit */
  2014.                   state = 0;            /* Start over */
  2015.                 else                    /* OK */
  2016.                   ipabuf[i++] = c;      /* Keep it */
  2017.                 d = 0;                  /* Reset digit counter */
  2018.             } else if (p == 3 && d > 0) { /* Not part of address */
  2019.                 ipabuf[i] = NUL;        /* If we have full IP address */
  2020.                 return((char *)ipabuf); /* Return it */
  2021.             } else {                    /* Otherwise */
  2022.                 state = 0;              /* Start over */
  2023.                 ipabuf[0] = NUL;        /* (in case no more chars left) */
  2024.             }
  2025.         }
  2026.     }                                   /* Fall thru at end of string */
  2027.     ipabuf[i] = NUL;                    /* Maybe we have one */
  2028.     return((p == 3 && d > 0) ? (char *)ipabuf : "");
  2029. }
  2030. #endif /* NOSPL */
  2031. /* Date Routines */
  2032. /* Z J D A T E  --  Convert yyyymmdd date to Day of Year */
  2033. static int jdays[12] = {  0,31,59,90,120,151,181,212,243,273,304,334 };
  2034. static int ldays[12] = {  0,31,60,91,121,152,182,213,244,274,305,335 };
  2035. static char zjdbuf[12] = { NUL, NUL };
  2036. /*
  2037.   Deinde, ne in posterum a XII kalendas aprilis aequinoctium recedat,
  2038.   statuimus bissextum quarto quoque anno (uti mos est) continuari debere,
  2039.   praeterquam in centesimis annis; qui, quamvis bissextiles antea semper
  2040.   fuerint, qualem etiam esse volumus annum MDC, post eum tamen qui deinceps
  2041.   consequentur centesimi non omnes bissextiles sint, sed in quadringentis
  2042.   quibusque annis primi quique tres centesimi sine bissexto transigantur,
  2043.   quartus vero quisque centesimus bissextilis sit, ita ut annus MDCC, MDCCC,
  2044.   MDCCCC bissextiles non sint. Anno vero MM, more consueto dies bissextus
  2045.   intercaletur, februario dies XXIX continente, idemque ordo intermittendi
  2046.   intercalandique bissextum diem in quadringentis quibusque annis perpetuo
  2047.   conservetur.  - Gregorius XIII, Anno Domini MDLXXXII.
  2048. */
  2049. char *
  2050. zjdate(date) char * date; {             /* date = yyyymmdd */
  2051.     char year[5];
  2052.     char month[3];
  2053.     char day[3];
  2054.     int d, m, x, y;
  2055.     int leapday, j;
  2056.     char * time = NULL;
  2057.     if (!date) date = "";               /* Validate arg */
  2058.     x = strlen(date);
  2059.     if (x < 1) return("0");
  2060.     if (x < 8) return("-1");
  2061.     for (x = 0; x < 8; x++)
  2062.       if (!isdigit(date[x]))
  2063.         return("-1");
  2064.     if (date[8] && date[9])
  2065.       time = date + 9;
  2066.     year[0] = date[0];                  /* Isolate year */
  2067.     year[1] = date[1];
  2068.     year[2] = date[2];
  2069.     year[3] = date[3];
  2070.     year[4] = '';
  2071.     month[0] = date[4];                 /* Month */
  2072.     month[1] = date[5];
  2073.     month[2] = '';;
  2074.     day[0] = date[6];                   /* And day */
  2075.     day[1] = date[7];
  2076.     day[2] = '';
  2077.     leapday = 0;                        /* Assume no leap day */
  2078.     y = atoi(year);
  2079.     m = atoi(month);
  2080.     d = atoi(day);
  2081.     if (m > 2) {                        /* No Leap day before March */
  2082.         if (y % 4 == 0) {               /* If year is divisible by 4 */
  2083.             leapday = 1;                /* It's a Leap year */
  2084.             if (y % 100 == 0) {         /* Except if divisible by 100 */
  2085.                 if (y % 400 != 0)       /* but not by 400 */
  2086.                   leapday = 0;
  2087.             }
  2088.         }
  2089.     }
  2090.     j = jdays[m - 1] + d + leapday;     /* Day of year */
  2091.     if (time)
  2092.       sprintf(zjdbuf,"%04d%03d %s",y,j,time);
  2093.     else
  2094.       sprintf(zjdbuf,"%04d%03d",y,j);
  2095.     return((char *)zjdbuf);
  2096. }
  2097. static char jzdbuf[32];
  2098. /* J Z D A T E  --  Convert Day of Year to yyyyddmm date */
  2099. char *
  2100. jzdate(date) char * date; {             /* date = yyyyddd */
  2101.     char year[5];                       /* with optional time */
  2102.     char day[4];
  2103.     char * time = NULL, * p;
  2104.     int d, m, x, y;
  2105.     int leapday, j;
  2106.     int * zz;
  2107.     if (!date) date = "";               /* Validate arg */
  2108.     x = strlen(date);
  2109.     debug(F111,"jzdate len",date,x);
  2110.     if (x < 1) return("0");
  2111.     if (x < 7) return("-1");
  2112.     if (x > 8) time = date + 8;
  2113.     for (x = 0; x < 7; x++)
  2114.       if (!isdigit(date[x]))
  2115.         return("-1");
  2116.     year[0] = date[0];                  /* Isolate year */
  2117.     year[1] = date[1];
  2118.     year[2] = date[2];
  2119.     year[3] = date[3];
  2120.     year[4] = '';
  2121.     debug(F110,"jzdate year",year,0);
  2122.     day[0] = date[4];                   /* And day */
  2123.     day[1] = date[5];
  2124.     day[2] = date[6];
  2125.     day[3] = '';
  2126.     debug(F110,"jzdate day",day,0);
  2127.     j = atoi(day);
  2128.     if (j > 366)
  2129.       return("-1");
  2130.     leapday = 0;                        /* Assume no leap day */
  2131.     y = atoi(year);
  2132.     if (y % 4 == 0) {                   /* If year is divisible by 4 */
  2133.         leapday = 1;                    /* It's a Leap year */
  2134.         if (y % 100 == 0) {             /* Except if divisible by 100 */
  2135.             if (y % 400 != 0)           /* but not by 400 */
  2136.               leapday = 0;
  2137.         }
  2138.     }
  2139.     debug(F101,"jzdate leapday","",leapday);
  2140.     zz = leapday ? ldays : jdays;
  2141.     for (x = 0; x < 11; x++)
  2142.       if (j > zz[x] && j <= zz[x+1])
  2143.         break;
  2144.     m = x + 1;
  2145.     debug(F101,"jzdate m","",m);
  2146.     d = j - zz[x];
  2147.     debug(F101,"jzdate d","",d);
  2148.     if (time)
  2149.       sprintf(jzdbuf,"%04d%02d%02d %s",y,m,d,time);
  2150.     else
  2151.       sprintf(jzdbuf,"%04d%02d%02d",y,m,d);
  2152.     debug(F101,"jzdate jzdbuf",jzdbuf,0);
  2153.     p = ckcvtdate((char *)jzdbuf, 0);   /* Convert to standard form */
  2154.     ckstrncpy(jzdbuf,p,32);
  2155.     if (!time) jzdbuf[8] = NUL;         /* Remove time if not wanted */
  2156.     return((char *)jzdbuf);
  2157. }
  2158. /* M J D  --  Modified Julian Date */
  2159. /*
  2160.   Call with:
  2161.     Standard-format date-time string: yyyymmdd[ hh:mm:ss].
  2162.     The time, if any, is ignored.
  2163.   Returns:
  2164.    -1L on error, otherwise:
  2165.    The number of days since 17 Nov 1858 (as a whole number)
  2166.   The Modified Julian Date is defined by the International Astronomical
  2167.   Union as the true Julian date minus 2400000.5 days.  The true Julian
  2168.   date is the number days since since noon of 1 January 4713 BCE of the
  2169.   Julian proleptic calendar.
  2170. */
  2171. long
  2172. mjd(date) char * date; {
  2173.     char year[5];
  2174.     char month[3];
  2175.     char day[3];
  2176.     int x, d, m, y;
  2177.     if (!date) date = "";               /* Validate arg */
  2178.     x = strlen(date);
  2179.     if (x < 1) return(0L);
  2180.     if (x < 8) return(-1L);
  2181.     for (x = 0; x < 8; x++)
  2182.       if (!isdigit(date[x]))
  2183.         return(-1L);
  2184.     year[0] = date[0];                  /* Isolate year */
  2185.     year[1] = date[1];
  2186.     year[2] = date[2];
  2187.     year[3] = date[3];
  2188.     year[4] = '';
  2189.     y = atoi(year) - 1900;
  2190.     month[0] = date[4];                 /* Month */
  2191.     month[1] = date[5];
  2192.     month[2] = '';;
  2193.     m = atoi(month);
  2194.     day[0] = date[6];                   /* And day */
  2195.     day[1] = date[7];
  2196.     day[2] = '';
  2197.     d = atoi(day);
  2198.     if (m - 2 < 1) {                    /* Arithmetic */
  2199.         m += 9;
  2200.         y--;
  2201.     } else {
  2202.         m -= 3;
  2203.     }
  2204.     return(15078 + (1461 * y) / 4 + (153 * m + 2) / 5 + d);
  2205. }
  2206. static char mjd2dbuf[12];
  2207. /*  M J D 2 D A T E  --  Converts MJD to yyyymmdd  */
  2208. char *
  2209. #ifdef CK_ANSIC
  2210. mjd2date(long mjd)
  2211. #else
  2212. mjd2date(mjd) long mjd;
  2213. #endif /* CK_ANSIC */
  2214. /* mjd2date */ {
  2215.     long jd, l, n;
  2216.     int d, m, y;
  2217.     jd = (long)(mjd + 2400001L);
  2218.     l = jd + 68569;
  2219.     n = 4 * l / 146097L;
  2220.     l = l - (146097 * n + 3) / 4;
  2221.     y = 4000 * (l + 1) / 1461001L;
  2222.     l = l - 1461 * y / 4 + 31;
  2223.     m = 80 * l / 2447;
  2224.     d = l - 2447 * m / 80;
  2225.     l = m / 11;
  2226.     m = m + 2 - 12 * l;
  2227.     y = 100 * (n - 49) + y + l;
  2228.     sprintf(mjd2dbuf,"%04d%02d%02d",y,m,d);
  2229.     return((char *)mjd2dbuf);
  2230. }
  2231. #ifndef NOSPL
  2232. static char ** flist = (char **) NULL;  /* File list for fnextfile() */
  2233. static int flistn = 0;                  /* Number of items in file list */
  2234. /*
  2235.   The function return-value buffer must be global, since fneval() returns a
  2236.   pointer to it.  fneval() is called only by zzstring(), which always copies
  2237.   the result out of this buffer to somewhere else, so it's OK to have only
  2238.   one buffer for this in most cases.  However, since function calls can be
  2239.   nested -- e.g. functions whose arguments are functions, or recursive
  2240.   functions, at some point we should convert this to an array of buffers,
  2241.   indexed by function depth (which might or might not be the same as the
  2242.   "depth" variable).  Also, since function results are potentially quite big,
  2243.   we'd need to allocate and deallocate dynamically as we descend and ascend
  2244.   function depth.  Left for a future release...
  2245. */
  2246. char fnval[FNVALL+2];                   /* Function return value  */
  2247. static int fndepth = 0;                 /* (we don't actually use this yet) */
  2248. int fnsuccess = 1;
  2249. extern int fnerror;
  2250. static char *                           /* Evaluate builtin functions */
  2251. fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
  2252.     int i=0, j=0, k=0, len1=0, len2=0, len3=0, n=0, t=0, x=0, y=0;
  2253.     int failed = 0;                     /* Return code, 0 = ok */
  2254.     long z = 0L;
  2255.     char *bp[FNARGS + 1];               /* Pointers to malloc'd strings */
  2256.     char c = NUL;
  2257.     char *p = NULL, *s = NULL;
  2258.     char *val1 = NULL, *val2 = NULL;    /* Pointers to numeric string values */
  2259. #ifdef RECURSIVE
  2260.     int rsave = recursive;
  2261. #endif /* RECURSIVE */
  2262. #ifdef OS2
  2263.     int zsave = zxpn;
  2264. #endif /* OS2 */
  2265.     for (i = 0; i < FNARGS; i++)        /* Initialize argument pointers */
  2266.       bp[i] = NULL;
  2267. /*
  2268.   IMPORTANT: Note that argn is not an accurate count of the number of
  2269.   arguments.  We can't really tell if an argument is null until after we
  2270.   execute the code below.  So argn is really the maximum number of arguments
  2271.   we might have.  In particular note that argn is always at least 1, even
  2272.   if the function is called with empty parentheses (but don't count on it).
  2273. */
  2274.     if (!fn) fn = "";                   /* Protect against null pointers */
  2275.     debug(F111,"fneval",fn,argn);
  2276.     debug(F110,"fneval",argp[0],0);
  2277.     if (argn > FNARGS)                  /* Discard excess arguments */
  2278.       argn = FNARGS;
  2279.     fndepth++;
  2280.     debug(F101,"fneval fndepth","",fndepth);
  2281.     p = fnval;
  2282.     fnval[0] = NUL;
  2283.     y = lookup(fnctab,fn,nfuncs,&x);    /* Look up the function name */
  2284.     if (y < 0) {                        /* Not found */
  2285.         failed = 1;
  2286.         if (fndiags) {                  /* FUNCTION DIAGNOSTIC ON */
  2287.             int x;
  2288.             x = strlen(fn);
  2289.             switch (y) {
  2290.               case -1:
  2291.                 if (x + 32 < FNVALL)
  2292.                   sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION:\f%s()>",fn);
  2293.                 else
  2294.                   sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION>");
  2295.                 break;
  2296.               case -2:
  2297.                 if (x + 26 < FNVALL)
  2298.                   sprintf(fnval,"<ERROR:NAME_AMBIGUOUS:\f%s()>",fn);
  2299.                 else
  2300.                   sprintf(fnval,"<ERROR:NAME_AMBIGUOUS>");
  2301.                 break;
  2302.               case -3:
  2303.                 sprintf(fnval,"<ERROR:FUNCTION_NAME_MISSING:\f()>");
  2304.                 break;
  2305.               default:
  2306.                 if (x + 26 < FNVALL)
  2307.                   sprintf(fnval,"<ERROR:LOOKUP_FAILURE:\f%s()>",fn);
  2308.                 else
  2309.                   sprintf(fnval,"<ERROR:LOOKUP_FAILURE>");
  2310.                 break;
  2311.             }
  2312.         }
  2313.         goto fnend;                     /* Always leave via common exit */
  2314.     }
  2315. #ifdef DEBUG
  2316.     if (deblog) {
  2317.         int j;
  2318.         for (j = 0; j < argn; j++)
  2319.           debug(F111,"fneval arg",argp[j],j);
  2320.     }
  2321. #endif /* DEBUG */
  2322.     for (j = argn-1; j >= 0; j--) {     /* Uncount empty trailing args */
  2323.         if (!argp[j])
  2324.           argn--;
  2325.         else if (!*(argp[j]))
  2326.           argn--;
  2327.         else break;
  2328.     }
  2329.     debug(F101,"fneval argn","",argn);
  2330. /*
  2331.   fliteral() and fcontents() are special functions that do not evaluate
  2332.   their arguments, and are treated specially here.  After these come the
  2333.   functions whose arguments are evaluated in the normal way.
  2334. */
  2335.     if (y == FN_LIT) {                  /* literal(arg1) */
  2336.         debug(F110,"flit",xp,0);
  2337.         p = xp ? xp : "";               /* Return a pointer to arg itself */
  2338.         goto fnend;
  2339.     }
  2340.     if (y == FN_CON) {                  /* Contents of variable, unexpanded. */
  2341.         char c;
  2342.         if (!(p = argp[0]) || !*p) {
  2343.             failed = 1;
  2344.             p = fnval;
  2345.             if (fndiags)
  2346.               sprintf(fnval,"<ERROR:MISSING_ARG:\fcontents()>");
  2347.             goto fnend;
  2348.         }
  2349.         p = brstrip(p);
  2350.         if (*p == CMDQ) p++;
  2351.         if ((c = *p) == '%') {          /* Scalar variable. */
  2352.             c = *++p;                   /* Get ID character. */
  2353.             p = "";                     /* Assume definition is empty */
  2354.             if (!c) {                   /* Double paranoia */
  2355.                 failed = 1;
  2356.                 p = fnval;
  2357.                 if (fndiags)
  2358.                   sprintf(fnval,"<ERROR:ARG_BAD_VARIABLE:\fcontents()>");
  2359.                 goto fnend;
  2360.             }
  2361.             if (c >= '0' && c <= '9') { /* Digit for macro arg */
  2362.                 if (maclvl < 0)         /* Digit variables are global */
  2363.                   p = g_var[c];         /* if no macro is active */
  2364.                 else                    /* otherwise */
  2365.                   p = m_arg[maclvl][c - '0']; /* they're on the stack */
  2366.             } else if (c == '*' && maclvl >= 0) {
  2367.                 p = m_line[maclvl];
  2368.                 if (!p) p = "";
  2369.             } else {
  2370.                 if (isupper(c)) c -= ('a'-'A');
  2371.                 p = g_var[c];           /* Letter for global variable */
  2372.             }
  2373.             if (!p) p = "";
  2374.             goto fnend;
  2375.         } else if (c == '&') {                  /* Array reference. */
  2376.             int vbi, d;
  2377.             if (arraynam(p,&vbi,&d) < 0) { /* Get name and subscript */
  2378.                 failed = 1;
  2379.                 p = fnval;
  2380.                 if (fndiags)
  2381.                   sprintf(fnval,"<ERROR:ARG_BAD_ARRAY:\fcontents()>");
  2382.                 goto fnend;
  2383.             }
  2384.             if (chkarray(vbi,d) > 0) {  /* Array is declared? */
  2385.                 vbi -= ARRAYBASE;       /* Convert name to index */
  2386.                 if (a_dim[vbi] >= d) {  /* If subscript in range */
  2387.                     char **ap;
  2388.                     ap = a_ptr[vbi];    /* get data pointer */
  2389.                     if (ap) {           /* and if there is one */
  2390.                         p = ap[d];
  2391.                         goto fnend;
  2392.                     }
  2393.                 }
  2394.             } else {
  2395.                 failed = 1;
  2396.                 p = fnval;
  2397.                 if (fndiags)
  2398.                   sprintf(fnval,"<ERROR:ARG_NOT_ARRAY:\fcontents()>");
  2399.                 goto fnend;
  2400.             }
  2401.         } else {
  2402.             failed = 1;
  2403.             p = fnval;
  2404.             if (fndiags)
  2405.               sprintf(fnval,"<ERROR:ARG_NOT_VARIABLE:\fcontents()>");
  2406.             goto fnend;
  2407.         }
  2408.     }
  2409.     p = fnval;                          /* Default result pointer */
  2410.     fnval[0] = NUL;                     /* Default result = empty string */
  2411.     for (i = 0; i < argn; i++) {        /* Loop to expand each argument */
  2412.         n = MAXARGLEN;                  /* Allow plenty of space */
  2413.         bp[i] = s = malloc(n+1);        /* Allocate space for this argument */
  2414.         if (bp[i] == NULL) {            /* Handle failure to get space */
  2415.             failed = 1;
  2416.             if (fndiags)
  2417.               sprintf(fnval,"<ERROR:MALLOC_FAILURE:\f%s()>",fn);
  2418.             goto fnend;
  2419.         }
  2420.         p = argp[i] ? argp[i] : "";     /* Point to this argument */
  2421. /*
  2422.   Trim leading and trailing spaces from the original argument, before
  2423.   evaluation.  This code new to edit 184.
  2424. */
  2425.         {
  2426.             int x, j;
  2427.             x = strlen(p);
  2428.             if (*p == '{' && *(p+x-1) == '}') {
  2429.                 p[x-1] = NUL;
  2430.                 p++;
  2431.                 x -= 2;
  2432.             } else {
  2433.                 j = x - 1;              /* Trim trailing whitespace */
  2434.                 while (j > 0 && (*(p + j) == SP || *(p + j) == HT))
  2435.                   *(p + j--) = NUL;
  2436.                 while (*p == SP || *p == HT) /* Strip leading whitespace */
  2437.                   p++;
  2438.             }
  2439.         }
  2440. /* Now evaluate the argument */
  2441.         debug(F111,"fneval calling zzstring",p,n);
  2442.         t = zzstring(p,&s,&n);          /* Expand arg into new space */
  2443.         debug(F101,"fneval zzstring","",t);
  2444.         debug(F101,"fneval zzstring","",n);
  2445.         if (t < 0) {
  2446.             debug(F101,"fneval zzstring fails, arg","",i);
  2447.             failed = 1;
  2448.             if (fndiags) {
  2449.                 if (n == 0)
  2450.                   sprintf(fnval,"<ERROR:ARG_TOO_LONG:\f%s()>",fn);
  2451.                 else
  2452.                   sprintf(fnval,"<ERROR:ARG_EVAL_FAILURE:\f%s()>",fn);
  2453.             }
  2454.             goto fnend;
  2455.         }
  2456.         debug(F111,"fneval arg",bp[i],i);
  2457.     }
  2458. #ifdef DEBUG
  2459.     if (deblog) {
  2460.         int j;
  2461.         for (j = 0; j < argn; j++) {
  2462.             debug(F111,"fneval arg post eval",argp[j],j);
  2463.             debug(F111,"fneval evaluated arg",bp[j],j);
  2464.         }
  2465.     }
  2466. #endif /* DEBUG */
  2467. /*
  2468.   From this point on, bp[0..argn-1] are not NULL and all must be freed
  2469.   before returning.
  2470. */
  2471.     if (argn < 1) {                     /* Catch required args missing */
  2472.         switch (y) {
  2473.           case FN_DEF:
  2474.           case FN_EVA:
  2475.           case FN_EXE:
  2476.           case FN_CHR:
  2477.           case FN_COD:
  2478.           case FN_MAX:
  2479.           case FN_MIN:
  2480.           case FN_MOD:
  2481.           case FN_FD:
  2482.           case FN_FS:
  2483.           case FN_TOD:
  2484.           case FN_FFN:
  2485.           case FN_BSN:
  2486.           case FN_RAW:
  2487.           case FN_CMD:
  2488.           case FN_2HEX:
  2489.           case FN_2OCT:
  2490.           case FN_DNAM:
  2491. #ifdef FN_ERRMSG
  2492.           case FN_ERRMSG:
  2493. #endif /* FN_ERRMSG */
  2494. #ifdef CK_KERBEROS
  2495.           case FN_KRB_TK:
  2496.           case FN_KRB_NX:
  2497.           case FN_KRB_IV:
  2498.           case FN_KRB_TT:
  2499.           case FN_KRB_FG:
  2500. #endif /* CK_KERBEROS */
  2501.           case FN_MJD2:
  2502.           case FN_N2TIM:
  2503.           case FN_DIM:
  2504.           case FN_DATEJ:
  2505.           case FN_PNCVT:
  2506.           case FN_PERM:
  2507.           case FN_ALOOK:
  2508.           case FN_TLOOK:
  2509.           case FN_ABS:
  2510.           case FN_FPABS:
  2511.           case FN_FPEXP:
  2512.           case FN_FPLOG:
  2513.           case FN_FPLN:
  2514.           case FN_FPMOD:
  2515.           case FN_FPSQR:
  2516.           case FN_FPADD:
  2517.           case FN_FPDIV:
  2518.           case FN_FPMUL:
  2519.           case FN_FPPOW:
  2520.           case FN_FPSUB:
  2521.           case FN_FPINT:
  2522.           case FN_FPROU:
  2523.           case FN_FPSIN:
  2524.           case FN_FPCOS:
  2525.           case FN_FPTAN:
  2526.           case FN_AADUMP:
  2527.             failed = 1;
  2528.             p = fnval;
  2529.             if (fndiags)
  2530.               sprintf(fnval,"<ERROR:MISSING_ARG:\f%s()>",fn);
  2531.             goto fnend;
  2532.         }
  2533.     }
  2534.     p = fnval;                          /* Reset these again. */
  2535.     fnval[0] = NUL;
  2536.     switch (y) {                        /* Do function on expanded args. */
  2537.       case FN_DEF:                      /* fdefinition(arg1) */
  2538.         k = mlook(mactab,bp[0],nmac);
  2539.         p = (k > -1) ? mactab[k].mval : "";
  2540.         goto fnend;
  2541.       case FN_EVA:                      /* fevaluate(arg1) */
  2542.         p = *(bp[0]) ? evalx(bp[0]) : "";
  2543.         if (!*p && fndiags) {
  2544.             failed = 1;
  2545.             p = fnval;
  2546.             if (fndiags)
  2547.               sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  2548.         }
  2549.         goto fnend;
  2550.       case FN_EXE:                      /* fexecute(arg1) */
  2551.         j = (int)strlen(s = bp[0]);     /* Length of macro invocation */
  2552.         p = "";                         /* Initialize return value to null */
  2553.         if (j) {                        /* If there is a macro to execute */
  2554.             while (*s == SP) s++,j--;   /* strip leading spaces */
  2555.             p = s;                      /* remember beginning of macro name */
  2556.             for (i = 0; i < j; i++) {   /* find end of macro name */
  2557.                 if (*s == SP)
  2558.                   break;
  2559.                 s++;
  2560.             }
  2561.             if (*s == SP)       {       /* if there was a space after */
  2562.                 *s++ = NUL;             /* terminate the macro name */
  2563.                 while (*s == SP) s++;   /* skip past any extra spaces */
  2564.             } else s = "";              /* maybe there are no arguments */
  2565.             if (p && *p)
  2566.               k = mlook(mactab,p,nmac); /* Look up the macro name */
  2567.             else
  2568.               k = -1;
  2569.             if (k < 0) {
  2570.                 failed = 1;
  2571.                 p = fnval;
  2572.                 if (fndiags)
  2573.                   sprintf(fnval,"<ERROR:NO_SUCH_MACRO:\f%s()>",fn);
  2574.                 goto fnend;
  2575.             }
  2576. /*
  2577.   This is just a WEE bit dangerous because we are copying up to 9 arguments
  2578.   into the space reserved for one.  It won't overrun the buffer, but if there
  2579.   are lots of long arguments we might lose some.  The other problem is that if
  2580.   the macro has more than 3 arguments, the 4th through last are all
  2581.   concatenated onto the third.  (The workaround is to use spaces rather than
  2582.   commas to separate them.)  Leaving it like this to avoid having to allocate
  2583.   tons more buffers.
  2584. */
  2585.             if (argn > 1) {             /* Commas used instead of spaces */
  2586.                 int i;
  2587.                 char *p = bp[0];        /* Reuse this space */
  2588.                 *p = NUL;               /* Make into dodo() arg list */
  2589.                 for (i = 1; i < argn; i++) {
  2590.                     strncat(p,bp[i],MAXARGLEN);
  2591.                     strncat(p," ",MAXARGLEN);
  2592.                 }
  2593.                 s = bp[0];              /* Point to new list */
  2594.             }
  2595.             p = "";                     /* Initialize return value */
  2596.             if (k >= 0) {               /* If macro found in table */
  2597.                 /* Go set it up (like DO cmd) */
  2598.                 if ((j = dodo(k,s,cmdstk[cmdlvl].ccflgs)) > 0) {
  2599.                     if (cmpush() > -1) { /* Push command parser state */
  2600.                         extern int ifc;
  2601.                         int ifcsav = ifc; /* Push IF condition on stack */
  2602.                         k = parser(1);  /* Call parser to execute the macro */
  2603.                         cmpop();        /* Pop command parser */
  2604.                         ifc = ifcsav;   /* Restore IF condition */
  2605.                         if (k == 0) {   /* No errors, ignore action cmds. */
  2606.                             p = mrval[maclvl+1]; /* If OK, set return value. */
  2607.                             if (p == NULL) p = "";
  2608.                         }
  2609.                     } else {            /* Can't push any more */
  2610.                         debug(F100,"fexec pushed too deep","",0);
  2611.                         printf("n?\fexec() too deeply nestedn");
  2612.                         while (cmpop() > -1) ;
  2613.                         p = "";
  2614.                     }
  2615.                 }
  2616.             }
  2617.         }
  2618.         goto fnend;
  2619. #ifdef RECURSIVE
  2620.       case FN_RDIR:                     /* frdir..() - Recursive dir count */
  2621.       case FN_RFIL:                     /* frfiles() - Recursive file count */
  2622.         /* recursive = 2; */            /* fall thru... */
  2623. #endif /* RECURSIVE */
  2624.       case FN_FC:                       /* ffiles() - File count. */
  2625.       case FN_DIR: {                    /* ffdir.() - Directory count. */
  2626.           char abuf[16], *s;
  2627.           char ** ap = NULL;
  2628.           int x, xflags = 0;
  2629.           if (matchdot)
  2630.             xflags |= ZX_MATCHDOT;
  2631.           if (y == FN_RDIR || y == FN_RFIL)
  2632.             xflags |= ZX_RECURSE;
  2633.           failed = 0;
  2634.           if (argn < 1) {
  2635.               p = "0";
  2636.               goto fnend;
  2637.           }
  2638.           if (y == FN_DIR || y == FN_RDIR) { /* Only list directories */
  2639.               xflags |= ZX_DIRONLY;
  2640. #ifdef OS2
  2641.               zxpn = 1;                 /* Use the alternate list */
  2642. #endif /* OS2 */
  2643.           } else {                      /* List only files */
  2644.               xflags |= ZX_FILONLY;
  2645. #ifdef OS2
  2646.               zxpn = 1;                 /* Use the alternate list */
  2647. #endif /* OS2 */
  2648.           }
  2649.           if (*(bp[0])) {
  2650.               k = nzxpand(bp[0],xflags);
  2651.               if (k < 0) k = 0;
  2652.               sprintf(fnval,"%d",k);
  2653.               p = fnval;
  2654.           } else
  2655.             p = "0";
  2656.           if (argn > 1) {               /* Assign list to array */
  2657.               fnval[0] = NUL;           /* Initial return value */
  2658.               ckstrncpy(abuf,bp[1],16); /* Get array reference */
  2659.               s = abuf;
  2660.               if (*s == CMDQ) s++;
  2661.               failed = 1;               /* Assume it's bad */
  2662.               p = fnval;                /* Point to result */
  2663.               if (fndiags)              /* Default is this error message */
  2664.                 sprintf(fnval,"<ERROR:ARG_BAD_ARRAY:\f%s()>",fn);
  2665.               if (s[0] != '&')          /* "Address" of array */
  2666.                 goto fnend;
  2667.               if (s[2])
  2668.                 if (s[2] != '[' || s[3] != ']')
  2669.                   goto fnend;
  2670.               if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
  2671.                 s[1] += 32;
  2672.               if ((x = dclarray(s[1],k)) < 0) /* File list plus count */
  2673.                 goto fnend;
  2674.               failed = 0;               /* Unset failure flag */
  2675.               ap = a_ptr[x];            /* Point to array we just declared */
  2676.               sprintf(fnval,"%d",k);
  2677.           }
  2678. #ifdef OS2
  2679.           if (ap) {                     /* We are making an array */
  2680.               int i;
  2681.               char tmp[16];
  2682.               ap[0] = NULL;             /* Containing number of files    */
  2683.               makestr(&(ap[0]),ckitoa(k));
  2684.               ckstrncpy(tmp,fnval,16);  /* Save return value */
  2685.               for (i = 1; i <= k; i++) { /* Fill it */
  2686.                   ap[i] = NULL;
  2687.                   znext(fnval);         /* Next filename */
  2688.                   if (!*fnval)          /* No more, done */
  2689.                     break;              /* In case a premature end */
  2690.                   makestr(&(ap[i]),fnval);
  2691.               }
  2692. #ifdef ZXREWIND
  2693.               k = zxrewind();           /* Reset the file expansion */
  2694. #else
  2695.               k = nzxpand(bp[0],xflags);
  2696. #endif /* ZXREWIND */
  2697.               ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
  2698.           }
  2699. #else /* OS2 */
  2700.           {                             /* Make copies of the list */
  2701.               int i; char tmp[16];
  2702.               if (flist) {              /* Free old file list, if any */
  2703.                   for (i = 0; flist[i]; i++) { /* and each string */
  2704.                       free(flist[i]);
  2705.                       flist[i] = NULL;
  2706.                   }
  2707.                   free(flist);
  2708.               }
  2709.               ckstrncpy(tmp,fnval,16);  /* Save our return value */
  2710.               flist = (char **) malloc((k+1) * sizeof(char *)); /* New array */
  2711.               if (flist) {
  2712.                   for (i = 0; i <= k; i++) { /* Fill it */
  2713.                       flist[i] = NULL;
  2714.                       znext(fnval);     /* Next filename */
  2715.                       if (!*fnval)      /* No more, done */
  2716.                         break;
  2717.                       makestr(&(flist[i]),fnval);
  2718.                   }
  2719.                   if (ap) {             /* If array pointer given */
  2720.                       ap[0] = NULL;
  2721.                       makestr(&(ap[0]),ckitoa(k));
  2722.                       for (i = 0; i < k; i++) { /* Copy file list to array */
  2723.                           ap[i+1] = NULL;
  2724.                           makestr(&(ap[i+1]),flist[i]);
  2725.                       }
  2726.                   }
  2727.               }
  2728.               ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
  2729.               flistn = 0;               /* Reset global list pointer */
  2730.           }
  2731. #endif /* OS2 */
  2732. #ifdef RECURSIVE
  2733.           recursive = rsave;
  2734. #endif /* RECURSIVE */
  2735. #ifdef OS2
  2736.           zxpn = zsave;
  2737. #endif /* OS2 */
  2738.       }
  2739.       goto fnend;
  2740.       case FN_FIL:                      /* fnextfile() - Next file in list. */
  2741.         p = fnval;                      /* (no args) */
  2742.         *p = NUL;
  2743. #ifdef OS2
  2744.         zxpn = 1;                       /* OS/2 - use the alternate list */
  2745.         znext(p);                       /* Call system-dependent function */
  2746.         zxpn = zsave;                   /* Restore original list */
  2747. #else
  2748.         if (flist)                      /* Others, use our own list. */
  2749.           if (flist[flistn])
  2750.             p = flist[flistn++];
  2751. #endif /* OS2 */
  2752.         goto fnend;
  2753.     } /* Break up big switch... */
  2754.     switch (y) {
  2755.       case FN_IND:                      /* findex(s1,s2,start) */
  2756.       case FN_RIX:                      /* frindex(s1,s2,start) */
  2757.       case FN_SEARCH:                   /* fsearch(pat,string,start) */
  2758.       case FN_RSEARCH: {                /* frsearch(pat,string,start) */
  2759.         int i = 0, right = 0, search = 0;
  2760.         right = (y == FN_RIX || y == FN_RSEARCH);
  2761.         search = (y == FN_SEARCH || y == FN_RSEARCH);
  2762.         p = "0";
  2763.         if (argn > 1) {                 /* Only works if we have 2 or 3 args */
  2764.             int start = 0;
  2765.             int mflag = 0;
  2766.             char * pat = NULL;
  2767.             len1 = (int)strlen(pat = bp[0]); /* length of string to look for */
  2768.             len2 = (int)strlen(s = bp[1]); /* length of string to look in */
  2769.             if (search) {               /* If pattern */
  2770.                 if (len1 == 0)          /* append "*" if not already there.. */
  2771.                   mflag++;
  2772.                 else if (pat[len1-1] != '*')
  2773.                   mflag++;
  2774.                 if (mflag) {
  2775.                     char * tmp;
  2776.                     tmp = malloc(len1+2);
  2777.                     if (tmp) {
  2778.                         sprintf(tmp,"%s*",pat);
  2779.                         pat = tmp;
  2780.                     } else
  2781.                       mflag = 0;
  2782.                 }
  2783.                 len1++;
  2784.             }
  2785.             if (len1 < 1 || len2 < 1)   /* Watch out for empty strings */
  2786.               goto fnend;
  2787.             start = right ? -1 : 0;     /* Default starting position */
  2788.             if (argn > 2) {
  2789.                 val1 = *(bp[2]) ? evalx(bp[2]) : "1";
  2790.                 if (chknum(val1)) {
  2791.                     int t;
  2792.                     t = atoi(val1);
  2793.                     if (!search) {      /* Index or Rindex */
  2794.                         j = len2 - len1; /* Length difference */
  2795.                         t--;            /* Convert position to 0-based */
  2796.                         if (t < 0) t = 0;
  2797.                         start = t;
  2798.                         if (!right && start < 0) start = 0;
  2799.                     } else {            /* Search or Rsearch */
  2800.                         int x;
  2801.                         if (t < 0) t = 0;
  2802.                         if (right) {    /* Right to left */
  2803.                             if (t > len2) t = len2;
  2804.                             start = len2 - t - 1;
  2805.                             if (start < 0) {
  2806.                                 if (mflag) if (pat) free(pat);
  2807.                                 goto fnend;
  2808.                             }
  2809.                             x = len2 - t;
  2810.                             s[x] = NUL;
  2811.                         } else {        /* Left to right */
  2812.                             start = t - 1;
  2813.                             if (start < 0) start = 0;
  2814.                             if (start >= len2) {
  2815.                                 if (mflag) if (pat) free(pat);
  2816.                                 goto fnend;
  2817.                             }
  2818.                         }
  2819.                     }
  2820.                 } else {
  2821.                     failed = 1;
  2822.                     if (fndiags) {
  2823.                         sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  2824.                         p = fnval;
  2825.                     }
  2826.                     if (mflag) if (pat) free(pat);
  2827.                     goto fnend;
  2828.                 }
  2829.             }
  2830.             if (search) {               /* fsearch() or frsearch() */
  2831.                 if (right) {
  2832.                     if (start < 0) start = len2 - 1;
  2833.                     for (i = start;
  2834.                          i >= 0 && !ckmatch(pat,s+i,inpcas[cmdlvl],1);
  2835.                          i--) ;
  2836.                     if (i < 0) i = 0; else i++;
  2837.                 } else {
  2838.                     for (i = start;
  2839.                          i < len2 && !ckmatch(pat,s+i,inpcas[cmdlvl],1);
  2840.                          i++) ;
  2841.                     if (i == len2) i = 0; else i++;
  2842.                 }
  2843.             } else {
  2844.                 i = ckindex(pat,bp[1],start,right,inpcas[cmdlvl]);
  2845.             }
  2846.             if (mflag) if (pat) free(pat);
  2847.             sprintf(fnval,"%d",i);
  2848.             p = fnval;
  2849.         }
  2850.         goto fnend;
  2851.       }
  2852.       case FN_RPL:                      /* freplace(s1,s2,s3) */
  2853.       /*
  2854.         s = bp[0] = source string
  2855.             bp[1] = match string
  2856.             bp[2] = replacement string
  2857.         p = fnval = destination (result) string
  2858.       */
  2859.         if (argn < 1)                   /* Nothing */
  2860.           goto fnend;
  2861.         if (argn < 2) {                 /* Only works if we have 2 or 3 args */
  2862.             ckstrncpy(p,bp[0],FNVALL);
  2863.         } else {
  2864.             len1 = (int)strlen(bp[0]);  /* length of string to look in */
  2865.             len2 = (int)strlen(bp[1]);  /* length of string to look for */
  2866.             len3 = (argn < 3) ? 0 : (int)strlen(bp[2]); /* Len of replacemnt */
  2867.             j = len1 - len2 + 1;
  2868.             if (j < 1 || len1 == 0 || len2 == 0) { /* Args out of whack */
  2869.                 ckstrncpy(p,bp[0],FNVALL); /* so just return original string */
  2870.                 p[FNVALL] = NUL;
  2871.             } else {
  2872.                 s = bp[0];              /* Point to beginning of string */
  2873.                 while (j--) {           /* For each character */
  2874.                     if (!ckstrcmp(bp[1],s,len2,inpcas[cmdlvl])) {
  2875.                         if (len3) {
  2876.                             strcpy(p,bp[2]);
  2877.                             p += len3;
  2878.                         }
  2879.                         s += len2;                  /* and skip past it. */
  2880.                     } else {            /* No, */
  2881.                         *p++ = *s++;    /* just copy this character */
  2882.                     }
  2883.                 }
  2884.                 *p = NUL;
  2885.                 while (*p++ = *s++);
  2886.             }
  2887.         }
  2888.         p = fnval;
  2889.         goto fnend;
  2890.       case FN_CHR:                      /* fcharacter(arg1) */
  2891.         val1 = *(bp[0]) ? evalx(bp[0]) : "";
  2892.         if (chknum(val1)) {             /* Must be numeric */
  2893.             i = atoi(val1);
  2894.             if (i >= 0 && i < 256) {    /* Must be an 8-bit value */
  2895.                 p = fnval;
  2896.                 *p++ = (char) i;
  2897.                 *p = NUL;
  2898.                 p = fnval;
  2899.             } else {
  2900.                 failed = 1;
  2901.                 if (fndiags)
  2902.                   sprintf(fnval,"<ERROR:ARG_OUT_OF_RANGE:\f%s()>",fn);
  2903.             }
  2904.         } else {
  2905.             failed = 1;
  2906.             if (fndiags)
  2907.               sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  2908.         }
  2909.         goto fnend;
  2910.       case FN_COD:                      /* fcode(char) */
  2911.         if ((int)strlen(bp[0]) > 0) {
  2912.             p = fnval;
  2913.             i = *bp[0];
  2914.             sprintf(p,"%d",(i & 0xff));
  2915.         } else p = "";                  /* Can't happen */
  2916.         goto fnend;
  2917.       case FN_LEN:                      /* flength(arg1) */
  2918.         if (argn > 0) {
  2919.             p = fnval;
  2920.             sprintf(p,"%d",(int)strlen(bp[0]));
  2921.         } else p = "0";
  2922.         goto fnend;
  2923.       case FN_LOW:                      /* flower(arg1) */
  2924.         s = bp[0] ? bp[0] : "";
  2925.         p = fnval;
  2926.         while (*s) {
  2927.             if (isupper(*s))
  2928.               *p = (char) tolower(*s);
  2929.             else
  2930.               *p = *s;
  2931.             p++; s++;
  2932.         }
  2933.         *p = NUL;
  2934.         p = fnval;
  2935.         goto fnend;
  2936.       case FN_MAX:                      /* fmax(arg1,arg2) */
  2937.       case FN_MIN:                      /* fmin(arg1,arg2) */
  2938.       case FN_MOD:                      /* fmod(arg1,arg2) */
  2939.         val1 = *(bp[0]) ? evalx(bp[0]) : "";
  2940.         free(bp[0]);                    /* Copy this because evalx() returns */
  2941.         bp[0] = NULL;                   /* Set it to NULL in case argn == 1 */
  2942.         if (argn > 1) {                 /* pointer to same */
  2943.             bp[0] = malloc((int)strlen(val1)+1); /* buffer next time. */
  2944.             strcpy(bp[0],val1);
  2945.             val1 = bp[0];
  2946.             val2 = *(bp[1]) ? evalx(bp[1]) : "";
  2947.             if (chknum(val1) && chknum(val2)) {
  2948.                 i = atoi(val1);
  2949.                 j = atoi(val2);
  2950.                 switch (y) {
  2951.                   case FN_MAX:
  2952.                     if (j < i) j = i;
  2953.                     break;
  2954.                   case FN_MIN:
  2955.                     if (j > i) j = i;
  2956.                     break;
  2957.                   case FN_MOD:
  2958.                     if (j == 0) {
  2959.                         failed = 1;
  2960.                         if (fndiags)
  2961.                           sprintf(fnval,"<ERROR:DIVIDE_BY_ZERO:\f%s()>",fn);
  2962.                         else
  2963.                           fnval[0] = NUL;
  2964.                         goto fnend;
  2965.                     } else
  2966.                       j = i % j;
  2967.                 }
  2968.                 p = fnval;
  2969.                 sprintf(p,"%d",j);
  2970.             } else {
  2971.                 failed = 1;
  2972.                 if (fndiags)
  2973.                   sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  2974.             }
  2975.         } else p = val1;
  2976.         goto fnend;
  2977.     } /* Break up big switch... */
  2978.     switch (y) {
  2979.       case FN_SUB:                      /* fsubstr(arg1,arg2,arg3) */
  2980.       case FN_RIG:                      /* fright(arg1,arg2) */
  2981.       case FN_LEF:                      /* fleft(arg1,arg2) */
  2982.         if (argn < 1)
  2983.           goto fnend;
  2984.         val1 = "";
  2985.         if (argn > 1)
  2986.           if (*(bp[1]))
  2987.             val1 =  evalx(bp[1]);
  2988.         if (bp[1]) free(bp[1]);         /* Have to copy this */
  2989.         bp[1] = malloc((int)strlen(val1)+1);
  2990.         if (!bp[1]) {
  2991.             failed = 1;
  2992.             if (fndiags)
  2993.               sprintf((p = fnval),"<ERROR:MALLOC:\f%s()>",fn);
  2994.             goto fnend;
  2995.         }
  2996.         strcpy(bp[1],val1);
  2997.         val1 = bp[1];
  2998.         val2 = "";
  2999.         if (argn > 2)
  3000.           if (*(bp[2]))
  3001.             val2 = evalx(bp[2]);
  3002.         if (
  3003.             ((argn > 1) && (int)strlen(val1) && !rdigits(val1)) ||
  3004.             ((y == FN_SUB) &&
  3005.               ((argn > 2) && (int)strlen(val2) && !rdigits(val2)))
  3006.             ) {
  3007.             failed = 1;
  3008.             if (fndiags)
  3009.               sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3010.         } else {
  3011.             int lx;
  3012.             p = fnval;                  /* pointer to result */
  3013.             lx = strlen(bp[0]);         /* length of arg1 */
  3014.             if (y == FN_SUB) {          /* substring */
  3015.                 k = (argn > 2) ? atoi(val2) : MAXARGLEN; /* length */
  3016.                 j = (argn > 1) ? atoi(val1) : 1; /* start pos for substr */
  3017.             } else if (y == FN_LEF) {   /* left */
  3018.                 k = (argn > 1) ? atoi(val1) : lx;
  3019.                 j = 1;
  3020.             } else {                             /* right */
  3021.                 k = (argn > 1) ? atoi(val1) : lx; /* length */
  3022.                 j = lx - k + 1;                  /* start pos for right */
  3023.                 if (j < 1) j = 1;
  3024.             }
  3025.             if (k > 0 && j <= lx) {              /* if start pos in range */
  3026.                 s = bp[0]+j-1;                   /* point to source string */
  3027.                 for (i = 0; (i < k) && (*p++ = *s++); i++) ;  /* copy */
  3028.             }
  3029.             *p = NUL;                   /* terminate the result */
  3030.             p = fnval;                  /* and point to it. */
  3031.         }
  3032.         goto fnend;
  3033.       case FN_UPP:                      /* fupper(arg1) */
  3034.         s = bp[0] ? bp[0] : "";
  3035.         p = fnval;
  3036.         while (*s) {
  3037.             if (islower(*s))
  3038.               *p = (char) toupper(*s);
  3039.             else
  3040.               *p = *s;
  3041.             p++; s++;
  3042.         }
  3043.         *p = NUL;
  3044.         p = fnval;
  3045.         goto fnend;
  3046.       case FN_REP:                      /* frepeat(text,number) */
  3047.         if (argn < 1)
  3048.           goto fnend;
  3049.         val1 = "1";
  3050.         if (argn > 1)
  3051.           if (*(bp[1]))
  3052.             val1 = evalx(bp[1]);
  3053.         if (chknum(val1)) {             /* Repeat count */
  3054.             n = atoi(val1);
  3055.             debug(F111,"SUNDAY frepeat n",val1,n);
  3056.             if (n > 0) {                /* Make n copies */
  3057.                 p = fnval;
  3058.                 *p = '';
  3059.                 k = (int)strlen(bp[0]); /* Make sure string has some length */
  3060.                 debug(F111,"SUNDAY frepeat k","",k);
  3061.                 debug(F111,"SUNDAY frepeat FNVALL","",FNVALL);
  3062.                 if (k * n >= FNVALL) {  /* But not too much... */
  3063.                     failed = 1;
  3064.                     if (fndiags)
  3065.                       sprintf(fnval,"<ERROR:RESULT_TOO_LONG:\f%s()>",fn);
  3066.                     else
  3067.                       fnval[0] = NUL;
  3068.                     p = fnval;
  3069.                     goto fnend;
  3070.                 }
  3071.                 if (k > 0) {            /* If there is something to copy */
  3072.                     for (i = 0; i < n; i++) { /* Copy loop */
  3073.                         s = bp[0];
  3074.                         for (j = 0; j < k; j++) {
  3075.                             if ((p - fnval) >= FNVALL)
  3076.                               break;    /* shouldn't happen... */
  3077.                             else
  3078.                               *p++ = *s++;
  3079.                         }
  3080.                     }
  3081.                     *p = NUL;
  3082.                 }
  3083.             }
  3084.         } else {
  3085.             failed = 1;
  3086.             if (fndiags)
  3087.               sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3088.         }
  3089.         p = fnval;
  3090.         goto fnend;
  3091. #ifndef NOFRILLS
  3092.       case FN_REV:                      /* freverse() */
  3093.         if (argn < 1)
  3094.           goto fnend;
  3095.         yystring(bp[0],&p);
  3096.         goto fnend;
  3097. #endif /* NOFRILLS */
  3098.       case FN_RPA:                      /* frpad() and flpad() */
  3099.       case FN_LPA:
  3100.         if (argn < 1)
  3101.           goto fnend;
  3102.         val1 = "";
  3103.         if (argn > 1)
  3104.           if (*(bp[1]))
  3105.             val1 = evalx(bp[1]);
  3106.         if (argn == 1 || !*val1) {      /* If a number wasn't given */
  3107.             p = fnval;                  /* just return the original string */
  3108.             ckstrncpy(p,bp[0],FNVALL);
  3109.         } else if (chknum(val1)) {      /* Repeat count */
  3110.             char pc;
  3111.             n = atoi(val1);
  3112.             if (n >= 0) {
  3113.                 p = fnval;
  3114.                 k = (int)strlen(bp[0]); /* Length of string to be padded */
  3115.                 if (k >= n) {           /* It's already long enough */
  3116.                     ckstrncpy(p,bp[0],FNVALL);
  3117.                 } else {
  3118.                     if (n + k <= FNVALL) {
  3119.                         pc = (char) ((argn < 3) ? SP : *bp[2]);
  3120.                         if (!pc) pc = SP;
  3121.                         if (y == FN_RPA) { /* RPAD */
  3122.                             strncpy(p,bp[0],k); /* (leave it like this) */
  3123.                             p[k] = NUL;
  3124.                             p += k;
  3125.                             for (i = k; i < n; i++)
  3126.                               *p++ = pc;
  3127.                         } else {        /* LPAD */
  3128.                             n -= k;
  3129.                             for (i = 0; i < n; i++)
  3130.                               *p++ = pc;
  3131.                             strncpy(p,bp[0],k); /* (leave it like this) */
  3132.                             p[k] = NUL;
  3133.                             p += k;
  3134.                         }
  3135.                     }
  3136.                     *p = NUL;
  3137.                 }
  3138.             }
  3139.         } else {
  3140.             failed = 1;
  3141.             if (fndiags)
  3142.               sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3143.         }
  3144.         p = fnval;
  3145.         goto fnend;
  3146. #ifdef ZFCDAT
  3147.       case FN_FD:                       /* fdate(filename) */
  3148.         p = fnval;
  3149.         s = zfcdat(bp[0]);
  3150.         if (!s) s = "";
  3151.         if (!*s) {
  3152.             failed = 1;
  3153.             if (fndiags)
  3154.               sprintf(fnval,"<ERROR:FILE_NOT_FOUND:\f%s()>",fn);
  3155.             goto fnend;
  3156.         }
  3157.         ckstrncpy(fnval,s,FNVALL);
  3158. #endif /* ZFCDAT */
  3159.         goto fnend;
  3160.     } /* Break up big switch... */
  3161.     switch (y) {
  3162.       case FN_FS:                       /* fsize(filename) */
  3163.         p = fnval;
  3164.         z = zchki(bp[0]);
  3165.         if (z < 0) {
  3166.             failed = 1;
  3167.             if (fndiags) {
  3168.                 if (z == -1)
  3169.                   sprintf(fnval,"<ERROR:FILE_NOT_FOUND:\f%s()>",fn);
  3170.                 else if (z == -2)
  3171.                   sprintf(fnval,"<ERROR:FILE_NOT_READABLE:\f%s()>",fn);
  3172.                 else if (z == -3)
  3173.                   sprintf(fnval,"<ERROR:FILE_NOT_ACCESSIBLE:\f%s()>",fn);
  3174.                 else
  3175.                   sprintf(fnval,"<ERROR:FILE_ERROR:\f%s()>",fn);
  3176.             }
  3177.             goto fnend;
  3178.         }
  3179.         sprintf(fnval,"%ld",z);
  3180.         goto fnend;
  3181.       case FN_VER:                      /* fverify() */
  3182.         p = "0";
  3183.         if (argn > 1) {                 /* Only works if we have 2 or 3 args */
  3184.             int start;
  3185.             char *s2, ch1, ch2;
  3186.             start = 0;
  3187.             if (argn > 2) {             /* Starting position specified */
  3188.                 val1 = *(bp[2]) ? evalx(bp[2]) : "0";
  3189.                 if (chknum(val1)) {
  3190.                     start = atoi(val1) /* - 1 */;
  3191.                     if (start < 0) start = 0;
  3192.                     if (start > (int)strlen(bp[1]))
  3193.                       goto verfin;
  3194.                 } else {
  3195.                     failed = 1;
  3196.                     if (fndiags)
  3197.                       sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3198.                     goto fnend;
  3199.                 }
  3200.             }
  3201.             i = start;
  3202.             p = "0";
  3203.             for (s = bp[1] + start; *s; s++,i++) {
  3204.                 ch1 = *s;
  3205.                 if (!inpcas[cmdlvl]) if (islower(ch1)) ch1 = toupper(ch1);
  3206.                 j = 0;
  3207.                 for (s2 = bp[0]; *s2; s2++) {
  3208.                     ch2 = *s2;
  3209.                     if (!inpcas[cmdlvl]) if (islower(ch2)) ch2 = toupper(ch2);
  3210.                     if (ch1 == ch2) {
  3211.                         j = 1;
  3212.                         break;
  3213.                     }
  3214.                 }
  3215.                 if (j == 0) {
  3216.                     sprintf(fnval,"%d",i+1);
  3217.                     p = fnval;
  3218.                     break;
  3219.                 }
  3220.             }
  3221.         }
  3222.       verfin:
  3223.         goto fnend;
  3224.       case FN_IPA:                      /* Find and return IP address */
  3225.         if (argn > 0) {                 /* in argument string. */
  3226.             int start;
  3227.             char *s2;
  3228.             start = 0;
  3229.             if (argn > 1) {             /* Starting position specified */
  3230.                 if (chknum(bp[1])) {
  3231.                     start = atoi(bp[1]) - 1;
  3232.                     if (start < 0) start = 0;
  3233.                 } else {
  3234.                     failed = 1;
  3235.                     if (fndiags)
  3236.                       sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3237.                     goto fnend;
  3238.                 }
  3239.             }
  3240.             p = getip(bp[0]+start);
  3241.         } else p = "";
  3242.         goto fnend;
  3243. #ifdef OS2
  3244.       case FN_CRY:
  3245.         p = "";
  3246.         if (argn > 0) {
  3247.             p = fnval;
  3248.             ckstrncpy(p,bp[0],FNVALL);
  3249.             ck_encrypt(p);
  3250.         }
  3251.         goto fnend;
  3252.       case FN_OOX:
  3253.         p = "";
  3254.         if (argn > 0)
  3255.           p = (char *) ck_oox(bp[0], (argn > 1) ? bp[1] : "");
  3256.         goto fnend;
  3257. #endif /* OS2 */
  3258.       case FN_HEX:                      /* fhexify(arg1) */
  3259.         if (argn < 1)
  3260.           goto fnend;
  3261.         if ((int)strlen(bp[0]) < (FNVALL / 2)) {
  3262.             s = bp[0];
  3263.             p = fnval;
  3264.             while (*s) {
  3265.                 x = (*s >> 4) & 0x0f;
  3266.                 *p++ = hexdigits[x];
  3267.                 x = *s++ & 0x0f;
  3268.                 *p++ = hexdigits[x];
  3269.             }
  3270.             *p = NUL;
  3271.             p = fnval;
  3272.         }
  3273.         goto fnend;
  3274.       case FN_UNH: {                    /* funhex(arg1) */
  3275.           int c[2], i;
  3276.           if (argn < 1)
  3277.             goto fnend;
  3278.           if ((int)strlen(bp[0]) < (FNVALL * 2)) {
  3279.               s = bp[0];
  3280.               p = fnval;
  3281.               while (*s) {
  3282.                   for (i = 0; i < 2; i++) {
  3283.                       c[i] = *s++;
  3284.                       if (!c[i]) { p = ""; goto unhexfin; }
  3285.                       if (islower(c[i])) c[i] = toupper(c[i]);
  3286.                       if (c[i] >= '0' && c[i] <= '9') {
  3287.                           c[i] -= 0x30;
  3288.                       } else if (c[i] >= 'A' && c[i] <= 'F') {
  3289.                           c[i] -= 0x37;
  3290.                       } else {
  3291.                           failed = 1;
  3292.                           if (fndiags)
  3293.                             sprintf(fnval,
  3294.                                     "<ERROR:ARG_OUT_OF_RANGE:\f%s()>",
  3295.                                     fn
  3296.                                     );
  3297.                           goto fnend;
  3298.                       }
  3299.                   }
  3300.                   *p++ = ((c[0] << 4) & 0xf0) | (c[1] & 0x0f);
  3301.               }
  3302.               *p = NUL;
  3303.               p = fnval;
  3304.           }
  3305.         unhexfin:
  3306.           goto fnend;
  3307.       }
  3308.       case FN_BRK: {                    /* fbreak() */
  3309.           char * c;                     /* Characters to break on */
  3310.           char c2, s2;
  3311.           int start = 0;
  3312.           int done = 0;
  3313.           if (argn < 1)
  3314.             goto fnend;
  3315.           if (argn > 2) {
  3316.               s = bp[2] ? bp[2] : "0";
  3317.               if (chknum(s)) {
  3318.                   start = atoi(s);
  3319.                   if (start < 0) start = 0;
  3320.                   if (start > (int)strlen(bp[0]))
  3321.                     goto brkfin;
  3322.               } else {
  3323.                   failed = 1;
  3324.                   if (fndiags)
  3325.                     sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3326.                   goto fnend;
  3327.               }
  3328.           }
  3329.           s = bp[0] + start;            /* Source pointer */
  3330.           while (*s && !done) {
  3331.               s2 = *s;
  3332.               if (!inpcas[cmdlvl] && islower(s2)) s2 = toupper(s2);
  3333.               c = bp[1] ? bp[1] : "";   /* Character to break on */
  3334.               while (*c) {
  3335.                   c2 = *c;
  3336.                   if (!inpcas[cmdlvl] && islower(c2)) c2 = toupper(c2);
  3337.                   if (c2 == s2) {
  3338.                       done = 1;
  3339.                       break;
  3340.                   }
  3341.                   c++;
  3342.               }
  3343.               if (done) break;
  3344.               *p++ = *s++;
  3345.           }
  3346.           *p = NUL;                     /* terminate the result */
  3347.           p = fnval;                    /* and point to it. */
  3348.         brkfin:
  3349.           goto fnend;
  3350.       }
  3351.       case FN_SPN: {                    /* fspan() */
  3352.           char *q;
  3353.           char c1, c2;
  3354.           int start = 0;
  3355.           if (argn < 1)
  3356.             goto fnend;
  3357.           if (argn > 2) {               /* Starting position */
  3358.               s = bp[2] ? bp[2] : "0";
  3359.               if (chknum(s)) {
  3360.                   start = atoi(s);
  3361.                   if (start < 0) start = 0;
  3362.               } else {
  3363.                   failed = 1;
  3364.                   if (fndiags)
  3365.                     sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3366.                   goto fnend;
  3367.               }
  3368.           }
  3369.           s = bp[0] + start;            /* Source pointer */
  3370.           if (argn > 1 &&
  3371.               (int)strlen(bp[1]) > 0 &&
  3372.               start <= (int)strlen(bp[0])) {
  3373.               while (*s) {              /* Loop thru source string */
  3374.                   q = bp[1];            /* Span string */
  3375.                   c1 = *s;
  3376.                   if (!inpcas[cmdlvl])
  3377.                     if (islower(c1)) c1 = toupper(c1);
  3378.                   x = 0;
  3379.                   while (c2 = *q++) {
  3380.                       if (!inpcas[cmdlvl])
  3381.                         if (islower(c2)) c2 = toupper(c2);
  3382.                       if (c1 == c2) { x = 1; break; }
  3383.                   }
  3384.                   if (!x) break;
  3385.                   *p++ = *s++;
  3386.               }
  3387.               *p = NUL;                 /* Terminate and return the result */
  3388.               p = fnval;
  3389.           }
  3390.           goto fnend;
  3391.       }
  3392.     } /* Break up big switch... */
  3393.     switch (y) {
  3394.       case FN_TRM:                      /* ftrim(s1[,s2]) */
  3395.       case FN_LTR:                      /* fltrim(s1[,s2]) */
  3396.         if (argn < 1)
  3397.           goto fnend;
  3398.         if ((len1 = (int)strlen(bp[0])) > 0) {
  3399.             if (len1 > FNVALL)
  3400.               len1 = FNVALL;
  3401.             s = " t";
  3402.             if (argn > 1)               /* Trim list given */
  3403.               s = bp[1];
  3404.             len2 = (int)strlen(s);
  3405.             if (len2 < 1) {             /* or not... */
  3406.                 s = " t";              /* Default is to trim whitespace */
  3407.                 len2 = 2;
  3408.             }
  3409.             if (y == FN_TRM) {          /* Trim from right */
  3410.                 char * q, p2, q2;
  3411.                 ckstrncpy(fnval,bp[0],FNVALL); /* Copy string to output */
  3412.                 p = fnval + len1 - 1;   /* Point to last character */
  3413.                 while (p >= (char *)fnval) { /* Go backwards */
  3414.                     q = s;              /* Point to trim list */
  3415.                     p2 = *p;
  3416.                     if (!inpcas[cmdlvl])
  3417.                       if (islower(p2)) p2 = toupper(p2);
  3418.                     while (*q) {        /* Is this char in trim list? */
  3419.                         q2 = *q;
  3420.                         if (!inpcas[cmdlvl])
  3421.                           if (islower(q2)) q2 = toupper(q2);
  3422.                         if (p2 == q2) { /* Yes, null it out */
  3423.                             *p = NUL;
  3424.                             break;
  3425.                         }
  3426.                         q++;
  3427.                     }
  3428.                     if (!*q)            /* Trim list exhausted */
  3429.                       break;            /* So we're done. */
  3430.                     p--;                /* Else keep trimming */
  3431.                 }
  3432.             } else {                    /* Trim from left */
  3433.                 char * q, p2, q2;
  3434.                 p = bp[0];              /* Source */
  3435.                 while (*p) {
  3436.                     p2 = *p;
  3437.                     if (!inpcas[cmdlvl])
  3438.                       if (islower(p2)) p2 = toupper(p2);
  3439.                     q = s;
  3440.                     while (*q) {        /* Is this char in trim list? */
  3441.                         q2 = *q;
  3442.                         if (!inpcas[cmdlvl])
  3443.                           if (islower(q2)) q2 = toupper(q2);
  3444.                         if (p2 == q2) { /* Yes, point past it */
  3445.                             p++;        /* and try next source character */
  3446.                             break;
  3447.                         }
  3448.                         q++;            /* No, try next trim character */
  3449.                     }
  3450.                     if (!*q)            /* Trim list exhausted */
  3451.                       break;            /* So we're done. */
  3452.                 }
  3453.                 ckstrncpy(fnval,p,FNVALL);
  3454.             }
  3455.             p = fnval;
  3456.         } else p = "";
  3457.         goto fnend;
  3458.       case FN_CAP:                      /* fcapitalize(arg1) */
  3459.         if (argn < 1)
  3460.           goto fnend;
  3461.         s = bp[0];
  3462.         p = fnval;
  3463.         x = 0;
  3464.         while (c = *s++) {
  3465.             if (isalpha(c)) {
  3466.                 if (x == 0) {
  3467.                     x = 1;
  3468.                     if (islower(c))
  3469.                       c = toupper(c);
  3470.                 } else if (isupper(c))
  3471.                   c = tolower(c);
  3472.             }
  3473.             *p++ = c;
  3474.         }
  3475.         *p = NUL;
  3476.         p = fnval;
  3477.         goto fnend;
  3478. #ifdef COMMENT
  3479.       case FN_TOD:                      /* Time of day to secs since midnite */
  3480.         sprintf(fnval,"%ld",tod2sec(bp[0]));
  3481.         goto fnend;
  3482. #endif /* COMMENT */
  3483.       case FN_FFN:                      /* Full pathname of file */
  3484.         zfnqfp(bp[0],FNVALL,p);
  3485.         if (!p) p = "";
  3486.         goto fnend;
  3487.       case FN_CHK: {                    /* fchecksum() */
  3488.           long chk = 0;
  3489.           p = (argn > 0) ? bp[0] : "";
  3490.           while (*p) chk += *p++;
  3491.           sprintf(fnval,"%lu",chk);
  3492.           p = fnval;
  3493.           goto fnend;
  3494.       }
  3495. #ifndef NOXFER
  3496.       case FN_CRC:                      /* fcrc16() */
  3497.         if (argn > 0)
  3498.           sprintf(fnval,"%u",chk3((CHAR *)bp[0],(int)strlen(bp[0])));
  3499.         else
  3500.           p = "0";
  3501.         goto fnend;
  3502. #endif /* NOXFER */
  3503.       case FN_BSN:                      /* fbasename() */
  3504.         zstrip(bp[0],&p);
  3505.         goto fnend;
  3506. #ifdef OS2
  3507.       case FN_SCRN_CX:                  /* fscrncurx() */
  3508.         p = fnval;
  3509.         sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->x);
  3510.         goto fnend;
  3511.       case FN_SCRN_CY:                  /* fscrncury() */
  3512.         p = fnval;
  3513.         sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->y);
  3514.         goto fnend;
  3515.       case FN_SCRN_STR: {               /* fscrnstr() */
  3516.           videoline * line = NULL;
  3517.           viocell * cells = NULL;
  3518.           int row = 0, col = 0, len = 0;
  3519.           /* NOTE: On Unicode systems, the screen contents are stored in */
  3520.           /* in Unicode.  Therefore, we should really be performing a    */
  3521.           /* conversion to the local character set.                      */
  3522.           if (bp[0] == NULL || bp[0][0] == '') {
  3523.               row = 0;
  3524.           } else {
  3525.               if (chknum(bp[0])) {
  3526.                   row = atoi(bp[0]);
  3527.                   if (row < 0)
  3528.                     row = 0;
  3529.               } else {
  3530.                   failed = 1;
  3531.                   if (fndiags)
  3532.                     sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3533.                   goto fnend;
  3534.               }
  3535.           }
  3536.           line = VscrnGetLineFromTop( VTERM, (USHORT) row );
  3537.           if (line != NULL) {
  3538.               if (bp[1] == NULL || bp[1][0] == '')
  3539.                 col = 0;
  3540.               else {
  3541.                   if (chknum(bp[0])) {
  3542.                       col = atoi(bp[1]);
  3543.                       if (col < 0 || col >= line->width)
  3544.                         col = 0;
  3545.                   } else {
  3546.                       failed = 1;
  3547.                       if (fndiags)
  3548.                         sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3549.                       goto fnend;
  3550.                   }
  3551.               }
  3552.               if (bp[2] == NULL || bp[2][0] == '') {
  3553.                   len = line->width - (col+1);
  3554.               } else {
  3555.                   if (!chknum(bp[2])) {
  3556.                       failed = 1;
  3557.                       if (fndiags)
  3558.                         sprintf(fnval,"<ERROR:ARG_NOT_NUMERIC:\f%s()>",fn);
  3559.                       goto fnend;
  3560.                   }
  3561.                   len = atoi(bp[2]);
  3562.                   if (len < 0 || len > line->width)
  3563.                     len = line->width;
  3564.               }
  3565.               cells = line->cells;
  3566.               for (i = 0; i < len; i++) {
  3567.                   int pos = i + col;
  3568.                   if (pos < line->width) {
  3569.                       fnval[i] = (CHAR) (cells[pos].c & 0xFF);
  3570.                       if (fnval[i] == 0)
  3571.                         fnval[i] = SP;
  3572.                   } else
  3573.                     fnval[i] = SP;
  3574.               }
  3575.               fnval[i] = '';
  3576.           } else {
  3577.               fnval[0] = '';
  3578.           }
  3579.           p = fnval;
  3580.           goto fnend;
  3581.       }
  3582. #endif /* OS2 */
  3583. #ifndef NOPUSH
  3584.       case FN_RAW:                      /* frawcommand() */
  3585.       case FN_CMD: {                    /* fcommand() */
  3586.           int x, c, n = FNVALL;
  3587.           x = 0;                        /* Completion flag */
  3588. /*
  3589.   ZIFILE can be safely used because we can't possibly be transferring a file
  3590.   while executing this function.
  3591. */
  3592.           if (!nopush && zxcmd(ZIFILE,bp[0]) > 0) { /* Open the command */
  3593.               while (n-- > -1) {        /* Read from it */
  3594.                   if ((c = zminchar()) < 0) {
  3595.                       x = 1;             /* EOF - set completion flag */
  3596.                       if (y == FN_CMD) { /* If not "rawcommand" */
  3597.                           p--;           /* remove trailing newlines */
  3598.                           while (*p == CR || *p == LF)
  3599.                             p--;
  3600.                           p++;
  3601.                       }
  3602.                       *p = NUL;         /* Terminate the string */
  3603.                       break;
  3604.                   } else                /* Command still running */
  3605.                     *p++ = c;           /* Copy the bytes */
  3606.               }
  3607.               zclose(ZIFILE);           /* Close the command */
  3608.           }
  3609.           /* Return null string if command's output was too long. */
  3610.           p = fnval;
  3611.           if (!x) {
  3612.               failed = 1;
  3613.               if (fndiags)
  3614.                 sprintf(fnval,"<ERROR:RESULT_TOO_LONG:\f%s()>",fn);
  3615.           }
  3616.           goto fnend;
  3617.       }
  3618. #endif /* NOPUSH */
  3619.     } /* Break up big switch... */
  3620.     switch (y) {
  3621.       case FN_STX:                      /* fstripx(string,c) */
  3622.         if (!(s = bp[0]))               /* Make sure there is a string */
  3623.           goto fnend;
  3624.         c = '.';                        /* Character to strip from */
  3625.         if (argn > 1) if (*bp[1]) c = *bp[1];