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

通讯/手机编程

开发平台:

Windows_Unix

  1.     extern char ** mtchs;
  2. #endif /* UNIX */
  3.     int i, j, k, x;
  4.     int fs = 0; /* Need to call fileselect() */
  5.     int getval = 0, asking = 0;
  6.     int simulate = 0, rc = 0;
  7.     long minsize = -1L, maxsize = -1L;
  8.     int havename = 0, confirmed = 0;
  9.     int qflag = 0;
  10.     char c;
  11.     struct FDB sw, fi, fl;
  12.     char
  13.       * del_aft = NULL,
  14.       * del_bef = NULL,
  15.       * del_naf = NULL,
  16.       * del_nbf = NULL,
  17.       * del_exc = NULL;
  18.     int
  19.       x_lis = -1,
  20.       /* x_dot = -1, */
  21.       x_hdg = -1;
  22.     char * dxlist[8];
  23.     for (i = 0; i < 8; i++) dxlist[i] = NULL;
  24.     g_matchdot = matchdot;
  25.     saveask = xaskmore;
  26.     if (del_lis > -1) x_lis    = del_lis;
  27.     if (del_dot > -1) matchdot = del_dot;
  28.     if (del_hdg > -1) x_hdg    = del_hdg;
  29.     if (del_pag > -1) xaskmore = del_pag;
  30.     if (del_ask > -1) asking   = del_ask;
  31.     cmfdbi(&sw, /* First FDB - command switches */
  32.    _CMKEY, /* fcode */
  33.    "File specification;n or switch",
  34.    "", /* default */
  35.    "", /* addtl string data */
  36.    ndeltab, /* addtl numeric data 1: tbl size */
  37.    4, /* addtl numeric data 2: 4 = cmswi */
  38.    xxstring, /* Processing function */
  39.    deltab, /* Keyword table */
  40.    &fi /* Pointer to next FDB */
  41.    );
  42.     cmfdbi(&fi, /* 2nd FDB - file to delete */
  43.    _CMIFI, /* fcode */
  44.    "File(s) to delete", /* hlpmsg */
  45.    "", /* default */
  46.    "", /* addtl string data */
  47.    0, /* addtl numeric data 1 */
  48.    0, /* addtl numeric data 2 */
  49.    xxstring,
  50.    NULL,
  51.    &fl
  52.    );
  53.     cmfdbi(&fl, /* Anything that doesn't match */
  54.    _CMFLD, /* fcode */
  55.    "", /* hlpmsg */
  56.    "", /* default */
  57.    "", /* addtl string data */
  58.    0, /* addtl numeric data 1 */
  59.    0, /* addtl numeric data 2 */
  60.    xxstring,
  61.    NULL,
  62.    NULL
  63.    );
  64.     while (!havename && !confirmed) {
  65. x = cmfdb(&sw); /* Parse something */
  66. if (x < 0) { /* Error */
  67.     if (x == -3)
  68.       break;
  69.     if (x == -2 || x == -9)
  70.       printf("?Does not match switch or filename: "%s"n",atmbuf);
  71.     return(x);
  72. }
  73. if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
  74.   break;
  75. c = cmgbrk(); /* Get break character */
  76. if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  77.     printf("?This switch does not take an argumentn");
  78.     rc = -9;
  79.     goto xdelete;
  80. }
  81. if (!getval && (cmgkwflgs() & CM_ARG)) {
  82.     printf("?This switch requires an argumentn");
  83.     rc = -9;
  84.     goto xdelete;
  85. }
  86. switch (k = cmresult.nresult) {
  87.   case DEL_AFT:
  88.   case DEL_BEF:
  89.   case DEL_NAF:
  90.   case DEL_NBF:
  91.     if (!getval) break;
  92.     if ((x = cmdate("File-time","",&s,0,xxstring)) < 0) {
  93. if (x == -3) {
  94.     printf("?Date-time requiredn");
  95.     x = -9;
  96. } else
  97.   rc = x;
  98. goto xdelete;
  99.     }
  100.     fs++;
  101.     switch (k) {
  102.       case DEL_AFT: makestr(&del_aft,s); break;
  103.       case DEL_BEF: makestr(&del_bef,s); break;
  104.       case DEL_NAF: makestr(&del_naf,s); break;
  105.       case DEL_NBF: makestr(&del_nbf,s); break;
  106.     }
  107.     break;
  108.   case DEL_DOT:
  109.     matchdot = 1;
  110.     break;
  111.   case DEL_NOD:
  112.     matchdot = 0;
  113.     break;
  114.   case DEL_EXC:
  115.     if (!getval) break;
  116.     if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
  117. if (x == -3) {
  118.     printf("?Pattern requiredn");
  119.     x = -9;
  120. } else
  121.   rc = x;
  122. goto xdelete;
  123.     }
  124.     fs++;
  125.     makestr(&del_exc,s);
  126.     break;
  127.   case DEL_HDG:
  128.     x_hdg = 1;
  129.     break;
  130.   case DEL_LIS:
  131.     x_lis = 1;
  132.     break;
  133.   case DEL_NOL:
  134.     x_lis = 0;
  135.     break;
  136. #ifndef CK_TTGWSIZ
  137.   case DEL_PAG:
  138.     xaskmore = 1;
  139.     break;
  140.   case DEL_NOP:
  141.     xaskmore = 0;
  142.     break;
  143. #endif /* CK_TTGWSIZ */
  144.   case DEL_QUI:
  145.     qflag = 1;
  146.     x_lis = 0;
  147.     break;
  148.   case DEL_VRB:
  149.     x_lis = 1;
  150.     break;
  151.   case DEL_SMA:
  152.   case DEL_LAR:
  153.     if (!getval) break;
  154.     if ((x = cmnum("File size in bytes","0",10,&y,xxstring)) < 0)
  155.       return(x);
  156.     fs++;
  157.     switch (cmresult.nresult) {
  158.       case DEL_SMA: minsize = y; break;
  159.       case DEL_LAR: maxsize = y; break;
  160.     }
  161.     break;
  162.   case DEL_SIM:
  163.     simulate = 1;
  164.     x_lis = 1;
  165.     break;
  166.   case DEL_ASK:
  167.     asking = 1;
  168.     break;
  169.   case DEL_NAS:
  170.     asking = 0;
  171.     break;
  172.   default:
  173.     printf("?Not implemented yet - "%s"n",atmbuf);
  174.     return(-9);
  175. }
  176.     }
  177.     if (qflag && (cmresult.fcode == _CMFLD)) {
  178. if ((x = cmcfm()) < 0)
  179.   return(x);
  180. else
  181.   return(success = 0);
  182.     }
  183.     if (cmresult.fcode != _CMIFI) {
  184. if (*atmbuf)
  185.   printf("?Not a deletable file: %sn",atmbuf);
  186. else
  187.   printf("?A file specification is requiredn");
  188. return(-9);
  189.     }
  190.     ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ); /* Safe copy of filespec */
  191.     if ((x = cmcfm()) < 0)
  192.       return(x);
  193. #ifdef IKSD
  194. #ifdef CK_LOGIN
  195.     if (inserver && isguest) {
  196. printf("?Sorry, DELETE unavailable to guestsn");
  197. return(-9);
  198.     }
  199. #endif /* CK_LOGIN */
  200. #endif /* IKSD */
  201. #ifndef OS2ORUNIX
  202.     if (simulate) {
  203. printf("?Sorry, /SIMULATE not implemented on this platformn");
  204. return(-9);
  205.     }
  206. #endif /* OS2ORUNIX */
  207. #ifdef COMMENT
  208.     /* (not needed) */
  209.     if (!iswild(tmpbuf)) {
  210. char *m;
  211. x = zchki(tmpbuf);
  212. if (x < 0) {
  213.     switch (x) {
  214.       case -2: m = "Not a regular file"; break;
  215.       case -1: m = "File not found or not accessible"; break;
  216.       default: m = "Can't delete";
  217.     }
  218.     printf("?%s: "%s"n",m,tmpbuf);
  219.     return(-9);
  220. }
  221.     }
  222. #endif /* COMMENT */
  223.     makelist(del_exc,dxlist,8);
  224. /* tmpbuf[] has the name - now do any needed conversions on it */
  225. #ifdef OS2
  226.     {   /* Lower level functions change / to , not good for CMD.EXE. */
  227. char *p = tmpbuf;
  228. while (*p) { /* Change them back to  */
  229.     if (*p == '/') *p = '\';
  230.     p++;
  231. }
  232.     }
  233. #endif /* OS2 */
  234. #ifdef VMS
  235.     if (iswild(tmpbuf)) {
  236. #ifdef COMMENT
  237. /* Does not handle '.' as version separator */
  238. char *p = tmpbuf;
  239. x = 0;
  240. while (*p) {
  241.     if (*p == ';') {
  242. x = 1;
  243. break;
  244.     } else
  245.       p++;
  246. }
  247. if (!x) strcat(tmpbuf,";*");
  248. #else
  249.         j = 0; x = 0; /* for end_dot and number of dots */
  250.         i = strlen(tmpbuf);
  251.         if (tmpbuf[i] == ';') {
  252.             strcat(tmpbuf,"0");
  253.         } else {
  254.             if (tmpbuf[i--] == '.')
  255.               j++;
  256.             for (; i >= 0; i--) {
  257.                 if (tmpbuf[i] == ';' || tmpbuf[i] == ':' ||
  258.                     tmpbuf[i] == ']' || tmpbuf[i] == '>')
  259.                   break;
  260.                 else if (tmpbuf[i] == '.')
  261.                   x++;
  262.             }
  263.             if (tmpbuf[i] != ';') { /* dot may have been used */
  264.                 if (j) { /* last char is dot */
  265.                   if (x)
  266.                     strcat(tmpbuf,"0"); /* second is version separator */
  267.                   else
  268.                     strcat(tmpbuf,";0"); /* 'foo.' */
  269.                 } else if (x == 1) /* lacking a version separator */
  270.   strcat(tmpbuf,";0");
  271. else if (x == 0) /* x == 2 has a version */
  272.   strcat(tmpbuf,".*;0");
  273.             }
  274.         }
  275. #endif /* COMMENT */
  276.     }
  277. #endif /* VMS */
  278.     debug(F110,"dodel tmpbuf",tmpbuf,0); /* Filename */
  279. #ifndef OS2ORUNIX /* No built-in DELETE code... */
  280.     sprintf(line,"%s %s",DELCMD,tmpbuf); /* Construct the system command. */
  281. #ifdef VMS
  282.     if (asking) { /* Maybe overwrite in VMS */
  283. if (x_lis) /* if options are needed... */
  284.   sprintf(line,"%s /confirm/log %s",DELCMD,tmpbuf);
  285. else
  286.   sprintf(line,"%s /confirm %s",DELCMD,tmpbuf);
  287.     } else if (x_lis)
  288.       sprintf(line,"%s /log %s",DELCMD,tmpbuf);
  289.     conres();
  290. #endif /* VMS */
  291.     debug(F110,"dodel line",line,0);
  292. #endif /* OS2ORUNIX */
  293. #ifdef MAC
  294.     success = (zdelet(tmpbuf) == 0);
  295. #else
  296. #ifdef COMMENT
  297.     nzxopts = ZX_FILONLY; /* Files only for now */
  298.     if (matchdot)  nzxopts |= ZX_MATCHDOT;
  299.     /* Note: No recursive -- recursive deleting not supported yet */
  300.     z = nzxpand(s,nzxopts); /* Expand file list */
  301. #endif /* COMMENT */
  302. #ifdef OS2ORUNIX
  303.     {
  304.         int filespace = 0;
  305.         int len = 0;
  306.         int count = 0;
  307. int lines = 0;
  308. int n = 0;
  309.         s = tmpbuf;
  310. if (x_hdg > 0) {
  311.     printf("Deleting %s...%sn", s, simulate ? " (SIMULATION)" : "");
  312.     n += 2;
  313. }
  314. #ifdef ZXREWIND
  315. z = zxrewind(); /* Rewind file list */
  316. #else
  317. nzxopts = ZX_FILONLY; /* Files only for now */
  318. if (matchdot)  nzxopts |= ZX_MATCHDOT;
  319. /* Note: No recursive -- recursive deleting not supported yet */
  320. z = nzxpand(s,nzxopts); /* Expand file list */
  321. #endif /* ZXREWIND */
  322. #ifdef UNIX
  323. sh_sort(mtchs,NULL,z,0,0,filecase);
  324. #endif /* UNIX */
  325.         if (z > 0) {
  326.             int i;
  327.             success = 1;
  328.             if (x_hdg > 0)
  329.               printf("n");
  330.     while (1) {
  331. znext(tmpbuf);
  332. if (!*tmpbuf)
  333.   break;
  334. if (fs) if (fileselect(tmpbuf,
  335. del_aft,del_bef,del_naf,del_nbf,
  336. minsize,maxsize,0,8,dxlist) < 1) {
  337.     if (x_lis > 0) {
  338. lines++;
  339. printf(" %s (SKIPPED)n",tmpbuf);
  340. #ifdef CK_TTGWSIZ
  341. if (++n > cmd_rows - 3)
  342.   if (!askmore()) goto xdelete; else n = 0;
  343. #endif /* CK_TTGWSIZ */
  344.     }
  345.     continue;
  346. }
  347. if (asking) {
  348.     int x;
  349.     sprintf(line," Delete %s? ",tmpbuf);
  350.     x = getyesno(line,1);
  351.     switch (x) {
  352.       case 0: continue;
  353.       case 1: break;
  354.       case 2: goto xdelete;
  355.     }
  356. }
  357. len = zchki(tmpbuf);
  358. if (simulate) {
  359.     filespace += len;
  360.     count++;
  361.     if (x_lis > 0) {
  362. lines++;
  363. printf(" %s (SELECTED)n",tmpbuf);
  364. if (++n > cmd_rows - 3)
  365.   if (!askmore()) goto xdelete; else n = 0;
  366.     }
  367. } else if (len >= 0) {
  368.     zdelet(tmpbuf);
  369.     if (zchki(tmpbuf) < 0) {
  370. filespace += len;
  371. count++;
  372. if (x_lis > 0) {
  373.     lines++;
  374.     printf(" %s (OK)n",tmpbuf);
  375.     if (++n > cmd_rows - 3)
  376.       if (!askmore()) goto xdelete; else n = 0;
  377. }
  378.     } else {
  379. success = 0;
  380. if (x_lis > 0) {
  381.     lines++;
  382.     printf(" %s (FAILED)n",tmpbuf);
  383.     if (++n > cmd_rows - 3)
  384.       if (!askmore()) goto xdelete; else n = 0;
  385. }
  386.     }
  387. } else if (x_lis > 0) {
  388.     lines++;
  389.     if (isdir(tmpbuf))
  390.       printf(" %s (FAILED: directory)n",tmpbuf);
  391.     else
  392.       printf(" %s (FAILED: not regular file)n",tmpbuf);
  393.     if (++n > cmd_rows - 3)
  394.       if (!askmore()) goto xdelete; else n = 0;
  395. }
  396.             }
  397.     if (x_hdg > 0) {
  398. if (lines > 0)
  399.   printf("n");
  400. if (++n > cmd_rows - 3)
  401.   if (!askmore()) goto xdelete; else n = 0;
  402. printf("%d file%s %sdeleted, %d byte%s %sfreed%sn",
  403.        count,
  404.        count != 1 ? "s" : "",
  405.        simulate ? "would be " : "",
  406.        filespace,
  407.        filespace != 1 ? "s" : "",
  408.        simulate ? "would be " : "",
  409.        simulate ? " (maybe)" : ""
  410.        );
  411.     }
  412.         } else if (x_lis > 0)
  413.   printf("?Can't delete: %sn",tmpbuf);
  414.     }
  415. #else /* OS2ORUNIX */
  416. #ifndef VMS /* Others - let the system do it. */
  417.     xsystem(line);
  418.     x = nzxpand(tmpbuf,nzxopts);
  419.     success = (x > 0) ? 0 : 1;
  420.     if (x_hdg > 0)
  421.       printf("%s - %sdeletedn", tmpbuf, success ? "" : "not ");
  422. #else
  423.     if (asking)
  424.       printf("n");
  425.     x = xsystem(line);                  /* zshcmd returns 1 for success */
  426.     success = (x > 0) ? 1 : 0;
  427.     if (x_hdg > 0 && !asking)
  428.       printf("%s - %sdeletedn", tmpbuf, success ? "" : "not ");
  429.     concb((char)escape);
  430. #endif /* VMS */
  431. #endif /* OS2ORUNIX */
  432. #endif /* MAC */
  433.   xdelete:
  434.     if (g_matchdot > -1) {
  435. matchdot = g_matchdot; /* Restore these... */
  436. g_matchdot = -1;
  437.     }
  438.     if (saveask > -1) {
  439. xaskmore = saveask;
  440. saveask = -1;
  441.     }
  442.     return((rc < 0) ? rc : success);
  443. }
  444. #endif /* NOFRILLS */
  445. #ifndef NOSPL /* The ELSE command */
  446. _PROTOTYP( VOID pushqcmd, (char *) );
  447. int
  448. doelse() {
  449.     if (!ifcmd[cmdlvl]) {
  450. printf("?ELSE doesn't follow IFn");
  451. return(-2);
  452.     }
  453. #ifdef COMMENT
  454. /*
  455.   Wrong.  This prevents IF..ELSE IF...ELSE IF...ELSE IF...ELSE...
  456.   from working.
  457. */
  458.     ifcmd[cmdlvl] = 0;
  459. #endif /* COMMENT */
  460.     if (!iftest[cmdlvl]) { /* If IF was false do ELSE part */
  461. if (maclvl > -1 || tlevel > -1) { /* In macro or command file */
  462.     debug(F100,"doelse pushing","",0);
  463. #ifdef COMMENT
  464.     pushcmd(NULL); /* save rest of command. */
  465. #else
  466.     /* This fixes certain obscure problems */
  467.     /* but breaks many other constructions that must work. */
  468.     pushqcmd(NULL);
  469. #endif /* COMMENT */
  470. } else { /* If interactive, */
  471.     cmini(ckxech); /* just start a new command */
  472.     printf("n"); /* (like in MS-DOS Kermit) */
  473.     if (pflag) prompt(xxstring);
  474. }
  475.     } else { /* Condition is false */
  476. if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0)
  477.   return(y); /* Gobble up rest of line */
  478.     }
  479.     return(0);
  480. }
  481. #endif /* NOSPL */
  482. #ifndef NOSPL
  483. int
  484. doswitch() {
  485.     char *lp, *ap; /* Macro argument pointer */
  486.     int x, y, pp = 0;
  487.     /* Get variable name */
  488.     if ((y = cmfld("Variable name","",&s,xxstring)) < 0)
  489.       return(y);
  490.     if (!strcmp(s,"(")) {
  491. pp++;
  492. if ((y = cmfld("Variable name","",&s,xxstring)) < 0)
  493.   return(y);
  494. s = tmpbuf;
  495.     }
  496.     if (*s == CMDQ) {
  497. if (chkvar(s) < 1) {
  498.     printf("?Variable name requiredn");
  499.     return(-9);
  500. }
  501.     }
  502.     ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
  503.     if (pp > 0) { /* If open paren given parse closing */
  504. if ((y = cmfld("Closing parenthesis","",&s,NULL)) < 0)
  505.   return(y);
  506. if (strcmp(atmbuf,")")) {
  507.     printf("?Closing parenthesis requiredn");
  508.     return(-9);
  509. }
  510.     }
  511.     lp = line;
  512.     strcpy(lp,"_switx "); /* _switx + space */
  513.     x = strlen(line);
  514.     lp += x;
  515.     ap = lp;
  516.     debug(F110,"SWITCH",tmpbuf,0);
  517.     ckstrncpy(lp,tmpbuf,LINBUFSIZ-x); /* + variable name */
  518.     x = strlen(tmpbuf);
  519.     lp += x;
  520.     strcat(lp," "); /* + space */
  521.     lp++;
  522.     debug(F110,"SWITCH 2",line,0);
  523.     /* Get body */
  524.     if ((y = cmtxt("series of cases","",&s,NULL)) < 0) return(y);
  525.     if ((y = (int)strlen(s)) < 1) return(-2);
  526.     if (s[0] != '{' && s[y-1] != '}') { /* Supply braces if missing */
  527. sprintf(tmpbuf,"{ %s }",s);
  528. s = tmpbuf;
  529.     }
  530.     if (litcmd(&s,&lp,(LINBUFSIZ - (lp - (char *)line) - 2)) < 0) {
  531. printf("?Unbalanced bracesn");
  532. return(0);
  533.     }
  534.     debug(F110,"SWITCH 3",line,0);
  535.     x = mlook(mactab,"_switx",nmac); /* Look up SWITCH macro definition */
  536.     if (x < 0) { /* Not there? */
  537. addmmac("_switx",sw_def); /* Put it back. */
  538. if ((x = mlook(mactab,"_switx",nmac)) < 0) { /* Look it up again. */
  539.     printf("?SWITCH macro definition gone!n"); /* Shouldn't happen. */
  540.     return(success = 0);
  541. }
  542.     }
  543.     debug(F110,"SWITCH command",line,0); /* Execute the SWITCH macro. */
  544.     return(success = dodo(x,ap,cmdstk[cmdlvl].ccflgs | CF_IMAC));
  545. }
  546. int
  547. dofor() { /* The FOR command. */
  548.     int i, fx, fy, fz; /* loop variables */
  549.     char *ap, *di; /* macro argument pointer */
  550.     int pp = 0; /* Paren level */
  551.     for (i = 0; i < 2; i++) {
  552. if ((y = cmfld("Variable name","",&s,NULL)) < 0) {
  553.     if (y == -3) {
  554. printf("?Variable name requiredn");
  555. return(-9);
  556.     } else
  557.       return(y);
  558. }
  559. if (strcmp(s,"("))
  560.   break;
  561. pp++;
  562.     }
  563.     if ((y = parsevar(s,&x,&z)) < 0) /* Check variable. */
  564.       return(y);
  565.     lp = line; /* Build a copy of the command */
  566.     strcpy(lp,"_forx ");
  567.     lp += (int)strlen(line); /* "_for" macro. */
  568.     ap = lp; /* Save pointer to macro args. */
  569.     if (*s == CMDQ) s++; /* Skip past backslash if any. */
  570.     while (*lp++ = *s++) ; /* copy it */
  571.     lp--; *lp++ = SP; /* add a space */
  572.     if ((y = cmnum("initial value","",10,&fx,xxstring)) < 0) {
  573. if (y == -3) return(-2);
  574. else return(y);
  575.     }
  576.     debug(F101,"dofor fx","",fx);
  577.     s = atmbuf; /* Copy the atom buffer */
  578.     if ((int)strlen(s) < 1) goto badfor;
  579. /*
  580.   In edit 192, we change the loop variables to be evaluated at loop entry,
  581.   not each time through the loop.  This was required in order to allow
  582.   v(argc) to be used as a loop variable, or in a loop-variable expression.
  583.   Thus, we can't have FOR loops that modify their own exit conditions by
  584.   changing the final value or the increment.  The problem with v(argc) was
  585.   that it is on the macro stack; after entry into the _forx macro, it is at
  586.   the wrong place.
  587. */
  588.     sprintf(tmpbuf,"%d",fx); /* Substitute actual value */
  589.     s = tmpbuf;
  590.     while (*lp++ = *s++) ; /* (what they actually typed) */
  591.     lp--; *lp++ = SP;
  592.     if ((y = cmnum("final value","",10,&fy,xxstring)) < 0) {
  593. if (y == -3) return(-2);
  594. else return(y);
  595.     }
  596.     debug(F101,"dofor fy","",fy);
  597.     s = atmbuf; /* Same deal */
  598.     if ((int)strlen(s) < 1)
  599.       goto badfor;
  600.     sprintf(tmpbuf,"%d",fy);
  601.     s = tmpbuf;
  602.     while (*lp++ = *s++) ;
  603.     lp--;
  604.     *lp++ = SP;
  605.     x_ifnum = 1; /* Increment or parenthesis */
  606.     di = (fx < fy) ? "1" : "-1"; /* Default increment */
  607.     if ((y = cmnum("increment",di,10,&fz,xxstring)) < 0) {
  608. debug(F111,"dofor increment",atmbuf,y);
  609. x_ifnum = 0;
  610. if (y == -3) { /* Premature termination */
  611.     return(-2);
  612. } else if (y == -2) { /* Maybe closing paren */
  613.     if (!strcmp(atmbuf,")")) {
  614. pp--; /* Count it */
  615. s = di; /* supply default interval */
  616. fz = atoi(s);
  617.     } else /* Not closing paren, invalid */
  618.       return(y);
  619. } else /* Other error */
  620.   return(y);
  621.     } else { /* Number */
  622. x_ifnum = 0;
  623. debug(F101,"dofor fz","",fz);
  624. s = atmbuf; /* Use it */
  625.     }
  626.     if ((int)strlen(s) < 1)
  627.       goto badfor;
  628.     sprintf(tmpbuf,"%d",fz); /* Same deal */
  629.     s = tmpbuf;
  630.     while (*lp++ = *s++) ;
  631.     lp--; *lp++ = SP;
  632.     /* Insert the appropriate comparison operator */
  633.     if (fz < 0)
  634.       *lp++ = '<';
  635.     else
  636.       *lp++ = '>';
  637.     *lp++ = SP;
  638.     if (pp > 0) { /* If open paren given parse closing */
  639. if ((y = cmfld("Closing parenthesis","",&s,NULL)) < 0)
  640.   return(y);
  641. if (strcmp(atmbuf,")")) {
  642.     printf("?Closing parenthesis requiredn");
  643.     return(-9);
  644. }
  645.     }
  646.     if ((y = cmtxt("Command to execute","",&s,NULL)) < 0) return(y);
  647.     if ((y = (int)strlen(s)) < 1) return(-2);
  648.     if (s[0] != '{' && s[y-1] != '}') { /* Supply braces if missing */
  649. sprintf(tmpbuf,"{ %s }",s);
  650. s = tmpbuf;
  651.     }
  652.     if (litcmd(&s,&lp,(LINBUFSIZ - (lp - (char *)line) - 2)) < 0) {
  653. printf("?Unbalanced bracesn");
  654. return(0);
  655.     }
  656. #ifdef COMMENT
  657. /* Too strict */
  658.     if (fz == 0) {
  659. printf("?Zero increment not allowedn");
  660. return(0);
  661.     }
  662. #endif /* COMMENT */
  663.     x = mlook(mactab,"_forx",nmac); /* Look up FOR macro definition */
  664.     if (x < 0) { /* Not there? */
  665. addmmac("_forx",for_def); /* Put it back. */
  666. if ((x = mlook(mactab,"_forx",nmac)) < 0) { /* Look it up again. */
  667.     printf("?FOR macro definition gone!n"); /* Shouldn't happen. */
  668.     return(success = 0);
  669. }
  670.     }
  671.     debug(F110,"FOR command",line,0); /* Execute the FOR macro. */
  672.     return(success = dodo(x,ap,cmdstk[cmdlvl].ccflgs | CF_IMAC));
  673. badfor: printf("?Incomplete FOR commandn");
  674.     return(-2);
  675. }
  676. #endif /* NOSPL */
  677. #ifndef NOFRILLS
  678. /* Do the BUG command */
  679. int
  680. dobug() {
  681.     int n;
  682.     char * s = "";
  683.     extern char * k_info_dir;
  684.     if (k_info_dir)
  685.       s = k_info_dir;
  686. #ifdef COMMENT
  687.     printf("n%s,%sn Numeric: %ld",versio,ckxsys,vernum);
  688. #endif /* COMMENT */
  689.     printf(
  690. "nBefore requesting technical support from Columbia U., please consult:nn"
  691.    );
  692.     n = 7;
  693. #ifdef OS2
  694.     printf(" . Your "Kermit 95" user manual (use the MANUAL command).n");
  695.     printf(" . The technical reference manual, "Using C-Kermit".n");
  696.     printf(" . The README.TXT file in Kermit 95's directory on your disk.n");
  697.     printf(" . The BUGS.TXT file in Kermit 95's directory on your disk.n");
  698.     n += 5;
  699. #else
  700.     printf(" . The book "Using C-Kermit" (type HELP for more info).n");
  701.     n += 1;
  702. #ifdef UNIX
  703.     printf(" . The %sckermit2.txt and %sckcbwr.txt files.n",s,s);
  704.     printf(" . The %sckubwr.txt and %sckuins.txt files.n",s,s);
  705.     n += 2;
  706. #else
  707. #ifdef VMS
  708.     printf(" . The CKERMIT2.TXT and CKCBWR.TXT files.n");
  709.     printf(" . The CKVBWR.TXT and CKVINS.TXT files.n");
  710.     n += 2;
  711. #else
  712. #ifdef datageneral
  713.     printf(" . The ckermit2.txt and ckcbwr.txt files.n");
  714.     printf(" . The ckdbwr.txt file.n");
  715.     n += 2;
  716. #else
  717. #ifdef STRATUS
  718.     printf(" . The ckermit2.txt and ckcbwr.txt files.n");
  719.     printf(" . The cklbwr.txt filen");
  720.     n += 2;
  721. #else
  722. #ifdef AMIGA
  723.     printf(" . The ckermit2.txt and ckcbwr.txt files.n");
  724.     printf(" . The ckibwr.txt filen");
  725.     n += 2;
  726. #else
  727. #ifdef GEMDOS
  728.     printf(" . The CKERMIT2.TXT and CKCBWR.TXT files.n");
  729.     printf(" . The CKSBWR.TXT filen");
  730.     n += 2;
  731. #else
  732. #ifdef MAC
  733.     printf(" . The ckermit2.txt and ckcbwr.txt files.n");
  734.     printf(" . The ckmbwr.txt filen");
  735.     n += 2;
  736. #else
  737. #ifdef OSK
  738.     printf(" . The ckermit2.txt and ckcbwr.txt files.n");
  739.     printf(" . The ck9bwr.txt filen");
  740.     n += 2;
  741. #else
  742.     printf(" . The CKERMIT2.TXT and CKCBWR.TXT files.n");
  743.     printf(" . The appropriate system-dependent CK?BWR.TXT file.n");
  744.     n += 2;
  745. #endif
  746. #endif
  747. #endif
  748. #endif
  749. #endif
  750. #endif
  751. #endif
  752. #endif
  753. #endif /* OS2 */
  754.     printf(" . Your own organization's support staff, if any.n");
  755.     printf(
  756. " . The comp.protocols.kermit.misc newsgroup.n");
  757.     printf(
  758. " . The Kermit support website, http://www.columbia.edu/kermit/support.html.n"
  759.    );
  760.     printf(
  761. " . The Kermit FAQ, http://www.columbia.edu/kermit/faq.html.n");
  762.     printf(
  763. " . The C-Kermit FAQ, http://www.columbia.edu/kermit/ckfaq.html.n");
  764.     n += 4;
  765.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  766.     printf("n
  767. If you still need help or have a bug to report after consulting these sources,"
  768.    );
  769.     printf("nsend e-mail to:nn");
  770.     n += 2;
  771.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  772.     printf("  kermit-support@columbia.edunn");
  773.     n += 1;
  774.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  775.     printf("Or contact us by post:nn");
  776.     printf(
  777. "  Kermit, Columbia University, 612 W 115 Street, New York NY  10025, USAnn"
  778.    );
  779.     n += 1;
  780.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  781.     printf("Or by fax at +1 (212) 663-8202.nn");
  782.     n += 1;
  783.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  784.     printf("Telephone support is available too:nn");
  785.     n += 1;
  786.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  787.     printf("  +1 (900) 555-5595, USA only, $2.50 per minuten");
  788.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  789.     printf(
  790.     "  +1 (212) 854-5126, from anywhere, $25.00 USD per call, MC/Visann");
  791.     n += 1;
  792.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  793. #ifndef NOSHOW
  794. #ifndef NOFRILLS
  795.     printf(
  796. "Before reporting problems, please use the SHOW VERSION and SHOW FEATURESn");
  797.     if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  798.     printf(
  799. "commands to get detailed program version and configuration information.nn");
  800. #endif /* NOFRILLS */
  801. #endif /* NOSHOW */
  802.     return(1);
  803. }
  804. #endif /* NOFRILLS */
  805. #ifndef NOSPL
  806. /*  T O D 2 S E C  --  Convert time of day as hh:mm:ss to secs since midnite */
  807. /*
  808.   Call with a string hh:mm or hh:mm:ss.
  809.   Returns a 0 to 86400 on success, or a negative number on failure.
  810. */
  811. long
  812. tod2sec(t) char * t; {
  813.     long t2;
  814.     long hh = 0L, mm = 0L, ss = 0L;
  815.     if (!t) t = "";
  816.     if (!*t)
  817.       return(-3);
  818.     debug(F110,"tod2sec",t,0);
  819.     if (isdigit(*t)) /* Get hours from argument */
  820.       hh = *t++ - '0';
  821.     else
  822.       return(-1L);
  823.     if (isdigit(*t))
  824.       hh = hh * 10 + *t++ - '0';
  825. #ifdef COMMENT
  826.     if (hh > 24L)
  827.       return(-1L);
  828. #endif /* COMMENT */
  829.     if (*t == ':')
  830.       t++;
  831.     else if (!*t)
  832.       goto xtod2sec;
  833.     else
  834.       return(-1L);
  835.     if (isdigit(*t)) /* Minutes */
  836.       mm = *t++ - '0';
  837.     else
  838.       return(-1L);
  839.     if (isdigit(*t))
  840.       mm = mm * 10 + *t++ - '0';
  841.     if (mm > 60L)
  842.       return(-1L);
  843.     if (*t == ':')
  844.       t++;
  845.     else if (!*t)
  846.       goto xtod2sec;
  847.     else
  848.       return(-1L);
  849.     if (isdigit(*t)) /* Seconds */
  850.       ss = *t++ - '0';
  851.     else
  852.       return(-1L);
  853.     if (isdigit(*t))
  854.       ss = ss * 10 + *t++ - '0';
  855.     if (ss > 60L)
  856.       return(-1L);
  857.     if (*t > 32) /* No trailing junk allowed */
  858.       return(-1L);
  859.   xtod2sec:
  860.     t2 = hh * 3600L + mm * 60L + ss; /* Seconds since midnight from arg */
  861.     debug(F101,"tod2sec t2","",t2);
  862.     return(t2);
  863. }
  864. int waitinterval = 1;
  865. #ifdef OLDWAIT
  866. #undef OLDWAIT
  867. #endif /* OLDWAIT */
  868. int kbchar = NUL;
  869. int
  870. dopaus(cx) int cx; {
  871.     long zz;
  872.     extern int sleepcan;
  873. #ifdef OLDWAIT
  874.     zz = -1L;
  875.     x_ifnum = 1; /* Turn off internal complaints */
  876.     if (cx == XXWAI)
  877.       y = cmnum("seconds to wait, or time of day hh:mm:ss","1",10,&x,xxstring);
  878.     else if (cx == XXPAU)
  879.       y = cmnum("seconds to pause, or time of day hh:mm:ss",
  880. "1",10,&x,xxstring);
  881.     else
  882.       y = cmnum("milliseconds to sleep, or time of day hh:mm:ss",
  883. "100",10,&x,xxstring);
  884.     x_ifnum = 0;
  885.     if (y < 0) {
  886. if (y == -2) { /* Invalid number or expression */
  887.     char *p = tmpbuf; /* Retrieve string from atmbuf */
  888.     int n = TMPBUFSIZ;
  889.     *p = NUL;
  890.     zzstring(atmbuf,&p,&n); /* Evaluate in case it's a variable */
  891.     zz = tod2sec(tmpbuf); /* Convert to secs since midnight */
  892.     if (zz < 0L) {
  893. printf("?Number, expression, or time of day requiredn");
  894. return(-9);
  895.     } else {
  896. char now[32]; /* Current time */
  897. char *p;
  898. long tnow;
  899. p = now;
  900. ztime(&p);
  901. tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
  902. if (zz < tnow) /* User's time before now */
  903.   zz += 86400L; /* So make it tomorrow */
  904. zz -= tnow; /* Seconds from now. */
  905.     }
  906. } else
  907.   return(y);
  908.     }
  909.     if (x < 0) x = 0;
  910.     switch (cx) {
  911.       case XXPAU: /* PAUSE */
  912.       case XXMSL: /* MSLEEP */
  913. if ((y = cmcfm()) < 0) return(y);
  914. break;
  915.       case XXWAI: /* WAIT */
  916. z = 0; /* Modem signal mask */
  917. while (1) { /* Read zero or more signal names */
  918.     y = cmkey(mstab,nms,"modem signal","",xxstring);
  919.     if (y == -3) break; /* -3 means they typed CR */
  920.     if (y < 0) return(y); /* Other negatives are errors */
  921.     z |= y; /* OR the bit into the signal mask */
  922. }
  923. if ((y = cmcfm()) < 0) return(y);
  924. break;
  925.       default: /* Shouldn't happen */
  926. return(-2);
  927.     }
  928. /* Command is entered, now do it. */
  929.     if (zz > -1L) { /* Time of day given? */
  930. x = zz;
  931. if (zz != (long) x) {
  932.     printf(
  933. "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.n"
  934.    );
  935.     return(-9);
  936. }
  937.     }
  938.     if (cx == XXMSL) { /* Millisecond sleep */
  939. msleep(zz < 0 ? x : x * 1000);
  940. return(success = 1);
  941.     }
  942.     if (cx == XXPAU && !sleepcan) { /* SLEEP CANCELLATION is OFF */
  943. sleep(x);
  944. return(success = 1);
  945.     }
  946.     /* WAIT, or else SLEEP with cancellation allowed... */
  947.     do { /* Sleep loop */
  948. int mdmsig;
  949. if (sleepcan) { /* Keyboard cancellation allowed? */
  950.     if (y = conchk()) { /* Did they type something? */
  951. #ifdef COMMENT
  952. while (y--) coninc(0); /* Yes, gobble it all up */
  953. #else
  954. /* There is a debate over whether PAUSE should absorb    */
  955. /* its cancelling character(s).  There are several       */
  956. /* reasons why it should gobble at least one character:  */
  957. /* (1) MS-DOS Kermit does it                             */
  958. /* (2) if not, subsequent PAUSE commands will terminate  */
  959. /*     immediately                                       */
  960. /* (3) if not, subsequent ASK commands will use it as    */
  961. /*     valid input.  If 13, then it will get no input   */
  962. /* (4) if not, then the character appears on the command */
  963. /*     line after all enclosing macros are complete.     */
  964. kbchar = coninc(0); /* Gobble one up */
  965. #endif /* COMMENT */
  966. break; /* And quit PAUSing or WAITing */
  967.     }
  968. }
  969. if (cx == XXWAI) { /* WAIT (z == modem signal mask) */
  970.     debug(F101,"WAIT x","",x);
  971.     if (z > 0) { /* Looking for any modem signals? */
  972. mdmsig = ttgmdm(); /* Yes, get them */
  973. if (mdmsig < 0) /* Failed */
  974.   return(success = 0);
  975. if ((mdmsig & z) == z) /* Got what we wanted? */
  976.   return(success = 1); /* Succeed */
  977.     }
  978.     if (x == 0) /* WAIT 0 and didn't get our signals */
  979.       break;
  980. }
  981. sleep(1); /* No interrupt, sleep one second */
  982.     } while (--x > 0);
  983.     if (cx == XXWAI) /* If WAIT and loop exhausted */
  984.       success = (z == 0); /* Fail. */
  985.     else /*  */
  986.       success = (x == 0); /* Set SUCCESS/FAILURE for PAUSE. */
  987.     return(success);
  988. #else  /* New code uses chained FDBs and allows FILE waits... */
  989.     char * m = ""; /* Help message */
  990.     struct FDB nu, fl, kw; /* Parse function descriptor blocks */
  991.     int filewait = 0;
  992.     int mdmsig = 0, fs = 0;
  993.     char filedate[32];
  994.     kbchar = 0;
  995.     switch (cx) {
  996.       case XXWAI: m = "seconds to wait, or time of day hh:mm:ss"; break;
  997.       case XXPAU: m = "seconds to pause, or time of day hh:mm:ss"; break;
  998.       case XXMSL: m = "milliseconds to sleep, or time of day hh:mm:ss"; break;
  999.     }
  1000.     zz = -1L;
  1001.     cmfdbi(&nu,
  1002.    _CMNUM, /* Number */
  1003.    m, /* Help message */
  1004.    (cx == XXMSL) ? "100" : "1", /* Default */
  1005.    "", /* N/A */
  1006.    0, /* N/A */
  1007.    0, /* N/A */
  1008.    xxstring, /* Processing function */
  1009.    NULL, /* N/A */
  1010.    &fl /* Next */
  1011.    );
  1012.     cmfdbi(&fl, /* Time of day */
  1013.    _CMFLD, /* Field */
  1014.    "", /* hlpmsg */
  1015.    "", /* default */
  1016.    "", /* addtl string data */
  1017.    0, /* addtl numeric data 1 */
  1018.    0, /* addtl numeric data 2 */
  1019.    xxstring, /* processing func */
  1020.    NULL, /* N/A */
  1021.    NULL /* No next */
  1022.    );
  1023.     x = cmfdb(&nu); /* Parse a number or a field */
  1024.     if (x < 0) {
  1025. if (x == -3)
  1026.   x = -2;
  1027. return(x);
  1028.     }
  1029.     switch (cmresult.fcode) {
  1030.       case _CMNUM: /* Number */
  1031. x = cmresult.nresult;
  1032. break;
  1033.       case _CMFLD: /* Field */
  1034. zz = tod2sec(cmresult.sresult); /* Convert to secs since midnight */
  1035. if (zz < 0L) {
  1036.     printf("?Number, expression, or time of day requiredn");
  1037.     return(-9);
  1038. } else {
  1039.     char now[32]; /* Current time */
  1040.     char *p;
  1041.     long tnow;
  1042.     p = now;
  1043.     ztime(&p);
  1044.     tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
  1045.     if (zz < tnow) /* User's time before now */
  1046.       zz += 86400L; /* So make it tomorrow */
  1047.     zz -= tnow; /* Seconds from now. */
  1048. }
  1049.     }
  1050.     debug(F101,"PAUSE/WAIT/MSLEEP zz","",zz);
  1051.     switch (cx) {
  1052.       case XXPAU: /* PAUSE */
  1053.       case XXMSL: /* MSLEEP */
  1054. if ((y = cmcfm()) < 0) return(y);
  1055. break;
  1056.       case XXWAI: /* WAIT */
  1057. z = 0; /* Modem signal mask */
  1058. y = cmkey(waittab,nwaittab,"","",xxstring);
  1059. if (y < 0) {
  1060.     if (y == -3) {
  1061. if ((y = cmcfm()) < 0)
  1062.   return(y);
  1063. break;
  1064.     } else
  1065.       return(y);
  1066. }
  1067. if (y == WAIT_FIL) { /* FILE */
  1068.     int wild = 0;
  1069.     if ((z = cmkey(wfswi,nwfswi,"event","",xxstring)) < 0)
  1070.       return(z);
  1071.     filewait = z;
  1072.     if (filewait == WF_MOD || filewait == WF_DEL)
  1073.       z = cmifi("Filename","",&s,&wild,xxstring);
  1074.     else
  1075.       z = cmfld("Filename","",&s,xxstring);
  1076.     if (z < 0)
  1077.       return(z);
  1078.     if (wild || (filewait == WF_CRE) && iswild(s)) {
  1079. printf("?Wildcards not valid heren");
  1080. return(-9);
  1081.     }
  1082.     strcpy(tmpbuf,s);
  1083.     if ((z = cmcfm()) < 0)
  1084.       return(z);
  1085.     break;
  1086. } else if (y != WAIT_MDM) { /* A modem signal */
  1087.     z |= y; /* OR the bit into the signal mask */
  1088. }
  1089. if (!filewait) { /* Modem signals... */
  1090.     while (1) { /* Get zero or more signal names */
  1091. y = cmkey(mstab,nms,"modem signal","",xxstring);
  1092. if (y == -3) break; /* -3 means they typed CR */
  1093. if (y < 0) return(y); /* Other negatives are errors */
  1094. z |= y; /* OR the bit into the signal mask */
  1095.     }
  1096.     if ((y = cmcfm()) < 0) return(y);
  1097.     break;
  1098. }
  1099.       default: /* Shouldn't happen */
  1100. return(-2);
  1101.     } /* switch (cx) */
  1102. /* Command is entered, now do it. */
  1103.     if (zz > -1L) { /* Time of day given? */
  1104. x = zz;
  1105. if (zz != (long) x) {
  1106.     printf(
  1107. "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.n"
  1108.    );
  1109.     return(-9);
  1110. }
  1111.     }
  1112.     if (sleepcan)
  1113.       concb((char)escape); /* Ensure single-char wakeup */
  1114.     if (cx == XXMSL) { /* Millisecond sleep */
  1115. msleep(zz < 0 ? x : x * 1000);
  1116. return(success = 1);
  1117.     }
  1118.     if (cx == XXPAU && !sleepcan) { /* SLEEP CANCELLATION is OFF */
  1119. sleep(x);
  1120. return(success = 1);
  1121.     }
  1122.     if (filewait) { /* FILE... */
  1123. fs = zchki(tmpbuf); /* Check if file exists */
  1124. switch (filewait) {
  1125.   case WF_DEL:
  1126.     if (fs == -1)
  1127.       return(success = 1);
  1128.     break;
  1129.   case WF_MOD:
  1130.     if (fs == -1) {
  1131. printf("?File does not exit: %sn",tmpbuf);
  1132. return(-9);
  1133.     }
  1134.     s = zfcdat(tmpbuf); /* Get current modification date */
  1135.     if (!s) s = "";
  1136.     if (ckstrncpy(filedate,s,32) != 17) {
  1137. printf("?Can't get modification time: %sn",tmpbuf);
  1138. return(-9);
  1139.     }
  1140.     break;
  1141.   case WF_CRE:
  1142.     if (fs > -1)
  1143.       return(success = 1);
  1144.     break;
  1145. }
  1146.     }
  1147.     do { /* Polling loop */
  1148. if (sleepcan) { /* Keyboard cancellation allowed? */
  1149.     if ((y = conchk()) > 0) { /* Did they type something? */
  1150. kbchar = coninc(0); /* Yes, get first char they typed */
  1151. debug(F000,"WAIT kbchar","",kbchar);
  1152. #ifdef COMMENT
  1153. while (--y > 0) /* Gobble the rest up */
  1154.   coninc(0);
  1155. #endif /* COMMENT */
  1156. return(success = 0); /* And quit PAUSing or WAITing */
  1157.     }
  1158. }
  1159. if (filewait == 0) {
  1160.     if (cx == XXWAI) { /* WAIT for modem signals */
  1161. if (z != 0) {
  1162.     mdmsig = ttgmdm(); /* Get them. */
  1163.     debug(F101,"WAIT ttgmdm","",mdmsig);
  1164.     if (mdmsig < 0) /* Failure to get them? */
  1165.       return(success = 0); /* Fail. */
  1166.     if ((mdmsig & z) == z) /* Got desired ones? */
  1167.       return(success = 1); /* Succeed. */
  1168. } else if (x == 0)
  1169.   return(success = 0);
  1170.     }
  1171. } else { /* FILE... */
  1172.     fs = zchki(tmpbuf); /* Get file status */
  1173.     if (filewait == WF_MOD) { /* Wait for modification */
  1174. if (fs == -1) /* Failure to get status */
  1175.   return(success = 0); /* so WAIT fails. */
  1176. s = zfcdat(tmpbuf); /* Get current modification time */
  1177. if (!s) s = ""; /* And compare with the time */
  1178. if (strcmp(s,filedate)) /* when the WAIT started */
  1179.   return(success = 1);
  1180.     } else if (filewait == WF_DEL) { /* Wait for deletion */
  1181. if (fs == -1) /* If file doesn't exist, */
  1182.   return(success = 1); /* succeed. */
  1183.     } else if (filewait == WF_CRE) { /* Wait for creation */
  1184. if (fs != -1) /* If file exists */
  1185.   return(success = 1); /* succeed. */
  1186.     }
  1187. }
  1188. if (x < 1) /* SLEEP/WAIT/PAUSE 0 */
  1189.   break;
  1190. sleep(waitinterval); /* No interrupt, sleep */
  1191. x -= waitinterval; /* Deduct sleep time */
  1192.     } while (x > 0);
  1193.     if (cx == XXWAI) /* WAIT time expired */
  1194.       success = (z == 0); /* Succeed if no modem signals */
  1195.     else /* For SLEEP or PAUSE, success */
  1196.       success = (x == 0); /* depends on whether it was */
  1197.     return(success); /* interrupted from the keyboard. */
  1198. #endif /* OLDWAIT */
  1199. }
  1200. #endif /* NOSPL */
  1201. #ifndef NOFRILLS
  1202. #ifdef ZCOPY
  1203. int
  1204. docopy() {
  1205.     int i, x, listing = 0, havename = 0;
  1206.     struct FDB sw, fi;
  1207.     int swapping = 0;
  1208.     int appending = 0;
  1209.     int fromb64 = 0;
  1210.     int tob64 = 0;
  1211.     cmfdbi(&sw, /* 2nd FDB - optional /PAGE switch */
  1212.    _CMKEY, /* fcode */
  1213.    "Filename or switch", /* hlpmsg */
  1214.    "", /* default */
  1215.    "", /* addtl string data */
  1216.    ncopytab, /* addtl numeric data 1: tbl size */
  1217.    4, /* addtl numeric data 2: 4 = cmswi */
  1218.    xxstring, /* Processing function */
  1219.    copytab, /* Keyword table */
  1220.    &fi /* Pointer to next FDB */
  1221.    );
  1222.     cmfdbi(&fi, /* 1st FDB - file to type */
  1223.    _CMIFI, /* fcode */
  1224.    "", /* hlpmsg */
  1225.    "", /* default */
  1226.    "", /* addtl string data */
  1227.    0, /* addtl numeric data 1 */
  1228.    0, /* addtl numeric data 2 */
  1229.    xxstring,
  1230.    NULL,
  1231.    NULL
  1232.    );
  1233.     while (!havename) {
  1234. x = cmfdb(&sw); /* Parse something */
  1235. if (x < 0) /* Error */
  1236.   return(x);
  1237. switch (cmresult.fcode) {
  1238.   case _CMKEY:
  1239.     switch (cmresult.nresult) {
  1240.       case DEL_LIS:
  1241.       case DEL_VRB:
  1242. listing = 1;
  1243. break;
  1244.       case DEL_NOL:
  1245.       case DEL_QUI:
  1246. listing = 0;
  1247. break;
  1248.       case 999:
  1249. swapping = 1;
  1250. break;
  1251.       case 998:
  1252. appending = 1;
  1253. break;
  1254. #ifndef NOSPL
  1255.       case 997:
  1256. fromb64 = 1;
  1257. break;
  1258.       case 996:
  1259. tob64 = 1;
  1260. break;
  1261. #endif /* NOSPL */
  1262.     }
  1263.     break;
  1264.   case _CMIFI:
  1265.     s = cmresult.sresult;
  1266.     havename = 1;
  1267.     break;
  1268.   default:
  1269.     return(-2);
  1270. }
  1271.     }
  1272.     if (cmresult.nresult > 0) { /* No wildcards allowed */
  1273. printf(
  1274.    "n?Multiple files not allowed - please specify a single file.n");
  1275. return(-9);
  1276.     }
  1277.     ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy of source name */
  1278.     p = line + (int)strlen(line) + 2; /* Place for destination name */
  1279.     if ((x = cmofi("destination name and/or directory",
  1280. #ifdef UNIX
  1281.    "."
  1282. #else
  1283.    ""
  1284. #endif /* UNIX */
  1285.    ,&s,xxstring)) < 0) {
  1286.         /* Get destination name */
  1287. if (x == -3) {
  1288.     printf("?Name for destination file requiredn");
  1289.     return(-9);
  1290. } else return(x);
  1291.     }
  1292.     ckstrncpy(p,s,LINBUFSIZ-(p-line)); /* Safe copy of destination name */
  1293.     if ((y = cmcfm()) < 0) return(y);
  1294.     if (appending && swapping) {
  1295. printf("?Sorry, /APPEND and /SWAP conflictn");
  1296. return(-9);
  1297.     }
  1298. #ifdef VMS
  1299.     conres(); /* Let Ctrl-C work. */
  1300. #endif /* VMS */
  1301.     debug(F110,"docopy line",line,0);
  1302.     debug(F110,"docopy p",p,0);
  1303.     if (iswild(line)) {
  1304. printf("?Wildcards not allowedn");
  1305. return(-9);
  1306.     }
  1307. #ifdef IKSD
  1308.     if (zchki(p) > -1) { /* Destination file exists? */
  1309. if (inserver && (!ENABLED(en_del)
  1310. #ifdef CK_LOGIN
  1311.  || isguest
  1312. #endif /* CK_LOGIN */
  1313.  )) {
  1314.     printf("?Sorry, changing existing files is disabledn");
  1315.     return(-9);
  1316. }
  1317.     }
  1318. #endif /* IKSD */
  1319.     if (listing) printf("%s => %s ",line,p);
  1320.     if (tob64 && fromb64) { /* To and from B64 = no conversion */
  1321. tob64 = 0;
  1322. fromb64 = 0;
  1323.     }
  1324.     if (!swapping && !appending && !fromb64 && !tob64) { /* Straight copy */
  1325. if ((x = zcopy(line,p)) < 0) { /* Let zcopy() do it. */
  1326.     switch (x) {
  1327.       case -2:
  1328. printf("?Not a regular file - "%s"n", line);
  1329. break;
  1330.       case -3:
  1331. printf("?Not found or not accessible - "%s"n", line);
  1332. break;
  1333.       case -4:
  1334. printf("?Permission deniedn");
  1335. break;
  1336.       case -5:
  1337. printf("?Source and destination are the same filen");
  1338. break;
  1339.       case -6:
  1340. printf("?Input/Output errorn");
  1341. break;
  1342.       case -7:
  1343. printf("?Error opening output file - "%s"n", p);
  1344. break;
  1345.       default:
  1346. printf("?Can't copy %s to %sn",line,p);
  1347.     }
  1348. #ifdef VMSORUNIX
  1349.     concb((char)escape);
  1350. #endif /* VMSORUNIX */
  1351.     return(-9);
  1352. } else {
  1353. #ifdef VMSORUNIX
  1354.     concb((char)escape);
  1355. #endif /* VMSORUNIX */
  1356.     if (listing) printf("(OK)n");
  1357.     return(success = 1);
  1358. }
  1359.     } else { /* Special options */
  1360. int prev, y, x = 0; /* Variables needed for them */
  1361. int rc = 0, i, t;
  1362. char ibuf[100];
  1363. char obuf[200];
  1364. FILE * in = NULL;
  1365. FILE * out = NULL;
  1366. errno = 0; /* Reset errno */
  1367. if ((in = fopen(line,"r")) == NULL) { /* Open input file */
  1368.     perror(line);
  1369.     return(-9);
  1370. }
  1371. if ((out = fopen(p, (appending ? "a" : "w"))) == NULL) {
  1372.     fclose(in);
  1373.     perror(p);
  1374.     return(-9);
  1375. }
  1376. #ifndef NOSPL
  1377. if (tob64) { /* Converting to Base-64 */
  1378.     while (1) {
  1379. prev = x;
  1380. if ((x = fread(ibuf,1,54,in)) < 1) {
  1381.     rc = 1;
  1382.     break;
  1383. }
  1384. if (prev % 3) {
  1385.     printf("?Phase error: %dn", prev);
  1386.     rc = -9;
  1387.     break;
  1388. }
  1389. if (swapping) {
  1390.     if (x & 1) {
  1391. printf("?Swap errorn");
  1392. rc = -9;
  1393. break;
  1394.     }
  1395.     for (i = 0; i < x; i+=2) {
  1396. t = ibuf[i];
  1397. ibuf[i] = ibuf[i+1];
  1398. ibuf[i+1] = t;
  1399.     }
  1400. }
  1401. if ((y = b8tob64(ibuf,x,obuf,180)) < 0) {
  1402.     printf("?Encoding errorn");
  1403.     rc = -9;
  1404.     break;
  1405. }
  1406. fprintf(out,"%sn",obuf);
  1407.     }
  1408. } else if (fromb64) { /* Converting from Base 64 */
  1409.     if ((out = fopen(p,appending ? "a" : "w")) == NULL) {
  1410. fclose(in);
  1411. perror(p);
  1412. return(-9);
  1413.     }
  1414.     x = 1;
  1415.     while (x) {
  1416. x = fread(ibuf,1,80,in);
  1417. if ((y = b64tob8(ibuf,x,obuf,80)) < 0) {
  1418.     printf("?Decoding errorn");
  1419.     rc = -9;
  1420.     break;
  1421. }
  1422. if (swapping) {
  1423.     if (x & 1) {
  1424. printf("?Swap errorn");
  1425. rc = -9;
  1426. break;
  1427.     }
  1428.     for (i = 0; i < y; i+=2) {
  1429. t = obuf[i];
  1430. obuf[i] = obuf[i+1];
  1431. obuf[i+1] = t;
  1432.     }
  1433. }
  1434. if (y > 0) {
  1435.     if (fwrite(obuf,1,y,out) < 1) {
  1436. perror(p);
  1437. rc = -9;
  1438. break;
  1439.     }
  1440. }
  1441.     }
  1442. } else
  1443. #endif /* NOSPL */
  1444. if (swapping) { /* Swapping bytes */
  1445.     char c[3];
  1446.     c[2] = NUL;
  1447.     while (1) {
  1448. x = fread((char *)c,1,2,in);
  1449. if (x < 1) {
  1450.     rc = 1;
  1451.     break;
  1452. } else if (x == 1) {
  1453.     c[1] = c[0];
  1454.     c[0] = NUL;
  1455.     printf(
  1456.      "?WARNING: source file contains odd number of bytesn");
  1457. }
  1458. if (fprintf(out,"%c%c",c[1],c[0]) == EOF) {
  1459.     perror(p);
  1460.     rc = -9;
  1461.     break;
  1462. }
  1463.     }
  1464. } else if (appending) { /* Appending to target file */
  1465.     char c;
  1466.     while (1) {
  1467. x = fread(&c,1,1,in);
  1468. if (x < 1) {
  1469.     rc = 1;
  1470.     break;
  1471. }
  1472. if (fwrite(&c,1,1,out) < 1) {
  1473.     perror(p);
  1474.     rc = -9;
  1475.     break;
  1476. }
  1477.     }
  1478. }
  1479. if (out) fclose(out);
  1480. if (in) fclose(in);
  1481. if (rc > -1) success = rc;
  1482. return(rc);
  1483.     }
  1484. }
  1485. #endif /* ZCOPY */
  1486. #endif /* NOFRILLS */
  1487. #ifndef NORENAME
  1488. #ifndef NOFRILLS
  1489. #ifdef ZRENAME
  1490. int
  1491. dorenam() {
  1492.     /* Parse a file or a directory name */
  1493.     int i, x, listing = 0, havename = 0;
  1494.     struct FDB sw, fi;
  1495.     cmfdbi(&sw, /* 2nd FDB - optional /PAGE switch */
  1496.    _CMKEY, /* fcode */
  1497.    "Filename or switch", /* hlpmsg */
  1498.    "", /* default */
  1499.    "", /* addtl string data */
  1500.    nqvswtab, /* addtl numeric data 1: tbl size */
  1501.    4, /* addtl numeric data 2: 4 = cmswi */
  1502.    xxstring, /* Processing function */
  1503.    qvswtab, /* Keyword table */
  1504.    &fi /* Pointer to next FDB */
  1505.    );
  1506.     cmfdbi(&fi, /* 1st FDB - file to type */
  1507.    _CMIFI, /* fcode */
  1508.    "", /* hlpmsg */
  1509.    "", /* default */
  1510.    "", /* addtl string data */
  1511.    0, /* addtl numeric data 1 */
  1512.    0, /* addtl numeric data 2 */
  1513.    xxstring,
  1514.    NULL,
  1515.    NULL
  1516.    );
  1517.     while (!havename) {
  1518. x = cmfdb(&sw); /* Parse something */
  1519. if (x < 0) /* Error */
  1520.   return(x);
  1521. switch (cmresult.fcode) {
  1522.   case _CMKEY:
  1523.     switch (cmresult.nresult) {
  1524.       case DEL_LIS:
  1525.       case DEL_VRB:
  1526. listing = 1;
  1527. break;
  1528.       case DEL_NOL:
  1529.       case DEL_QUI:
  1530. listing = 0;
  1531. break;
  1532.     }
  1533.     break;
  1534.   case _CMIFI:
  1535.     s = cmresult.sresult;
  1536.     havename = 1;
  1537.     break;
  1538.   default:
  1539.     return(-2);
  1540. }
  1541.     }
  1542.     if (cmresult.nresult > 0) { /* No wildcards allowed */
  1543. printf(
  1544.    "n?Multiple files not allowed - please specify a single file.n");
  1545. return(-9);
  1546.     }
  1547.     ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy of the old name */
  1548.     p = line + (int)strlen(line) + 2; /* Place for new name */
  1549.     if ((x = cmofi("New name","",&s,xxstring)) < 0) { /* Get new name */
  1550. if (x == -3) {
  1551.     printf("?New name for file requiredn");
  1552.     return(-9);
  1553. } else return(x);
  1554.     }
  1555.     ckstrncpy(p,s,LINBUFSIZ-(p-line)); /* Make a safe copy of the new name */
  1556.     if ((y = cmcfm()) < 0) return(y);
  1557. #ifdef VMS
  1558.     conres(); /* Let Ctrl-C work. */
  1559. #endif /* VMS */
  1560.     debug(F110,"dorename line",line,0);
  1561.     debug(F110,"dorename p",p,0);
  1562.     if (listing) printf("%s => %s ",line,p);
  1563.     if (zrename(line,p) < 0) {
  1564. printf("?Can't rename %s to %sn",line,p);
  1565. #ifdef VMS
  1566. concb((char)escape);
  1567. #endif /* VMS */
  1568. return(-9);
  1569.     } else {
  1570. #ifdef VMS
  1571. concb((char)escape);
  1572. #endif /* VMS */
  1573. if (listing) printf("(OK)n");
  1574. return(success = 1);
  1575.     }
  1576. }
  1577. #endif /* ZRENAME */
  1578. #endif /* NOFRILLS */
  1579. #endif /* NORENAME */
  1580. #ifndef NOSPL
  1581. /* Do the RETURN command */
  1582. int
  1583. doreturn(s) char *s; {
  1584.     int x; char *p;
  1585.     extern int tra_asg;
  1586.     if (maclvl < 0) {
  1587. printf("n?Can't return from level %dn",maclvl);
  1588. return(success = 0);
  1589.     }
  1590.     lp = line; /* Expand return value now */
  1591.     x = LINBUFSIZ-1;
  1592.     if (!s) s = "";
  1593.     if (zzstring(s,&lp,&x) > -1) {
  1594. s = line;
  1595. debug(F110,"RETURN parse",s,0);
  1596.     }
  1597.     /* Pop from all FOR/WHILE/SWITCH/XIFs */
  1598.     while ((maclvl > 0) &&
  1599.    (m_arg[maclvl-1][0]) &&
  1600.    (cmdstk[cmdlvl].src == CMD_MD) &&
  1601.    (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
  1602.     !strncmp(m_arg[maclvl-1][0],"_for",4) ||
  1603.     !strncmp(m_arg[maclvl-1][0],"_swi",4) ||
  1604.     !strncmp(m_arg[maclvl-1][0],"_whi",4))) {
  1605. debug(F110,"RETURN popping",m_arg[maclvl-1][0],0);
  1606. dogta(XXPTA); /* Put args back */
  1607. popclvl(); /* Pop up two levels */
  1608. popclvl();
  1609. debug(F101,"RETURN maclvl 2","",maclvl);
  1610.     }
  1611.     if (tra_asg) { /* If tracing show return value */
  1612. if (*s)
  1613.   printf("<<< %s: "%s"n", m_arg[maclvl][0], s);
  1614. else
  1615.   printf("<<< %s: (null)n", m_arg[maclvl][0]);
  1616.     }
  1617.     popclvl(); /* Pop from enclosing TAKE or macro */
  1618.     debug(F101,"RETURN maclvl 3","",maclvl);
  1619.     x = (int)strlen(s); /* Length of return value */
  1620.     if (x > 0) { /* Have return value? */
  1621. p = malloc(x+2); /* Allocate a place to keep it */
  1622. if (mrval[maclvl+1]) { /* Free old one, if any */
  1623.     free(mrval[maclvl+1]);
  1624.     mrval[maclvl+1] = NULL;
  1625. }
  1626. if (p) { /* Did we get a place? */
  1627.     strcpy(p, s); /* Yes, copy the string into it. */
  1628.     mrval[maclvl+1] = p; /* Make return value point to it. */
  1629.     debug(F110,"RETURN copy",mrval[maclvl],0);
  1630. } else { /* No, could not get space. */
  1631.     mrval[maclvl+1] = NULL; /* Return null pointer. */
  1632.     x = 0; /* Set failure return code. */
  1633. }
  1634.     } else if (mrval[maclvl+1]) {
  1635. makestr(&(mrval[maclvl+1]),NULL); /* Blank return code */
  1636.     }
  1637. #ifdef COMMENT
  1638.     /* What the heck is this? */
  1639.     return(success = x ? 1 : 0); /* Return status code */
  1640. #else
  1641.     /* RETURN should not affect SUCCESS/FAILURE */
  1642.     return(0);
  1643. #endif /* COMMENT */
  1644. }
  1645. #endif /* NOSPL */
  1646. #ifndef NOSPL
  1647. /* Do the OPEN command */
  1648. int
  1649. doopen()  { /* OPEN { append, read, write } */
  1650.     int x, y, z = 0; char *s;
  1651.     static struct filinfo fcb; /* (must be static) */
  1652.     if ((x = cmkey(opntab,nopn,"mode","",xxstring)) < 0) {
  1653. if (x == -3) {
  1654.     printf("?Mode requiredn");
  1655.     return(-9);
  1656. } else return(x);
  1657.     }
  1658.     switch (x) {
  1659.       case OPN_FI_R: /* Old file (READ) */
  1660. if (chkfn(ZRFILE) > 0) {
  1661.     printf("?Read file already openn");
  1662.     return(-2);
  1663. }
  1664. if ((z = cmifi("File to read","",&s,&y,xxstring)) < 0) {
  1665.     if (z == -3) {
  1666. printf("?Input filename requiredn");
  1667. return(-9);
  1668.     } else return(z);
  1669. }
  1670. if (y) { /* No wildcards allowed */
  1671.     printf("n?Please specify a single filen");
  1672.     return(-2);
  1673. }
  1674. ckstrncpy(line,s,LINBUFSIZ);
  1675. if ((int)strlen(line) < 1) return(-2);
  1676. if ((z = cmnum("buffer size","4096",10,&y,xxstring)) < 0)
  1677.   return(z);
  1678. if (y < 1) {
  1679.     printf("?Positive number requiredn");
  1680.     return(-9);
  1681. }
  1682. if ((z = cmcfm()) < 0) return(z);
  1683.         readblock = y;
  1684. if (readbuf)
  1685.   free(readbuf);
  1686. if (!(readbuf = (CHAR *) malloc(readblock+1))) {
  1687.     printf("?Can't allocate read buffern");
  1688.     return(-9);
  1689. }
  1690. return(success = zopeni(ZRFILE,line));
  1691. #ifndef MAC
  1692. #ifndef NOPUSH
  1693.       case OPN_PI_R: /* Pipe/Process (!READ) */
  1694. if (nopush) {
  1695.     printf("?Read from pipe disabledn");
  1696.     return(success=0);
  1697. }
  1698. if (chkfn(ZRFILE) > 0) {
  1699.     printf("?Read file already openn");
  1700.     return(-2);
  1701. }
  1702.         if ((y = cmtxt("System command to read from","",&s,xxstring)) < 0) {
  1703.     if (y == -3) {
  1704. printf("?Command name requiredn");
  1705. return(-9);
  1706.     } else return(y);
  1707. }
  1708. ckstrncpy(line,s,LINBUFSIZ);
  1709. if ((int)strlen(line) < 1) return(-2);
  1710. if ((y = cmcfm()) < 0) return(y);
  1711. if (!readbuf) {
  1712.     if (!(readbuf = (CHAR *) malloc(readblock+1))) {
  1713. printf("?Can't allocate read buffern");
  1714. return(-9);
  1715.     }
  1716. }
  1717. return(success = zxcmd(ZRFILE,line));
  1718.       case OPN_PI_W: /* Write to pipe */
  1719. if (nopush) {
  1720.     printf("?Write to pipe disabledn");
  1721.     return(success=0);
  1722. }
  1723. if (chkfn(ZWFILE) > 0) {
  1724.     printf("?Write file already openn");
  1725.     return(-2);
  1726. }
  1727.         if ((y = cmtxt("System command to write to","",&s,xxstring)) < 0) {
  1728.     if (y == -3) {
  1729. printf("?Command name requiredn");
  1730. return(-9);
  1731.     } else return(y);
  1732. }
  1733. ckstrncpy(line,s,LINBUFSIZ);
  1734. if ((int)strlen(line) < 1) return(-2);
  1735. if ((y = cmcfm()) < 0) return(y);
  1736. success = zxcmd(ZWFILE,line);
  1737. if (!success && msgflg)
  1738.   printf("Can't open process for writing: %sn",line);
  1739. return(success);
  1740. #endif /* NOPUSH */
  1741. #endif /* MAC */
  1742.       case OPN_FI_W: /* New file (WRITE) */
  1743.       case OPN_FI_A: /* (APPEND) */
  1744. if ((z = cmofi("Name of local file to create","",&s,xxstring)) < 0) {
  1745.     if (z == -3) {
  1746. printf("?Filename requiredn");
  1747. return(-9);
  1748.     } else return(z);
  1749. }
  1750. if (z == 2) {
  1751.     printf("?Sorry, %s is a directory namen",s);
  1752.     return(-9);
  1753. }
  1754. if (chkfn(ZWFILE) > 0) {
  1755.     printf("?Write/Append file already openn");
  1756.     return(-2);
  1757. }
  1758.         fcb.bs = fcb.cs = fcb.rl = fcb.fmt = fcb.org = fcb.cc = fcb.typ = 0;
  1759. fcb.lblopts = 0;
  1760. fcb.dsp = (x == OPN_FI_W) ? XYFZ_N : XYFZ_A; /* Create or Append */
  1761. ckstrncpy(line,s,LINBUFSIZ);
  1762. if ((int)strlen(line) < 1) return(-2);
  1763. if ((y = cmcfm()) < 0) return(y);
  1764. return(success = zopeno(ZWFILE,line,NULL,&fcb));
  1765. #ifndef NOLOCAL
  1766.       case OPN_SER: /* OPEN PORT or LINE */
  1767.       case OPN_NET: { /* OPEN HOST */
  1768.   extern int didsetlin, ttnproto;
  1769.   if (x == OPN_NET) {
  1770.       z = ttnproto;
  1771.       ttnproto = NP_NONE;
  1772.   }
  1773.   if ((y = setlin((x == OPN_SER) ? XYLINE : XYHOST, 1, 0)) < 0) {
  1774.       if (x == OPN_NET)
  1775. ttnproto = z;
  1776.       success = 0;
  1777.   }
  1778.   didsetlin++;
  1779.   return(y);
  1780.       }
  1781. #endif /* NOLOCAL */
  1782.       default:
  1783. printf("?Not implemented");
  1784. return(-2);
  1785.     }
  1786. }
  1787. #endif /* NOSPL */
  1788. #ifndef NOXFER
  1789. /*  D O X G E T  --  GET command parser with switches  */
  1790. #ifdef CK_LABELED
  1791. int g_lf_opts = -1;
  1792. extern int lf_opts;
  1793. #endif /* CK_LABELED */
  1794. int
  1795. doxget(cx) int cx; {
  1796.     extern int /* External variables we need */
  1797. #ifdef RECURSIVE
  1798.       recursive,
  1799. #endif /* RECURSIVE */
  1800.       xfermode, fdispla, protocol,
  1801.       g_binary, g_xfermode, g_displa, g_rpath;
  1802.     extern char * rcv_move; /* Directory to move new files to */
  1803.     extern char * rcv_rename; /* What to rename new files to */
  1804.     extern char * g_rcv_move;
  1805.     extern char * g_rcv_rename;
  1806.     extern char * rcvexcept[]; /* RECEIVE / GET exception list */
  1807.     int opkt  =  0; /* Flag for O-Packet needed */
  1808. #ifdef PIPESEND
  1809.     extern int pipesend;
  1810.     extern char * rcvfilter, * g_rfilter;
  1811. #endif /* PIPESEND */
  1812.     extern struct keytab rpathtab[];
  1813.     extern int nrpathtab;
  1814.     extern long calibrate;
  1815.     int asname = 0; /* Flag for have as-name */
  1816.     int konly = 0; /* Kermit-only function */
  1817.     int c, i, n, confirmed = 0; /* Workers */
  1818.     int getval = 0; /* Whether to get switch value */
  1819.     int rcvcmd = 0; /* Whether it is the RECEIVE command */
  1820.     int mget = 0; /* Whether it is the MGET command */
  1821.     struct stringint { /* Temporary array for switch values */
  1822. char * sval;
  1823. int ival;
  1824.     } pv[SND_MAX+1];
  1825.     struct FDB sw, fl, cm; /* FDBs for each parse function */
  1826.     char * cmdstr = "this command";
  1827.     debug(F101,"xget cx","",cx);
  1828.     oopts = -1;
  1829.     omode = -1;
  1830.     for (i = 0; i <= SND_MAX; i++) { /* Initialize switch values */
  1831. pv[i].sval = NULL;
  1832. pv[i].ival = -1;
  1833.     }
  1834.     /* Preset switch values based on top-level command that called us */
  1835.     switch (cx) {
  1836.       case XXREC: /* RECEIVE */
  1837. cmdstr = "RECEIVE";
  1838. rcvcmd = 1; break;
  1839.       case XXGET: /* GET */
  1840. cmdstr = "GET";
  1841. konly = 1;
  1842. break;
  1843. #ifdef CK_RESEND
  1844.       case XXREGET: /* REGET */
  1845. cmdstr = "REGET";
  1846. konly = 1;
  1847. pv[SND_BIN].ival = 1; /* Implies /BINARY */
  1848. pv[SND_RES].ival = 1; break;
  1849. #endif /* CK_RESEND */
  1850.       case XXRETR: /* RETRIEVE */
  1851. cmdstr = "RETRIEVE";
  1852. konly = 1;
  1853. pv[SND_DEL].ival = 1; break;
  1854. #ifdef PIPESEND
  1855.       case XXCREC: /* CRECEIVE */
  1856. cmdstr = "CRECEIVE";
  1857. konly = 1;
  1858. rcvcmd = 1;
  1859. pv[SND_CMD].ival = 1; break;
  1860.       case XXCGET: /* CGET */
  1861. cmdstr = "CGET";
  1862. konly = 1;
  1863. pv[SND_CMD].ival = 1; break;
  1864. #endif /* PIPESEND */
  1865. #ifndef NOMGET
  1866.       case XXMGET: /* MGET */
  1867. cmdstr = "MGET";
  1868. konly = 1;
  1869. mget = 1; break;
  1870. #endif /* NOMGET */
  1871.     }
  1872.     debug(F111,"xget rcvcmd",cmdstr,rcvcmd);
  1873.     debug(F101,"xget konly","",konly);
  1874. #ifdef CK_XYZ
  1875.     if (!rcvcmd && protocol != PROTO_K) {
  1876. printf("?Sorry, %s works only with Kermit protocoln",cmdstr);
  1877. return(-9);
  1878.     }
  1879. #endif /* CK_XYZ */
  1880.     /* Set up chained parse functions... */
  1881.     cmfdbi(&sw, /* First FDB - command switches */
  1882.    _CMKEY, /* fcode */
  1883.    rcvcmd ?
  1884.    "Optional name/template to store incoming files under, or switch" :
  1885.    "Remote filename, or switch", /* hlpmsg */
  1886.    "", /* default */
  1887.    "", /* addtl string data */
  1888.    rcvcmd ? nrcvtab : ngettab, /* addtl numeric data 1: tbl size */
  1889.    4, /* addtl numeric data 2: 4 = cmswi */
  1890.    xxstring, /* Processing function */
  1891.    rcvcmd ? rcvtab : gettab, /* Keyword table */
  1892.    &fl /* Pointer to next FDB */
  1893.    );
  1894.     if (rcvcmd || mget) /* RECEIVE or MGET */
  1895.       cmfdbi(&fl,
  1896.    _CMTXT, /* fcode */
  1897.    rcvcmd ? /* hlpmsg */
  1898.      "Output filename or Command" : /* Output filename */
  1899.      "File(s) to GET",     /* Files we are asking for */
  1900.    "", /* default */
  1901.    "", /* addtl string data */
  1902.    0, /* addtl numeric data 1 */
  1903.    0, /* addtl numeric data 2 */
  1904. #ifdef CK_XYZ
  1905.    (protocol == PROTO_X || protocol == PROTO_XC) ?
  1906.      xxstring :
  1907.      (rcvcmd ? (xx_strp)0  : xxstring)
  1908. #else
  1909.    rcvcmd ? (xx_strp)0  : xxstring /* Processing function */
  1910. #endif /* CK_XYZ */
  1911.      ,
  1912.    NULL,
  1913.    &cm
  1914.    );
  1915.     else
  1916.       cmfdbi(&fl, /* Remote filename or command */
  1917.    _CMFLD, /* fcode */
  1918.    "Remote filename", /* hlpmsg */
  1919.    "", /* default */
  1920.    "", /* addtl string data */
  1921.    0, /* addtl numeric data 1 */
  1922.    0, /* addtl numeric data 2 */
  1923.    xxstring,
  1924.    NULL,
  1925.    &cm
  1926.    );
  1927.     cmfdbi(&cm, /* Confirmation */
  1928.    _CMCFM, /* fcode */
  1929.    "", /* hlpmsg */
  1930.    "", /* default */
  1931.    "", /* addtl string data */
  1932.    0, /* addtl numeric data 1 */
  1933.    0, /* addtl numeric data 2 */
  1934.    NULL,
  1935.    NULL,
  1936.    NULL
  1937.    );
  1938.     /* (See doxsend() for fuller commentary) */
  1939.     while (1) { /* Parse 0 or more switches */
  1940. x = cmfdb(&sw); /* Parse something */
  1941. debug(F101,"xget cmfdb","",x);
  1942. if (x < 0) /* Error */
  1943.   goto xgetx; /* or reparse needed */
  1944. if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
  1945.   break;
  1946. c = cmgbrk(); /* Get break character */
  1947. if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  1948.     printf("?This switch does not take an argumentn");
  1949.     x = -9;
  1950.     goto xgetx;
  1951. }
  1952. if (!getval && (cmgkwflgs() & CM_ARG)) {
  1953.     printf("?This switch requires an argumentn");
  1954.     x = -9;
  1955.     goto xgetx;
  1956. }
  1957. n = cmresult.nresult; /* Numeric result = switch value */
  1958. debug(F101,"xget switch","",n);
  1959. switch (n) { /* Process the switch */
  1960. #ifdef PIPESEND
  1961.   case SND_CMD: /* These take no args */
  1962.     if (nopush) {
  1963. printf("?Sorry, system command access is disabledn");
  1964. x = -9;
  1965. goto xgetx;
  1966.     } else if (rcvfilter) {
  1967. printf(
  1968. "?Sorry, no GET /COMMAND when RECEIVE FILTER selectedn");
  1969. x = -9;
  1970. goto xgetx;
  1971.     }
  1972.     if (rcvcmd)
  1973.       sw.hlpmsg = "Command, or switch"; /* Change help message */
  1974.     /* Fall thru... */
  1975. #endif /* PIPESEND */
  1976.   case SND_REC: /* /RECURSIVE */
  1977.     pv[SND_PTH].ival = PATH_REL; /* Implies relative pathnames */
  1978.     pv[n].ival = 1; /* Set the recursive flag */
  1979.     break;
  1980.   case SND_RES: /* /RECOVER */
  1981.     pv[SND_BIN].ival = 1; /* Implies /BINARY */
  1982.     pv[n].ival = 1; /* Set the resend flag */
  1983.     break;
  1984.   case SND_DEL: /* /DELETE */
  1985.   case SND_SHH: /* /QUIET */
  1986.           case SND_CAL: /* /CALIBRATE */
  1987.     pv[n].ival = 1; /* Just set the appropriate flag */
  1988.     break;
  1989.   /* File transfer modes - each undoes the others */
  1990.   case SND_BIN: /* Binary */
  1991.   case SND_TXT: /* Text */
  1992.   case SND_IMG: /* Image */
  1993.   case SND_LBL: /* Labeled */
  1994.     pv[SND_BIN].ival = 0; /* Unset all */
  1995.     pv[SND_TXT].ival = 0;
  1996.     pv[SND_IMG].ival = 0;
  1997.     pv[SND_LBL].ival = 0;
  1998.     pv[n].ival = 1; /* Set the requested one */
  1999.     break;
  2000.   case SND_EXC: /* Excludes */
  2001.     if (!getval) break;
  2002.     if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
  2003. if (x == -3) {
  2004.     printf("?Pattern requiredn");
  2005.     x = -9;
  2006. }
  2007. goto xgetx;
  2008.     }
  2009.     if (pv[n].sval) free(pv[n].sval);
  2010.     y = strlen(s);
  2011.     if (y > 256) {
  2012. printf("?Pattern too long - 256 maxn");
  2013. x = -9;
  2014. goto xgetx;
  2015.     }
  2016.     pv[n].sval = malloc(y+1);
  2017.     if (pv[n].sval) {
  2018. strcpy(pv[n].sval,s);
  2019. pv[n].ival = 1;
  2020.     }
  2021.     break;
  2022. #ifdef COMMENT
  2023.   /* Not implemented */
  2024.   case SND_PRI: /* GET to printer */
  2025.     pv[n].ival = 1;
  2026.     if (!getval) break;
  2027.     if ((x = cmfld("Print options","",&s,xxstring)) < 0)
  2028.       goto xgetx;
  2029.     pv[n].sval = malloc((int)strlen(s)+1);
  2030.     if (pv[n].sval)
  2031.       strcpy(pv[n].sval,s);
  2032.     break;
  2033. #endif /* COMMENT */
  2034.   case SND_MOV: /* MOVE after */
  2035.   case SND_REN: /* RENAME after */
  2036.     if (!getval) break;
  2037.     if ((x = cmfld(n == SND_MOV ?
  2038.    "device and/or directory for source file after sending" :
  2039.    "new name for source file after sending",
  2040.    "",
  2041.    &s,
  2042.    n == SND_MOV ? xxstring : NULL
  2043.    )) < 0) {
  2044. if (x == -3) {
  2045.     printf("%sn", n == SND_MOV ?
  2046.    "?Destination required" :
  2047.    "?New name required"
  2048.    );
  2049.     x = -9;
  2050. }
  2051. goto xgetx;
  2052.     }
  2053.     if (pv[n].sval) {
  2054. free(pv[n].sval);
  2055. pv[n].sval = NULL;
  2056.     }
  2057.     s = brstrip(s);
  2058.     y = strlen(s);
  2059.     if (y > 0) {
  2060. pv[n].sval = malloc(y+1);
  2061. if (pv[n].sval) {
  2062.     strcpy(pv[n].sval,s);
  2063.     pv[n].ival = 1;
  2064. }
  2065.     }
  2066.     break;
  2067.   case SND_ASN: /* As-name */
  2068.     if (!getval) break;
  2069.     if (mget) {
  2070. printf("?Sorry, as-name not allowed with MGETn");
  2071. x = -9;
  2072. goto xgetx;
  2073.     }
  2074.     if ((x = cmfld("Name to store it under","",&s,NULL)) < 0)
  2075.       goto xgetx;
  2076.     s = brstrip(s);
  2077.     if ((y = strlen(s)) > 0) {
  2078. if (pv[n].sval) free(pv[n].sval);
  2079. pv[n].sval = malloc(y+1);
  2080. if (pv[n].sval) {
  2081.     strcpy(pv[n].sval,s);
  2082.     pv[n].ival = 1;
  2083. }
  2084.     }
  2085.     break;
  2086. #ifdef PIPESEND
  2087.   case SND_FLT: /* Filter */
  2088.     debug(F101,"xget /filter getval","",getval);
  2089.     if (!getval) break;
  2090.     if ((x = cmfld("Filter program to receive through",
  2091.    "",&s,NULL)) < 0) {
  2092. if (x == -3)
  2093.   s = "";
  2094. else
  2095.   goto xgetx;
  2096.     }
  2097.     s = brstrip(s);
  2098.     y = strlen(s);
  2099.     for (x = 0; x < y; x++) { /* Make sure they included "v(...)" */
  2100. if (s[x] != '\') continue;
  2101. if (s[x+1] == 'v') break;
  2102.     }
  2103.     if (x == y) {
  2104. printf(
  2105. "?Filter must contain a replacement variable for filename.n"
  2106.        );
  2107. x = -9;
  2108. goto xgetx;
  2109.     }
  2110.     pv[n].ival = 1;
  2111.     if (pv[n].sval) {
  2112. free(pv[n].sval);
  2113. pv[n].sval = NULL;
  2114.     }
  2115.     if ((y = strlen(s)) > 0) {
  2116. if (pv[n].sval = malloc(y+1))
  2117.   strcpy(pv[n].sval,s);
  2118.     }
  2119.     break;
  2120. #endif /* PIPESEND */
  2121.   case SND_PTH: /* Pathnames */
  2122.     if (!getval) {
  2123. pv[n].ival = PATH_REL;
  2124. break;
  2125.     }
  2126.     if ((x = cmkey(rpathtab,nrpathtab,"","on",xxstring)) < 0)
  2127.       goto xgetx;
  2128.     pv[n].ival = x; /* Ditto */
  2129.     break;
  2130.   case SND_NAM: /* Filenames */
  2131.     if (!getval) break;
  2132.     if ((x = cmkey(fntab,nfntab,"","converted",xxstring)) < 0)
  2133.       goto xgetx;
  2134.     pv[n].ival = x;
  2135.     break;
  2136.   case SND_PRO: /* Protocol to use */
  2137.     if (!getval) break;
  2138.     if ((x = cmkey(protos,nprotos,"File-transfer protocol","",
  2139.    xxstring)) < 0) {
  2140. if (x == -3)
  2141.   x = 0;
  2142. else
  2143.   goto xgetx;
  2144.     }
  2145.     debug(F111,"xget /proto",atmbuf,x);
  2146.     pv[n].ival = x;
  2147.     if (konly && x != PROTO_K) {
  2148. printf(
  2149. "?Sorry, this command works only with Kermit protocoln"
  2150.        );
  2151. x = -9;
  2152. goto xgetx;
  2153.     }
  2154.     break;
  2155.   default:
  2156.     printf("?Unexpected switch value - %dn",cmresult.nresult);
  2157.     x = -9;
  2158.     goto xgetx;
  2159. }
  2160.     }
  2161.     debug(F101,"xget cmresult fcode","",cmresult.fcode);
  2162.     cmarg = line; /* Initialize string pointers */
  2163.     cmarg2 = tmpbuf;
  2164.     asname = 0;
  2165.     line[0] = NUL; /* and buffers. */
  2166.     tmpbuf[0] = NUL;
  2167.     switch (cmresult.fcode) { /* How did we get out of switch loop */
  2168.       case _CMFLD: /* Remote filespec */
  2169. ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
  2170. break;
  2171.       case _CMTXT: /* As-name */
  2172. if (rcvcmd) {
  2173.     ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
  2174.     if ((int)strlen(tmpbuf) > 0)
  2175.       asname = 1;
  2176. } else {
  2177.     ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
  2178. }
  2179.       case _CMCFM: /* Confirmation */
  2180. confirmed = 1;
  2181. break;
  2182.       default:
  2183. printf("?Unexpected function code: %dn",cmresult.fcode);
  2184. x = -9;
  2185. goto xgetx;
  2186.     }
  2187.     debug(F110,"xget string",cmarg,0);
  2188.     debug(F101,"xget confirmed","",confirmed);
  2189.     cmarg = brstrip(cmarg); /* Strip any braces */
  2190.     if (!confirmed) { /* CR not typed yet, get more fields */
  2191. if (pv[SND_CMD].ival > 0) {
  2192.     debug(F100,"xget calling cmtxt","",0);
  2193.     x = cmtxt("Local command to pipe into","",&s,NULL);
  2194.     if (x < 0 && x != -3) goto xgetx;
  2195.     if (x != -3) {
  2196. ckstrncpy(tmpbuf,s,TMPBUFSIZ);
  2197. asname = 1;
  2198.     }
  2199. } else if (!rcvcmd) {
  2200. #ifdef VMS
  2201.     /* cmofi() fails if you give it a directory name */
  2202.     x = cmfld("Name or directory for incoming file","",&s,NULL);
  2203.     debug(F111,"xget cmfld",s,x);
  2204. #else
  2205.     x = cmofi("Name or directory for incoming file","",&s,NULL);
  2206.     debug(F111,"xget cmofi",s,x);
  2207. #endif /* VMS */
  2208.     if (x < 0 && x != -3) goto xgetx;
  2209.     if (x != -3) {
  2210. ckstrncpy(tmpbuf,s,TMPBUFSIZ);
  2211. if ((x = cmcfm()) < 0) goto xgetx;
  2212. asname = 1;
  2213.     }
  2214. }
  2215.     }
  2216.     /* Arrive here with cmarg and cmarg2 all set */
  2217.     debug(F111,"xget asname",cmarg2,asname);
  2218.     if (!asname) {
  2219. if (pv[SND_ASN].sval)
  2220.   ckstrncpy(tmpbuf,pv[SND_ASN].sval,TMPBUFSIZ);
  2221. else
  2222.   tmpbuf[0] = NUL;
  2223.     }
  2224.     cmarg2 = brstrip(cmarg2); /* Strip outer braces if any. */
  2225.     debug(F110,"xget cmarg",cmarg,0);
  2226.     debug(F110,"xget cmarg2",cmarg2,0);
  2227.     if (!*cmarg &&
  2228. (cx == XXGET || cx == XXREGET || cx == XXCGET || cx == XXMGET)) {
  2229. printf("?A remote file specification is requiredn");
  2230. x = -9;
  2231. goto xgetx;
  2232.     }
  2233. #ifdef PIPESEND
  2234.     if (pv[SND_CMD].ival > 0) { /* /COMMAND sets pipesend flag */
  2235. x = -9;
  2236. if (!*cmarg2) {
  2237.     printf("?Command requiredn");
  2238.     goto xgetx;
  2239. } else if (nopush) {
  2240.     printf("?Sorry, system command access is disabledn");
  2241.     goto xgetx;
  2242. } else if (rcvfilter) {
  2243.     printf("?Sorry, no GET /COMMAND while RECEIVE FILTER selectedn");
  2244.     goto xgetx;
  2245. } else
  2246.   pipesend = 1;
  2247.     }
  2248.     debug(F101,"xget /COMMAND pipesend","",pipesend);
  2249. #endif /* PIPESEND */
  2250. #ifdef CK_RESEND
  2251.     if (pv[SND_RES].ival > 0) { /* REGET or GET /RECOVER */
  2252. #ifdef RECURSIVE
  2253. if (pv[SND_REC].ival > 0) { /* RECURSIVE */
  2254. #ifdef COMMENT
  2255.     printf("?Unsupported option combination: /RECOVER /RECURSIVEn");
  2256.     x = -9;
  2257.     goto xgetx;
  2258. #else
  2259.     opkt = 1;
  2260. #endif /* COMMENT */
  2261. }
  2262. #endif /* RECURSIVE */
  2263. if (pv[SND_DEL].ival > 0) { /* /DELETE */
  2264. #ifdef COMMENT
  2265.     printf("?Unsupported option combination: /RECOVER /DELETEn");
  2266.     x = -9;
  2267.     goto xgetx;
  2268. #else
  2269.     opkt = 1;
  2270. #endif /* COMMENT */
  2271. }
  2272.     }
  2273. #endif /* CK_RESEND */
  2274.     if (pv[SND_EXC].ival > 0) /* /EXCEPT */
  2275.       makelist(pv[SND_EXC].sval,rcvexcept,8);
  2276. #ifdef IKS_OPTION
  2277.     if (!rcvcmd) {
  2278.         if (!iks_wait(KERMIT_REQ_START,1)) {
  2279.     printf(
  2280.       "?A Kermit Server is unavailable to process this commandn");
  2281.     x = -9; /* correct the return code */
  2282.     goto xgetx;
  2283.         }
  2284.     }
  2285. #endif /* IKS_OPTION */
  2286. #ifdef CK_XYZ
  2287.     if ((pv[SND_PRO].ival < 0 &&
  2288.          (protocol == PROTO_X || protocol == PROTO_XC) ||
  2289.          pv[SND_PRO].ival > -1 &&
  2290.          (pv[SND_PRO].ival == PROTO_X || pv[SND_PRO].ival == PROTO_XC)) &&
  2291. rcvcmd && !*cmarg2) {
  2292. printf(
  2293. "Sorry, you must specify a name when receiving a file with XMODEM protocoln"
  2294.        );
  2295. x = -9;
  2296. goto xgetx;
  2297.     }
  2298. #endif /* CK_XYZ */
  2299. #ifdef RECURSIVE
  2300.     if (pv[SND_REC].ival > 0) { /* RECURSIVE */
  2301. recursive = 1;
  2302. pv[SND_PTH].ival = PATH_REL; /* Implies relative pathnames too */
  2303.     }
  2304. #endif /* RECURSIVE */
  2305.     /* Save global protocol parameters */
  2306.     g_proto = protocol;
  2307. #ifdef CK_LABELED
  2308.     g_lf_opts = lf_opts; /* Save labeled transfer options */
  2309. #endif /* CK_LABELED */
  2310.     g_urpsiz = urpsiz; /* Receive packet length */
  2311.     g_spsizf = spsizf; /* Send packet length flag */
  2312.     g_spsiz = spsiz; /* Send packet length */
  2313.     g_spsizr = spsizr; /* etc etc */
  2314.     g_spmax = spmax;
  2315.     g_wslotr = wslotr;
  2316.     g_prefixing = prefixing;
  2317.     g_fncact = fncact;
  2318.     g_fncnv = fncnv;
  2319.     g_fnspath = fnspath;
  2320.     g_fnrpath = fnrpath;
  2321.     if (pv[SND_PRO].ival > -1) { /* Change according to switch */
  2322. protocol = pv[SND_PRO].ival;
  2323.         if (ptab[protocol].rpktlen > -1)   /* copied from initproto() */
  2324.             urpsiz = ptab[protocol].rpktlen;
  2325.         if (ptab[protocol].spktflg > -1)
  2326.             spsizf = ptab[protocol].spktflg;
  2327.         if (ptab[protocol].spktlen > -1) {
  2328.             spsiz = ptab[protocol].spktlen;
  2329.             if (spsizf)
  2330.                 spsizr = spmax = spsiz;
  2331.         }
  2332.         if (ptab[protocol].winsize > -1)
  2333.             wslotr = ptab[protocol].winsize;
  2334.         if (ptab[protocol].prefix > -1)
  2335.             prefixing = ptab[protocol].prefix;
  2336.         if (ptab[protocol].fnca > -1)
  2337.             fncact  = ptab[protocol].fnca;
  2338.         if (ptab[protocol].fncn > -1)
  2339.             fncnv   = ptab[protocol].fncn;
  2340.         if (ptab[protocol].fnsp > -1)
  2341.             fnspath = ptab[protocol].fnsp;
  2342.         if (ptab[protocol].fnrp > -1)
  2343.             fnrpath = ptab[protocol].fnrp;
  2344.     }
  2345.     debug(F101,"xget protocol","",protocol);
  2346.     debug(F111,"xget cmarg2",cmarg2,xfermode);
  2347.     g_xfermode = xfermode;
  2348.     g_binary = binary;
  2349.     if (pv[SND_BIN].ival > 0) { /* Change according to switch */
  2350. xfermode = XMODE_M;
  2351. binary = XYFT_B; /* FILE TYPE BINARY */
  2352. omode = GMOD_BIN; /* O-Packet mode */
  2353. debug(F101,"doxget /BINARY xfermode","",xfermode);
  2354.     } else if (pv[SND_TXT].ival > 0) { /* Ditto for /TEXT */
  2355. xfermode = XMODE_M;
  2356. binary = XYFT_T;
  2357. omode = GMOD_TXT;
  2358. debug(F101,"doxget /TEXT xfermode","",xfermode);
  2359.     } else if (pv[SND_IMG].ival > 0) {
  2360. xfermode = XMODE_M;
  2361. #ifdef VMS
  2362. binary = XYFT_I;
  2363. #else
  2364. binary = XYFT_B;
  2365. #endif /* VMS */
  2366. omode = GMOD_TXT;
  2367. debug(F101,"doxget /IMAGE xfermode","",xfermode);
  2368.     }
  2369. #ifdef CK_LABELED
  2370.     else if (pv[SND_LBL].ival > 0) {
  2371. xfermode = XMODE_M;
  2372. binary = XYFT_L;
  2373. omode = GMOD_LBL;
  2374. debug(F101,"doxget /LABELED xfermode","",xfermode);
  2375.     }
  2376. #endif /* CK_LABELED */
  2377.     debug(F101,"xget binary","",binary);
  2378.     debug(F101,"xget omode","",omode);
  2379. #ifdef PIPESEND
  2380.     if (pv[SND_FLT].ival > 0) {
  2381. g_rfilter = rcvfilter;
  2382. if (!pv[SND_FLT].sval) {
  2383.     rcvfilter = NULL;
  2384. } else {
  2385.     rcvfilter = (char *) malloc((int) strlen(pv[SND_FLT].sval) + 1);
  2386.     if (rcvfilter) strcpy(rcvfilter,pv[SND_FLT].sval);
  2387. }
  2388.     }
  2389. #endif /* PIPESEND */
  2390. #ifdef CK_TMPDIR
  2391.     if (pv[SND_MOV].ival > 0) {
  2392. int len;
  2393. char * p = pv[SND_MOV].sval;
  2394. #ifdef CK_LOGIN
  2395. if (isguest) {
  2396.     printf("?Sorry, /MOVE-TO not available to guestsn");
  2397.     x = -9;
  2398.     goto xgetx;
  2399. }
  2400. #endif /* CK_LOGIN */
  2401. len = strlen(p);
  2402. if (!isdir(p)) { /* Check directory */
  2403. #ifdef CK_MKDIR
  2404.     char * s = NULL;
  2405.     s = (char *)malloc(len + 4);
  2406.     if (s) {
  2407. strcpy(s,p);
  2408. #ifdef datageneral
  2409. if (s[len-1] != ':') { s[len++] = ':'; s[len] = NUL; }
  2410. #else
  2411. if (s[len-1] != '/') { s[len++] = '/'; s[len] = NUL; }
  2412. #endif /* datageneral */
  2413. s[len++] = 'X';
  2414. s[len] = NUL;
  2415. x = zmkdir(s);
  2416. free(s);
  2417. if (x < 0) {
  2418.     printf("?Can't create "%s"n",p);
  2419.     x = -9;
  2420.     goto xgetx;
  2421. }
  2422.     }
  2423. #else
  2424.     printf("?Directory "%s" not foundn",p);
  2425.     x = -9;
  2426.     goto xgetx;
  2427. #endif /* CK_MKDIR */
  2428. }
  2429. makestr(&rcv_move,p);
  2430.     }
  2431. #endif /* CK_TMPDIR */
  2432.     if (pv[SND_REN].ival > 0) { /* /RENAME-TO:name */
  2433. char * p = pv[SND_REN].sval;
  2434. #ifdef CK_LOGIN
  2435. if (isguest) {
  2436.     printf("?Sorry, /RENAME-TO not available to guestsn");
  2437.     x = -9;
  2438.     goto xgetx;
  2439. }
  2440. #endif /* CK_LOGIN */
  2441. if (!p) p = "";
  2442. if (!*p) {
  2443.     printf("?New name required for /RENAMEn");
  2444.     x = -9;
  2445.     goto xgetx;
  2446. }
  2447. p = brstrip(p);
  2448. makestr(&rcv_rename,p);
  2449. debug(F110,"xget rcv_rename","",0);
  2450.     }
  2451. #ifdef CALIBRATE
  2452.     if (pv[SND_CAL].ival > 0)
  2453.       calibrate = 1L;
  2454. #endif /* CALIBRATE */
  2455.     g_displa = fdispla;
  2456.     if (pv[SND_SHH].ival > 0)
  2457.       fdispla = 0;
  2458.     debug(F101,"xget display","",fdispla);
  2459.     if (pv[SND_NAM].ival > -1) { /* /FILENAMES */
  2460. g_fncnv = fncnv; /* Save global value */
  2461. fncnv = pv[SND_NAM].ival;
  2462. debug(F101,"xsend fncnv","",fncnv);
  2463. /* We should also handle O packet filename option here */
  2464. /* but we don't really need to since WHATAMI already handles it */
  2465.     }
  2466.     if (pv[SND_PTH].ival > -1) { /* PATHNAMES */
  2467. g_rpath = fnrpath; /* Save global values */
  2468. fnrpath = pv[SND_PTH].ival;
  2469. debug(F101,"xsend fnrpath","",fnrpath);
  2470. #ifndef NZLTOR
  2471. if (fnrpath != PATH_OFF) {
  2472.     g_fncnv = fncnv;
  2473.     fncnv = XYFN_L;
  2474.     debug(F101,"xsend fncnv","",fncnv);
  2475. }
  2476. /* We should also handle O packet pathname option here */
  2477. /* but we don't really need to since WHATAMI already handles it */
  2478. #endif /* NZLTOR */
  2479.     }
  2480.     /* Set protocol start state */
  2481.     if (opkt) { /* Extended GET Options*/
  2482. sstate = (CHAR) 'o';
  2483. oopts = 0;
  2484. if (pv[SND_DEL].ival > 0) oopts |= GOPT_DEL; /* GET /DELETE */
  2485. if (pv[SND_RES].ival > 0) oopts |= GOPT_RES; /* GET /RECOVER */
  2486. if (pv[SND_REC].ival > 0) oopts |= GOPT_REC; /* GET /RECURSIVE */
  2487.     } else if (rcvcmd)
  2488.       sstate = (CHAR) 'v'; /* RECEIVE or CRECEIVE */
  2489.     else if (pv[SND_DEL].ival > 0)
  2490.       sstate = (CHAR) 'h'; /* GET /DELETE (= RETRIEVE) */
  2491.     else if (pv[SND_RES].ival > 0)
  2492.       sstate = (CHAR) 'j'; /* GET /RECOVER (= REGET) */
  2493.     else
  2494.       sstate = (CHAR) 'r'; /* Regular GET */
  2495.     getcmd = 1;
  2496.     debug(F000,"xget sstate","",sstate);
  2497. #ifdef MAC
  2498.     what = W_RECV;
  2499.     scrcreate();
  2500. #endif /* MAC */
  2501.     if (local) {
  2502. if (pv[SND_SHH].ival != 0)
  2503.   displa = 1;
  2504. ttflui();
  2505.     }
  2506.     x = 0;
  2507. #ifdef PIPESEND
  2508.     if (pipesend)
  2509.       goto xgetx;
  2510. #endif /* PIPESEND */
  2511. #ifdef CK_TMPDIR
  2512. /*
  2513.   cmarg2 is also allowed to be a device or directory name;
  2514.   even the name of a directory that doesn't exist.
  2515. */
  2516.     y = strlen(cmarg2);
  2517.     debug(F111,"xget strlen(cmarg2)",cmarg2,y);
  2518.     if ((y > 0) &&
  2519. #ifdef OS2
  2520. ((isalpha(cmarg2[0]) &&
  2521.  cmarg2[1] == ':' &&
  2522.  cmarg2[2] == NUL) ||
  2523. (cmarg[y-1] == '/' || cmarg[y-1] == '\') ||
  2524. isdir(cmarg2))
  2525. #else
  2526. #ifdef UNIXOROSK
  2527. (cmarg2[y-1] == '/' || isdir(cmarg2))
  2528. #else
  2529. #ifdef VMS
  2530. (cmarg2[y-1] == ']' || cmarg2[y-1] == '>' || isdir(cmarg2))
  2531. #else
  2532. #ifdef STRATUS
  2533. (cmarg2[y-1] == '>' || isdir(cmarg2))
  2534. #else
  2535. #ifdef datageneral
  2536. (cmarg2[y-1] == ':' || cmarg[0] == ':' || isdir(cmarg2))
  2537. #else
  2538. isdir(cmarg2)
  2539. #endif /* datageneral */
  2540. #endif /* STRATUS */
  2541. #endif /* VMS */
  2542. #endif /* UNIXOROSK */
  2543. #endif /* OS2 */
  2544. ) {
  2545. debug(F110,"doxget RECEIVE cmarg2 disk or dir",cmarg2,0);
  2546. if (!f_tmpdir) {
  2547.     int x;
  2548.     s = zgtdir();
  2549.     if (s) {
  2550. ckstrncpy(savdir,s,TMPDIRLEN); /* remember old disk/dir */
  2551. f_tmpdir = 1; /* and that we did this */
  2552.     } else {
  2553. printf("?Can't get current directoryn");
  2554. cmarg2 = "";
  2555. f_tmpdir = 0;
  2556. x = -9;
  2557. goto xgetx;
  2558.     }
  2559. #ifdef CK_MKDIR
  2560.     x = zchki(cmarg2); /* Does as-name exist? */
  2561.     if (x == -1) { /* Doesn't exist */
  2562. char * p = NULL; /* Try to create it */
  2563. x = strlen(cmarg2);
  2564. if (p = (char *)malloc(x+4)) {
  2565.     sprintf(p,"%s%s",cmarg2,"x.x");
  2566.     x = zmkdir(p);
  2567.     free(p);
  2568.     if (x < 0) {
  2569. printf("?Can't create %sn",cmarg2);
  2570. x = -9;
  2571. goto xgetx;
  2572.     }
  2573. }
  2574.     }
  2575. #endif /* CK_MKDIR */
  2576.     if (!zchdir(cmarg2)) { /* change to given disk/directory, */
  2577. printf("?Can't access %sn",cmarg2);
  2578. x = -9;
  2579. goto xgetx;
  2580.     }
  2581.     cmarg2 = "";
  2582. }
  2583.     }
  2584. #endif /* CK_TMPDIR */
  2585.     ckstrncpy(fspec,cmarg,CKMAXPATH); /* Note - this is a REMOTE filespec */
  2586.     debug(F111,"xget fspec",fspec,fspeclen);
  2587.     debug(F110,"xget cmarg2",cmarg2,0);
  2588.   xgetx:
  2589.     for (i = 0; i < SND_MAX; i++)
  2590.       if (pv[i].sval)
  2591. free(pv[i].sval);
  2592.     return(x);
  2593. }
  2594. #endif /* NOXFER */
  2595. #ifndef NOSPL
  2596. /*
  2597.   D O G T A  --  Do _GETARGS or _PUTARGS Command.
  2598.   Used by XIF, FOR, WHILE, and SWITCH, each of which are implemented as
  2599.   2-level macros; the first level defines the macro, the second runs it.
  2600.   This routine hides the fact that they are macros by importing the
  2601.   macro arguments (if any) from two levels up, to make them available
  2602.   in the IF, FOR, SWITCH, and WHILE commands themselves; for example as
  2603.   loop indices, etc, and within the IF/FOR/WHILE/SWITCH body itself.
  2604. */
  2605. int
  2606. dogta(cx) int cx; {
  2607.     int i, n; char c; char mbuf[4]; char *p;
  2608.     extern int topargc, cmdint;
  2609.     extern char ** topxarg;
  2610.     if ((y = cmcfm()) < 0)
  2611.       return(y);
  2612.     if (cx == XXGTA)
  2613.       debug(F101,"dogta _GETARGS maclvl","",maclvl);
  2614.     else if (cx == XXPTA)
  2615.       debug(F101,"dogta _PUTARGS maclvl","",maclvl);
  2616.     else
  2617.       return(-2);
  2618.     if (maclvl < 1)
  2619.       return(success = 0);
  2620.     /* Make new copies of macro arguments /%0..9 */
  2621.     mbuf[0] = '%'; mbuf[1] = '0'; mbuf[2] = NUL; /* Argument name buf */
  2622.     for (i = 0; i < 10; i++) { /* For all args */
  2623. c = (char) (i + '0'); /* Make name */
  2624. mbuf[1] = (char) c; /* Insert digit */
  2625. if (cx == XXGTA) { /* Get arg from level-minus-2 */
  2626.     if (maclvl == 1) p = g_var[c]; /* If at level 1 use globals 0..9 */
  2627.     else p = m_arg[maclvl-2][i]; /* Otherwise they're on the stack */
  2628.     addmac(mbuf,p);
  2629.     if (maclvl > 1)
  2630.       makestr(&(m_line[maclvl]),m_line[maclvl-2]);
  2631. } else if (cx == XXPTA) { /* Put args level+2 */
  2632.     if (cmdint)
  2633.       connoi(); /* Turn off interrupts. */
  2634.     maclvl -= 2; /* This is gross.. */
  2635.     p = m_arg[maclvl+2][i];
  2636.     addmac(mbuf,m_arg[maclvl+2][i]);
  2637.     maclvl += 2;
  2638.     if (cmdint)
  2639.       conint(trap,stptrap); /* Restore interrupts */
  2640.     count[cmdlvl - 2]  = count[cmdlvl];
  2641.     intime[cmdlvl - 2] = intime[cmdlvl];
  2642.     inpcas[cmdlvl - 2] = inpcas[cmdlvl];
  2643.     takerr[cmdlvl - 2] = takerr[cmdlvl];
  2644.     merror[cmdlvl - 2] = merror[cmdlvl];
  2645.     xquiet[cmdlvl - 2] = xquiet[cmdlvl];
  2646. } else return(success = 0); /* Bad call to this routine */
  2647.     }
  2648.     /* Now take care of the argument vector array &_[] and v(return) */
  2649.     /* Here we just copy the pointers */
  2650.     if (cx == XXGTA) { /* GETARGS from 2 levels up */
  2651. if (maclvl == 1) {
  2652.     a_ptr[0] = topxarg; /* &_[] array */
  2653.     a_dim[0] = topargc - 1; /* Dimension doesn't include [0] */
  2654.     m_xarg[maclvl] = topxarg;
  2655.     n_xarg[maclvl] = topargc; /* But v(argc) does include %0 */
  2656.     macargc[maclvl] = topargc;
  2657.             makestr(&(mrval[maclvl+1]),mrval[0]); /* (see vnlook()) */
  2658. } else {
  2659.     a_ptr[0] = m_xarg[maclvl-2];
  2660.     a_dim[0] = n_xarg[maclvl-2];
  2661.     m_xarg[maclvl] = m_xarg[maclvl-2];
  2662.     n_xarg[maclvl] = n_xarg[maclvl-2];
  2663.     macargc[maclvl] = n_xarg[maclvl-2];
  2664.             makestr(&(mrval[maclvl+1]),mrval[maclvl-1]); /* (see vnlook()) */
  2665. }
  2666.     } else { /* PUTARGS 2 levels down */
  2667. if (maclvl+2 >= MACLEVEL)
  2668.   return(success = 0);
  2669. a_ptr[0] = m_xarg[maclvl+2];
  2670.         m_xarg[maclvl] = m_xarg[maclvl+2];
  2671. a_dim[0] = n_xarg[maclvl+2];
  2672. n_xarg[maclvl] = n_xarg[maclvl+2];
  2673. macargc[maclvl] = n_xarg[maclvl+2];
  2674.     }
  2675.     return(1); /* Internal command - don't change success */
  2676. }
  2677. #endif /* NOSPL */
  2678. #ifndef NOSPL
  2679. /*
  2680.   Do the GOTO and [_]FORWARD commands.
  2681.   s = Label to search for, cx = function code: XXGOTO, XXFWD, or XXXFWD.
  2682. */
  2683. #ifdef BIGBUFOK
  2684. #define LBLMAXLEN 255 /* Max label length */
  2685. #else
  2686. #define LBLMAXLEN 63
  2687. #endif /* BIGBUFOK */
  2688. int
  2689. dogoto(s, cx) char *s; int cx; {
  2690.     int i, j, x, y, z, bc;
  2691.     int stopflg = 0;
  2692.     char * cmd; /* Name of this command */
  2693.     char tmplbl[LBLMAXLEN+1], *lp; /* Current label from command stream */
  2694.     char tmp2[LBLMAXLEN+1]; /* SWITCH label conversion buffer */
  2695.     char tmp3[LBLMAXLEN+1]; /* Target label */
  2696.     stopflg = (cx == XXXFWD); /* _FORWARD (used in SWITCH) */
  2697.     bc = 0; /* Brace counter */
  2698.     cmd = (cx == XXGOTO) ? "GOTO" : ((cx == XXFWD) ? "FORWARD" : "_FORWARD");
  2699. #ifdef DEBUG
  2700.     if (deblog) {
  2701. debug(F111,"GOTO command",cmd,cx);
  2702. debug(F101,"GOTO cmdlvl","",cmdlvl);
  2703. debug(F101,"GOTO maclvl","",maclvl);
  2704. debug(F101,"GOTO tlevel","",tlevel);
  2705.     }
  2706. #endif /* DEBUG */
  2707.     debug(F110,cmd,s,0);
  2708.     ckstrncpy(tmp3+1,s,LBLMAXLEN-1);
  2709.     s = tmp3+1;
  2710.     if (*s != ':') { /* Make copy of label */
  2711. tmp3[0] = ':'; /* guaranteed to start with ":" */
  2712. s--;
  2713.     }
  2714.     if (s[1] == '.' || s[1] == SP || s[1] == NUL) {
  2715. printf("?Bad label syntax - '%s'n",s);
  2716. return(success = 0);
  2717.     }
  2718.     if (cmdlvl == 0) {
  2719. printf("?Sorry, %s only works in a command file or macron",cmd);
  2720. return(success = 0);
  2721.     }
  2722.     y = strlen(s); /* y = length of target label */
  2723.     debug(F111,cmd,s,y);
  2724.     while (cmdlvl > 0) { /* As long as not at top level... */
  2725. if (cmdstk[cmdlvl].src == CMD_MD) { /* GOTO inside macro */
  2726.     int i, m, flag;
  2727.     char *xp, *tp;
  2728.     /* GOTO: rewind the macro; FORWARD: start at current position */
  2729.     lp = (cx == XXGOTO) ? macx[maclvl] : macp[maclvl];
  2730.     m = (int)strlen(lp) - y + 1;
  2731.     debug(F111,"GOTO in macro",lp,m);
  2732.     flag = 1; /* flag for valid label position */
  2733.     for (i = 0; i < m; i++,lp++) { /* search for label in macro body */
  2734. if (*lp == '{') /* But only at this level */
  2735.   bc++; /* Anything inside braces is off */
  2736. else if (*lp == '}') /* limits. */
  2737.   bc--;
  2738. if (stopflg && bc > 0) /* This is good for SWITCH */
  2739.   continue; /* but interferes with WHILE, etc. */
  2740. if (*lp == ',') {
  2741.     flag = 1;
  2742.     continue;
  2743. }
  2744. if (flag) { /* If in valid label position */
  2745.     if (*lp == SP) /* eat leading spaces */
  2746.       continue;
  2747.     if (*lp != ':') { /* Look for label introducer */
  2748. flag = 0; /* this isn't it */
  2749. continue; /* keep looking */
  2750.     }
  2751. }
  2752. if (!flag) /* We don't have a label */
  2753.   continue; /*  so keep looking... */
  2754. xp = lp; tp = tmplbl; /* Copy the label from the macro */
  2755. j = 0; /* to make it null-terminated */
  2756. while (*tp = *xp) {
  2757.     if (j++ > LBLMAXLEN) /* j = length of word from macro */
  2758.       break;
  2759.     if (*tp < 33 || *tp == ',') /* Look for end of word */
  2760.       break;
  2761.     else tp++, xp++; /* Next character */
  2762. }
  2763. *tp = NUL; /* In case we stopped early */
  2764. /* Now do caseless string comparison, using longest length */
  2765. debug(F111,"macro GOTO label",s,y);
  2766. debug(F111,"macro target label",tmplbl,j);
  2767. if (stopflg) { /* Allow variables as SWITCH labels */
  2768.     int n = LBLMAXLEN - 1;
  2769.     char * p = tmp2;
  2770.     zzstring(tmplbl,&p,&n);
  2771.     ckstrncpy(tmplbl,tmp2,LBLMAXLEN);
  2772.     tmp2[49] = NUL;
  2773. }
  2774. debug(F111,"GOTO s",s,y);
  2775. debug(F111,"GOTO tmplbl",tmplbl,j);
  2776. if (stopflg) {
  2777.     z = ckmatch(tmplbl,s,inpcas[cmdlvl],1) ? 0 : 1;
  2778. } else {
  2779.     z = (stopflg && inpcas[cmdlvl]) ?
  2780.       strcmp(s,tmplbl) :
  2781. ckstrcmp(s,tmplbl,(y > j) ? y : j, 0);
  2782. }
  2783. if (!z)
  2784.   break;
  2785. else if (stopflg &&
  2786.  !ckstrcmp(":default",tmplbl,(8 > j) ? 8 : j, 0))
  2787.   break;
  2788. else
  2789.   flag = 0;
  2790.     }
  2791.     debug(F111,"GOTO macro i",cmd,i);
  2792.     debug(F111,"GOTO macro m",cmd,m);
  2793.     if (i >= m) { /* Didn't find the label */
  2794. debug(F101,"GOTO failed cmdlvl","",cmdlvl);
  2795. if (stopflg)
  2796.   return(0);
  2797. if ((maclvl > 0) &&
  2798.        (m_arg[maclvl-1][0]) &&
  2799.        (cmdstk[cmdlvl].src == CMD_MD) &&
  2800.        (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
  2801. !strncmp(m_arg[maclvl-1][0],"_for",4) ||
  2802. !strncmp(m_arg[maclvl-1][0],"_swi",4) ||
  2803. !strncmp(m_arg[maclvl-1][0],"_whi",4))) {
  2804.     dogta(XXPTA); /* Restore args */
  2805.     debug(F101,"GOTO in XIF/FOR/WHI/SWI popping","",cmdlvl);
  2806.     popclvl(); /* Pop an extra level */
  2807. }
  2808. debug(F101,"GOTO popping","",cmdlvl);
  2809. if (!popclvl()) { /* pop up to next higher level */
  2810.     printf("?Label '%s' not foundn",s); /* if none */
  2811.     return(0); /* quit */
  2812. } else continue; /* otherwise look again */
  2813.     }
  2814.     debug(F110,"GOTO found macro label",tmplbl,0);
  2815.     macp[maclvl] = lp; /* set macro buffer pointer */
  2816.     return(1);
  2817. } else if (cmdstk[cmdlvl].src == CMD_TF) {
  2818.     x = 0; /* GOTO issued in take file */
  2819.     debug(F111,"GOTO in TAKE file",cmd,cx);
  2820.     if (cx == XXGOTO) { /* If GOTO, but not FORWARD, */
  2821. rewind(tfile[tlevel]); /* search file from beginning */
  2822. tfline[tlevel] = 0;
  2823.     }
  2824.     while (! feof(tfile[tlevel])) {
  2825. if (fgets(line,LINBUFSIZ,tfile[tlevel]) == NULL) /* Get line */
  2826.   break; /* If no more, done, label not found */
  2827. tfline[tlevel]++;
  2828. lp = line; /* Got line */
  2829. while (*lp == SP || *lp == HT)
  2830.   lp++; /* Strip leading whitespace */
  2831. if (*lp != ':') continue; /* Check for label introducer */
  2832. tp = lp; /* Get end of word */
  2833. j = 0;
  2834. while (*tp) { /* And null-terminate it */
  2835.     if (*tp < 33) {
  2836. *tp = NUL;
  2837. break;
  2838.     } else tp++, j++;
  2839. }
  2840. if (!ckstrcmp(lp,s,(y > j) ? y : j,0)) { /* Caseless compare */
  2841.     x = 1; /* Got it */
  2842.     break; /* done. */
  2843. } else if (stopflg &&
  2844.    !ckstrcmp(":default",tmplbl,(8 > j) ? 8 : j,0)) {
  2845.     x = 1;
  2846.     break;
  2847. }
  2848.     }
  2849.     if (x == 0) { /* If not found, print message */
  2850. debug(F101,"GOTO failed at cmdlvl","",cmdlvl);
  2851. if (stopflg)
  2852.   return(0);
  2853. if (!popclvl()) { /* pop up to next higher level */
  2854.     printf("?Label '%s' not foundn",s); /* if none */
  2855.     return(0); /* quit */
  2856. } else continue; /* otherwise look again */
  2857.     }
  2858.     return(x); /* Send back return code */
  2859. }
  2860.     }
  2861.     printf("?Stack problem in GOTO %sn",s); /* Shouldn't see this */
  2862.     return(0);
  2863. }
  2864. #endif /* NOSPL */
  2865. /* Finish parsing and do the IF, XIF, and WHILE commands */
  2866. #ifndef NOSPL
  2867. /*  C H K V A R  --  Check (if it's a) Variable  */
  2868. #ifdef OLDCHKVAR
  2869. /*
  2870.   Crude and disgusting, but needed for OS/2, DOS, and Windows, where filenames
  2871.   have backslashes in them.  How do we know if a backslash in a filename is a
  2872.   directory separator, or if it's a Kermit backslash?  This routine does a
  2873.   rough syntax check of the next few characters and if it looks like it MIGHT
  2874.   be a variable, then it tries to evaluate it, and if the result is not empty,
  2875.   we say it's a variable, although sometimes it might not be -- some cases are
  2876.   truly ambiguous.  For example there might a DOS directory called %a, and
  2877.   we also have a variable with the same name.  This is all for the sake of not
  2878.   having to tell PC users that they have to double all backslashes in file
  2879.   and directory names.
  2880. */
  2881. #else
  2882. /*
  2883.   Somewhat less crude & disgusting.  The previous method was nondeterministic
  2884.   and (worse) it interfered with macro argument passing.  So now we only
  2885.   check the syntax of backslash-items to see if they are variables, but we
  2886.   do NOT check their values.
  2887. */
  2888. #endif /* OLDCHKVAR */
  2889. /*
  2890.   Call with a string pointer pointing at the backslash of the purported
  2891.   variable.  Returns 1 if it has the syntax of a variable, 0 if not.
  2892. */
  2893. int
  2894. chkvar(s) char *s; {
  2895.     int z = 0; /* Return code - assume failure. */
  2896.     if (!s) s = ""; /* Watch our for null pointers. */
  2897.     if (!*s) return(0); /* Empty arg so not a variable. */
  2898.     if (*s == CMDQ) { /* Object begins with backslash. */
  2899. char c;
  2900. c = s[1]; /* Character following backslash. */
  2901. if (c) {
  2902.     int t = 0;
  2903.     if (c == CMDQ) /* Quoted backslash */
  2904.       return(1);
  2905.     c = (char) (islower(c) ? toupper(c) : c); /* Otherwise... */
  2906.     if (c == '%') { /* Simple variable */
  2907. #ifdef OLDCHKVAR
  2908. t = 1;
  2909. #else
  2910. return(1);
  2911. #endif /* OLDCHKVAR */
  2912.     } else if (c == '&') { /* Array */
  2913. if (s[3] == '[')
  2914.   t = ckindex("]",s,4,0,1);
  2915. #ifndef OLDCHKVAR
  2916. return((t > 0) ? 1 : 0);
  2917. #endif /* OLDCHKVAR */
  2918.     } else if (c == '$' || /* Environment variable */
  2919.        c == 'V' || /* Built-in variable */
  2920.        c == 'M') { /* Macro name */
  2921.         t = (s[2] == '(');
  2922. #ifndef OLDCHKVAR
  2923. return((t > 0) ? 1 : 0);
  2924. #endif /* OLDCHKVAR */
  2925.     } else if (c == 'F') { /* Function reference */
  2926. /* Don't actually call it - it might have side effects */
  2927. int x;
  2928. if (x = ckindex("(",s,3,0,1)) /* Just check syntax */
  2929.   if (x = ckindex(")",s,x,0,1))
  2930.     z = 1;
  2931. /* Insert a better syntax check here if necessary */
  2932.     }
  2933. #ifdef OLDCHKVAR
  2934.     if (t) {
  2935. t = 255; /* This lets us test v(xxx) */
  2936. lp = line; /* and even f...(xxx) */
  2937. zzstring(s,&lp,&t); /* Evaluate it, whatever it is. */
  2938. t = strlen(line); /* Get its length. */
  2939. debug(F111,"chkvar",line,t);
  2940. z = t > 0; /* If length > 0, it's defined */
  2941.     }
  2942. #endif /* OLDCHKVAR */
  2943. }
  2944.     }
  2945.     return(z);
  2946. }
  2947. /*  B O O L E X P  --  Evaluate a Boolean expression  */
  2948. #define BOOLLEN 1024
  2949. static char boolval[BOOLLEN];
  2950. int
  2951. boolexp(cx) int cx; {
  2952.     int x, y, z; char *s, *p;
  2953.     int parens = 0, pcount = 0, ecount = 0;
  2954.     extern int cmfldflgs;
  2955.     char *q, *bx;
  2956.     struct FDB kw, nu, fl;
  2957. #ifdef FNFLOAT
  2958.     CKFLOAT f1 = 0.0, f2 = 0.0;
  2959.     int f1flag = 0, f2flag = 0;
  2960. #endif /* FNFLOAT */
  2961. #ifdef OS2
  2962.     extern int keymac;
  2963. #endif /* OS2 */
  2964.     not = 0; /* Flag for whether "NOT" was seen */
  2965.     z = 0; /* Initial IF condition */
  2966.     ifargs = 0; /* Count of IF condition words */
  2967.     bx = boolval; /* Initialize boolean value */
  2968.     *bx = NUL;
  2969.   ifagain:
  2970.     cmfdbi(&kw, /* First FDB - command switches */
  2971.    _CMKEY, /* fcode */
  2972.    "Number, numeric-valued variable, Boolean expression, or keyword",
  2973.    "", /* default */
  2974.    "", /* addtl string data */
  2975.    nif, /* addtl numeric data 1: tbl size */
  2976.    0, /* addtl numeric data 2: 4 = silent */
  2977.    xxstring, /* Processing function */
  2978.    iftab, /* Keyword table */
  2979.    &nu /* Pointer to next FDB */
  2980.    );
  2981.     cmfdbi(&nu, /* 2nd FDB - An integer */
  2982.    _CMNUM, /* fcode */
  2983.    "", /* hlpmsg */
  2984.    "", /* Default */
  2985.    "", /* addtl string data */
  2986.    0,
  2987.    0,
  2988.    xxstring,
  2989.    NULL,
  2990. #ifndef FNFLOAT
  2991.    &fl
  2992. #else
  2993.    NULL
  2994. #endif /* FNFLOAT */
  2995.    );
  2996. #ifndef FNFLOAT
  2997.     cmfdbi(&fl, /* A floating-point number */
  2998.    _CMFLD, /* fcode */
  2999.    "", /* hlpmsg */
  3000.    "", /* default */
  3001.    "", /* addtl string data */
  3002.    0, /* addtl numeric data 1 */
  3003.    0, /* addtl numeric data 2 */
  3004.    xxstring,
  3005.    NULL,
  3006.    NULL
  3007.    );
  3008. #endif /* FNFLOAT */
  3009.     x = cmfdb(&kw); /* Parse a keyword or a number */
  3010.     if (x < 0) {
  3011. if (x == -3)
  3012.   x = -2;
  3013. return(x);
  3014.     }
  3015.     debug(F111,"boolval switch","",cmresult.fcode);
  3016.     switch (cmresult.fcode) { /* What did we get? */
  3017. #ifdef FNFLOAT
  3018.       case _CMFLD: /* A "field" */
  3019. if (isfloat(cmresult.sresult,0)) { /* A floating-point number? */
  3020.     f1 = floatval; /* Yes, get its value */
  3021.     f1flag = 1; /* remember we did this */
  3022.     ifc = 9999; /* Set special "if-code" */
  3023. } else
  3024.   return(-2);
  3025. #endif /* FNFLOAT */
  3026.       case _CMNUM: /* A number... */
  3027. ifc = 9999; /* Set special "if-code" */
  3028. break;
  3029.       case _CMKEY: /* A keyword */
  3030. ifc = cmresult.nresult; /* Get if-code */
  3031. break;
  3032.       default:
  3033. return(-2);
  3034.     }
  3035.     switch (ifc) { /* set z = 1 for true, 0 for false */
  3036.       case 9999: /* Number */
  3037. #ifdef FNFLOAT
  3038. if (f1flag) {
  3039.     z = (f1 == 0.0) ? 0 : 1;
  3040. } else
  3041. #endif /* FNFLOAT */
  3042. z = (cmresult.nresult == 0) ? 0 : 1;
  3043. break;
  3044.       case XXIFLP: /* Left paren */
  3045. if (pcount == 0 && ifargs > 0)
  3046.   return(-2);
  3047. parens = 1;
  3048. pcount++;
  3049. ifargs++;
  3050. *bx++ = '(';
  3051. goto ifagain;
  3052.       case XXIFRP: /* Right paren */
  3053. if (!parens)
  3054.   return(-2);
  3055. if (--pcount < 0)
  3056.   return(-2);
  3057. ifargs++;
  3058. *bx++ = ')';
  3059. *bx = NUL;
  3060. if (pcount == 0)
  3061.   goto ifend;
  3062. goto ifagain;
  3063.       case XXIFAN: /* AND (&&) */
  3064. ifargs++;
  3065. if (!ecount)
  3066.   return(-2);
  3067. *bx++ = '&';
  3068. goto ifagain;
  3069.       case XXIFOR: /* OR (||) */
  3070. ifargs++;
  3071. if (!ecount)
  3072.   return(-2);
  3073. *bx++ = '|';
  3074. goto ifagain;
  3075.       case XXIFNO: /* IF NOT [ NOT [ NOT ... ] ] */
  3076. if (bx > boolval) { /* evala() doesn't like cascaded */
  3077.     if (*(bx-1) == '!') { /* unary operators... */
  3078. *(bx-1) = NUL; /* So here, two wrongs make a right. */
  3079. bx--;
  3080.     } else {
  3081. *bx++ = '!';
  3082.     }
  3083. } else {
  3084.     *bx++ = '!';
  3085. }
  3086. ifargs++;
  3087. goto ifagain;
  3088.       case XXIFTR: /* IF TRUE */
  3089. z = 1;
  3090. debug(F101,"if true","",z);
  3091. ifargs += 1;
  3092. break;
  3093.       case XXIFNT: /* IF FALSE */
  3094. z = 0;
  3095. debug(F101,"if true","",z);
  3096. ifargs += 1;
  3097. break;
  3098.       case XXIFSU: /* IF SUCCESS */
  3099. z = ( success != 0 ) ? 1 : 0;
  3100. debug(F101,"if success","",z);
  3101. ifargs += 1;
  3102. break;
  3103.       case XXIFFA: /* IF FAILURE */
  3104. z = ( success == 0 ) ? 1 : 0;
  3105. debug(F101,"if failure","",z);
  3106. ifargs += 1;
  3107. break;
  3108.       case XXIFDE: /* IF DEFINED */
  3109. if ((x = cmfld("Macro or variable name","",&s,NULL)) < 0) {
  3110.     if (x == -3) return(-2);
  3111.     else return(x);
  3112. }
  3113. if (*s == CMDQ) {
  3114.     z = chkvar(s); /* Starts with backslash */
  3115.     if (z > 0) { /* Yes... */
  3116. int t, x; /* Get its value into a local buffer */
  3117. char * lp;
  3118. char line[256]; /* Note that value might be longer */
  3119. t = 255; /* than buffer so if zzstring fails  */
  3120. lp = line; /* check for that -- overflow means */
  3121. line[0] = NUL; /* the quantity is defined. */
  3122. x = zzstring(s,&lp,&t);
  3123. if ((x < 0 && t != 255) || !line[0])
  3124.   z = 0;
  3125. debug(F111,"if defined zzstring",line,z);
  3126. debug(F101,"if defined zzstring t","",t);
  3127.     }
  3128. } else {
  3129.     z = (mxlook(mactab,s,nmac) > -1); /* Look for exact match */
  3130. }
  3131. debug(F111,"if defined final",s,z);
  3132. ifargs += 2;
  3133. break;
  3134.       case XXIFBG: /* IF BACKGROUND */
  3135.       case XXIFFG: /* IF FOREGROUND */
  3136. bgchk(); /* Check background status */
  3137. if (ifc == XXIFFG) /* Foreground */
  3138.   z = pflag ? 1 : 0;
  3139.         else z = pflag ? 0 : 1; /* Background */
  3140. ifargs += 1;
  3141. break;
  3142.       case XXIFCO: /* IF COUNT */
  3143. z = ( --count[cmdlvl] > 0 );
  3144. if (cx == XXWHI) count[cmdlvl] += 2; /* Don't ask... */
  3145. debug(F101,"if count","",z);
  3146. ifargs += 1;
  3147. break;
  3148.       case XXIFEX: /* IF EXIST */
  3149. #ifdef CK_TMPDIR
  3150.       case XXIFDI: /* IF DIRECTORY */
  3151. #endif /* CK_TMPDIR */
  3152.       case XXIFAB: /* IF ABSOLUTE */
  3153. if ((x = cmfld(
  3154.        ((ifc == XXIFDI) ? "Directory name" : "File"),
  3155.        "",&s,
  3156. #ifdef OS2
  3157.        NULL /* This allows 's in filenames */
  3158. #else
  3159.        xxstring
  3160. #endif /* OS2 */
  3161.        )) < 0) {
  3162.     if (x == -3) {
  3163. extern int cmflgs;
  3164. if (cmflgs == 1) {
  3165.     printf("?File or directory name requiredn");
  3166.     return(-9);
  3167. }
  3168.     } else return(x);
  3169. }
  3170. s = brstrip(s);
  3171. if (ifc == XXIFAB) {
  3172.     z = isabsolute(s);
  3173. } else if (ifc == XXIFEX) {
  3174.     z = (zchki(s) > -1L);
  3175.     debug(F101,"if exist 1","",z);
  3176. #ifdef OS2
  3177.     if (!z) { /* File not found. */
  3178. int t; /* Try expanding variables */
  3179. t = LINBUFSIZ-1; /* and looking again. */
  3180. lp = line;
  3181. zzstring(s,&lp,&t);
  3182. s = line;
  3183. z = ( zchki(s) > -1L );
  3184. debug(F101,"if exist 2","",z);
  3185.     }
  3186. #endif /* OS2 */
  3187. #ifdef CK_TMPDIR
  3188. } else {
  3189. #ifdef VMS
  3190.     z = (zchki(s) == -2)
  3191. #else
  3192. /* Because this doesn't catch $DISK1:[FOO]BLAH.DIR;1 */
  3193.     z = isdir(s)
  3194. #ifdef OS2
  3195.       || (isalpha(s[0]) && s[1] == ':' && s[2] == NUL)
  3196. #endif /* OS2 */
  3197. #endif /* VMS */
  3198.       ;
  3199.     debug(F101,"if directory 1","",z);
  3200.     if (!z) { /* File not found. */
  3201. int t; /* Try expanding variables */
  3202. t = LINBUFSIZ-1; /* and looking again. */
  3203. lp = line;
  3204. zzstring(s,&lp,&t);
  3205. s = line;
  3206. z = isdir(s)
  3207. #ifdef OS2
  3208.   || (isalpha(s[0]) && s[1] == ':' && s[2] == NUL)
  3209. #endif /* OS2 */
  3210.     ;
  3211. debug(F101,"if directory 2","",z);
  3212.     }
  3213. #endif /* CK_TMPDIR */
  3214. }
  3215. ifargs += 2;
  3216. break;
  3217.       case XXIFEQ:  /* IF EQUAL (string comparison) */
  3218.       case XXIFLL: /* IF Lexically Less Than */
  3219.       case XXIFLG: /* If Lexically Greater Than */
  3220. if ((x = cmfld("first word or variable name","",&s,xxstring)) < 0) {
  3221.     if (x == -3) {
  3222. printf("?Text requiredn");
  3223. return(-9);
  3224.     } else return(x);
  3225. }
  3226. s = brstrip(s); /* Strip braces */
  3227. x = (int)strlen(s);
  3228. if (x > LINBUFSIZ-1) {
  3229.     printf("?IF: strings too longn");
  3230.     return(-2);
  3231. }
  3232. lp = line; /* lp points to first string */
  3233.         ckstrncpy(line,s,LINBUFSIZ);
  3234. if ((y = cmfld("second word or variable name","",&s,xxstring)) < 0) {
  3235.     if (y == -3) {
  3236. printf("?Text requiredn");
  3237. return(-9);
  3238.     } else return(y);
  3239. }
  3240. s = brstrip(s);
  3241. y = (int)strlen(s);
  3242. if (x + y + 2 > LINBUFSIZ) {
  3243.     printf("?IF: strings too longn");
  3244.     return(-2);
  3245. }
  3246. tp = lp + x + 2; /* tp points to second string */
  3247. strcpy(tp,s);
  3248. x = ckstrcmp(lp,tp,-1,inpcas[cmdlvl]); /* Use longest length */
  3249. switch (ifc) {
  3250.   case XXIFEQ:  /* IF EQUAL (string comparison) */
  3251.     z = (x == 0);
  3252.     break;
  3253.   case XXIFLL: /* IF Lexically Less Than */
  3254.     z = (x < 0);
  3255.     break;
  3256.   case XXIFLG: /* If Lexically Greater Than */
  3257.     z = (x > 0);
  3258.     break;
  3259. }
  3260. debug(F101,"IF EQ result","",z);
  3261. ifargs += 3;
  3262. break;
  3263.       case XXIFAE: /* IF (arithmetically) = */
  3264.       case XXIFNQ: /* IF != (not arithmetically equal) */
  3265.       case XXIFLT: /* IF <  */
  3266.       case XXIFLE: /* IF <= */
  3267.       case XXIFGE: /* IF >= */
  3268.       case XXIFGT: { /* IF >  */
  3269. /* Really should use longs here... */
  3270. /* But cmnum parses ints. */
  3271. int n1 = 0, n2 = 0;
  3272. x = cmfld("first number or variable name","",&s,xxstring);
  3273. if (x == -3) {
  3274.     printf("?Quantity requiredn");
  3275.     return(-9);
  3276. }
  3277. if (x < 0) return(x);
  3278. debug(F101,"xxifgt cmfld","",x);
  3279. lp = line;
  3280.         ckstrncpy(line,s,LINBUFSIZ);
  3281. debug(F110,"xxifgt exp1",lp,0);
  3282. /* The following bit is for compatibility with old versions of MS-DOS Kermit */
  3283. if (!ckstrcmp(lp,"count",5,0)) {
  3284.     n1 = count[cmdlvl];
  3285. } else if (!ckstrcmp(lp,"version",7,0)) {
  3286.     n1 = (int) vernum;
  3287. } else if (!ckstrcmp(lp,"argc",4,0)) {
  3288.     n1 = (int) macargc[maclvl];
  3289. } else {
  3290. /* End of compatibility bit */
  3291. #ifdef FNFLOAT
  3292.     /* Allow floating-point comparisons. */
  3293.     /* ckstrchr() test is used in addition to isfloat() since */
  3294.     /* isfloat() succeeds also for integers and we don't want to */
  3295.     /* do floating-point comparisons unless we have to. */
  3296.     if (ckstrchr(lp,'.') && isfloat(lp,0)) {
  3297. f1 = floatval;
  3298. f1flag = 1;
  3299.     } else
  3300. #endif /* FNFLOAT */
  3301.     if (chknum(lp)) {
  3302. n1 = atoi(lp);
  3303.     } else { /* Check for arithmetic expression */
  3304. q = evala(lp); /* cmnum() does this but ... */
  3305. if (chknum(q)) /* we're not using cmnum(). */
  3306.   n1 = atoi(q);
  3307. else
  3308.   return(-2);
  3309.     }
  3310. }
  3311. y = cmfld("second number or variable name","",&s,xxstring);
  3312. if (y == -3) {
  3313.     printf("?Quantity requiredn");
  3314.     return(-9);
  3315. }
  3316. if (y < 0) return(y);
  3317.         if ((int)strlen(s) < 1) return(-2);
  3318. x = (int)strlen(lp);
  3319. tp = line + x + 2;
  3320. strcpy(tp,s);
  3321. debug(F110,"xxifgt exp2",tp,0);
  3322. if (!ckstrcmp(tp,"count",5,0)) {
  3323.     n2 = count[cmdlvl];
  3324. } else if (!ckstrcmp(tp,"version",7,0)) {
  3325.     n2 = (int) vernum;
  3326. } else if (!ckstrcmp(tp,"argc",4,0)) {
  3327.     n2 = (int) macargc[maclvl];
  3328. } else {
  3329. #ifdef FNFLOAT
  3330.     if (ckstrchr(lp,'.') && isfloat(tp,0)) {
  3331. f2 = floatval;
  3332. f2flag = 1;
  3333.     } else
  3334. #endif /* FNFLOAT */
  3335.     if (chknum(tp)) {
  3336. n2 = atoi(tp);
  3337.     } else {
  3338. q = evala(tp);
  3339. if (chknum(q))
  3340.   n2 = atoi(q);
  3341. else
  3342.   return(-2);
  3343.     }
  3344. }
  3345. debug(F101,"xxifft ifc","",ifc);
  3346. #ifdef FNFLOAT
  3347. if (f1flag && !f2flag) {
  3348.     f2 = (CKFLOAT)n2;
  3349.     f2flag = 1;
  3350. }
  3351. if (f2flag && !f1flag)
  3352.   f1 = (CKFLOAT)n1;
  3353. if (f1flag)
  3354.   z = ((f1 <  f2 && ifc == XXIFLT)
  3355.        || (f1 != f2 && ifc == XXIFNQ)
  3356.        || (f1 <= f2 && ifc == XXIFLE)
  3357.        || (f1 == f2 && ifc == XXIFAE)
  3358.        || (f1 >= f2 && ifc == XXIFGE)
  3359.        || (f1 >  f2 && ifc == XXIFGT));
  3360. else
  3361. #endif /* FNFLOAT */
  3362.   z = ((n1 <  n2 && ifc == XXIFLT)
  3363.        || (n1 != n2 && ifc == XXIFNQ)
  3364.        || (n1 <= n2 && ifc == XXIFLE)
  3365.        || (n1 == n2 && ifc == XXIFAE)
  3366.        || (n1 >= n2 && ifc == XXIFGE)
  3367.        || (n1 >  n2 && ifc == XXIFGT));
  3368. debug(F101,"xxifft z","",z);
  3369. ifargs += 3;
  3370. break; }
  3371.       case XXIFNU: /* IF NUMERIC */
  3372. x = cmfld("variable name or constant","",&s,NULL);
  3373. if (x == -3) {
  3374.     extern int cmflgs;
  3375.     if (cmflgs == 1) {
  3376. printf("?Quantity requiredn");
  3377. return(-9);
  3378.     }
  3379. } else if (x < 0)
  3380.   return(x);
  3381. x = LINBUFSIZ-1;
  3382. lp = line;
  3383. zzstring(s,&lp,&x);
  3384. lp = line;
  3385. debug(F110,"xxifnu quantity",lp,0);
  3386.         z = chknum(lp);
  3387. #ifdef COMMENT
  3388. /*
  3389.   This works, but it's not wise -- IF NUMERIC is mostly used to see if a
  3390.   string really does contain only numeric characters.  If they want to force
  3391.   evaluation, they can use feval() on the argument string.
  3392. */
  3393. if (!z) { /* Not a number */
  3394.     x_ifnum = 1; /* Avoid "eval" error messages */
  3395.     q = evala(lp); /* Maybe it's an expression */
  3396.     z = chknum(q); /* that evaluates to a number */
  3397.     x_ifnum = 0; /* Put eval messages back to normal */
  3398.     if (z) debug(F110,"xxifnu exp",lp,0);
  3399. }
  3400. #endif /* COMMENT */
  3401.         debug(F101,"xxifnu chknum","",z);
  3402. ifargs += 2;
  3403. break;
  3404. #ifdef ZFCDAT
  3405.       case XXIFNE: { /* IF NEWER */
  3406. char d1[20], * d2; /* Buffers for 2 dates */
  3407. if ((z = cmifi("First file","",&s,&y,xxstring)) < 0)
  3408.   return(z);
  3409. strcpy(d1,zfcdat(s));
  3410. if ((z = cmifi("Second file","",&s,&y,xxstring)) < 0)
  3411.   return(z);
  3412. d2 = zfcdat(s);
  3413. if ((int)strlen(d1) != 17 || (int)strlen(d2) != 17) {
  3414.     printf("?Failure to get file daten");
  3415.     return(-9);
  3416. }
  3417. debug(F110,"xxifnewer d1",d1,0);
  3418. debug(F110,"xxifnewer d2",d2,0);
  3419. z = (strcmp(d1,d2) > 0) ? 1 : 0;
  3420.         debug(F101,"xxifnewer","",z);
  3421. ifargs += 2;
  3422. break;
  3423.       }
  3424. #endif /* ZFCDAT */
  3425. #ifdef CK_IFRO
  3426.       case XXIFRO: /* REMOTE-ONLY advisory */
  3427. ifargs++;
  3428. #ifdef NOLOCAL
  3429. z = 1;
  3430. #else
  3431. z = remonly;
  3432. #endif /* NOLOCAL */
  3433. break;
  3434. #endif /* CK_IFRO */
  3435.       case XXIFAL: /* ALARM */
  3436. ifargs++;
  3437. debug(F101,"IF ALARM ck_alarm","",ck_alarm);
  3438. debug(F110,"IF ALARM alrm_date",alrm_date,0);
  3439. debug(F110,"IF ALARM alrm_time",alrm_time,0);
  3440. if (ck_alarm < 1L || alrm_date[0] < '0' || alrm_time[0] < '0') {
  3441.     z = 0; /* ALARM not SET */
  3442.     break; /* so IF ALARM fails */
  3443. }
  3444. strcpy(tmpbuf,ckcvtdate("",1)); /* Get current date and time */
  3445. s = tmpbuf;
  3446. s[8] = NUL;
  3447. z = (int) strncmp(tmpbuf,alrm_date,8); /* Compare dates */
  3448. debug(F101,"IF ALARM date z","",z);
  3449. if (z == 0) { /* Dates are the same */
  3450.     /* Compare times */
  3451.     z = (tod2sec(tmpbuf+9) >= atol(alrm_time)) ? 1 : -1;
  3452.     debug(F101,"IF ALARM time z","",z);
  3453. }
  3454. tmpbuf[0] = NUL; /* z >= 0 if alarm is passed */
  3455. z = ((z >= 0) ? 1 : 0); /* z <  0 otherwise */
  3456. debug(F101,"IF ALARM final z","",z);
  3457. break;
  3458.       case XXIFOP: /* IF OPEN */
  3459. if ((x = cmkey(iotab,niot,"file or log","",xxstring)) < 0)
  3460.   return(x);
  3461. if (x == 9999 || x == ZSTDIO) {
  3462.     bgchk(); /* Check background status */
  3463.     z = pflag ? 1 : 0;
  3464. } else if (x == 8888) {
  3465.     z = local ? ttchk() > -1 : 0;
  3466. #ifdef CKLOGDIAL
  3467.         } else if (x == 7777) {
  3468.     extern int dialog;
  3469.     z = dialog ? 1 : 0;
  3470. #endif /* CKLOGDIAL */
  3471. } else
  3472.   z = (chkfn(x) > 0) ? 1 : 0;
  3473. ifargs += 1;
  3474. break;
  3475. #ifdef OS2
  3476.       case XXIFSD: /* Started-From-Dialer */
  3477. ifargs++;
  3478. z = StartedFromDialer;
  3479. break;
  3480.       case XXIFTM: /* Terminal-Macro */
  3481. ifargs++;
  3482. z = cmdstk[cmdlvl].ccflgs & CF_KMAC;
  3483. break;
  3484. #endif /* OS2 */
  3485.       case XXIFEM: /* Emulation is active */
  3486. #ifdef OS2
  3487. z = 1;
  3488. #else
  3489. z = 0;
  3490. #endif /* OS2 */
  3491. break;
  3492.       case XXIFIK:                      /* Running as IKSD? */
  3493.         z = inserver;
  3494.         break;
  3495.       case XXIFTA: /* Connection is TAPI */
  3496. z = 0;
  3497. #ifdef NT
  3498. if (local && !network && tttapi)
  3499.   z = 1;
  3500. #endif /* NT */
  3501. break;
  3502.       case XXIFMA: /* IF MATCH */
  3503. x = cmfld("String or variable","",&s,xxstring);
  3504. if (x == -3) {
  3505.     extern int cmflgs;
  3506.     if (cmflgs == 1) {
  3507. printf("?String requiredn");
  3508. return(-9);
  3509.     }
  3510. } else if (x < 0)
  3511.   return(x);
  3512. ckstrncpy(line,s,LINBUFSIZ);
  3513. s = brstrip(line);
  3514. debug(F110,"xxifma string",line,0);
  3515. x = cmfld("Pattern","",&p,xxstring);
  3516. if (x == -3) {
  3517.     extern int cmflgs;
  3518.     if (cmflgs == 1) {
  3519. printf("?Pattern requiredn");
  3520. return(-9);
  3521.     }
  3522. } else if (x < 0)
  3523.   return(x);
  3524. ckstrncpy(tmpbuf,p,TMPBUFSIZ);
  3525. p = brstrip(tmpbuf);
  3526. debug(F110,"xxifma pattern",tmpbuf,0);
  3527. z = ckmatch(p,s,inpcas[cmdlvl],1);
  3528. break;
  3529.       case XXIFFL: { /* IF FLAG */
  3530.   extern int ooflag;
  3531.   z = ooflag;
  3532.   break;
  3533.       }
  3534.       case XXIFAV: { /* IF AVAILABLE */
  3535.   if ((x = cmkey(availtab,availtabn,"","",xxstring)) < 0)
  3536.     return(x);
  3537.   switch (x) {
  3538.     case AV_KRB4:
  3539.               z = ck_krb4_is_installed();
  3540.               break;
  3541.     case AV_KRB5:
  3542.               z = ck_krb5_is_installed();
  3543.               break;
  3544.             case AV_SRP:
  3545.               z = ck_srp_is_installed();
  3546.               break;
  3547.             case AV_SSL:
  3548.               z = ck_ssleay_is_installed();
  3549.       break;
  3550.             case AV_NTLM:
  3551.               z = ck_ntlm_is_installed();
  3552.       break;
  3553.             case AV_CRYPTO:
  3554.       z = ck_crypt_is_installed();
  3555.       break;
  3556.     default:
  3557.               z = 0;
  3558.   }
  3559.   break;
  3560.       }
  3561.       case XXIFAT: /* IF ASKTIMEOUT */
  3562. z = asktimedout;
  3563. break;
  3564.       case XXIFRD: /* IF READABLE */
  3565.       case XXIFWR: /* IF WRITEABLE */
  3566. if ((x = cmfld("File or directory name",
  3567.        "",
  3568.        &s,
  3569. #ifdef OS2
  3570.        NULL /* This allows 's in filenames */
  3571. #else
  3572.        xxstring
  3573. #endif /* OS2 */
  3574.        )) < 0) {
  3575.     if (x == -3) {
  3576. extern int cmflgs;
  3577. if (cmflgs == 1) {
  3578.     printf("?File or directory name requiredn");
  3579.     return(-9);
  3580. }
  3581.     } else return(x);
  3582. }
  3583. s = brstrip(s);
  3584. /*
  3585.   zchk[io]() do not do what we want here for directories, so we set
  3586.   a global flag telling it to behave specially in this case.  Othewise
  3587.   we'd have to change the API and change all ck?fio.c modules accordingly.
  3588. */
  3589. y = 0; /* Try-again control */
  3590. #ifdef OS2
  3591.   ifrdagain:
  3592. #endif /* OS2 */
  3593. if (ifc == XXIFRD) { /* IF READABLE */
  3594.     zchkid = 1;
  3595.     z = zchki(s) > -1;
  3596.     zchkid = 0;
  3597. } else if (ifc == XXIFWR) { /* IF WRITEABLE */
  3598.     zchkod = 1;
  3599.     z = zchko(s) > -1;
  3600.     zchkod = 0;
  3601. }
  3602. #ifdef OS2
  3603. if (!z && !y) { /* File not found. */
  3604.     int t; /* Try expanding variables */
  3605.     t = LINBUFSIZ-1; /* and looking again. */
  3606.     lp = line;
  3607.     zzstring(s,&lp,&t);
  3608.     s = line;
  3609.     z = zchko(s) > -1;
  3610.     y++;
  3611.     goto ifrdagain;
  3612. }
  3613. #endif /* OS2 */
  3614. ifargs += 2;
  3615. break;
  3616.       case XXIFQU: /* IF QUIET */
  3617. z = quiet ? 1 : 0;
  3618. debug(F101,"if quiet","",z);
  3619. ifargs += 1;
  3620. break;
  3621.       case XXIFWI: /* WILD */
  3622. if ((x = cmfld("File specification","",&s,xxstring)) < 0) return(x);
  3623. z = iswild(s);
  3624. break;
  3625.       case XXIFCK: /* C-KERMIT */
  3626. #ifdef OS2
  3627.         z = 0;
  3628. #else
  3629.         z = 1;
  3630. #endif /* OS2 */
  3631.         break;
  3632.       case XXIFK9: /* K-95 */
  3633. #ifdef OS2
  3634.         z = 1;
  3635. #else
  3636.         z = 0;
  3637. #endif /* OS2 */
  3638.         break;
  3639.       case XXIFMS: /* MS-KERMIT */
  3640.         z = 0;
  3641.         break;
  3642.       case XXIFLO: /* IF LOCAL */
  3643. z = local ? 1 : 0;
  3644.         break;
  3645.       case XXIFCM: { /* IF COMMAND */
  3646.   extern struct keytab cmdtab[];
  3647.   extern int ncmd;
  3648.   if ((x = cmfld("Word","",&s,xxstring)) < 0)
  3649.     return(x);
  3650.   z = lookup(cmdtab,s,ncmd,&y);
  3651.   z = (z == -2 || z > -1) ? 1 : 0;
  3652.   break;
  3653.       }
  3654. #ifdef CKFLOAT
  3655.       case XXIFFP: /* IF FLOAT */
  3656. if ((x = cmfld("Number","",&s,xxstring)) < 0)
  3657.   if (x != -3) /* e.g. empty variable */
  3658.     return(x);
  3659. z = isfloat(s,0);
  3660. break;
  3661. #endif /* CKFLOAT */
  3662.       default: /* Shouldn't happen */
  3663. return(-2);
  3664.     } /* end of switch */
  3665.     if (z)
  3666.       *bx++ = '1';
  3667.     else
  3668.       *bx++ = '0';
  3669.     *bx = NUL;
  3670.     if (bx > boolval + BOOLLEN - 2) {
  3671. printf("?Boolean expression too long");
  3672. return(-9);
  3673.     }
  3674.     ecount++; /* Expression counter */
  3675.     debug(F101,"boolexp parens","",parens);
  3676.     debug(F101,"boolexp pcount","",pcount);
  3677.     if (parens && pcount > 0)
  3678.       goto ifagain;
  3679.   ifend: /* No more - done */
  3680.     *bx = NUL;
  3681.     z = atoi(evalx(boolval));
  3682.     debug(F111,"boolexp boolval",boolval,z);
  3683.     return(z);
  3684. }
  3685. /*  D O I F  --  Do the IF command  */
  3686. int
  3687. doif(cx) int cx; {
  3688.     int x, y, z; char *s, *p;
  3689.     char *q;
  3690. #ifdef OS2
  3691.     extern int keymac;
  3692. #endif /* OS2 */
  3693.     debug(F101,"doif cx","",cx);
  3694.     z = boolexp(cx); /* Evaluate the condition(s) */
  3695.     debug(F101,"doif boolexp","",z);
  3696.     if (z < 0)
  3697.       return(z);
  3698.     if (cx == XXIF) { /* Allow IF to have XIF semantics. */
  3699. char * p;
  3700. p = cmpeek();
  3701. if (!p) p = "";
  3702. while (*p) {
  3703.     if (*p == SP || *p == HT)
  3704.       p++;
  3705.     else
  3706.       break;
  3707. }
  3708. if (*p == '{')
  3709.   cx = XXIFX;
  3710.     }
  3711.     switch (cx) { /* Separate handling for IF and XIF */
  3712.       case XXASSER: /* And ASSERT */
  3713. if ((x = cmcfm()) < 0)
  3714.   return(x);
  3715. return(success = z);
  3716.       case XXIF: /* This is IF... */
  3717. ifcmd[cmdlvl] = 1; /* We just completed an IF command */
  3718.         debug(F101,"doif condition","",z);
  3719. if (z) { /* Condition is true */
  3720.     iftest[cmdlvl] = 1; /* Remember that IF succeeded */
  3721.     if (maclvl > -1) { /* In macro, */
  3722. pushcmd(NULL); /* save rest of command. */
  3723.     } else if (tlevel > -1) { /* In take file, */
  3724. debug(F100, "doif: pushing command", "", 0);
  3725. pushcmd(NULL); /* save rest of command. */
  3726.     } else { /* If interactive, */
  3727. cmini(ckxech); /* just start a new command */
  3728. printf("n"); /* (like in MS-DOS Kermit) */
  3729. if (pflag) prompt(xxstring);
  3730.     }
  3731. } else { /* Condition is false */
  3732.     iftest[cmdlvl] = 0; /* Remember command failed. */
  3733.     if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0)
  3734.       return(y); /* Gobble up rest of line */
  3735. }
  3736. return(0);
  3737.       case XXIFX: { /* This is XIF (Extended IF) */
  3738.   char *p;
  3739.   char e[5];
  3740.   int i;
  3741.   if ((y = cmtxt("Object command","",&s,NULL)) < 0)
  3742.     return(y); /* Get object command. */
  3743.   p = s;
  3744.   lp = line;
  3745.   debug(F111,"doif THEN part 1",s,z);
  3746.   if (litcmd(&p,&lp,LINBUFSIZ - 1) < 0) { /* Quote THEN-part */
  3747.       return(-2);
  3748.   }
  3749.   debug(F111,"doif THEN part 2",line,z);
  3750.   while (*p == SP) p++; /* Strip trailing spaces */
  3751.   ifcmd[cmdlvl] = 0; /* Assume ELSE part in same line */
  3752.   iftest[cmdlvl] = z ? 1 : 0;
  3753.   if (*p) { /* At end? */
  3754.       if (!z) { /* No, use ELSE-part, if any */
  3755.   for (i = 0; i < 4; i++) e[i] = *p++;
  3756.   if (ckstrcmp(e,"else",4,0)) /* See if we have an ELSE */
  3757.     return(-2); /* Something else - error. */
  3758.   debug(F110,"doif ELSE line 1",p,0);
  3759.   while (*p == SP) p++; /* Skip spaces */
  3760.   if (*p != '{') { /* Brace ELSE part if necessary */
  3761.       sprintf(tmpbuf,"{ %s }",p);
  3762.                       p = tmpbuf;
  3763.       debug(F110,"doif ELSE line 2",p,0);
  3764.   }
  3765.   lp = line; /* Write over THEN part... */
  3766.   *lp = NUL; /* with ELSE part. */
  3767.   if (litcmd(&p,&lp,LINBUFSIZ - 2) < 0) {
  3768.       return(-2);
  3769.   }
  3770.   while (*p == SP) p++; /* Strip trailing spaces */
  3771.   if (*p) return(-2); /* Should be nothing here. */
  3772.   debug(F110,"doif ELSE line 3",line,0);
  3773.       }
  3774.   } else { /* At end, treat like an IF command */
  3775.       if (!z) line[0] = NUL; /* Condition not true and no ELSE */
  3776.       ifcmd[cmdlvl] = 1; /* Allow ELSE on next line */
  3777.       debug(F101,"IF condition","",z);
  3778.   }
  3779.   if (line[0]) {
  3780.       x = mlook(mactab,"_xif",nmac); /* Get index of "_xif" macro. */
  3781.       if (x < 0) { /* Not there? */
  3782.   addmmac("_xif",xif_def); /* Put it back. */
  3783.   if (mlook(mactab,"_xif",nmac) < 0) { /* Look it up again. */
  3784.       printf("?XIF macro gone!n");
  3785.       return(success = 0);
  3786.   }
  3787.       }
  3788.       dodo(x,line,cmdstk[cmdlvl].ccflgs | CF_IMAC);
  3789.   }
  3790.   return(0);
  3791.       }
  3792.       case XXWHI: { /* WHILE Command */
  3793.   p = cmdbuf; /* Capture IF condition */
  3794.   ifcond[0] = NUL; /* from command buffer */
  3795.   while (*p == SP) p++;
  3796.   while (*p != SP) p++;
  3797.   ifcp = ifcond;
  3798.   strcpy(ifcp,"{ \flit(if ( not ");
  3799.   ifcp += (int)strlen(ifcp);
  3800. #ifdef COMMENT
  3801. /*
  3802.   This doesn't work because it breaks on the first left brace, which does
  3803.   not necessarily start the command list, e.g. "while equal %a {35}".
  3804. */
  3805.   while (*p != '{' && *p != NUL) *ifcp++ = *p++;
  3806.   p = " ) goto _..bot) } ";
  3807.   while (*ifcp++ = *p++) ;
  3808. #else
  3809. /*
  3810.   The command parser sets cmbptr to the spot where it left off parsing in
  3811.   the command buffer.
  3812. */
  3813.   {
  3814.       extern char * cmbptr;
  3815.       if (cmbptr) {
  3816.   while (p < cmbptr && *p != NUL)
  3817.     *ifcp++ = *p++;
  3818.   p = " ) goto _..bot) } ";
  3819.   while (*ifcp++ = *p++) ;
  3820.       } else {
  3821.   printf("?Internal error parsing WHILE conditionn");
  3822.   return(-9);
  3823.       }
  3824.   }
  3825. #endif /* COMMENT */
  3826.   debug(F110,"WHILE cmd",ifcond,0);
  3827.   if ((y = cmtxt("Object command","",&s,NULL)) < 0)
  3828.     return(y); /* Get object command. */
  3829.   p = s;
  3830.   lp = line;
  3831.   if (litcmd(&p,&lp,LINBUFSIZ - 2) < 0) { /* Quote object command */
  3832.       return(-2);
  3833.   }
  3834.   debug(F110,"WHILE body",line,0);
  3835.   if (line[0]) {
  3836.       char *p;
  3837.       x = mlook(mactab,"_while",nmac); /* index of "_while" macro. */
  3838.       if (x < 0) { /* Not there? */
  3839.   addmmac("_while",whil_def); /* Put it back. */
  3840.   if (mlook(mactab,"_while",nmac) < 0) { /* Look it up again */
  3841.       printf("?WHILE macro definition gone!n");
  3842.       return(success = 0);
  3843.   }
  3844.       }
  3845.       p = malloc((int)strlen(ifcond) + (int)strlen(line) + 2);
  3846.       if (p) {
  3847.   strcpy(p,ifcond);
  3848.   strcat(p,line);
  3849.   debug(F110,"WHILE dodo",p,0);
  3850.   dodo(x,p,cmdstk[cmdlvl].ccflgs | CF_IMAC);
  3851.   free(p);
  3852.   p = NULL;
  3853.       } else {
  3854.   printf("?Can't allocate storage for WHILE command");
  3855.   return(success = 0);
  3856.       }
  3857.   }
  3858.   return(0);
  3859.       }
  3860.       default:
  3861. return(-2);
  3862.     }
  3863. }
  3864. #endif /* NOSPL */
  3865. /* Set up a TAKE command file */
  3866. int
  3867. dotake(s) char *s; {
  3868. #ifndef NOSPL
  3869.     extern int tra_cmd;
  3870. #endif /* NOSPL */
  3871. #ifdef OS2
  3872.     extern int term_io;
  3873.     int term_io_sav = term_io;
  3874. #endif /* OS2 */
  3875.     debug(F111,"dotake file",s,cmdlvl);
  3876.     if ((tfile[++tlevel] = fopen(s,"r")) == NULL) {
  3877. perror(s);
  3878. debug(F110,"dotake fail",s,0);
  3879. tlevel--;
  3880. return(success = 0);
  3881.     } else {
  3882. tfline[tlevel] = 0; /* Line counter */
  3883. #ifdef VMS
  3884. conres(); /* So Ctrl-C will work */
  3885. #endif /* VMS */
  3886. #ifdef OS2
  3887. term_io = 0; /* Disable Terminal Emulator I/O */
  3888. #endif /* OS2 */
  3889. #ifndef NOSPL
  3890. cmdlvl++; /* Entering a new command level */
  3891. debug(F101,"dotake cmdlvl","",cmdlvl);
  3892. debug(F101,"dotake tlevel","",tlevel);
  3893. if (cmdlvl > CMDSTKL) {
  3894.     debug(F100,"dotake stack overflow","",0);
  3895.     cmdlvl--;
  3896.     fclose(tfile[tlevel--]);
  3897.     printf("?TAKE files and/or DO commands nested too deeplyn");
  3898.     return(success = 0);
  3899. }
  3900. if (tfnam[tlevel]) { /* Copy the filename */
  3901.     free(tfnam[tlevel]);
  3902.     tfnam[tlevel] = NULL;
  3903. }
  3904. if (tfnam[tlevel] = malloc(strlen(s) + 1))
  3905.   strcpy(tfnam[tlevel],s);
  3906. ifcmd[cmdlvl] = 0; /* Set variables for this cmd file */
  3907. iftest[cmdlvl] = 0;
  3908. count[cmdlvl]  = count[cmdlvl-1];  /* Inherit this */
  3909. intime[cmdlvl] = intime[cmdlvl-1]; /* Inherit this */
  3910. inpcas[cmdlvl] = inpcas[cmdlvl-1]; /* Inherit this */
  3911. takerr[cmdlvl] = takerr[cmdlvl-1]; /* Inherit this */
  3912. merror[cmdlvl] = merror[cmdlvl-1]; /* Inherit this */
  3913. xquiet[cmdlvl] = quiet;
  3914. cmdstk[cmdlvl].src = CMD_TF; /* Say we're in a TAKE file */
  3915. cmdstk[cmdlvl].lvl = tlevel; /* nested at this level */
  3916. cmdstk[cmdlvl].ccflgs = cmdstk[cmdlvl-1].ccflgs;
  3917. #else
  3918. takerr[tlevel] = takerr[tlevel-1]; /* Inherit this */
  3919. #endif /* NOSPL */
  3920.     }
  3921. #ifndef NOSPL
  3922.     if (tra_cmd)
  3923.       printf("[%d] +F: "%s"n",cmdlvl,s);
  3924. #endif /* NOSPL */
  3925. #ifdef OS2
  3926.     term_io = term_io_sav;
  3927. #endif /* OS2 */
  3928.     return(1);
  3929. }
  3930. #endif /* NOICP */