ckucmd.c
资源名称:cku197.tar.Z [点击查看]
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:151k
源码类别:
通讯/手机编程
开发平台:
Windows_Unix
- x = strlen(atmbuf);
- if (ckstrcmp(atmbuf,xdef,x,0)) /* Matches default? */
- bleep(BP_WARN); /* No */
- else { /* Yes */
- p = xdef + x;
- printf("%s ", p);
- #ifdef GEMDOS
- fflush(stdout);
- #endif /* GEMDOS */
- addbuf(p);
- inword = cmflgs = 0;
- debug(F110,"cmtxt: addbuf",cmdbuf,0);
- }
- }
- break;
- case 3: /* Question Mark */
- if (*xhlp == NUL)
- printf(" Text string");
- else
- printf(" %s",xhlp);
- printf("n%s%s",cmprom,cmdbuf);
- fflush(stdout);
- break;
- default:
- printf("?Unexpected return code from gtword() - %dn",x);
- return(-2);
- }
- x = gtword(0);
- }
- }
- /* C M K E Y -- Parse a keyword */
- /*
- Call with:
- table -- keyword table, in 'struct keytab' format;
- n -- number of entries in table;
- xhlp -- pointer to help string;
- xdef -- pointer to default keyword;
- f -- processing function (e.g. to evaluate variables)
- pmsg -- 0 = don't print error messages
- 1 = print error messages
- 2 = include CM_HLP keywords even if invisible
- 3 = 1+2
- 4 = parse a switch (keyword possibly ending in : or =)
- Returns:
- -3 -- no input supplied and no default available
- -2 -- input doesn't uniquely match a keyword in the table
- -1 -- user deleted too much, command reparse required
- n >= 0 -- value associated with keyword
- */
- int
- cmkey(table,n,xhlp,xdef,f)
- /* cmkey */ struct keytab table[]; int n; char *xhlp, *xdef; xx_strp f; {
- return(cmkey2(table,n,xhlp,xdef,"",f,1));
- }
- int
- cmkeyx(table,n,xhlp,xdef,f)
- /* cmkeyx */ struct keytab table[]; int n; char *xhlp, *xdef; xx_strp f; {
- return(cmkey2(table,n,xhlp,xdef,"",f,0));
- }
- int
- cmswi(table,n,xhlp,xdef,f)
- /* cmswi */ struct keytab table[]; int n; char *xhlp, *xdef; xx_strp f; {
- return(cmkey2(table,n,xhlp,xdef,"",f,4));
- }
- int
- cmkey2(table,n,xhlp,xdef,tok,f,pmsg)
- struct keytab table[];
- int n;
- char *xhlp,
- *xdef;
- char *tok;
- xx_strp f;
- int pmsg;
- { /* cmkey2 */
- int i, tl, y, z = 0, zz, xc, wordlen = 0, cmswitch;
- char *xp, *zq;
- if (!xhlp) xhlp = "";
- if (!xdef) xdef = "";
- cmfldflgs = 0;
- if (!table) {
- printf("?Keyword table missingn");
- return(-9);
- }
- tl = (int)strlen(tok);
- inword = xc = cc = 0; /* Clear character counters. */
- cmswitch = pmsg & 4; /* Flag for parsing a switch */
- debug(F101,"cmkey: pmsg","",pmsg);
- debug(F101,"cmkey: cmflgs","",cmflgs);
- /* debug(F101,"cmkey: cmdbuf","",cmdbuf);*/
- ppvnambuf[0] = NUL;
- if ((zz = cmflgs) == 1) { /* Command already entered? */
- if (setatm(xdef,0) < 0) { /* Yes, copy default into atom buf */
- printf("?Default too longn");
- return(-9);
- }
- } else
- zz = gtword((pmsg == 4) ? 1 : 0); /* Otherwise get a command word */
- debug(F101,"cmkey table length","",n);
- debug(F101,"cmkey cmflgs","",cmflgs);
- debug(F101,"cmkey zz","",zz);
- debug(F101,"cmkey cc","",cc);
- rtimer(); /* Reset timer */
- while (1) {
- xc += cc;
- debug(F111,"cmkey gtword xc",atmbuf,xc);
- switch (zz) {
- case -10: /* Timeout */
- if (gtimer() < timelimit) {
- zz = gtword((pmsg == 4) ? 1 : 0);
- continue;
- } else {
- #ifdef IKSD
- extern int inserver;
- if (inserver) {
- printf("rnIKSD IDLE TIMEOUT: %d secrn", timelimit);
- doexit(GOOD_EXIT,0);
- }
- #endif /* IKSD */
- return(-10);
- }
- case -5:
- return(cmflgs = 0);
- case -9:
- printf("Command or field too longn");
- case -4: /* EOF */
- case -3: /* Null Command/Quit/Timeout */
- case -2: /* Buffer overflow */
- case -1: /* Or user did some deleting. */
- return(cmflgs = zz);
- case 0: /* User terminated word with space */
- case 1: /* or newline */
- case 4: /* or switch ending in : or = */
- wordlen = cc; /* Length if no conversion */
- if (cc == 0) { /* Supply default if we got nothing */
- if ((wordlen = setatm(xdef,(zz == 4) ? 2 : 0)) < 0) {
- printf("?Default too longn");
- return(-9);
- }
- }
- if (zz == 1 && cc == 0) /* Required field missing */
- return(-3);
- if (f) { /* If a conversion function is given */
- char * pp;
- zq = atxbuf; /* apply it */
- pp = atxbuf;
- atxn = CMDBL;
- if ((*f)(atmbuf,&zq,&atxn) < 0) return(-2);
- debug(F110,"cmkey atxbuf after *f",atxbuf,0);
- if (!*pp) /* Supply default if we got nothing */
- pp = xdef;
- ckstrncpy(ppvnambuf,atmbuf,PPVLEN);
- if ((wordlen = setatm(pp,(zz == 4) ? 2 : 0)) < 0) {
- printf("Evaluated keyword too longn");
- return(-9);
- }
- }
- if (cmswitch && *atmbuf != '/') {
- if (pmsg & 1) {
- bleep(BP_FAIL);
- printf("?Not a switch - %sn",atmbuf);
- }
- cmflgs = -2;
- return(-6);
- }
- if (cmswitch) {
- int i;
- for (i = 0; i < wordlen; i++) {
- if (atmbuf[i] == ':' || atmbuf[i] == '=') {
- atmbuf[i] = NUL;
- break;
- }
- }
- }
- y = lookup(table,atmbuf,n,&z); /* Look up the word in the table */
- switch (y) {
- case -3: /* Nothing to look up */
- break;
- case -2: /* Ambiguous */
- cmflgs = -2;
- if (pmsg & 1) {
- bleep(BP_FAIL);
- printf("?Ambiguous - %sn",atmbuf);
- return(-9);
- }
- return(-2);
- case -1: /* Not found at all */
- if (tl) {
- for (i = 0; i < tl; i++) /* Check for token */
- if (tok[i] == *atmbuf) { /* Got one */
- debug(F000,"cmkey token:",atmbuf,*atmbuf);
- ungword(); /* Put back the following word */
- return(-5); /* Special return code for token */
- }
- }
- if (tl == 0) { /* No tokens were included */
- #ifdef OS2
- /* In OS/2 and Windows, allow for a disk letter like DOS */
- if (isalpha(*atmbuf) && *(atmbuf+1) == ':')
- return(-7);
- #endif /* OS2 */
- if ((pmsg & 1) && !quiet) {
- bleep(BP_FAIL);
- printf("?No keywords match - %sn",atmbuf); /* cmkey */
- }
- return(cmflgs = -9);
- } else {
- if (cmflgs == 1 || cmswitch) /* cmkey2 or cmswi */
- return(cmflgs = -6);
- else
- return(cmflgs = -2);
- /* The -6 code is to let caller try another table */
- }
- break;
- default:
- #ifdef CK_RECALL
- if (test(table[z].flgs,CM_NOR)) no_recall = 1;
- #endif /* CK_RECALL */
- if (zz == 4)
- swarg = 1;
- cmkwflgs = table[z].flgs;
- break;
- }
- return(y);
- case 2: /* User terminated word with ESC */
- debug(F101,"cmkey Esc cc","",cc);
- if (cc == 0) {
- if (*xdef != NUL) { /* Nothing in atmbuf */
- printf("%s ",xdef); /* Supply default if any */
- #ifdef GEMDOS
- fflush(stdout);
- #endif /* GEMDOS */
- addbuf(xdef);
- if (setatm(xdef,0) < 0) {
- printf("?Default too longn");
- return(-9);
- }
- inword = cmflgs = 0;
- debug(F111,"cmkey: default",atmbuf,cc);
- } else {
- debug(F101,"cmkey Esc pmsg","",0);
- #ifdef COMMENT
- /*
- Chained FDBs... The idea is that this function might not have a default,
- but the next one might. But if it doesn't, there is no way to come back to
- this one. To be revisited later...
- */
- if (xcmfdb) /* Chained fdb -- try next one */
- return(-3);
- #endif /* COMMENT */
- if (pmsg & (1|4)) { /* So for now just beep */
- bleep(BP_WARN);
- }
- break;
- }
- }
- if (f) { /* If a conversion function is given */
- char * pp;
- zq = atxbuf; /* apply it */
- pp = atxbuf;
- atxn = CMDBL;
- if ((*f)(atmbuf,&zq,&atxn) < 0)
- return(-2);
- if (!*pp)
- pp = xdef;
- if (setatm(pp,0) < 0) {
- printf("Evaluated keyword too longn");
- return(-9);
- }
- }
- y = lookup(table,atmbuf,n,&z); /* Something in atmbuf */
- debug(F111,"cmkey lookup y",atmbuf,y);
- debug(F111,"cmkey lookup z",atmbuf,z);
- if (y == -2 && z >= 0 && z < n) { /* Ambiguous */
- #ifndef NOPARTIAL
- int j, k, len = 9999; /* Do partial completion */
- /* Skip past any abbreviations in the table */
- for ( ; z < n; z++) {
- if (table[z].flgs & CM_ABR == 0)
- break;
- if (!(table[z].flgs & CM_HLP) || (pmsg & 2))
- break;
- }
- debug(F111,"cmkey partial z",atmbuf,z);
- debug(F111,"cmkey partial n",atmbuf,n);
- for (j = z+1; j < n; j++) {
- debug(F111,"cmkey partial j",table[j].kwd,j);
- if (ckstrcmp(atmbuf,table[j].kwd,cc,0))
- break;
- if (table[j].flgs & CM_ABR)
- continue;
- if ((table[j].flgs & CM_HLP) && !(pmsg & 2))
- continue;
- k = ckstrpre(table[z].kwd,table[j].kwd);
- debug(F111,"cmkey partial k",table[z].kwd,k);
- if (k < len)
- len = k; /* Length of longest common prefix */
- }
- debug(F111,"cmkey partial len",table[z].kwd,len);
- if (len != 9999 && len > cc) {
- strcat(atmbuf,table[z].kwd+cc);
- atmbuf[len] = NUL;
- printf("%s",atmbuf+cc);
- strcat(cmdbuf,atmbuf+cc);
- xc += (len - cc);
- cc = len;
- }
- #endif /* NOPARTIAL */
- bleep(BP_WARN);
- break;
- } else if (y == -3) {
- bleep(BP_WARN);
- break;
- } else if (y == -1) { /* Not found */
- if ((pmsg & 1) && !quiet) {
- bleep(BP_FAIL);
- printf("?No keywords match - "%s"n",atmbuf);
- }
- cmflgs = -2;
- return(-9);
- }
- /*
- If we found it, but it's a help-only keyword and the "help" bit is not
- set in pmsg, then not found.
- */
- debug(F101,"cmkey flgs","",table[z].flgs);
- if (test(table[z].flgs,CM_HLP) && ((pmsg & 2) == 0)) {
- if ((pmsg & 1) && !quiet) {
- bleep(BP_FAIL);
- printf("?No keywords match - %sn",atmbuf);
- }
- cmflgs = -2;
- return(-9);
- }
- /*
- See if the keyword just found has the CM_ABR bit set in its flgs field, and
- if so, search forwards in the table for a keyword that has the same kwval
- but does not have CM_ABR (or CM_INV?) set, and then expand using the full
- keyword. WARNING: This assumes that (a) keywords are in alphabetical order,
- and (b) the CM_ABR bit is set only if the the abbreviated keyword is a true
- abbreviation (left substring) of the full keyword.
- */
- if (test(table[z].flgs,CM_ABR)) {
- int zz;
- for (zz = z+1; zz < n; zz++)
- if ((table[zz].kwval == table[z].kwval) &&
- (!test(table[zz].flgs,CM_ABR)) &&
- (!test(table[zz].flgs,CM_INV))) {
- z = zz;
- break;
- }
- }
- xp = table[z].kwd + cc;
- if (cmswitch && test(table[z].flgs,CM_ARG)) {
- #ifdef VMS
- printf("%s=",xp);
- brkchar = '=';
- #else
- printf("%s:",xp);
- brkchar = ':';
- #endif /* VMS */
- } else {
- printf("%s ",xp);
- brkchar = SP;
- }
- #ifdef CK_RECALL
- if (test(table[z].flgs,CM_NOR)) no_recall = 1;
- #endif /* CK_RECALL */
- cmkwflgs = table[z].flgs;
- #ifdef GEMDOS
- fflush(stdout);
- #endif /* GEMDOS */
- addbuf(xp);
- if (cmswitch && test(table[z].flgs,CM_ARG)) {
- bp--; /* Replace trailing space with : */
- #ifdef VMS
- *bp++ = '=';
- #else
- *bp++ = ':';
- #endif /* VMS */
- *bp = NUL;
- np = bp;
- swarg = 1;
- }
- inword = 0;
- cmflgs = 0;
- debug(F110,"cmkey: addbuf",cmdbuf,0);
- return(y);
- case 3: /* User typed "?" */
- if (f) { /* If a conversion function is given */
- char * pp;
- zq = atxbuf; /* do the conversion now. */
- pp = atxbuf;
- atxn = CMDBL;
- if ((*f)(atmbuf,&zq,&atxn) < 0) return(-2);
- if (setatm(pp,0) < 0) {
- printf("?Evaluated keyword too longn");
- return(-9);
- }
- }
- y = lookup(table,atmbuf,n,&z); /* Look up what we have so far. */
- if (y == -1) {
- cmflgs = -2;
- if ((pmsg & 1) && !quiet) {
- bleep(BP_FAIL);
- printf(" No keywords matchn");
- return(-9);
- }
- return(-2);
- }
- if (*xhlp == NUL)
- printf(" One of the following:n");
- else
- printf(" %s, one of the following:n",xhlp);
- #ifdef OLDHELP
- if ((y > -1) &&
- !test(table[z].flgs,CM_ABR) &&
- ((z >= n-1) || ckstrcmp(table[z].kwd,table[z+1].kwd,cc,0))
- ) {
- printf(" %sn",table[z].kwd);
- } else {
- clrhlp();
- for (i = 0; i < n; i++) {
- if (!ckstrcmp(table[i].kwd,atmbuf,cc,0)
- && !test(table[i].flgs,CM_INV)
- )
- addhlp(table[i].kwd);
- }
- dmphlp();
- }
- #else /* New way ... */
- {
- int x;
- x = pmsg & (2|4); /* See kwdhelp() comments */
- if (atmbuf[0]) /* If not at beginning of field */
- x |= 1; /* also show invisibles */
- kwdhelp(table,n,atmbuf,"","",1,x);
- }
- #endif /* OLDHELP */
- #ifndef NOSPL
- {
- extern int topcmd;
- if (tl > 0 && topcmd != XXHLP) /* This is bad... */
- printf("or the name of a macro ("do ?" for a list)n");
- }
- #endif /* NOSPL */
- if (*atmbuf == NUL) {
- if (tl == 1)
- printf("or the token %cn",*tok);
- else if (tl > 1)
- printf("or one of the tokens: %sn",ckspread(tok));
- }
- printf("%s%s", cmprom, cmdbuf);
- fflush(stdout);
- break;
- default:
- printf("n%d - Unexpected return code from gtwordn",zz);
- return(cmflgs = -2);
- }
- zz = gtword(0);
- debug(F111,"cmkey gtword zz",atmbuf,zz);
- }
- }
- int
- chktok(tlist) char *tlist; {
- char *p;
- p = tlist;
- while (*p != NUL && *p != *atmbuf) p++;
- return((*p) ? (int) *p : 0);
- }
- /* Routines for parsing and converting dates and times */
- #define isdatesep(c) (c==SP||c=='-'||c=='/'||c=='.'||c=='_')
- #define istimesep(c) (c==':' || c=='P'||c=='p'||c=='A'||c=='a')
- char cmdatebuf[18] = { NUL, NUL };
- #define TU_DAYS 0
- #define TU_WEEKS 1
- #define TU_MONTHS 2
- #define TU_YEARS 3
- static struct keytab timeunits[] = {
- { "days", TU_DAYS, 0 },
- { "months", TU_MONTHS, 0 },
- { "weeks", TU_WEEKS, 0 },
- { "wks", TU_WEEKS, 0 },
- { "years", TU_YEARS, 0 },
- { "yrs", TU_YEARS, 0 }
- };
- static int nunits = (sizeof(timeunits) / sizeof(struct keytab));
- /* C M C V T D A T E -- Converts free-form date to standard form. */
- /*
- Call with
- s = pointer to free-format date-time
- t = 0: return time only if time was given in s
- t = 1: always return time (00:00:00 if no time given in s)
- t = 2: allow time to be > 24:00:00
- Returns:
- -1 on failure, 0 or greater on success with result in cmdate[].
- */
- int
- cmcvtdate(s,t) char * s; int t; {
- int rc = 0, x, i, hh, mm, ss, pmflag = 0, nodate = 0, len;
- int units;
- char * fld[3], * p;
- char * year, * month = NULL, * day;
- char * hour = "00", * min = "00", * sec = "00";
- char tmpbuf[8];
- char xbuf[32];
- char ybuf[32];
- char dbuf[26];
- char daybuf[3];
- char monbuf[3];
- char yearbuf[5];
- debug(F110,"cmcvtdate",s,0);
- if (!s) s = "";
- tmpbuf[0] = NUL;
- while (*s == SP) s++; /* Gobble any leading blanks */
- len = strlen(s);
- if (len == 0) {
- s = ckdate();
- len = 17;
- debug(F110,"cmcvtdate now",s,0);
- }
- if (len > 30) { /* Check length of arg */
- debug(F101,"cmcvtdate date too long","",-1);
- return(-1);
- }
- ckstrncpy(xbuf,s,32); /* Make a local copy we can poke */
- s = xbuf; /* Point to it */
- s[len] = NUL;
- /* First we handle "today", "yesterday", "tomorrow", etc */
- if (ckstrchr("+-TtYy",s[0])) {
- int i, k, n, minus = 0;
- long jd;
- jd = mjd(ckdate());
- debug(F111,"cmcvtdate NEW",s,jd);
- if (s[0] == '+' || s[0] == '-') { /* {+,-} <number> <timeunits> */
- char * kp, * np;
- char tmpyear[5];
- char * dp;
- if (s[0] == '-') /* Sign */
- minus = 1;
- kp = s+1; /* Skip intervening spaces */
- while (*kp) {
- if (*kp == SP) kp++;
- else break;
- }
- if (!*kp)
- return(-1);
- np = kp; /* Number */
- while (*kp) {
- if (isdigit(*kp)) kp++;
- else break;
- }
- if (!*kp)
- return(-1);
- n = atoi(np);
- if (minus) n = 0 - n;
- debug(F101,"cmcvtdate offset n","",n);
- while (*kp) { /* Find end of number */
- if (isdigit(*kp)) kp++;
- else break;
- }
- while (*kp) { /* Skip spaces again */
- if (*kp == SP) kp++;
- else break;
- }
- debug(F110,"cmcvtdate unit start",kp,0);
- p = kp; /* Units */
- while (*p) {
- if (isalpha(*p)) {
- p++;
- } else if (isdatesep(*p)) { /* Have a date separator */
- *p++ = NUL;
- break;
- } else
- return(-1);
- }
- while (*p) { /* Skip any spaces */
- if (*p == SP) p++;
- else break;
- }
- debug(F110,"cmcvtdate time pointer",p,0);
- debug(F110,"cmcvtdate unit",kp,0);
- x = lookup(timeunits,kp,nunits,&k); /* Look up units */
- if (x < 0) {
- debug(F111,"cmcvtdate lookup fails",kp,x);
- return(-1);
- }
- units = x;
- debug(F111,"cmcvtdate offset units",timeunits[k].kwd,units);
- switch (units) { /* Handle each unit */
- case TU_DAYS: /* Days */
- jd += n;
- strcpy(ybuf,mjd2date(jd));
- if (*p) {
- ybuf[8] = ' ';
- strcpy(ybuf+9,p);
- } else
- strcpy(ybuf+8," 00:00:00");
- s = ybuf;
- len = strlen(ybuf);
- debug(F111,"cmcvtdate days",s,len);
- goto normal;
- case TU_WEEKS: /* Weeks */
- jd += (7 * n);
- strcpy(ybuf,mjd2date(jd));
- if (*p) {
- ybuf[8] = ' ';
- strcpy(ybuf+9,p);
- } else
- strcpy(ybuf+8," 00:00:00");
- s = ybuf;
- len = strlen(ybuf);
- debug(F111,"cmcvtdate weeks",s,len);
- goto normal;
- case TU_MONTHS: { /* Months */
- char tmpmonth[3];
- int xyear, xmonth;
- dp = ckdate();
- tmpyear[0] = dp[0];
- tmpyear[1] = dp[1];
- tmpyear[2] = dp[2];
- tmpyear[3] = dp[3];
- tmpyear[4] = NUL;
- tmpmonth[0] = dp[4];
- tmpmonth[1] = dp[5];
- tmpmonth[2] = NUL;
- xyear = atoi(tmpyear);
- xmonth = atoi(tmpmonth);
- xmonth += n;
- xyear += (xmonth / 12);
- xmonth = (xmonth % 12);
- if (xmonth <= 0) {
- xmonth += 12;
- xyear--;
- }
- sprintf(ybuf,"%04d%02d%s",xyear,xmonth,dp+6);
- if (*p) {
- ybuf[8] = ' ';
- strcpy(ybuf+9,p);
- } else
- strcpy(ybuf+8," 00:00:00");
- s = ybuf;
- len = strlen(ybuf);
- debug(F111,"cmcvtdate months",s,len);
- goto normal;
- }
- case TU_YEARS: { /* Years */
- dp = ckdate();
- tmpyear[0] = dp[0];
- tmpyear[1] = dp[1];
- tmpyear[2] = dp[2];
- tmpyear[3] = dp[3];
- tmpyear[4] = NUL;
- sprintf(ybuf,"%04d%s",(atoi(tmpyear)+n),dp+4);
- if (*p) {
- ybuf[8] = ' ';
- strcpy(ybuf+9,p);
- } else
- strcpy(ybuf+8," 00:00:00");
- s = ybuf;
- len = strlen(ybuf);
- debug(F111,"cmcvtdate years",s,len);
- goto normal;
- }
- }
- return(-1);
- }
- i = ckstrpre(s,"today"); /* TODAY */
- if (i > 2 && (s[i] == NUL || isdatesep(s[i]))) {
- strncpy(ybuf,ckdate(),8);
- strcpy(ybuf+8," 00:00:00");
- if (s[i])
- strcpy(ybuf+8,s+i);
- s = ybuf;
- len = strlen(s);
- debug(F111,"cmcvtdate today",s,len);
- goto normal;
- }
- i = ckstrpre(s,"tomorrow"); /* TOMORROW */
- if (i > 2 && (s[i] == NUL || isdatesep(s[i]))) {
- jd++;
- strncpy(ybuf,mjd2date(jd),8);
- strcpy(ybuf+8," 00:00:00");
- if (s[i]) strcpy(ybuf+8,s+i);
- s = ybuf;
- len = strlen(s);
- debug(F111,"cmcvtdate tomorrow",s,len);
- goto normal;
- }
- i = ckstrpre(s,"yesterday"); /* YESTERDAY */
- if (i > 0 && (s[i] == NUL || isdatesep(s[i]))) {
- jd--;
- strncpy(ybuf,mjd2date(jd),8);
- strcpy(ybuf+8," 00:00:00");
- if (s[i]) strcpy(ybuf+8,s+i);
- s = ybuf;
- len = strlen(s);
- debug(F111,"cmcvtdate yesterday",s,len);
- goto normal;
- }
- }
- normal:
- if (len >= 8) { /* Already in right format? */
- if (isdigit(s[0]) && isdigit(s[1]) &&
- isdigit(s[2]) && isdigit(s[3]) &&
- isdigit(s[4]) && isdigit(s[5]) &&
- isdigit(s[6]) && isdigit(s[7]))
- if (!s[8]) {
- strcat(s," 00:00:00");
- ckstrncpy(cmdatebuf,s,18);
- debug(F111,"cmcvtdate yyyymmdd",s,rc);
- return(rc);
- } else if (len == 17 &&
- isdigit(s[9]) && isdigit(s[10]) &&
- isdigit(s[12]) && isdigit(s[13]) &&
- isdigit(s[15]) && isdigit(s[16]) &&
- s[11] == ':' && s[14] == ':' &&
- (s[8] == SP || s[8] == '-' || s[8] == '_')) {
- ckstrncpy(cmdatebuf,s,18);
- debug(F111,"cmcvtdate yyyymmdd hh:mm:ss",s,rc);
- return(rc);
- } else { /* We have a numeric date */
- debug(F111,"cmcvtdate yyyymmdd xxx",s,rc);
- p = s+9; /* Start of time field */
- yearbuf[0] = s[0]; yearbuf[1] = s[1];
- yearbuf[2] = s[2]; yearbuf[3] = s[3];
- yearbuf[4] = NUL; year = yearbuf;
- monbuf[0] = s[4]; monbuf[1] = s[5];
- monbuf[2] = NUL; month = monbuf;
- daybuf[0] = s[6]; daybuf[1] = s[7];
- daybuf[2] = NUL; day = daybuf;
- goto dotime;
- }
- }
- fld[i = 0] = (p = s); /* First field */
- while (*p) { /* Get next two fields */
- if (isdatesep(*p)) { /* Have a date separator */
- *p++ = NUL; /* Replace by NUL */
- if (*p) { /* Now we're at the next field */
- while (*p == SP) p++; /* Skip leading spaces */
- if (!*p) break; /* Make sure we still have something */
- if (i == 2) /* Last one? */
- break;
- fld[++i] = p; /* No, record pointer to this one */
- } else
- break;
- } else if (istimesep(*p)) { /* Have a time separator */
- if (isalpha(*p) && !isdigit(*(p-1))) { /* Might be letter */
- p++; /* in month name... */
- continue;
- }
- if (i != 0) { /* After a date */
- debug(F111,"cmcvtdate date bad timesep",p,-1);
- return(-1);
- }
- nodate = 1; /* Or without a date */
- break;
- }
- p++;
- }
- if (p > s && i == 0) /* Make sure we have a date */
- nodate = 1;
- if (nodate) { /* No date */
- char *tmp; /* Substitute today's date */
- ztime(&tmp);
- if (!tmp) {
- debug(F101,"cmcvtdate null ztime","",-1);
- return(-1);
- }
- if (!*tmp) {
- debug(F101,"cmcvtdate emtpy ztime","",-1);
- return(-1);
- }
- ckstrncpy(dbuf,tmp,26); /* Reformat */
- if (dbuf[8] == SP) dbuf[8] = '0';
- fld[0] = dbuf+8;
- dbuf[10] = NUL;
- fld[1] = dbuf+4;
- dbuf[7] = NUL;
- fld[2] = dbuf+20;
- dbuf[24] = NUL;
- p = s; /* Back up source pointer to reparse */
- } else if (i != 2) {
- debug(F101,"cmcvtdate fail A","",-1);
- return(-1);
- }
- if (!rdigits(fld[0])) { /* Now parse the date */
- debug(F101,"cmcvtdate fail B","",-1);
- return(-1);
- }
- if (!rdigits(fld[1])) {
- if ((x = lookup(cmonths,fld[1],12,NULL)) < 0) {
- debug(F101,"cmcvtdate fail C","",-1);
- return(-1);
- }
- sprintf(tmpbuf,"%02d",x);
- month = tmpbuf;
- }
- if (((int)strlen(fld[0]) == 4)) { /* yyyy-xx-dd */
- year = fld[0];
- day = fld[2];
- if (!month)
- month = fld[1]; /* yyyy-mm-dd */
- } else if (((int)strlen(fld[2]) == 4)) { /* xx-xx-yyyy */
- year = fld[2];
- if (month) { /* dd-name-yyyy */
- day = fld[0];
- } else { /* xx-xx-yyyy */
- int f0, f1;
- f0 = atoi(fld[0]);
- f1 = atoi(fld[1]);
- if ((f0 > 12) && (f1 <= 12)) {
- day = fld[0]; /* mm-dd-yyyy */
- month = fld[1];
- } else if ((f0 <= 12) && (f1 > 12)) {
- if (!rdigits(fld[1]))
- return(-1);
- else
- day = fld[1]; /* dd-mm-yyyy */
- month = fld[0];
- #ifdef COMMENT
- } else if ((f0 <= 12) && (f1 <= 12)) {
- if (!quiet)
- printf("?Day and month are ambiguous - "%s"n", o);
- return(-9);
- #endif /* COMMENT */
- } else {
- debug(F101,"cmcvtdate fail D","",-1);
- return(-1);
- }
- }
- } else {
- debug(F101,"cmcvtdate fail E","",-1);
- return(-1);
- }
- x = atoi(month);
- sprintf(tmpbuf,"%02d",x); /* 2-digit numeric month */
- dotime:
- debug(F110,"cmcvtdate dotime s",s,0);
- debug(F110,"cmcvtdate dotime p",p,0);
- if ((x = atoi(day)) > 31) {
- debug(F101,"cmcvtdate fail K","",-1);
- return(-1);
- }
- if (!*p && t == 0) {
- sprintf(cmdatebuf,"%s%s%02d",year,month,x);
- return(0);
- }
- fld[i = 0] = *p ? p : "00"; /* First time field */
- fld[1] = "00";
- fld[2] = "00";
- while (*p) { /* Get the rest, if any */
- if (istimesep(*p)) {
- debug(F000,"cmcvtdate timesep:",p,*p);
- if (*p == 'P' || *p == 'p') {
- if (*(p+1) != 'M' && *(p+1) != 'm') {
- debug(F101,"cmcvtdate fail F","",-1);
- return(-1);
- } else if (!*(p+2)) {
- pmflag = 1;
- *p = NUL;
- break;
- } else {
- debug(F101,"cmcvtdate fail F","",-1);
- return(-1);
- }
- } else if (*p == 'A' || *p == 'a') {
- if (*(p+1) != 'M' && *(p+1) != 'm') {
- debug(F101,"cmcvtdate fail F","",-1);
- return(-1);
- }
- if (*(p+2)) {
- debug(F101,"cmcvtdate fail F","",-1);
- return(-1);
- }
- *p = NUL;
- break;
- }
- *p++ = NUL;
- if (*p) {
- while (*p == SP) p++;
- if (!*p) break;
- if (i == 2)
- break;
- fld[++i] = p;
- } else
- break;
- }
- p++;
- }
- debug(F101,"cmcvtdate time i","",i);
- debug(F110,"cmcvtdate time fld[0]",fld[0],0);
- debug(F110,"cmcvtdate time fld[1]",fld[1],0);
- debug(F110,"cmcvtdate time fld[2]",fld[2],0);
- if (!rdigits(fld[0]))
- return(-1);
- hour = fld[0];
- if (i >= 1) {
- if (!rdigits(fld[1]))
- return(-1);
- else
- min = fld[1];
- }
- if (i == 2) {
- if (!rdigits(fld[2]))
- return(-1);
- else
- sec = fld[2];
- }
- hh = atoi(hour);
- if (pmflag && hh <= 11)
- hh += 12;
- if ((t != 2 && hh > 24) || hh < 0) {
- debug(F101,"cmcvtdate fail G","",-1);
- return(-1);
- }
- if ((mm = atoi(min)) > 59) {
- debug(F101,"cmcvtdate fail H","",-1);
- return(-1);
- }
- if ((ss = atoi(sec)) > 59) {
- debug(F101,"cmcvtdate fail I","",-1);
- return(-1);
- }
- if (mm < 0 || ss < 0) return(-1);
- if (t != 2 && (ss > 0 || mm > 0) && hh > 23) {
- debug(F101,"cmcvtdate fail J","",-1);
- return(-1);
- }
- debug(F110,"cmcvtdate year",year,0);
- debug(F110,"cmcvtdate month",month,0);
- debug(F101,"cmcvtdate x","",x);
- debug(F101,"cmcvtdate hh","",hh);
- debug(F101,"cmcvtdate mm","",mm);
- debug(F101,"cmcvtdate ss","",ss);
- sprintf(cmdatebuf,"%s%s%02d %02d:%02d:%02d",year,month,x,hh,mm,ss);
- #ifdef DEBUG
- if (deblog) {
- debug(F101,"cmcvtdate hour","",hh);
- debug(F101,"cmcvtdate minute","",mm);
- debug(F101,"cmcvtdate second","",ss);
- debug(F111,"cmcvtdate result",cmdatebuf,rc);
- }
- #endif /* DEBLOG */
- return(0);
- }
- /* C K C V T D A T E -- Like cmcvtdate(), but returns string. */
- /* For use by date-related functions */
- /* See calling conventions for cmcvtdate() above. */
- char *
- ckcvtdate(p,t) char * p; int t; {
- if (cmcvtdate(p,t) < 0)
- return("<BAD_DATE_OR_TIME>"); /* fblah() error message */
- else
- return((char *) cmdatebuf);
- }
- /* C M D A T E -- Parse a date and/or time */
- /*
- Accepts date in various formats. If the date is recognized,
- this routine returns 0 or greater with the result string pointer
- pointing to a buffer containing the date as "yyyymmdd hh:mm:ss".
- */
- int
- cmdate(xhlp,xdef,xp,quiet,f) char *xhlp, *xdef, **xp; int quiet; xx_strp f; {
- int /* i, */ x, rc;
- char *o, *s, *zq;
- cmfldflgs = 0;
- if (!xhlp) xhlp = "";
- if (!xdef) xdef = "";
- if (!*xhlp) xhlp = "Date and/or time";
- *xp = "";
- rc = cmfld(xhlp,xdef,&s,(xx_strp)0);
- debug(F101,"cmdate cmfld rc","",rc);
- if (rc < 0)
- return(rc);
- debug(F110,"cmdate 1",s,0);
- o = s; /* Remember what they typed. */
- s = brstrip(s);
- debug(F110,"cmdate 2",s,0);
- x = 0;
- if (f) { /* If a conversion function is given */
- char * pp;
- zq = atxbuf; /* do the conversion. */
- pp = atxbuf;
- atxn = CMDBL;
- if ((x = (*f)(s,&zq,&atxn)) < 0) return(-2);
- if (!*pp)
- pp = xdef;
- if (setatm(pp,0) < 0) {
- if (!quiet) printf("?Evaluated date too longn");
- return(-9);
- }
- s = atxbuf;
- }
- rc = cmcvtdate(s,1);
- if (rc < 0) {
- if (!quiet) printf("Invalid date or time - "%s"n", o);
- return(-9);
- }
- *xp = cmdatebuf;
- return(rc);
- }
- #ifdef CK_RECALL /* Command-recall functions */
- /* C M R I N I -- Initialize or change size of command recall buffer */
- int
- cmrini(n) int n; {
- int i;
- if (recall && in_recall) { /* Free old storage, if any */
- for (i = 0; i < cm_recall; i++) {
- if (recall[i]) {
- free(recall[i]);
- recall[i] = NULL;
- }
- }
- free(recall);
- recall = NULL;
- }
- cm_recall = n; /* Set new size */
- rlast = current = -1; /* Initialize pointers */
- if (n > 0) {
- recall = (char **)malloc((cm_recall + 1) * sizeof(char *));
- if (!recall)
- return(1);
- for (i = 0; i < cm_recall; i++) {
- recall[i] = NULL;
- }
- in_recall = 1; /* Recall buffers init'd */
- }
- return(0);
- }
- /* C M A D D N E X T -- Force addition of next command */
- VOID
- cmaddnext() {
- if (on_recall && in_recall) { /* Even if it doesn't come */
- force_add = 1; /* from the keyboard */
- no_recall = 0;
- }
- }
- /* C M G E T C M D -- Find most recent matching command */
- char *
- cmgetcmd(s) char * s; {
- int i;
- for (i = current; i >= 0; i--) { /* Search backward thru history list */
- if (!recall[i]) continue; /* This one's null, skip it */
- if (ckmatch(s,recall[i],0,1)) /* Match? */
- return(recall[i]); /* Yes, return pointer */
- }
- return(NULL); /* No match, return NULL pointer */
- }
- /* A D D C M D -- Add a command to the recall buffer */
- VOID
- addcmd(s) char * s; {
- int len;
- if (!s) s = cmdbuf;
- len = strlen(s);
- #ifdef CKSYSLOG
- /* Log all interactive commands */
- /* Logging macros & TAKE files is way too much */
- if (ckxlogging) {
- if (ckxsyslog >= SYSLG_CX || ckxsyslog >= SYSLG_CM && !cmdsrc())
- cksyslog(SYSLG_CX, 1, "command", s, NULL);
- }
- #endif /* CKSYSLOG */
- if ((!cmdsrc() || force_add) && /* Reading commands from keyboard? */
- (on_recall) && /* Recall is turned on? */
- (cm_recall > 0) && /* Saving commands? */
- !no_recall && /* Not not saving this command? */
- len > 0) { /* Non-null command? */
- force_add = 0;
- if (rlast >= cm_recall - 1) { /* Yes, buffer full? */
- int i; /* Yes. */
- if (recall[0]) { /* Discard oldest command */
- free(recall[0]);
- recall[0] = NULL;
- }
- for (i = 0; i < rlast; i++) { /* The rest */
- recall[i] = recall[i+1]; /* move back */
- }
- rlast--; /* Now we have one less */
- }
- rlast++; /* Index of last command in buffer */
- current = rlast; /* Also now the current command */
- if (current >= cm_recall) {
- printf("Oops, command recall errorn");
- } else {
- recall[current] = malloc(len+1);
- if (recall[current])
- strcpy(recall[current],s);
- }
- }
- }
- #endif /* CK_RECALL */
- int
- cmgetlc(s) char * s; { /* Get leading char */
- char c;
- while ((c = *s++) <= SP) ;
- return(c);
- }
- /* C M C F M -- Parse command confirmation (end of line) */
- /*
- Returns
- -2: User typed anything but whitespace or newline
- -1: Reparse needed
- 0: Confirmation was received
- */
- int
- cmcfm() {
- int x, xc;
- debug(F101,"cmcfm: cmflgs","",cmflgs);
- debug(F110,"cmcfm: atmbuf",atmbuf,0);
- inword = xc = cc = 0;
- setatm("",0); /* (Probably unnecessary) */
- while (cmflgs != 1) {
- x = gtword(0);
- xc += cc;
- switch (x) {
- case -9:
- printf("Command or field too longn");
- case -4: /* EOF */
- case -2:
- case -1:
- return(x);
- case 1: /* End of line */
- if (xc > 0) {
- if (xcmfdb) {
- return(-6);
- } else {
- printf("?Not confirmed - %sn",atmbuf);
- return(-9);
- }
- } else break; /* Finish up below */
- case 2: /* ESC */
- if (xc == 0) {
- bleep(BP_WARN);
- continue; /* or fall thru. */
- }
- case 0: /* Space */
- if (xc == 0) /* If no chars typed, continue, */
- continue; /* else fall thru. */
- /* else fall thru... */
- case 3: /* Question mark */
- if (xc > 0) {
- if (xcmfdb) {
- return(-6);
- } else {
- printf("?Not confirmed - %sn",atmbuf);
- return(-9);
- }
- }
- printf(
- "n Press the Return or Enter key to confirm the commandn");
- printf("%s%s",cmprom,cmdbuf);
- fflush(stdout);
- continue;
- }
- }
- #ifdef CK_RECALL
- addcmd(cmdbuf);
- #endif /* CK_RECALL */
- return(0);
- }
- /* The following material supports chained parsing functions. */
- /* See ckucmd.h for FDB and OFDB definitions. */
- struct OFDB cmresult = { /* Universal cmfdb result holder */
- NULL,
- 0,
- NULL,
- 0
- };
- VOID
- cmfdbi(p,fc,s1,s2,s3,n1,n2,f,k,nxt) /* Initialize an FDB */
- struct FDB * p;
- int fc;
- char * s1, * s2, * s3;
- int n1, n2;
- xx_strp f;
- struct keytab * k;
- struct FDB * nxt; {
- p->fcode = fc;
- p->hlpmsg = s1;
- p->dflt = s2;
- p->sdata = s3;
- p->ndata1 = n1;
- p->ndata2 = n2;
- p->spf = f;
- p->kwdtbl = k;
- p->nxtfdb = nxt;
- }
- /* C M F D B -- Parse a field with several possible functions */
- int
- cmfdb(fdbin) struct FDB * fdbin; {
- #ifndef NOSPL
- extern int x_ifnum; /* IF NUMERIC - disables warnings */
- #endif /* NOSPL */
- struct FDB * in = fdbin;
- struct OFDB * out = &cmresult;
- int x = 0, n;
- char *s, *xp, *m = NULL;
- int errbits = 0;
- xp = bp;
- out->fcode = -1; /* Initialize output struct */
- out->fdbaddr = NULL;
- out->sresult = NULL;
- out->nresult = 0;
- /*
- Currently we make one trip through the FDBs. So if the user types Esc or
- Tab at the beginning of a field, only the first FDB is examined for a
- default. If the user types ?, help is given only for one FDB. We should
- search through the FDBs for all matching possibilities -- and in particular
- display the pertinent context-sensitive help for each function, rather than
- the only the first one that works, and then rewind the FDB pointer so we
- are not locked out of the earlier ones.
- */
- cmfldflgs = 0;
- while (1) { /* Loop through the chain of FDBs */
- nomsg = 1;
- xcmfdb = 1;
- s = NULL;
- n = 0;
- debug(F101,"cmfdb in->fcode","",in->fcode);
- switch (in->fcode) { /* Current parsing function code */
- case _CMNUM:
- #ifndef NOSPL
- x_ifnum = 1; /* Disables warning messages */
- #endif /* NOSPL */
- x = cmnum(in->hlpmsg,in->dflt,10,&n,in->spf);
- #ifndef NOSPL
- x_ifnum = 0;
- #endif /* NOSPL */
- debug(F101,"cmfdb cmnum","",x);
- if (x < 0) errbits |= 1;
- break;
- case _CMOFI:
- x = cmofi(in->hlpmsg,in->dflt,&s,in->spf);
- debug(F101,"cmfdb cmofi","",x);
- if (x < 0) errbits |= 2;
- break;
- case _CMIFI:
- x = cmifi2(in->hlpmsg,
- in->dflt,
- &s,
- &n,
- in->ndata1,
- in->sdata,
- in->spf,
- in->ndata2
- );
- debug(F101,"cmfdb cmifi2 x","",x);
- debug(F101,"cmfdb cmifi2 n","",n);
- if (x < 0) errbits |= 4;
- break;
- case _CMFLD:
- cmfldflgs = in->ndata1;
- x = cmfld(in->hlpmsg,in->dflt,&s,in->spf);
- debug(F101,"cmfdb cmfld","",x);
- if (x < 0) errbits |= 8;
- break;
- case _CMTXT:
- x = cmtxt(in->hlpmsg,in->dflt,&s,in->spf);
- debug(F101,"cmfdb cmtxt","",x);
- if (x < 0) errbits |= 16;
- break;
- case _CMKEY:
- x = cmkey2(in->kwdtbl,
- in->ndata1,
- in->hlpmsg,in->dflt,in->sdata,in->spf,in->ndata2);
- debug(F101,"cmfdb cmkey","",x);
- if (x < 0) errbits |= ((in->ndata2 & 4) ? 32 : 64);
- break;
- case _CMCFM:
- x = cmcfm();
- debug(F101,"cmfdb cmcfm","",x);
- if (x < 0) errbits |= 128;
- break;
- default:
- debug(F101,"cmfdb - unexpected function code","",in->fcode);
- printf("?cmfdb - unexpected function code: %dn",in->fcode);
- }
- debug(F101,"cmfdb x","",x);
- debug(F101,"cmfdb cmflgs","",cmflgs);
- debug(F101,"cmfdb crflag","",crflag);
- debug(F101,"cmfdb qmflag","",qmflag);
- debug(F101,"cmfdb esflag","",esflag);
- if (x > -1) { /* Success */
- out->fcode = in->fcode; /* Fill in output struct */
- out->fdbaddr = in;
- out->sresult = s;
- out->nresult = (in->fcode == _CMKEY) ? x : n;
- out->kflags = (in->fcode == _CMKEY) ? cmkwflgs : 0;
- debug(F101,"cmfdb out->nresult","",out->nresult);
- nomsg = 0;
- xcmfdb = 0;
- debug(F111,"cmfdb cmdbuf & crflag",cmdbuf,crflag);
- if (crflag) {
- cmflgs = 1;
- #ifdef CK_RECALL
- debug(F101,"cmfdb code","",in->fcode);
- if (in->fcode != _CMCFM)
- addcmd(cmdbuf);
- #endif /* CK_RECALL */
- }
- return(x); /* and return */
- }
- in = in->nxtfdb; /* Failed, get next parsing function */
- nomsg = 0;
- xcmfdb = 0;
- if (!in) { /* No more */
- debug(F101,"cmfdb failure x","",x);
- debug(F101,"cmfdb failure errbits","",errbits);
- if (x == -6)
- x = -9;
- if (x == -9) {
- /* Make informative messages for a few common cases */
- switch (errbits) {
- case 4+32: m = "Does not match filename or switch"; break;
- case 4+64: m = "Does not match filename or keyword"; break;
- case 1+32: m = "Not a number or valid keyword"; break;
- case 1+64: m = "Not a number or valid switch"; break;
- default: m = "Not valid in this position";
- }
- printf("?%s: "%s"n",m, atmbuf);
- }
- return(x);
- }
- if (x != -2 && x != -6 && x != -9 && x != -3) /* Editing or somesuch */
- return(x); /* Go back and reparse */
- pp = np = bp = xp; /* Back up pointers */
- cmflgs = -1; /* Force a reparse */
- #ifndef NOSPL
- if (!askflag) { /* If not executing ASK-class cmd... */
- #endif /* NOSPL */
- if (crflag) { /* If CR was typed, put it back */
- pushc = LF; /* But as a linefeed */
- } else if (qmflag) { /* Ditto for Question mark */
- pushc = '?';
- } else if (esflag) { /* and Escape or Tab */
- pushc = ESC;
- }
- #ifndef NOSPL
- }
- #endif /* NOSPL */
- }
- }
- #ifdef OLDHELP
- /* Keyword help routines */
- /* C L R H L P -- Initialize/Clear the help line buffer */
- static VOID
- clrhlp() { /* Clear the help buffer */
- hlpbuf[0] = NUL;
- hh = hx = 0;
- }
- /* A D D H L P -- Add a string to the help line buffer */
- static VOID
- addhlp(s) char *s; { /* Add a word to the help buffer */
- int j;
- hh++; /* Count this column */
- for (j = 0; (j < hc) && (*s != NUL); j++) { /* Fill the column */
- hlpbuf[hx++] = *s++;
- }
- if (*s != NUL) /* Still some chars left in string? */
- hlpbuf[hx-1] = '+'; /* Mark as too long for column. */
- if (hh < (hw / hc)) { /* Pad col with spaces if necessary */
- for (; j < hc; j++) {
- hlpbuf[hx++] = SP;
- }
- } else { /* If last column, */
- hlpbuf[hx++] = NUL; /* no spaces. */
- dmphlp(); /* Print it. */
- return;
- }
- }
- /* D M P H L P -- Dump the help line buffer */
- static VOID
- dmphlp() { /* Print the help buffer */
- hlpbuf[hx++] = NUL;
- if ( hlpbuf[0] )
- printf(" %sn",hlpbuf);
- clrhlp();
- }
- #endif /* OLDHELP */
- /* G T W O R D -- Gets a "word" from the command input stream */
- /*
- Usage: retcode = gtword(brk);
- brk = 0 for normal word breaks (space, CR, Esc, ?)
- brk = 1 to add / : = (for parsing switches)
- Returns:
- -10 Timelimit set and timed out
- -9 if input was too long
- -4 if end of file (e.g. pipe broken)
- -3 if null field
- -2 if command buffer overflows
- -1 if user did some deleting
- 0 if word terminates with SP or tab
- 1 if ... CR
- 2 if ... ESC
- 3 if ... ? (question mark)
- 4 if ... : or = and called with brk != 0
- With:
- pp pointing to beginning of word in buffer
- bp pointing to after current position
- atmbuf containing a copy of the word
- cc containing the number of characters in the word copied to atmbuf
- */
- int
- ungword() { /* Unget a word */
- debug(F101,"ungword cmflgs","",cmflgs);
- if (ungw) return(0);
- cmfsav = cmflgs;
- ungw = 1;
- cmflgs = 0;
- return(0);
- }
- /* Un-un-get word. Undo ungword() if it has been done. */
- VOID
- unungw() {
- debug(F110,"unungw atmbuf",atmbuf,cmflgs);
- if (ungw) {
- ungw = 0;
- cmflgs = cmfsav;
- atmbuf[0] = NUL;
- }
- }
- static int
- gtword(brk) int brk; {
- int c; /* Current char */
- int quote = 0; /* Flag for quote character */
- int echof = 0; /* Flag for whether to echo */
- int comment = 0; /* Flag for in comment */
- char *cp = NULL; /* Comment pointer */
- int eintr = 0;
- int bracelvl = 0; /* nested brace counter [jrs] */
- int iscontd = 0;
- char lastchar = NUL;
- char prevchar = NUL;
- char lbrace, rbrace;
- #ifdef RTU
- extern int rtu_bug;
- #endif /* RTU */
- #ifdef IKSD
- extern int inserver;
- #endif /* IKSD */
- #ifdef CK_LOGIN
- extern int x_logged;
- #endif /* CK_LOGIN */
- extern int kstartactive;
- #ifdef datageneral
- extern int termtype; /* DG terminal type flag */
- extern int con_reads_mt; /* Console read asynch is active */
- if (con_reads_mt) connoi_mt(); /* Task would interfere w/cons read */
- #endif /* datageneral */
- if (cmfldflgs & 1) {
- lbrace = '(';
- rbrace = ')';
- } else {
- lbrace = '{';
- rbrace = '}';
- }
- crflag = 0;
- qmflag = 0;
- esflag = 0;
- if (swarg) { /* No leading space for switch args */
- inword = 1;
- swarg = 0;
- }
- debug(F000,"gtword brkchar","",brkchar);
- debug(F101,"gtword brk","",brk);
- if (ungw) { /* Have a word saved? */
- int x;
- debug(F110,"gtword ungetting from pp",pp,0);
- while (*pp++ == SP) ;
- if (setatm(pp,2) < 0) {
- printf("?Saved word too longn");
- return(-9);
- }
- strncpy(atmbuf,pp,ATMBL);
- atmbuf[ATMBL] = NUL;
- x = strlen(atmbuf);
- while (x > 0 && atmbuf[x-1] == SP) /* Trim trailing spaces */
- atmbuf[--x] = NUL;
- ungw = 0;
- cmflgs = cmfsav;
- debug(F111,"gtword returning atmbuf",atmbuf,cmflgs);
- return(cmflgs);
- }
- pp = np; /* Start of current field */
- debug(F110,"gtword cmdbuf",cmdbuf,0);
- debug(F110,"gtword bp",bp,0);
- debug(F110,"gtword pp",pp,0);
- while (bp < cmdbuf+CMDBL) { /* Big get-a-character loop */
- echof = 0; /* Assume we don't echo because */
- chsrc = 0; /* character came from reparse buf. */
- #ifdef BS_DIRSEP
- CMDIRPARSE:
- #endif /* BS_DIRSEP */
- c = *bp;
- if (!c) { /* If no char waiting in reparse buf */
- if (dpx && (!pushc
- #ifndef NOSPL
- || askflag
- #endif /* NOSPL */
- )) /* get from tty, set echo flag */
- echof = 1;
- debug(F101,"gtword timelimit","",timelimit);
- c = cmdgetc(timelimit); /* Read a command character. */
- debug(F101,"gtword c","",c);
- debug(F111,"gtword dpx,echof",ckitoa(dpx),echof);
- if (timelimit && c < -1) { /* Timed out */
- return(-10);
- }
- #ifndef NOXFER
- /*
- The following allows packet recognition in the command parser.
- Presently it works only for Kermit packets, and if our current protocol
- happens to be anything besides Kermit, we simply force it to Kermit.
- We don't use the APC mechanism here for mechanical reasons, and also
- because this way, it works even with minimally configured interactive
- versions. Add Zmodem later...
- */
- #ifdef CK_AUTODL
- if (!local && cmdadl /* Autodownload enabled? */
- #ifdef IKS_OPTION
- || TELOPT_SB(TELOPT_KERMIT).kermit.me_start
- #endif /* IKS_OPTION */
- ) {
- int k;
- k = kstart((CHAR)c); /* Kermit S or I packet? */
- if (k) {
- int ksign = 0;
- if (k < 0) { /* Minus-Protocol? */
- #ifdef NOSERVER
- goto noserver; /* Need server mode for this */
- #else
- ksign = 1; /* Remember */
- k = 0 - k; /* Convert to actual protocol */
- justone = 1; /* Flag for protocol module */
- #endif /* NOSERVER */
- } else
- justone = 0;
- k--; /* Adjust kstart's return value */
- if (k == PROTO_K) {
- extern int protocol, g_proto;
- extern CHAR sstate;
- g_proto = protocol;
- protocol = PROTO_K; /* Crude... */
- sstate = ksign ? 'x' : 'v';
- cmdbuf[0] = NUL;
- return(-3);
- }
- }
- }
- #ifdef NOSERVER
- noserver:
- #endif /* NOSERVER */
- #endif /* CK_AUTODL */
- #endif /* NOXFER */
- chsrc = 1; /* Remember character source is tty. */
- brkchar = c;
- #ifdef IKSD
- if (inserver && c < 0) { /* End of session? */
- debug(F111,"gtword c < 0","exiting",c);
- return(-4); /* Cleanup and terminate */
- }
- #endif /* IKSD */
- #ifdef OS2
- if (c < 0) { /* Error */
- if (c == -3) { /* Empty word? */
- if (blocklvl > 0) /* In a block */
- continue; /* so keep looking for block end */
- else
- return(-3); /* Otherwise say we got nothing */
- } else { /* Not empty word */
- return(-4); /* So some kind of i/o error */
- }
- }
- #else
- #ifdef MAC
- if (c == -3) /* Empty word... */
- if (blocklvl > 0)
- continue;
- else
- return(-3);
- #endif /* MAC */
- #endif /* OS2 */
- if (c == EOF) { /* This can happen if stdin not tty. */
- #ifdef EINTR
- /*
- Some operating and/or C runtime systems return EINTR for no good reason,
- when the end of the standard input "file" is encountered. In cases like
- this, we get into an infinite loop; hence the eintr counter, which is reset
- to 0 upon each call to this routine.
- */
- debug(F101,"gtword EOF","",errno);
- if (errno == EINTR && ++eintr < 4) /* When bg'd process is */
- continue; /* fg'd again. */
- #endif /* EINTR */
- return(-4);
- }
- c &= cmdmsk; /* Strip any parity bit */
- } /* if desired. */
- /* Now we have the next character */
- debug(F000,"gtword char","",c);
- if (quote && (c == CR || c == LF)) { /* Enter key following quote */
- *bp++ = CMDQ; /* Double it */
- *bp = NUL;
- quote = 0;
- }
- if (quote == 0) { /* If this is not a quoted character */
- if (c == CMDQ) { /* Got the quote character itself */
- if (!comment && quoting)
- quote = 1; /* Flag it if not in a comment */
- }
- if (c == FF) { /* Formfeed. */
- c = NL; /* Replace with newline */
- cmdclrscn(); /* Clear the screen */
- }
- if (c == HT) { /* Tab */
- if (comment) /* If in comment, */
- c = SP; /* substitute space */
- else /* otherwise */
- c = ESC; /* substitute ESC (for completion) */
- }
- if (c == ';' || c == '#') { /* Trailing comment */
- if (inword == 0 && quoting) { /* If not in a word */
- comment = 1; /* start a comment. */
- cp = bp; /* remember where it starts. */
- }
- }
- if (!kstartactive && /* Not in possible Kermit packet */
- !comment && c == SP) { /* Space not in comment */
- *bp++ = (char) c; /* deposit in buffer if not already */
- debug(F101,"gtword echof 2","",echof);
- #ifdef BEBOX
- if (echof) {
- putchar(c); /* echo it. */
- fflush(stdout);
- fflush(stderr);
- }
- #else
- if (echof) { /* echo it. */
- putchar((CHAR)c);
- if (timelimit)
- fflush(stdout);
- }
- #endif /* BEBOX */
- if (inword == 0) { /* If leading, gobble it. */
- pp++;
- continue;
- } else { /* If terminating, return. */
- if ((*pp != lbrace) || (bracelvl == 0)) {
- np = bp;
- cmbptr = np;
- if (setatm(pp,0) < 0) {
- printf("?Field too long error 1n");
- debug(F111,"gtword too long #1",pp,strlen(pp));
- return(-9);
- }
- brkchar = c;
- inword = cmflgs = 0;
- return(0);
- }
- continue;
- }
- }
- if (!kstartactive && !comment && brk && (c == '=' || c == ':')) {
- *bp++ = (char) c;
- #ifdef BEBOX
- if (echof) {
- putchar(c); /* echo it. */
- fflush(stdout);
- fflush(stderr);
- }
- #else
- if (echof) {
- putchar((CHAR)c);
- if (timelimit)
- fflush(stdout);
- }
- #endif /* BEBOX */
- if ((*pp != lbrace) || (bracelvl == 0)) {
- np = bp;
- cmbptr = np;
- if (setatm(pp,0) < 0) {
- printf("?Field too long error 1n");
- debug(F111,"gtword too long #1",pp,strlen(pp));
- return(-9);
- }
- inword = cmflgs = 0;
- brkchar = c;
- return(4);
- }
- }
- if (c == lbrace)
- bracelvl++;
- if (c == rbrace) {
- bracelvl--;
- if (linebegin)
- blocklvl--;
- }
- if (c == LF || c == CR) { /* CR or LF. */
- if (echof) {
- cmdnewl((char)c); /* echo it. */
- #ifdef BEBOX
- fflush(stdout);
- fflush(stderr);
- #endif /* BEBOX */
- }
- {
- /* Trim trailing comment and whitespace */
- char *qq;
- if (comment) { /* Erase comment */
- while (bp >= cp) /* Back to comment pointer */
- *bp-- = NUL;
- bp++;
- pp = bp; /* Adjust other pointers */
- inword = 0; /* and flags */
- comment = 0;
- cp = NULL;
- }
- qq = inword ? pp : (char *)cmdbuf;
- /* Erase trailing whitespace */
- while (bp > qq && (*(bp-1) == SP || *(bp-1) == HT)) {
- bp--;
- debug(F000,"erasing","",*bp);
- *bp = NUL;
- }
- lastchar = (bp > qq) ? *(bp-1) : NUL;
- prevchar = (bp > qq+1) ? *(bp-2) : NUL;
- }
- if (linebegin && blocklvl > 0) /* Blank line in {...} block */
- continue;
- linebegin = 1; /* At beginning of next line */
- iscontd = prevchar != CMDQ &&
- (lastchar == '-' || lastchar == lbrace);
- debug(F101,"gtword iscontd","",iscontd);
- if (iscontd) { /* If line is continued... */
- if (chsrc) { /* If reading from tty, */
- if (*(bp-1) == lbrace) { /* Check for "begin block" */
- *bp++ = SP; /* Insert a space for neatness */
- blocklvl++; /* Count block nesting level */
- } else { /* Or hyphen */
- bp--; /* Overwrite the hyphen */
- }
- *bp = NUL; /* erase the dash, */
- continue; /* and go back for next char now. */
- }
- } else if (blocklvl > 0) { /* No continuation character */
- if (chsrc) { /* But we're in a "block" */
- *bp++ = ','; /* Add comma */
- *bp = NUL;
- continue;
- }
- } else { /* No continuation, end of command. */
- *bp = NUL; /* Terminate the command string. */
- if (comment) { /* If we're in a comment, */
- comment = 0; /* Say we're not any more, */
- *cp = NUL; /* cut it off. */
- }
- np = bp; /* Where to start next field. */
- cmbptr = np;
- if (setatm(pp,0) < 0) { /* Copy field to atom buffer */
- debug(F111,"gtword too long #2",pp,strlen(pp));
- printf("?Field too long error 2n");
- return(-9);
- }
- inword = 0; /* Not in a word any more. */
- crflag = 1;
- debug(F110,"gtword","crflag is set",0);
- return(cmflgs = 1);
- }
- }
- /* Question mark */
- if ((c == '?')
- && quoting
- && !kstartactive
- && !comment
- && cmdsrc() == 0 /* Commands coming from terminal */
- && chsrc != 0 /* and NOT from reparse buffer! */
- ) {
- putchar((CHAR)c);
- *bp = NUL;
- if (setatm(pp,0) < 0) {
- debug(F111,"gtword too long #3",pp,strlen(pp));
- printf("?Too long #3n");
- return(-9);
- }
- qmflag = 1;
- return(cmflgs = 3);
- }
- if (c == ESC) { /* ESC */
- if (!comment) {
- *bp = NUL;
- if (setatm(pp,0) < 0) {
- debug(F111,"gtword too long #4",pp,strlen(pp));
- printf("?Too long #4n");
- return(-9);
- }
- esflag = 1;
- return(cmflgs = 2);
- } else {
- bleep(BP_WARN);
- continue;
- }
- }
- if (c == BS || c == RUB) { /* Character deletion */
- if (bp > cmdbuf) { /* If still in buffer... */
- cmdchardel(); /* erase it. */
- bp--; /* point behind it, */
- #ifdef COMMENT
- if (*bp == SP) inword = 0; /* Flag if current field gone */
- #else
- /* fixed by Ulli Schlueter */
- if (*bp == lbrace) bracelvl--; /* Adjust brace count */
- if (*bp == rbrace) bracelvl++;
- if ((*bp == SP) && /* Flag if current field gone */
- (*pp != lbrace || bracelvl == 0))
- inword = 0;
- #endif /* COMMENT */
- *bp = NUL; /* Erase character from buffer. */
- } else { /* Otherwise, */
- bleep(BP_WARN);
- cmres(); /* and start parsing a new command. */
- *bp = *atmbuf = NUL;
- }
- if (pp < bp) continue;
- else return(cmflgs = -1);
- }
- if (c == LDEL) { /* ^U, line deletion */
- while ((bp--) > cmdbuf) {
- cmdchardel();
- *bp = NUL;
- }
- cmres(); /* Restart the command. */
- *bp = *atmbuf = NUL;
- inword = 0;
- return(cmflgs = -1);
- }
- if (c == WDEL) { /* ^W, word deletion */
- if (bp <= cmdbuf) { /* Beep if nothing to delete */
- bleep(BP_WARN);
- cmres();
- *bp = *atmbuf = NUL;
- return(cmflgs = -1);
- }
- bp--;
- /* Back up over any trailing nonalphanums */
- /* This is dependent on ASCII collating sequence */
- /* but isalphanum() is not available everywhere. */
- for ( ; (bp >= cmdbuf) &&
- (*bp < '0') ||
- (*bp > '9' && *bp < '@') ||
- (*bp > 'Z' && *bp < 'a') ||
- (*bp > 'z') ; bp--) {
- cmdchardel();
- *bp = NUL;
- }
- /* Now delete back to rightmost remaining nonalphanum */
- for ( ; (bp >= cmdbuf) && (*bp) ; bp--) {
- if ((*bp < '0') ||
- (*bp > '9' && *bp < '@') ||
- (*bp > 'Z' && *bp < 'a') ||
- (*bp > 'z'))
- break;
- cmdchardel();
- *bp = NUL;
- }
- bp++;
- inword = 0;
- return(cmflgs = -1);
- }
- if (c == RDIS) { /* ^R, redisplay */
- #ifdef COMMENT
- *bp = NUL;
- printf("n%s%s",cmprom,cmdbuf);
- #else
- char *cpx; char cx;
- *bp = NUL;
- printf("n%s",cmprom);
- cpx = cmdbuf;
- while (cx = *cpx++) {
- #ifdef isprint
- putchar((CHAR) (isprint(cx) ? cx : '^'));
- #else
- putchar((CHAR) ((cx >= SP && cx < DEL) ? cx : '^'));
- #endif /* isprint */
- }
- #endif /* COMMENT */
- fflush(stdout);
- continue;
- }
- #ifdef CK_RECALL
- if (chsrc && on_recall && /* Reading commands from keyboard? */
- (cm_recall > 0) && /* Saving commands? */
- (c == C_UP || c == C_UP2)) { /* Go up one */
- if (current < 0) { /* Nowhere to go, */
- bleep(BP_WARN);
- continue;
- }
- if (recall[current]) {
- if (!strcmp(recall[current],cmdbuf)) {
- if (current > 0) {
- current--;
- } else {
- bleep(BP_WARN);
- continue;
- }
- }
- }
- if (recall[current]) { /* We have a previous command */
- while ((bp--) > cmdbuf) { /* Erase current line */
- cmdchardel();
- *bp = NUL;
- }
- ckstrncpy(cmdbuf,recall[current],CMDBL);
- #ifdef OSK
- fflush(stdout);
- write(fileno(stdout), "r", 1);
- printf("%s%s",cmprom,cmdbuf);
- #else
- printf("r%s%s",cmprom,cmdbuf);
- #endif /* OSK */
- current--;
- }
- return(cmflgs = -1); /* Force a reparse */
- }
- if (chsrc && on_recall && /* Reading commands from keyboard? */
- (cm_recall > 0) && /* Saving commands? */
- (c == C_DN)) { /* Down one */
- if (current + 1 > rlast) { /* Already at bottom, just beep */
- bleep(BP_WARN);
- continue;
- }
- current++; /* OK to go down */
- if (recall[current]) {
- if (!strcmp(recall[current],cmdbuf)) {
- if (current + 1 > rlast) { /* At bottom, beep */
- bleep(BP_WARN);
- continue;
- } else
- current++;
- }
- }
- if (recall[current]) {
- while ((bp--) > cmdbuf) { /* Erase current line */
- cmdchardel();
- *bp = NUL;
- }
- ckstrncpy(cmdbuf,recall[current],CMDBL);
- #ifdef OSK
- fflush(stdout);
- write(fileno(stdout), "r", 1);
- printf("%s%s",cmprom,cmdbuf);
- #else
- printf("r%s%s",cmprom,cmdbuf);
- #endif /* OSK */
- return(cmflgs = -1); /* Force reparse */
- }
- }
- #endif /* CK_RECALL */
- if (c < SP && quote == 0) { /* Any other unquoted control char */
- if (!chsrc) { /* If cmd file, point past it */
- bp++;
- } else {
- bleep(BP_WARN);
- }
- continue; /* continue, don't put in buffer */
- }
- linebegin = 0; /* Not at beginning of line */
- #ifdef BEBOX
- if (echof) {
- cmdecho((char) c, 0); /* Echo what was typed. */
- fflush (stdout);
- fflush(stderr);
- }
- #else
- if (echof) cmdecho((char) c, 0); /* Echo what was typed. */
- #endif /* BEBOX */
- } else { /* This character was quoted. */
- int qf = 1;
- quote = 0; /* Unset the quote flag. */
- debug(F000,"gtword quote 0","",c);
- /* Quote character at this level is only for SP, ?, and controls */
- /* If anything else was quoted, leave quote in, and let */
- /* the command-specific parsing routines handle it, e.g.