/* * `from' may contain an address followed by other characters, * at least in /boot, so we permit whitespace (and more) after the address. * we do ensure that "delete" cannot be parsed as "de::". * * some callers don't check the return value for errors, so * set `to' to something distinctive in the case of a parse error. */ vlong parseip(uchar *to, char *from) { int i, elipsis = 0, v4 = 1; ulong x; char *p, *op; memset(to, 0, IPaddrlen); p = from; for(i = 0; i < IPaddrlen && ipcharok(*p); i+=2){ op = p; x = strtoul(p, &p, 16); if(*p == '.' || (*p == 0 && i == 0)){ /* ends with v4? */ if(i > IPaddrlen-4){ memset(to, 0, IPaddrlen); return -1; /* parse error */ } p = v4parseip(to+i, op); i += 4; break; } /* v6: at most 4 hex digits, followed by colon or delim */ if(x != (ushort)x || *p != ':' && !delimchar(*p)) { memset(to, 0, IPaddrlen); return -1; /* parse error */ } to[i] = x>>8; to[i+1] = x; if(*p == ':'){ v4 = 0; if(*++p == ':'){ /* :: is elided zero short(s) */ if (elipsis) { memset(to, 0, IPaddrlen); return -1; /* second :: */ } elipsis = i+2; p++; } } else if (p == op) /* strtoul made no progress? */ break; } if (p == from || !delimchar(*p)) { memset(to, 0, IPaddrlen); return -1; /* parse error */ } if(i < IPaddrlen){ memmove(&to[elipsis+IPaddrlen-i], &to[elipsis], i-elipsis); memset(&to[elipsis], 0, IPaddrlen-i); } if(v4){ to[10] = to[11] = 0xff; return nhgetl(to + IPv4off); } else return 6; }
int _inet_pton(int af, const char *src, void *dst) { int i, elipsis = 0; unsigned char *to; unsigned long x; const char *p, *op; if(af == AF_INET) return _inet_aton(src, (struct in_addr*)dst); if(af != AF_INET6){ errno = EAFNOSUPPORT; return -1; } to = ((struct in6_addr*)dst)->s6_addr; memset(to, 0, 16); p = src; for(i = 0; i < 16 && ipcharok(*p); i+=2){ op = p; x = strtoul(p, (char**)&p, 16); if(x != (unsigned short)x || *p != ':' && !delimchar(*p)) return 0; /* parse error */ to[i] = x>>8; to[i+1] = x; if(*p == ':'){ if(*++p == ':'){ /* :: is elided zero short(s) */ if (elipsis) return 0; /* second :: */ elipsis = i+2; p++; } } else if (p == op) /* strtoul made no progress? */ break; } if (p == src || !delimchar(*p)) return 0; /* parse error */ if(i < 16){ memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis); memset(&to[elipsis], 0, 16-i); } return 1; }
int readline(char *buf, int size) { int idx; int len; int key; int i; int done; int hist_idx; int dir; if (size <= 0) { errno = EINVAL; return -1; } idx = 0; len = 0; done = 0; hist_idx = history_len; while (!done) { fflush(stdout); key = getkey(); if (key < 0) return key; if (key == KEY_TAB) { int start; int end; int split; char mask[MAXPATH]; struct direntry dirent; start = idx; while (start > 0 && !delimchar(buf[start - 1])) start--; end = split = start; while (end < len && !delimchar(buf[end])) { if (buf[end] == PS1 || buf[end] == PS2) split = end + 1; end++; } dir = find_dir(buf, start, end, split, mask); if (dir >= 0) { while (_readdir(dir, &dirent, 1) > 0) { int newlen = len - (end - split) + dirent.namelen; if (like(dirent.name, mask) && newlen < size - 1) { memmove(buf + split + dirent.namelen, buf + end, len - end); memcpy(buf + split, dirent.name, dirent.namelen); while (idx < split) putchar(buf[idx++]); while (idx > split) { putchar('\b'); idx--; } for (i = split; i < newlen; i++) putchar(buf[i]); if (newlen < len) { for (i = newlen; i < len; i++) putchar(' '); for (i = newlen; i < len; i++) putchar('\b'); } end = split + dirent.namelen; len = newlen; idx = end; for (i = end; i < len; i++) putchar('\b'); fflush(stdout); key = getkey(); if (key < 0) break; if (key != KEY_TAB) break; } } close(dir); if (key < 0) return key; } } switch (key) { case KEY_LEFT: if (idx > 0) { putchar('\b'); idx--; } break; case KEY_RIGHT: if (idx < len) { putchar(buf[idx]); idx++; } break; case KEY_CTRL_LEFT: if (idx > 0) { putchar('\b'); idx--; } while (idx > 0 && buf[idx - 1] != ' ') { putchar('\b'); idx--; } break; case KEY_CTRL_RIGHT: while (idx < len && buf[idx] != ' ') { putchar(buf[idx]); idx++; } if (idx < len) { putchar(buf[idx]); idx++; } break; case KEY_HOME: while (idx > 0) { putchar('\b'); idx--; } break; case KEY_END: while (idx < len) { putchar(buf[idx]); idx++; } break; case KEY_DEL: if (idx < len) { len--; memmove(buf + idx, buf + idx + 1, len - idx); for (i = idx; i < len; i++) putchar(buf[i]); putchar(' '); putchar('\b'); for (i = idx; i < len; i++) putchar('\b'); } break; case KEY_INS: insmode = !insmode; break; case KEY_BACKSPACE: if (idx > 0) { putchar('\b'); idx--; len--; memmove(buf + idx, buf + idx + 1, len - idx); for (i = idx; i < len; i++) putchar(buf[i]); putchar(' '); putchar('\b'); for (i = idx; i < len; i++) putchar('\b'); } break; case KEY_ESC: if (_break_on_escape) { buf[len] = 0; errno = EINTR; return -1; } else { for (i = 0; i < idx; i++) putchar('\b'); for (i = 0; i < len; i++) putchar(' '); for (i = 0; i < len; i++) putchar('\b'); idx = len = 0; } break; case KEY_EOF: if (len == 0) return -1; break; case KEY_ENTER: putchar('\r'); putchar('\n'); done = 1; break; case KEY_UP: if (hist_idx > 0) { hist_idx--; for (i = 0; i < idx; i++) putchar('\b'); for (i = 0; i < len; i++) putchar(' '); for (i = 0; i < len; i++) putchar('\b'); len = strlen(history[hist_idx]); if (len > size - 1) len = size - 1; idx = len; memcpy(buf, history[hist_idx], len); for (i = 0; i < len; i++) putchar(buf[i]); } break; case KEY_DOWN: if (hist_idx < history_len - 1) { hist_idx++; for (i = 0; i < idx; i++) putchar('\b'); for (i = 0; i < len; i++) putchar(' '); for (i = 0; i < len; i++) putchar('\b'); len = strlen(history[hist_idx]); if (len > size - 1) len = size - 1; idx = len; memcpy(buf, history[hist_idx], len); for (i = 0; i < len; i++) putchar(buf[i]); } break; case KEY_UNKNOWN: break; default: if (key >= 0x20 && key <= 0xFF) { if (insmode) { if (len < size - 1) { if (idx < len) memmove(buf + idx + 1, buf + idx, len - idx); buf[idx] = key; len++; for (i = idx; i < len; i++) putchar(buf[i]); idx++; for (i = idx; i < len; i++) putchar('\b'); } } else { if (idx < size - 1) { buf[idx] = key; putchar(buf[idx]); if (idx == len) len++; idx++; } } } } } buf[len] = 0; add_to_history(buf); return len; }