static const char* parse_char(const char* ptr, char* out) { int o; switch (*ptr) { case 0: return ptr; case '\\': switch (*++ptr) { case 'n': *out = '\n'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': o = *ptr - '0'; if (isoctal(ptr[1])) { o = (o << 3) | (*++ptr - '0'); if (isoctal(ptr[1])) o = (o << 3) | (*++ptr - '0'); } *out = 0; break; default: *out = *ptr; } break; default: *out = *ptr; } return ptr + 1; }
int xgettok(XFILE *xfp, char sepa, char *tok, int len) { int i = 0; int c = 0; int quoted=0; while (i < len && (c = xgetc(xfp)) != EOF && (quoted || (c != sepa && !isspace(c)))) { if (c == '"') { quoted = !quoted; continue; } tok[i++] = c; if (i >= 4 && tok[i-4] == '\\' && isoctal(tok[i-3]) && isoctal(tok[i-2]) && isoctal(tok[i-1]) && ((tok[i]=0), (c = strtol(tok+i-3,NULL, 8)) < 256)) { i -= 4; tok[i++] = c; } } if (c == '\n') xungetc(c, xfp); if (!i) return 0; if (i >= len || (sepa && c != sepa)) return -1; tok[i] = '\0'; return 1; }
int scancreate (SCAN *scan, LOGSET *logset) { struct passwd *passwd; struct group *group; while (isblank (*scan->cp)) { ++scan->cp; } if (isoctal (*scan->cp)) { logset->mode = (mode_t) (0); for (scan->sp = scan->token; isoctal (*scan->cp); *scan->sp++ = *scan->cp++) { logset->mode <<= 3; logset->mode += *scan->cp - '0'; } *scan->sp = (char) (0); if (!isblank (*scan->cp) && !isbreak (*scan->cp)) { error (0, 0, "%s:%d create mode %s has illegal octal syntax.", scan->file, scan->line, scan->token); return (1); } while (isblank (*scan->cp)) { ++scan->cp; } } if (isalnum (*scan->cp)) { for (scan->sp = scan->token; isalnum (*scan->cp); *scan->sp++ = *scan->cp++); *scan->sp = (char) (0); if ((passwd = getpwnam (scan->token)) == (struct passwd *) (0)) { error (0, 0, "%s:%d user '%s' does not exist on this host.", scan->file, scan->line, scan->token); return (1); } logset->uid = passwd->pw_uid; endpwent (); } if (isgroup (*scan->cp)) { ++scan->cp; for (scan->sp = scan->token; isalnum (*scan->cp); *scan->sp++ = *scan->cp++); *scan->sp = (char) (0); if ((group = getgrnam (scan->token)) == (struct group *) (0)) { error (0, 0, "%s:%d group '%s' does not exist on this host.", scan->file, scan->line, scan->token); return (1); } logset->gid = group->gr_gid; endgrent (); } return (0); }
/* process one , two or three octal digits moving a pointer forward by reference */ static int octal(char **start_p) { register char *p = *start_p; register unsigned x; x = (unsigned) (*p++ - '0'); if (isoctal(*p)) { x = (x << 3) + (unsigned) (*p++ - '0'); if (isoctal(*p)) x = (x << 3) + (unsigned) (*p++ - '0'); } *start_p = p; return (int) (x & 0xff); }
/*********************************************************************** # # Routine : GeneralCmds_DoUmask # # Purpose : Umask command. # # Parameter: INPUT aPtr Application structure pointer # INPUT argc Argument count # INPUT argv Vector of pointers to arguments # # Returns : Nothing # #***********************************************************************/ void GeneralCmds_DoUmask(GeneralCmds_TheApplicationTypePtrType aPtr, int argc, const char **argv) { const char *cp; int mask; if (argc <= 1) { mask = umask(0); umask(mask); printf(" %03o\n", mask); return; } mask = 0; cp = argv[1]; while (isoctal(*cp)) mask = mask * 8 + *cp++ - '0'; if (*cp || (mask & ~0777)) { GeneralCmds_ShowUser(aPtr, "Bad umask value\n"); return; } umask(mask); }
uint8_t octalorliteral (char *string) { uint8_t rc; uint16_t numdigit; /* read in octal sequence */ for ( rc = 0, numdigit=0; isoctal(*string) && (numdigit<3); numdigit++ ) { rc *= (uint8_t) 8; rc += (uint8_t) (*string++ - '0'); } /* if it wasn't an octal sequence, take next char literal */ if (!numdigit) { rc = *++string; } #ifdef DIAG fprintf(stderr,"Octal %d\n",(int) rc); #endif return(rc); }
int main(int argc, char **argv) { char *cp; int mode; if (argc < 3) { fprintf(stderr, "You must specify a mode number and at least one file or directory.\n"); goto usage; } mode = 0; cp = argv[1]; while (isoctal(*cp)) mode = mode * 8 + (*cp++ - '0'); if (*cp) { fprintf(stderr, "Mode must be an octal number\n"); goto usage; } argc--; argv++; while (argc-- > 1) { if (chmod(argv[1], mode) < 0) perror(argv[1]); argv++; } exit(0); usage: fprintf(stderr, "usage: %s mode file1 [file2] ...\n", argv[0]); fprintf(stderr, "Mode must be specified as an octal number (i.e. 755 is 'rwxr-xr-x')\n"); exit(1); }
static void unescape_fstab(char *spec) { char *p, *q; p = q = spec; while (*p) { if (p[0] == '\\' && isoctal(p[1]) && isoctal(p[2]) && isoctal(p[3])) { *q++ = ((p[1] - '0') << 6) | ((p[2] - '0') << 3) | (p[3] - '0'); p += 3; } else *q++ = *p++; } }
static int16_t atoo(char *string) { int16_t sum = 0; if (!string) return(-1); for (;isoctal(*string);string++) { sum *= 8; sum += *string - '0'; } if ((sum<0)||(*string)) return(-1); else return(sum); }
/* *INDENT-ON* */ /* process the escape characters in a string, in place . */ char * rm_escape(char *s, size_t *lenp) { register char *p, *q; char *t; int i; q = p = s; while (*p) { if (*p == '\\') { escape_test[ET_END].in = *++p; /* sentinal */ i = 0; while (escape_test[i].in != *p) i++; if (i != ET_END) /* in table */ { p++; *q++ = escape_test[i].out; } else if (isoctal(*p)) { t = p; *q++ = (char) octal(&t); p = t; } else if (*p == 'x' && ishex(*(UChar *) (p + 1))) { t = p + 1; *q++ = (char) hex(&t); p = t; } else if (*p == 0) /* can only happen with command line assign */ *q++ = '\\'; else { /* not an escape sequence */ *q++ = '\\'; *q++ = *p++; } } else *q++ = *p++; } *q = 0; if (lenp != 0) *lenp = (unsigned) (q - s); return s; }
mode_t modespec (char const *string) { char const *sp = string; mode_t mode = 0; if (!string) { error (1, EINVAL, __func__); } while (isoctal (*sp)) { mode *= 8; mode += *sp++ - '0'; } if (*sp) { error (1, EINVAL, "[%s]", string); } if ((mode < 0x0001) || (mode > 0x0FFF)) { error (1, EINVAL, "Mode %s exceeds range %04o to %04o", string, 0x0001, 0x0FFFF); } return (mode); }
/* * unvis - decode characters previously encoded by vis */ int unvis(char *cp, int c, int *astate, int flag) { if (flag & UNVIS_END) { if (*astate == S_OCTAL2 || *astate == S_OCTAL3) { *astate = S_GROUND; return (UNVIS_VALID); } return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD); } switch (*astate & ~S_HTTP) { case S_GROUND: *cp = 0; if (c == '\\') { *astate = S_START; return (0); } if (flag & VIS_HTTPSTYLE && c == '%') { *astate = S_START | S_HTTP; return (0); } *cp = c; return (UNVIS_VALID); case S_START: if (*astate & S_HTTP) { if (ishex(tolower(c))) { *cp = isdigit(c) ? (c - '0') : (tolower(c) - 'a'); *astate = S_HEX2; return (0); } } switch(c) { case '\\': *cp = c; *astate = S_GROUND; return (UNVIS_VALID); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': *cp = (c - '0'); *astate = S_OCTAL2; return (0); case 'M': *cp = 0200; *astate = S_META; return (0); case '^': *astate = S_CTRL; return (0); case 'n': *cp = '\n'; *astate = S_GROUND; return (UNVIS_VALID); case 'r': *cp = '\r'; *astate = S_GROUND; return (UNVIS_VALID); case 'b': *cp = '\b'; *astate = S_GROUND; return (UNVIS_VALID); case 'a': *cp = '\007'; *astate = S_GROUND; return (UNVIS_VALID); case 'v': *cp = '\v'; *astate = S_GROUND; return (UNVIS_VALID); case 't': *cp = '\t'; *astate = S_GROUND; return (UNVIS_VALID); case 'f': *cp = '\f'; *astate = S_GROUND; return (UNVIS_VALID); case 's': *cp = ' '; *astate = S_GROUND; return (UNVIS_VALID); case 'E': *cp = '\033'; *astate = S_GROUND; return (UNVIS_VALID); case '\n': /* * hidden newline */ *astate = S_GROUND; return (UNVIS_NOCHAR); case '$': /* * hidden marker */ *astate = S_GROUND; return (UNVIS_NOCHAR); } *astate = S_GROUND; return (UNVIS_SYNBAD); case S_META: if (c == '-') *astate = S_META1; else if (c == '^') *astate = S_CTRL; else { *astate = S_GROUND; return (UNVIS_SYNBAD); } return (0); case S_META1: *astate = S_GROUND; *cp |= c; return (UNVIS_VALID); case S_CTRL: if (c == '?') *cp |= 0177; else *cp |= c & 037; *astate = S_GROUND; return (UNVIS_VALID); case S_OCTAL2: /* second possible octal digit */ if (isoctal(c)) { /* * yes - and maybe a third */ *cp = (*cp << 3) + (c - '0'); *astate = S_OCTAL3; return (0); } /* * no - done with current sequence, push back passed char */ *astate = S_GROUND; return (UNVIS_VALIDPUSH); case S_OCTAL3: /* third possible octal digit */ *astate = S_GROUND; if (isoctal(c)) { *cp = (*cp << 3) + (c - '0'); return (UNVIS_VALID); } /* * we were done, push back passed char */ return (UNVIS_VALIDPUSH); case S_HEX2: /* second mandatory hex digit */ if (ishex(tolower(c))) { *cp = (isdigit(c) ? (*cp << 4) + (c - '0') : (*cp << 4) + (tolower(c) - 'a' + 10)); } *astate = S_GROUND; return (UNVIS_VALID); default: /* * decoder in unknown state - (probably uninitialized) */ *astate = S_GROUND; return (UNVIS_SYNBAD); } }
char * oescape::unescape (register char * string) { register char * sp = string; register char * cp = string; if (string) for (sp = cp = string; (* sp = * cp++); ++ sp) { if (* sp == '\\') { if (isoctal (* cp)) { unsigned digits = 3; while ((digits--) && isoctal (* cp)) { * sp *= 8; * sp += * cp++ - '0'; } continue; } if ((* cp == 'x') || (* cp == 'X')) { cp++; * sp = 0; if (oascii::isxdigit (* cp)) { * sp = (* sp << 4) + oascii::todigit (* cp++); } if (oascii::isxdigit (* cp)) { * sp = (* sp << 4) + oascii::todigit (* cp++); } continue; } #if oESCAPE_NOTABLE switch (* cp) { case 'a': * sp = '\a'; break; case 'b': * sp = '\b'; break; case 'f': * sp = '\f'; break; case 'n': * sp = '\n'; break; case 'r': * sp = '\r'; break; case 't': * sp = '\t'; break; case 'v': * sp = '\v'; break; case '?': * sp = '\?'; break; case '\'': * sp = '\''; break; case '\"': * sp = '\"'; break; case '\\': * sp = '\\'; break; default: * sp = * cp; break; } cp++; #else * sp = oescape::unescape (* cp++); #endif continue; } #if oESCAPE_ISO_646_1983 if (* sp == '?') { if (* cp == '?') { switch (* ++ cp) { case '=': * sp = '#'; break; case '(': * sp = '['; break; case '/': * sp = '\\'; break; case ')': * sp = ']'; break; case '\'': * sp = '^'; break; case '<': * sp = '{'; break; case '!': * sp = '|'; break; case '>': * sp = '}'; break; case '-': * sp = '~'; break; default: * ++ sp = '?'; * ++ sp = * cp; break; } cp++; } continue; } #endif if (* sp == '^') { * sp = oascii::tocntrl (* cp++); continue; } } return (string); }
/* * 'Clean up' this string. */ static char *clean( char *s, int sending ) /* set to 1 when sending (putting) this string. */ { char temp[STR_LEN], env_str[STR_LEN], cur_chr; register char *s1, *phchar; int add_return = sending; #define isoctal(chr) (((chr) >= '0') && ((chr) <= '7')) #define isalnumx(chr) ((((chr) >= '0') && ((chr) <= '9')) \ || (((chr) >= 'a') && ((chr) <= 'z')) \ || (((chr) >= 'A') && ((chr) <= 'Z')) \ || (chr) == '_') s1 = temp; while (*s) { cur_chr = *s++; if (cur_chr == '^') { cur_chr = *s++; if (cur_chr == '\0') { *s1++ = '^'; break; } cur_chr &= 0x1F; if (cur_chr != 0) { *s1++ = cur_chr; } continue; } if (use_env && cur_chr == '$') { /* ARI */ phchar = env_str; while (isalnumx(*s)) *phchar++ = *s++; *phchar = '\0'; phchar = getenv(env_str); if (phchar) while (*phchar) *s1++ = *phchar++; continue; } if (cur_chr != '\\') { *s1++ = cur_chr; continue; } cur_chr = *s++; if (cur_chr == '\0') { if (sending) { *s1++ = '\\'; *s1++ = '\\'; } break; } switch (cur_chr) { case 'b': *s1++ = '\b'; break; case 'c': if (sending && *s == '\0') add_return = 0; else *s1++ = cur_chr; break; case '\\': case 'K': case 'p': case 'd': if (sending) *s1++ = '\\'; *s1++ = cur_chr; break; case 'T': if (sending && phone_num) { for (phchar = phone_num; *phchar != '\0'; phchar++) *s1++ = *phchar; } else { *s1++ = '\\'; *s1++ = 'T'; } break; case 'U': if (sending && phone_num2) { for (phchar = phone_num2; *phchar != '\0'; phchar++) *s1++ = *phchar; } else { *s1++ = '\\'; *s1++ = 'U'; } break; case 'q': quiet = 1; break; case 'r': *s1++ = '\r'; break; case 'n': *s1++ = '\n'; break; case 's': *s1++ = ' '; break; case 't': *s1++ = '\t'; break; case 'N': if (sending) { *s1++ = '\\'; *s1++ = '\0'; } else *s1++ = 'N'; break; case '$': /* ARI */ if (use_env) { *s1++ = cur_chr; break; } /* FALL THROUGH */ default: if (isoctal (cur_chr)) { cur_chr &= 0x07; if (isoctal (*s)) { cur_chr <<= 3; cur_chr |= *s++ - '0'; if (isoctal (*s)) { cur_chr <<= 3; cur_chr |= *s++ - '0'; } } if (cur_chr != 0 || sending) { if (sending && (cur_chr == '\\' || cur_chr == 0)) *s1++ = '\\'; *s1++ = cur_chr; } break; } if (sending) *s1++ = '\\'; *s1++ = cur_chr; break; } } if (add_return) *s1++ = '\r'; *s1++ = '\0'; /* guarantee closure */ *s1++ = '\0'; /* terminate the string */ return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */ }
/* * v_increment -- [count]#[#+-] * Increment/decrement a keyword number. * * PUBLIC: int v_increment __P((SCR *, VICMD *)); */ int v_increment(SCR *sp, VICMD *vp) { enum nresult nret; u_long ulval; long change, ltmp, lval; size_t beg, blen, end, len, nlen, wlen; int base, isempty, rval; CHAR_T *ntype, nbuf[100]; CHAR_T *bp, *p, *t; /* Validate the operator. */ if (vp->character == '#') vp->character = '+'; if (vp->character != '+' && vp->character != '-') { v_emsg(sp, vp->kp->usage, VIM_USAGE); return (1); } /* If new value set, save it off, but it has to fit in a long. */ if (F_ISSET(vp, VC_C1SET)) { if (vp->count > LONG_MAX) { inc_err(sp, NUM_OVER); return (1); } change = vp->count; } else change = 1; /* Get the line. */ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) { if (isempty) goto nonum; return (1); } /* * Skip any leading space before the number. Getting a cursor word * implies moving the cursor to its beginning, if we moved, refresh * now. */ for (beg = vp->m_start.cno; beg < len && ISSPACE(p[beg]); ++beg); if (beg >= len) goto nonum; if (beg != vp->m_start.cno) { sp->cno = beg; (void)vs_refresh(sp, 0); } #undef ishex #define ishex(c) (ISXDIGIT(c)) #undef isoctal #define isoctal(c) ((c) >= '0' && (c) <= '7') /* * Look for 0[Xx], or leading + or - signs, guess at the base. * The character after that must be a number. Wlen is set to * the remaining characters in the line that could be part of * the number. */ wlen = len - beg; if (p[beg] == '0' && wlen > 2 && (p[beg + 1] == 'X' || p[beg + 1] == 'x')) { base = 16; end = beg + 2; if (!ishex(p[end])) goto decimal; ntype = p[beg + 1] == 'X' ? fmt[HEXC] : fmt[HEXL]; } else if (p[beg] == '0' && wlen > 1) { base = 8; end = beg + 1; if (!isoctal(p[end])) goto decimal; ntype = fmt[OCTAL]; } else if (wlen >= 1 && (p[beg] == '+' || p[beg] == '-')) { base = 10; end = beg + 1; ntype = fmt[SDEC]; if (!isdigit(p[end])) goto nonum; } else { decimal: base = 10; end = beg; ntype = fmt[DEC]; if (!isdigit(p[end])) { nonum: msgq(sp, M_ERR, "181|Cursor not in a number"); return (1); } } /* Find the end of the word, possibly correcting the base. */ while (++end < len) { switch (base) { case 8: if (isoctal(p[end])) continue; if (p[end] == '8' || p[end] == '9') { base = 10; ntype = fmt[DEC]; continue; } break; case 10: if (isdigit(p[end])) continue; break; case 16: if (ishex(p[end])) continue; break; default: abort(); /* NOTREACHED */ } break; } wlen = (end - beg); /* * XXX * If the line was at the end of the buffer, we have to copy it * so we can guarantee that it's NULL-terminated. We make the * buffer big enough to fit the line changes as well, and only * allocate once. */ GET_SPACE_RETW(sp, bp, blen, len + 50); if (end == len) { MEMMOVE(bp, &p[beg], wlen); bp[wlen] = '\0'; t = bp; } else t = &p[beg]; /* * Octal or hex deal in unsigned longs, everything else is done * in signed longs. */ if (base == 10) { if ((nret = nget_slong(&lval, t, NULL, 10)) != NUM_OK) goto err; ltmp = vp->character == '-' ? -change : change; if (lval > 0 && ltmp > 0 && !NPFITS(LONG_MAX, lval, ltmp)) { nret = NUM_OVER; goto err; } if (lval < 0 && ltmp < 0 && !NNFITS(LONG_MIN, lval, ltmp)) { nret = NUM_UNDER; goto err; } lval += ltmp; /* If we cross 0, signed numbers lose their sign. */ if (lval == 0 && ntype == fmt[SDEC]) ntype = fmt[DEC]; nlen = SPRINTF(nbuf, sizeof(nbuf), ntype, lval); } else { if ((nret = nget_uslong(&ulval, t, NULL, base)) != NUM_OK) goto err; if (vp->character == '+') { if (!NPFITS(ULONG_MAX, ulval, change)) { nret = NUM_OVER; goto err; } ulval += change; } else { if (ulval < change) { nret = NUM_UNDER; goto err; } ulval -= change; } /* Correct for literal "0[Xx]" in format. */ if (base == 16) wlen -= 2; nlen = SPRINTF(nbuf, sizeof(nbuf), ntype, wlen, ulval); } /* Build the new line. */ MEMMOVE(bp, p, beg); MEMMOVE(bp + beg, nbuf, nlen); MEMMOVE(bp + beg + nlen, p + end, len - beg - (end - beg)); len = beg + nlen + (len - beg - (end - beg)); nret = NUM_OK; rval = db_set(sp, vp->m_start.lno, bp, len); if (0) { err: rval = 1; inc_err(sp, nret); } if (bp != NULL) FREE_SPACEW(sp, bp, blen); return (rval); }
static char translate_escape(char **s) /***************************************************************************** * translate the character(s) after a '\' into a single character. ****************************************************************************/ { char *in_str; short counter; char inchar; char outchar; in_str = *s; switch (inchar = *in_str++) { case 'a': outchar = '\a'; break; case 'b': outchar = '\b'; break; case 'f': outchar = '\f'; break; case 'n': outchar = '\n'; break; case 'r': outchar = '\r'; break; case 't': outchar = '\t'; break; case 'v': outchar = '\v'; break; case '?': outchar = '\?'; break; case '\\': outchar = '\\'; break; case '\'': outchar = '\''; break; case '\"': outchar = '\"'; break; case 'x': outchar = 0; inchar = *in_str; while (isxdigit(inchar)) { if (inchar <= '9') inchar -= '0'; else if (inchar <= 'F') inchar -= 'A' - 10; else inchar -= 'a' - 10; outchar = (outchar << 4) | inchar; inchar = *++in_str; } break; default: if (isoctal(inchar)) { counter = 4; outchar = 0; while (--counter) { outchar = (outchar << 3) | (inchar & 0x07); inchar = *in_str; if (isoctal(inchar)) ++in_str; else break; } } else outchar = inchar; break; } *s = in_str; return outchar; }
static int parse_modes (mode *table, char *string, uint16_t *num) { char *ptr; char *temptable[32]; uint16_t tempnum = 0; int i,i2,factor; /* call parse_patterns(). Clever, huh? */ if (parse_patterns(temptable,string,&tempnum,FALSE,TXT(T_TOO_MANY_MODES),32)==-1) return(-1); /* tempnum now has # of items in temptable, temptable has pointers to the individual mode specifiers */ if ((*num+tempnum)>Maxmodes) { fprintf (stderr,"%s (%d max)\n",TXT(T_TOO_MANY_MODES),Maxmodes); return(-1); } for (i=0;i<tempnum;i++) { ptr = temptable[i]; #ifdef DIAG fprintf(stderr,"parse_modes: parsing '%s'\n",ptr); #endif if (*ptr == NOT_CHARACTER) { ptr++; table[i+*num].negative = TRUE; } else table[i+*num].negative = FALSE; if (!*ptr) { fprintf(stderr,TXT(T_ILLEGAL_MODE_SPEC),temptable[i]); exit(0xBAD); } /* is it a nonnegative octal number? */ if (isoctal(*ptr)) { int j; j = atoo(ptr); if (j<0) { fprintf(stderr,TXT(T_NUM_OUT_OF_RANGE),temptable[i]); exit(0xBAD); } else { #ifdef DIAG fprintf(stderr,"parse_modes: got octal 0%o\n",j); #endif table[i+*num].fmode = j; } } else { /* it is a symbolic type definition */ for (factor=0;*ptr!='=';ptr++) { switch(*ptr) { case 'u': factor |= 0100; break; case 'g': factor |= 010; break; case 'o': factor |= 01; break; case 'a': factor = 0111; break; default: fprintf(stderr,TXT(T_ILLEGAL_MODE_SPEC),temptable[i]); exit(0xBAD); } } /* ptr now points to '=' */ for (++ptr,i2=0;*ptr;ptr++) { switch(*ptr) { case 'r': i2 |= S_IROTH; break; case 'w': i2 |= S_IWOTH; break; case 'x': case 's': i2 |= S_IXOTH; break; default: fprintf(stderr,TXT(T_ILLEGAL_MODE_SPEC),temptable[i]); exit(0xBAD); } } table[i+*num].fmode = i2*factor; #ifdef DIAG fprintf(stderr,"parse_modes: table[%d].fmode = 0%o\n",i+*num,table[i+*num].fmode); #endif } /* else */ } /* for */ *num += tempnum; return(0); }
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_unvis(char *cp, int c, int *astate, int flag) { _DIAGASSERT(cp != NULL); _DIAGASSERT(astate != NULL); if (flag & UNVIS_END) { if (*astate == S_OCTAL2 || *astate == S_OCTAL3) { *astate = S_GROUND; return (UNVIS_VALID); } return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD); } switch (*astate) { case S_GROUND: *cp = 0; if (c == '\\') { *astate = S_START; return (0); } *cp = c; return (UNVIS_VALID); case S_START: switch(c) { case '\\': *cp = c; *astate = S_GROUND; return (UNVIS_VALID); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': *cp = (c - '0'); *astate = S_OCTAL2; return (0); case 'M': *cp = (u_char)0200; *astate = S_META; return (0); case '^': *astate = S_CTRL; return (0); case 'n': *cp = '\n'; *astate = S_GROUND; return (UNVIS_VALID); case 'r': *cp = '\r'; *astate = S_GROUND; return (UNVIS_VALID); case 'b': *cp = '\b'; *astate = S_GROUND; return (UNVIS_VALID); case 'a': *cp = '\007'; *astate = S_GROUND; return (UNVIS_VALID); case 'v': *cp = '\v'; *astate = S_GROUND; return (UNVIS_VALID); case 't': *cp = '\t'; *astate = S_GROUND; return (UNVIS_VALID); case 'f': *cp = '\f'; *astate = S_GROUND; return (UNVIS_VALID); case 's': *cp = ' '; *astate = S_GROUND; return (UNVIS_VALID); case 'E': *cp = '\033'; *astate = S_GROUND; return (UNVIS_VALID); case '\n': /* * hidden newline */ *astate = S_GROUND; return (UNVIS_NOCHAR); case '$': /* * hidden marker */ *astate = S_GROUND; return (UNVIS_NOCHAR); } *astate = S_GROUND; return (UNVIS_SYNBAD); case S_META: if (c == '-') *astate = S_META1; else if (c == '^') *astate = S_CTRL; else { *astate = S_GROUND; return (UNVIS_SYNBAD); } return (0); case S_META1: *astate = S_GROUND; *cp |= c; return (UNVIS_VALID); case S_CTRL: if (c == '?') *cp |= 0177; else *cp |= c & 037; *astate = S_GROUND; return (UNVIS_VALID); case S_OCTAL2: /* second possible octal digit */ if (isoctal(c)) { /* * yes - and maybe a third */ *cp = (*cp << 3) + (c - '0'); *astate = S_OCTAL3; return (0); } /* * no - done with current sequence, push back passed char */ *astate = S_GROUND; return (UNVIS_VALIDPUSH); case S_OCTAL3: /* third possible octal digit */ *astate = S_GROUND; if (isoctal(c)) { *cp = (*cp << 3) + (c - '0'); return (UNVIS_VALID); } /* * we were done, push back passed char */ return (UNVIS_VALIDPUSH); default: /* * decoder in unknown state - (probably uninitialized) */ *astate = S_GROUND; return (UNVIS_SYNBAD); } }
/* * unvis - decode characters previously encoded by vis */ int unvis(char *cp, int c, int *astate, int flag) { unsigned char uc = (unsigned char)c; unsigned char st, ia, is, lc; /* * Bottom 8 bits of astate hold the state machine state. * Top 8 bits hold the current character in the http 1866 nv string decoding */ #define GS(a) ((a) & 0xff) #define SS(a, b) (((uint32_t)(a) << 24) | (b)) #define GI(a) ((uint32_t)(a) >> 24) _DIAGASSERT(cp != NULL); _DIAGASSERT(astate != NULL); st = GS(*astate); if (flag & UNVIS_END) { switch (st) { case S_OCTAL2: case S_OCTAL3: case S_HEX2: *astate = SS(0, S_GROUND); return UNVIS_VALID; case S_GROUND: return UNVIS_NOCHAR; default: return UNVIS_SYNBAD; } } switch (st) { case S_GROUND: *cp = 0; if ((flag & VIS_NOESCAPE) == 0 && c == '\\') { *astate = SS(0, S_START); return UNVIS_NOCHAR; } if ((flag & VIS_HTTP1808) && c == '%') { *astate = SS(0, S_HEX1); return UNVIS_NOCHAR; } if ((flag & VIS_HTTP1866) && c == '&') { *astate = SS(0, S_AMP); return UNVIS_NOCHAR; } if ((flag & VIS_MIMESTYLE) && c == '=') { *astate = SS(0, S_MIME1); return UNVIS_NOCHAR; } *cp = c; return UNVIS_VALID; case S_START: switch(c) { case '\\': *cp = c; *astate = SS(0, S_GROUND); return UNVIS_VALID; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': *cp = (c - '0'); *astate = SS(0, S_OCTAL2); return UNVIS_NOCHAR; case 'M': *cp = (char)0200; *astate = SS(0, S_META); return UNVIS_NOCHAR; case '^': *astate = SS(0, S_CTRL); return UNVIS_NOCHAR; case 'n': *cp = '\n'; *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'r': *cp = '\r'; *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'b': *cp = '\b'; *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'a': *cp = '\007'; *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'v': *cp = '\v'; *astate = SS(0, S_GROUND); return UNVIS_VALID; case 't': *cp = '\t'; *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'f': *cp = '\f'; *astate = SS(0, S_GROUND); return UNVIS_VALID; case 's': *cp = ' '; *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'E': *cp = '\033'; *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'x': *astate = SS(0, S_HEX); return UNVIS_NOCHAR; case '\n': /* * hidden newline */ *astate = SS(0, S_GROUND); return UNVIS_NOCHAR; case '$': /* * hidden marker */ *astate = SS(0, S_GROUND); return UNVIS_NOCHAR; } goto bad; case S_META: if (c == '-') *astate = SS(0, S_META1); else if (c == '^') *astate = SS(0, S_CTRL); else goto bad; return UNVIS_NOCHAR; case S_META1: *astate = SS(0, S_GROUND); *cp |= c; return UNVIS_VALID; case S_CTRL: if (c == '?') *cp |= 0177; else *cp |= c & 037; *astate = SS(0, S_GROUND); return UNVIS_VALID; case S_OCTAL2: /* second possible octal digit */ if (isoctal(uc)) { /* * yes - and maybe a third */ *cp = (*cp << 3) + (c - '0'); *astate = SS(0, S_OCTAL3); return UNVIS_NOCHAR; } /* * no - done with current sequence, push back passed char */ *astate = SS(0, S_GROUND); return UNVIS_VALIDPUSH; case S_OCTAL3: /* third possible octal digit */ *astate = SS(0, S_GROUND); if (isoctal(uc)) { *cp = (*cp << 3) + (c - '0'); return UNVIS_VALID; } /* * we were done, push back passed char */ return UNVIS_VALIDPUSH; case S_HEX: if (!isxdigit(uc)) goto bad; /*FALLTHROUGH*/ case S_HEX1: if (isxdigit(uc)) { *cp = xtod(uc); *astate = SS(0, S_HEX2); return UNVIS_NOCHAR; } /* * no - done with current sequence, push back passed char */ *astate = SS(0, S_GROUND); return UNVIS_VALIDPUSH; case S_HEX2: *astate = S_GROUND; if (isxdigit(uc)) { *cp = xtod(uc) | (*cp << 4); return UNVIS_VALID; } return UNVIS_VALIDPUSH; case S_MIME1: if (uc == '\n' || uc == '\r') { *astate = SS(0, S_EATCRNL); return UNVIS_NOCHAR; } if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) { *cp = XTOD(uc); *astate = SS(0, S_MIME2); return UNVIS_NOCHAR; } goto bad; case S_MIME2: if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) { *astate = SS(0, S_GROUND); *cp = XTOD(uc) | (*cp << 4); return UNVIS_VALID; } goto bad; case S_EATCRNL: switch (uc) { case '\r': case '\n': return UNVIS_NOCHAR; case '=': *astate = SS(0, S_MIME1); return UNVIS_NOCHAR; default: *cp = uc; *astate = SS(0, S_GROUND); return UNVIS_VALID; } case S_AMP: *cp = 0; if (uc == '#') { *astate = SS(0, S_NUMBER); return UNVIS_NOCHAR; } *astate = SS(0, S_STRING); /*FALLTHROUGH*/ case S_STRING: ia = *cp; /* index in the array */ is = GI(*astate); /* index in the string */ lc = is == 0 ? 0 : nv[ia].name[is - 1]; /* last character */ if (uc == ';') uc = '\0'; for (; ia < __arraycount(nv); ia++) { if (is != 0 && nv[ia].name[is - 1] != lc) goto bad; if (nv[ia].name[is] == uc) break; } if (ia == __arraycount(nv)) goto bad; if (uc != 0) { *cp = ia; *astate = SS(is + 1, S_STRING); return UNVIS_NOCHAR; } *cp = nv[ia].value; *astate = SS(0, S_GROUND); return UNVIS_VALID; case S_NUMBER: if (uc == ';') return UNVIS_VALID; if (!isdigit(uc)) goto bad; *cp += (*cp * 10) + uc - '0'; return UNVIS_NOCHAR; default: bad: /* * decoder in unknown state - (probably uninitialized) */ *astate = SS(0, S_GROUND); return UNVIS_SYNBAD; } }
/* * vis - visually encode characters */ char * vis(char *dst, int c, int flag, int nextc) { if (((u_int)c <= UCHAR_MAX && isascii(c) && isgraph(c)) || ((flag & VIS_SP) == 0 && c == ' ') || ((flag & VIS_TAB) == 0 && c == '\t') || ((flag & VIS_NL) == 0 && c == '\n') || ((flag & VIS_SAFE) && (c == '\b' || c == '\007' || c == '\r'))) { *dst++ = c; if (c == '\\' && (flag & VIS_NOSLASH) == 0) *dst++ = '\\'; *dst = '\0'; return (dst); } if (flag & VIS_CSTYLE) { switch(c) { case '\n': *dst++ = '\\'; *dst++ = 'n'; goto done; case '\r': *dst++ = '\\'; *dst++ = 'r'; goto done; case '\b': *dst++ = '\\'; *dst++ = 'b'; goto done; case '\a': *dst++ = '\\'; *dst++ = 'a'; goto done; case '\v': *dst++ = '\\'; *dst++ = 'v'; goto done; case '\t': *dst++ = '\\'; *dst++ = 't'; goto done; case '\f': *dst++ = '\\'; *dst++ = 'f'; goto done; case ' ': *dst++ = '\\'; *dst++ = 's'; goto done; case '\0': *dst++ = '\\'; *dst++ = '0'; if (isoctal(nextc)) { *dst++ = '0'; *dst++ = '0'; } goto done; } } if (((c & 0177) == ' ') || (flag & VIS_OCTAL)) { *dst++ = '\\'; *dst++ = ((((unsigned int)c) >> 6) & 07) + '0'; *dst++ = ((((unsigned int)c) >> 3) & 07) + '0'; *dst++ = (((u_char)c) & 07) + '0'; goto done; }
/* * 'Clean up' this string. */ char * clean(char *s, int sending) { char temp[STR_LEN], cur_chr; char *s1, *phchar; int add_return = sending; #define isoctal(chr) (((chr) >= '0') && ((chr) <= '7')) s1 = temp; /* Don't overflow buffer, leave room for chars we append later */ while (*s && s1 - temp < (off_t)(sizeof(temp) - 2 - add_return)) { cur_chr = *s++; if (cur_chr == '^') { cur_chr = *s++; if (cur_chr == '\0') { *s1++ = '^'; break; } cur_chr &= 0x1F; if (cur_chr != 0) { *s1++ = cur_chr; } continue; } if (cur_chr != '\\') { *s1++ = cur_chr; continue; } cur_chr = *s++; if (cur_chr == '\0') { if (sending) { *s1++ = '\\'; *s1++ = '\\'; } break; } switch (cur_chr) { case 'b': *s1++ = '\b'; break; case 'c': if (sending && *s == '\0') add_return = 0; else *s1++ = cur_chr; break; case '\\': case 'K': case 'p': case 'd': if (sending) *s1++ = '\\'; *s1++ = cur_chr; break; case 'T': if (sending && phone_num) { for ( phchar = phone_num; *phchar != '\0'; phchar++) *s1++ = *phchar; } else { *s1++ = '\\'; *s1++ = 'T'; } break; case 'U': if (sending && phone_num2) { for ( phchar = phone_num2; *phchar != '\0'; phchar++) *s1++ = *phchar; } else { *s1++ = '\\'; *s1++ = 'U'; } break; case 'q': quiet = 1; break; case 'r': *s1++ = '\r'; break; case 'n': *s1++ = '\n'; break; case 's': *s1++ = ' '; break; case 't': *s1++ = '\t'; break; case 'N': if (sending) { *s1++ = '\\'; *s1++ = '\0'; } else *s1++ = 'N'; break; default: if (isoctal (cur_chr)) { cur_chr &= 0x07; if (isoctal (*s)) { cur_chr <<= 3; cur_chr |= *s++ - '0'; if (isoctal (*s)) { cur_chr <<= 3; cur_chr |= *s++ - '0'; } } if (cur_chr != 0 || sending) { if (sending && (cur_chr == '\\' || cur_chr == 0)) *s1++ = '\\'; *s1++ = cur_chr; } break; } if (sending) *s1++ = '\\'; *s1++ = cur_chr; break; } } if (add_return) *s1++ = '\r'; *s1++ = '\0'; /* guarantee closure */ *s1++ = '\0'; /* terminate the string */ return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */ }