예제 #1
0
파일: args.c 프로젝트: Freeaqingme/OpenBSD
/*
 * Convert an expression of the following forms to an off_t
 * 	1) A positive decimal number.
 *	2) A positive decimal number followed by a b (mult by 512).
 *	3) A positive decimal number followed by a k (mult by 1024).
 *	4) A positive decimal number followed by a m (mult by 1048576).
 *	5) A positive decimal number followed by a w (mult by sizeof int)
 *	6) Two or more positive decimal numbers (with/without k,b or w).
 *	   separated by x (also * for backwards compatibility), specifying
 *	   the product of the indicated values.
 */
static off_t
get_off(char *val)
{
	off_t num, t;
	char *expr;

	num = strtoq(val, &expr, 0);
	if (num == QUAD_MAX)			/* Overflow. */
		err(1, "%s", oper);
	if (expr == val)			/* No digits. */
		errx(1, "%s: illegal numeric value", oper);

	switch(*expr) {
	case 'b':
		t = num;
		num *= 512;
		if (t > num)
			goto erange;
		++expr;
		break;
	case 'k':
	case 'K':
		t = num;
		num *= 1024;
		if (t > num)
			goto erange;
		++expr;
		break;
	case 'm':
	case 'M':
		t = num;
		num *= 1048576;
		if (t > num)
			goto erange;
		++expr;
		break;
	case 'w':
		t = num;
		num *= sizeof(int);
		if (t > num)
			goto erange;
		++expr;
		break;
	}

	switch(*expr) {
		case '\0':
			break;
		case '*':			/* Backward compatible. */
		case 'x':
			t = num;
			num *= get_off(expr + 1);
			if (t > num)
erange:				errx(1, "%s: %s", oper, strerror(ERANGE));
			break;
		default:
			errx(1, "%s: illegal numeric value", oper);
	}
	return (num);
}
예제 #2
0
static long
dehumanize(const char *value)
{
        char    *vtp;
        long    iv;
 
        if (value == NULL)
                return (0);
        iv = strtoq(value, &vtp, 0);
        if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) {
                return (0);
        }
        switch (vtp[0]) {
        case 't': case 'T':
                iv *= 1024;
        case 'g': case 'G':
                iv *= 1024;
        case 'm': case 'M':
                iv *= 1024;
        case 'k': case 'K':
                iv *= 1024;
        case '\0':
                break;
        default:
                return (0);
        }
        return (iv);
}
예제 #3
0
/*
 * Read the offsets written by writeoffsets().
 */
void
readoffsets(struct disk *disks, const char *save_file) {
	FILE *fp;
	struct disk *dp;
	char *space, buf[1024];

	if ((fp = fopen(save_file, "r")) == NULL) {
		if (debug > 1 && errno == ENOENT)
			fprintf(stderr, "open %s failed: %s [continuing]\n",
				save_file, strerror(errno));
		if (errno != ENOENT)
			syslog(LOG_NOTICE, "open %s failed: %m", save_file);
		return;
	}

	while (fgets(buf, sizeof buf, fp) != NULL) {
		if ((space = strchr(buf, ' ')) == NULL)
			continue;
		*space = '\0';

		for (dp = disks;
		    dp->device != NULL && strcmp(dp->device, buf) != 0; dp++)
			; /* nothing */

		if (dp->device != NULL) {
			if (debug)
				fprintf(stderr, "%s: seek %s", buf, space + 1);
			dseek(dp, (off_t)strtoq(space + 1, NULL, 0), SEEK_SET);
		}
	}
	fclose(fp);
	if (debug)
		fprintf(stderr, "readoffsets: done\n");
}
예제 #4
0
static Q_INT64 read_int_ascii( QDataStream *s )
{
    register int n = 0;
    char buf[40];
    for ( ;; ) {
	buf[n] = s->device()->getch();
	if ( buf[n] == '\n' || n > 38 )		// $-terminator
	    break;
	n++;
    }
    buf[n] = '\0';

#if defined(__LP64__) || defined(Q_OS_OSF)
    // sizeof(long) == 8
    return strtol(buf, (char **)0, 10);
#else
#  if defined(Q_OS_TEMP)
    return strtol( buf, (char**)0, 10 );
#  elif defined(Q_OS_WIN)
    return _atoi64( buf );
#  elif defined(Q_OS_HPUX)
    return __strtoll( buf, (char**)0, 10 );
#  elif defined(Q_OS_MACX) && defined(QT_MACOSX_VERSION) && QT_MACOSX_VERSION < 0x1020
    return strtoq( buf, (char**)0, 10 );
#  else
    return strtoll( buf, (char**)0, 10 );	// C99 function
#  endif
#endif
}
예제 #5
0
/*
 * Return a quad_t value from an environment variable.
 */
int
getenv_quad(const char *name, quad_t *data)
{
	char	*value;
	char	*vtp;
	quad_t	iv;

	value = getenv(name);
	if (value == NULL)
		return (0);
	iv = strtoq(value, &vtp, 0);
	if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) {
		freeenv(value);
		return (0);
	}
	switch (vtp[0]) {
	case 't': case 'T':
		iv *= 1024;
	case 'g': case 'G':
		iv *= 1024;
	case 'm': case 'M':
		iv *= 1024;
	case 'k': case 'K':
		iv *= 1024;
	case '\0':
		break;
	default:
		freeenv(value);
		return (0);
	}
	*data = iv;
	freeenv(value);
	return (1);
}
예제 #6
0
static off_t
str_offt(char *val)
{
	char *expr;
	off_t num, t;

	num = strtoq(val, &expr, 0);
	if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
		return(0);

	switch(*expr) {
	case 'b':
		t = num;
		num *= 512;
		if (t > num)
			return(0);
		++expr;
		break;
	case 'k':
		t = num;
		num *= 1024;
		if (t > num)
			return(0);
		++expr;
		break;
	case 'm':
		t = num;
		num *= 1048576;
		if (t > num)
			return(0);
		++expr;
		break;
	case 'w':
		t = num;
		num *= sizeof(int);
		if (t > num)
			return(0);
		++expr;
		break;
	}

	switch(*expr) {
		case '\0':
			break;
		case '*':
		case 'x':
			t = num;
			num *= str_offt(expr + 1);
			if (t > num)
				return(0);
			break;
		default:
			return(0);
	}
	return(num);
}
예제 #7
0
/**
 * eva_strtoll:
 * @str: the string to parse a longlong integer (gint64) from.
 * @endp: optional place to store the character right past
 * the number in @str.  If *endp == @str, then you may assume an error
 * occurred.
 * @base: the assumed base for the number to parse.  eg "2" to
 * parse a binary, "8" for octal, "10" for decimal, "16" for hexidecimal.
 * Also, "0" is autodetects the C-style base.
 *
 * Like strtol, but for 64-bit integers.
 *
 * returns: the parsed integer.
 */
gint64
eva_strtoll  (const char *str,
	      char      **endp,
	      int         base)
{
#if HAVE_STRTOQ
  return strtoq (str, endp, base);
#elif HAVE_STRTOLL
  return strtoll (str, endp, base);
#else
  return strtol (str, endp, base);
#endif
}
예제 #8
0
/*
 * Return an integer value from an environment variable.
 */
int
getenv_int(char *name, int *data)
{
    char	*value, *vtp;
    quad_t	iv;
    
    if ((value = getenv(name)) == NULL)
	return(0);
    
    iv = strtoq(value, &vtp, 0);
    if ((vtp == value) || (*vtp != 0))
	return(0);
    
    *data = (int)iv;
    return(1);
}
예제 #9
0
파일: args.c 프로젝트: lilinj2000/freebsd
/*
 * Convert an expression of the following forms to an off_t.  This is the
 * same as get_num(), but it uses signed numbers.
 *
 * The major problem here is that an off_t may not necessarily be a intmax_t.
 */
static off_t
get_off_t(const char *val)
{
	intmax_t num, mult, prevnum;
	char *expr;

	errno = 0;
	num = strtoq(val, &expr, 0);
	if (errno != 0)				/* Overflow or underflow. */
		err(1, "%s", oper);
	
	if (expr == val)			/* No valid digits. */
		errx(1, "%s: illegal numeric value", oper);

	mult = postfix_to_mult(*expr);

	if (mult != 0) {
		prevnum = num;
		num *= mult;
		/* Check for overflow. */
		if ((prevnum > 0) != (num > 0) || num / mult != prevnum)
			goto erange;
		expr++;
	}

	switch (*expr) {
		case '\0':
			break;
		case '*':			/* Backward compatible. */
		case 'X':
		case 'x':
			mult = (intmax_t)get_off_t(expr + 1);
			prevnum = num;
			num *= mult;
			if ((prevnum > 0) == (num > 0) && num / mult == prevnum)
				break;
erange:
			errx(1, "%s: %s", oper, strerror(ERANGE));
		default:
			errx(1, "%s: illegal numeric value", oper);
	}
	return (num);
}
예제 #10
0
Bool
StrUtil_StrToInt64(int64 *out,      // OUT: The output value
                   const char *str) // IN : String to parse
{
   char *ptr;

   ASSERT(out);
   ASSERT(str);

   errno = 0;

#if defined(_WIN32)
   *out = _strtoi64(str, &ptr, 0);
#elif defined(__FreeBSD__)
   *out = strtoq(str, &ptr, 0);
#else
   *out = strtoll(str, &ptr, 0);
#endif

   return ptr[0] == '\0' && errno != ERANGE;
}
예제 #11
0
파일: cmp.c 프로젝트: SylvestreG/bitrig
int
main(int argc, char *argv[])
{
	struct stat sb1, sb2;
	off_t skip1, skip2;
	int ch, fd1, fd2, special;
	char *file1, *file2;

	setlocale(LC_ALL, "");

	while ((ch = getopt(argc, argv, "ls")) != -1)
		switch (ch) {
		case 'l':		/* print all differences */
			lflag = 1;
			break;
		case 's':		/* silent run */
			sflag = 1;
			break;
		case '?':
		default:
			usage();
		}

	argv += optind;
	argc -= optind;

	if (lflag && sflag)
		errx(ERR_EXIT, "only one of -l and -s may be specified");

	if (argc < 2 || argc > 4)
		usage();

	/* Backward compatibility -- handle "-" meaning stdin. */
	special = 0;
	if (strcmp(file1 = argv[0], "-") == 0) {
		special = 1;
		fd1 = 0;
		file1 = "stdin";
	} else if ((fd1 = open(file1, O_RDONLY, 0)) < 0) {
		if (sflag)
			exit(ERR_EXIT);
		else
			err(ERR_EXIT, "%s", file1);
	}
	if (strcmp(file2 = argv[1], "-") == 0) {
		if (special) {
			if (sflag)
				exit(ERR_EXIT);
			else
				errx(ERR_EXIT,
					"standard input may only be specified once");
		}
		special = 1;
		fd2 = 0;
		file2 = "stdin";
	} else if ((fd2 = open(file2, O_RDONLY, 0)) < 0) {
		if (sflag)
			exit(ERR_EXIT);
		else
			err(ERR_EXIT, "%s", file2);
	}

	skip1 = argc > 2 ? strtoq(argv[2], NULL, 0) : 0;
	skip2 = argc == 4 ? strtoq(argv[3], NULL, 0) : 0;

	if (!special) {
		if (fstat(fd1, &sb1)) {
			if (sflag)
				exit(ERR_EXIT);
			else
				err(ERR_EXIT, "%s", file1);
		}
		if (!S_ISREG(sb1.st_mode))
			special = 1;
		else {
			if (fstat(fd2, &sb2)) {
				if (sflag)
					exit(ERR_EXIT);
				else
					err(ERR_EXIT, "%s", file2);
			}
			if (!S_ISREG(sb2.st_mode))
				special = 1;
		}
	}

	if (special)
		c_special(fd1, file1, skip1, fd2, file2, skip2);
	else
		c_regular(fd1, file1, skip1, sb1.st_size,
		    fd2, file2, skip2, sb2.st_size);
	return 0;
}
예제 #12
0
static int
luaA_sysctl_set(lua_State *L)
{
	int	i;
	int	len;
	int	intval;
	int	mib[CTL_MAXNAME];
	unsigned int uintval;
	u_int	kind;
	long	longval;
	unsigned long ulongval;
	size_t	s;
	size_t newsize = 0;
#if __FreeBSD_version < 900000
	quad_t	quadval;
#else
	int64_t i64val;
	uint64_t u64val;
	intmax_t intmaxval;
	uintmax_t uintmaxval;
#endif
	char	fmt[BUFSIZ];
	char	oid[BUFSIZ];
	char	nvalbuf[BUFSIZ];
	char	*endptr;
	void	*newval = NULL;

	/* get first argument from lua */
	s = strlcpy(oid, luaL_checkstring(L, 1), sizeof(oid));
	if (s >= sizeof(oid))
		return (luaL_error(L, "oid too long: '%s'", oid));
	/* get second argument from lua */
	s = strlcpy(nvalbuf, luaL_checkstring(L, 2), sizeof(nvalbuf));
	if (s >= sizeof(nvalbuf))
		return (luaL_error(L, "new value too long"));
	newval = nvalbuf;
	newsize = s;

	len = name2oid(oid, mib);
	if (len < 0)
		return (luaL_error(L, "unknown iod '%s'", oid));
	if (oidfmt(mib, len, fmt, sizeof(fmt), &kind) != 0)
		return (luaL_error(L, "couldn't find format of oid '%s'", oid));
	if ((kind & CTLTYPE) == CTLTYPE_NODE)
		return (luaL_error(L, "oid '%s' isn't a leaf node", oid));
	if (!(kind & CTLFLAG_WR)) {
		if (kind & CTLFLAG_TUN)
			return (luaL_error(L, "oid '%s' is a read only tunable. "
					"Tunable values are set in /boot/loader.conf", oid));
		else
			return (luaL_error(L, "oid '%s' is read only", oid));
	}
	if ((kind & CTLTYPE) == CTLTYPE_INT	||
	    (kind & CTLTYPE) == CTLTYPE_UINT	||
	    (kind & CTLTYPE) == CTLTYPE_LONG	||
	    (kind & CTLTYPE) == CTLTYPE_ULONG	||
#if __FreeBSD_version < 900000
	    (kind & CTLTYPE) == CTLTYPE_QUAD
#else
	    (kind & CTLTYPE) == CTLTYPE_S64 || (kind & CTLTYPE) == CTLTYPE_U64
#endif
	) {
		if (strlen(newval) == 0)
			return (luaL_error(L, "empty numeric value"));
	}

	switch (kind & CTLTYPE) {
	case CTLTYPE_INT:
		if (strcmp(fmt, "IK") == 0) {
			if (!set_IK(newval, &intval))
				return (luaL_error(L, "invalid value '%s'", (char *)newval));
		} else {
			longval = strtol(newval, &endptr, 0);
			if (endptr == newval || *endptr != '\0' ||
					longval > INT_MAX || longval < INT_MIN) {
				return (luaL_error(L, "invalid integer: '%s'", (char *)newval));
			}
			intval = (int)longval;
		}
		newval = &intval;
		newsize = sizeof(intval);
		break;
	case CTLTYPE_UINT:
		ulongval = strtoul(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0' || ulongval > UINT_MAX) {
			return (luaL_error(L, "invalid unsigned integer: '%s'", (char *)newval));
		}
		uintval = (unsigned int)ulongval;
		newval = &uintval;
		newsize = sizeof(uintval);
		break;
	case CTLTYPE_LONG:
		longval = strtol(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0') {
			return (luaL_error(L, "invalid long integer: '%s'", (char *)newval));
		}
		newval = &longval;
		newsize = sizeof(longval);
		break;
	case CTLTYPE_ULONG:
		ulongval = strtoul(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0') {
			return (luaL_error(L, "invalid unsigned long integer: '%s'",
					(char *)newval));
		}
		newval = &ulongval;
		newsize = sizeof(ulongval);
		break;
	case CTLTYPE_STRING:
		break;
#if __FreeBSD_version < 900000
	case CTLTYPE_QUAD:
		quadval = strtoq(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0') {
			return (luaL_error(L, "invalid quad_t: '%s'", (char *)newval));
		}
		newval = &quadval;
		newsize = sizeof(quadval);
		break;
#else
	case CTLTYPE_S64:
		intmaxval = strtoimax(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0' ||
				intmaxval > INT64_MAX || intmaxval < INT64_MIN) {
			return (luaL_error(L, "invalid int64_t integer: '%s'", (char *)newval));
		}
		i64val = (int64_t)intmaxval;
		newval = &i64val;
		newsize = sizeof(i64val);
		break;
	case CTLTYPE_U64:
		uintmaxval = strtoumax(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0' || uintmaxval > UINT64_MAX) {
			return (luaL_error(L, "invalid int64_t integer: '%s'", (char *)newval));
		}
		u64val = (uint64_t)uintmaxval;
		newval = &u64val;
		newsize = sizeof(u64val);
		break;
#endif
	case CTLTYPE_OPAQUE:
		if (strcmp(fmt, "T,dev_t") == 0) {
			set_T_dev_t(L, newval, &newval, &newsize);
			break;
		}
		/* FALLTHROUGH */
	default:
		return (luaL_error(L, "oid '%s' is type %d, cannot set that",
		    oid, kind & CTLTYPE));
	}

	if (sysctl(mib, len, NULL, NULL, newval, newsize) == -1) {
		switch (errno) {
		case EOPNOTSUPP:
			return (luaL_error(L, "%s: value is not available", oid));
		case ENOTDIR:
			return (luaL_error(L, "%s: specification is incomplete", oid));
		case ENOMEM:
			/* really? with ENOMEM !?! */
			return (luaL_error(L, "%s: type is unknown to this program", oid));
		default:
			i = strerror_r(errno, nvalbuf, sizeof(nvalbuf));
			if (i != 0)
				return (luaL_error(L, "strerror_r failed"));
			else
				return (luaL_error(L, "%s: %s", oid, nvalbuf));
		}
		/* NOTREACHED */
	}
	return (0);
}
예제 #13
0
int
vsscanf(const char *inp, char const *fmt0, va_list ap)
{
	int inr;
	const u_char *fmt = (const u_char *)fmt0;
	int c;			/* character from format, or conversion */
	size_t width;		/* field width, or 0 */
	char *p;		/* points into all kinds of strings */
	int n;			/* handy integer */
	int flags;		/* flags as defined above */
	char *p0;		/* saves original value of p when necessary */
	int nassigned;		/* number of fields assigned */
	int nconversions;	/* number of conversions */
	int nread;		/* number of characters consumed from fp */
	int base;		/* base argument to conversion function */
	char ccltab[256];	/* character class table for %[...] */
	char buf[BUF];		/* buffer for numeric conversions */

	/* `basefix' is used to avoid `if' tests in the integer scanner */
	static short basefix[17] =
		{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };

	inr = strlen(inp);
	
	nassigned = 0;
	nconversions = 0;
	nread = 0;
	base = 0;		/* XXX just to keep gcc happy */
	for (;;) {
		c = *fmt++;
		if (c == 0)
			return (nassigned);
		if (isspace(c)) {
			while (inr > 0 && isspace(*inp))
				nread++, inr--, inp++;
			continue;
		}
		if (c != '%')
			goto literal;
		width = 0;
		flags = 0;
		/*
		 * switch on the format.  continue if done;
		 * break once format type is derived.
		 */
again:		c = *fmt++;
		switch (c) {
		case '%':
literal:
			if (inr <= 0)
				goto input_failure;
			if (*inp != c)
				goto match_failure;
			inr--, inp++;
			nread++;
			continue;

		case '*':
			flags |= SUPPRESS;
			goto again;
		case 'l':
			if (flags & LONG) {
				flags &= ~LONG;
				flags |= LONGLONG;
			} else
				flags |= LONG;
			goto again;
		case 'q':
			flags |= LONGLONG;	/* not quite */
			goto again;
		case 'h':
			if (flags & SHORT) {
				flags &= ~SHORT;
				flags |= SHORTSHORT;
			} else
				flags |= SHORT;
			goto again;

		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			width = width * 10 + c - '0';
			goto again;

		/*
		 * Conversions.
		 */
		case 'd':
			c = CT_INT;
			base = 10;
			break;

		case 'i':
			c = CT_INT;
			base = 0;
			break;

		case 'o':
			c = CT_INT;
			flags |= UNSIGNED;
			base = 8;
			break;

		case 'u':
			c = CT_INT;
			flags |= UNSIGNED;
			base = 10;
			break;

		case 'X':
		case 'x':
			flags |= PFXOK;	/* enable 0x prefixing */
			c = CT_INT;
			flags |= UNSIGNED;
			base = 16;
			break;

		case 's':
			c = CT_STRING;
			break;

		case '[':
			fmt = __sccl(ccltab, fmt);
			flags |= NOSKIP;
			c = CT_CCL;
			break;

		case 'c':
			flags |= NOSKIP;
			c = CT_CHAR;
			break;

		case 'p':	/* pointer format is like hex */
			flags |= POINTER | PFXOK;
			c = CT_INT;
			flags |= UNSIGNED;
			base = 16;
			break;

		case 'n':
			nconversions++;
			if (flags & SUPPRESS)	/* ??? */
				continue;
			if (flags & SHORTSHORT)
				*va_arg(ap, char *) = nread;
			else if (flags & SHORT)
				*va_arg(ap, short *) = nread;
			else if (flags & LONG)
				*va_arg(ap, long *) = nread;
			else if (flags & LONGLONG)
				*va_arg(ap, long long *) = nread;
			else
				*va_arg(ap, int *) = nread;
			continue;
		}

		/*
		 * We have a conversion that requires input.
		 */
		if (inr <= 0)
			goto input_failure;

		/*
		 * Consume leading white space, except for formats
		 * that suppress this.
		 */
		if ((flags & NOSKIP) == 0) {
			while (isspace(*inp)) {
				nread++;
				if (--inr > 0)
					inp++;
				else 
					goto input_failure;
			}
			/*
			 * Note that there is at least one character in
			 * the buffer, so conversions that do not set NOSKIP
			 * can no longer result in an input failure.
			 */
		}

		/*
		 * Do the conversion.
		 */
		switch (c) {

		case CT_CHAR:
			/* scan arbitrary characters (sets NOSKIP) */
			if (width == 0)
				width = 1;
			if (flags & SUPPRESS) {
				size_t sum = 0;
				for (;;) {
					if ((n = inr) < (int)width) {
						sum += n;
						width -= n;
						inp += n;
						if (sum == 0)
							goto input_failure;
						break;
					} else {
						sum += width;
						inr -= width;
						inp += width;
						break;
					}
				}
				nread += sum;
			} else {
				bcopy(inp, va_arg(ap, char *), width);
				inr -= width;
				inp += width;
				nread += width;
				nassigned++;
			}
			nconversions++;
			break;

		case CT_CCL:
			/* scan a (nonempty) character class (sets NOSKIP) */
			if (width == 0)
				width = (size_t)~0;	/* `infinity' */
			/* take only those things in the class */
			if (flags & SUPPRESS) {
				n = 0;
				while (ccltab[(unsigned char)*inp]) {
					n++, inr--, inp++;
					if (--width == 0)
						break;
					if (inr <= 0) {
						if (n == 0)
							goto input_failure;
						break;
					}
				}
				if (n == 0)
					goto match_failure;
			} else {
				p0 = p = va_arg(ap, char *);
				while (ccltab[(unsigned char)*inp]) {
					inr--;
					*p++ = *inp++;
					if (--width == 0)
						break;
					if (inr <= 0) {
						if (p == p0)
							goto input_failure;
						break;
					}
				}
				n = p - p0;
				if (n == 0)
					goto match_failure;
				*p = 0;
				nassigned++;
			}
			nread += n;
			nconversions++;
			break;

		case CT_STRING:
			/* like CCL, but zero-length string OK, & no NOSKIP */
			if (width == 0)
				width = (size_t)~0;
			if (flags & SUPPRESS) {
				n = 0;
				while (!isspace(*inp)) {
					n++, inr--, inp++;
					if (--width == 0)
						break;
					if (inr <= 0)
						break;
				}
				nread += n;
			} else {
				p0 = p = va_arg(ap, char *);
				while (!isspace(*inp)) {
					inr--;
					*p++ = *inp++;
					if (--width == 0)
						break;
					if (inr <= 0)
						break;
				}
				*p = 0;
				nread += p - p0;
				nassigned++;
			}
			nconversions++;
			continue;

		case CT_INT:
			/* scan an integer as if by the conversion function */
#ifdef hardway
			if (width == 0 || width > sizeof(buf) - 1)
				width = sizeof(buf) - 1;
#else
			/* size_t is unsigned, hence this optimisation */
			if (--width > sizeof(buf) - 2)
				width = sizeof(buf) - 2;
			width++;
#endif
			flags |= SIGNOK | NDIGITS | NZDIGITS;
			for (p = buf; width; width--) {
				c = *inp;
				/*
				 * Switch on the character; `goto ok'
				 * if we accept it as a part of number.
				 */
				switch (c) {

				/*
				 * The digit 0 is always legal, but is
				 * special.  For %i conversions, if no
				 * digits (zero or nonzero) have been
				 * scanned (only signs), we will have
				 * base==0.  In that case, we should set
				 * it to 8 and enable 0x prefixing.
				 * Also, if we have not scanned zero digits
				 * before this, do not turn off prefixing
				 * (someone else will turn it off if we
				 * have scanned any nonzero digits).
				 */
				case '0':
					if (base == 0) {
						base = 8;
						flags |= PFXOK;
					}
					if (flags & NZDIGITS)
					    flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
					else
					    flags &= ~(SIGNOK|PFXOK|NDIGITS);
					goto ok;

				/* 1 through 7 always legal */
				case '1': case '2': case '3':
				case '4': case '5': case '6': case '7':
					base = basefix[base];
					flags &= ~(SIGNOK | PFXOK | NDIGITS);
					goto ok;

				/* digits 8 and 9 ok iff decimal or hex */
				case '8': case '9':
					base = basefix[base];
					if (base <= 8)
						break;	/* not legal here */
					flags &= ~(SIGNOK | PFXOK | NDIGITS);
					goto ok;

				/* letters ok iff hex */
				case 'A': case 'B': case 'C':
				case 'D': case 'E': case 'F':
				case 'a': case 'b': case 'c':
				case 'd': case 'e': case 'f':
					/* no need to fix base here */
					if (base <= 10)
						break;	/* not legal here */
					flags &= ~(SIGNOK | PFXOK | NDIGITS);
					goto ok;

				/* sign ok only as first character */
				case '+': case '-':
					if (flags & SIGNOK) {
						flags &= ~SIGNOK;
						goto ok;
					}
					break;

				/* x ok iff flag still set & 2nd char */
				case 'x': case 'X':
					if (flags & PFXOK && p == buf + 1) {
						base = 16;	/* if %i */
						flags &= ~PFXOK;
						goto ok;
					}
					break;
				}

				/*
				 * If we got here, c is not a legal character
				 * for a number.  Stop accumulating digits.
				 */
				break;
		ok:
				/*
				 * c is legal: store it and look at the next.
				 */
				*p++ = c;
				if (--inr > 0)
					inp++;
				else 
					break;		/* end of input */
			}
			/*
			 * If we had only a sign, it is no good; push
			 * back the sign.  If the number ends in `x',
			 * it was [sign] '0' 'x', so push back the x
			 * and treat it as [sign] '0'.
			 */
			if (flags & NDIGITS) {
				if (p > buf) {
					inp--;
					inr++;
				}
				goto match_failure;
			}
			c = ((u_char *)p)[-1];
			if (c == 'x' || c == 'X') {
				--p;
				inp--;
				inr++;
			}
			if ((flags & SUPPRESS) == 0) {
				u_quad_t res;

				*p = 0;
				if ((flags & UNSIGNED) == 0)
				    res = strtoq(buf, (char **)NULL, base);
				else
				    res = strtouq(buf, (char **)NULL, base);
				if (flags & POINTER)
					*va_arg(ap, void **) =
						(void *)(uintptr_t)res;
				else if (flags & SHORTSHORT)
					*va_arg(ap, char *) = res;
				else if (flags & SHORT)
					*va_arg(ap, short *) = res;
				else if (flags & LONG)
					*va_arg(ap, long *) = res;
				else if (flags & LONGLONG)
					*va_arg(ap, long long *) = res;
				else
					*va_arg(ap, int *) = res;
				nassigned++;
			}
			nread += p - buf;
			nconversions++;
			break;

		}
	}
input_failure:
	return (nconversions != 0 ? nassigned : -1);
match_failure:
	return (nassigned);
}
예제 #14
0
/*
 * Parse a name into a MIB entry.
 * Lookup and print out the MIB entry if it exists.
 * Set a new value if requested.
 */
static void
parse(const char *string)
{
	size_t len;
	int i, j;
	void *newval = NULL;
	int intval;
	unsigned int uintval;
	long longval;
	unsigned long ulongval;
	size_t newsize = 0;
	quad_t quadval;
	u_quad_t uquadval;
	int mib[CTL_MAXNAME];
	char *cp, fmt[BUFSIZ];
	const char *name;
	char *name_allocated = NULL;
	u_int kind;

	if ((cp = strchr(string, '=')) != NULL) {
		if ((name_allocated = malloc(cp - string + 1)) == NULL)
			err(1, "malloc failed");
		strlcpy(name_allocated, string, cp - string + 1);
		name = name_allocated;
		
		while (isspace(*++cp))
			;

		newval = cp;
		newsize = strlen(cp);
	} else {
		name = string;
	}

	len = CTL_MAXNAME;
	if (sysctlnametomib(name, mib, &len) < 0) {
		if (errno == ENOENT) {
			errx(1, "unknown oid '%s'", name);
		} else {
			err(1, "sysctlnametomib(\"%s\")", name);
		}
	}

	if (oidfmt(mib, len, fmt, &kind))
		err(1, "couldn't find format of oid '%s'", name);

	if (newval == NULL) {
		if ((kind & CTLTYPE) == CTLTYPE_NODE) {
			sysctl_all(mib, len);
		} else {
			i = show_var(mib, len);
			if (!i && !bflag)
				putchar('\n');
		}
	} else {
		if ((kind & CTLTYPE) == CTLTYPE_NODE)
			errx(1, "oid '%s' isn't a leaf node", name);

		if (!(kind&CTLFLAG_WR))
			errx(1, "oid '%s' is read only", name);
	
		switch (kind & CTLTYPE) {
			case CTLTYPE_INT:
				if (!(strcmp(fmt, "IK") == 0)) {
					if (!set_IK(newval, &intval))
						errx(1, "invalid value '%s'",
						    (char *)newval);
				} else
					intval = (int) strtol(newval, NULL, 0);
				newval = &intval;
				newsize = sizeof(intval);
				break;
			case CTLTYPE_UINT:
				uintval = (int) strtoul(newval, NULL, 0);
				newval = &uintval;
				newsize = sizeof uintval;
				break;
			case CTLTYPE_LONG:
				longval = strtol(newval, NULL, 0);
				newval = &longval;
				newsize = sizeof longval;
				break;
			case CTLTYPE_ULONG:
				ulongval = strtoul(newval, NULL, 0);
				newval = &ulongval;
				newsize = sizeof ulongval;
				break;
			case CTLTYPE_STRING:
				break;
			case CTLTYPE_QUAD:
				quadval = strtoq(newval, NULL, 0);
				newval = &quadval;
				newsize = sizeof(quadval);
				break;
			case CTLTYPE_UQUAD:
				uquadval = strtouq(newval, NULL, 0);
				newval = &uquadval;
				newsize = sizeof(uquadval);
				break;
			case CTLTYPE_OPAQUE:
				if (strcmp(fmt, "T,dev_t") == 0 ||
				    strcmp(fmt, "T,udev_t") == 0
				) {
					set_T_dev_t((char*)newval, &newval,
						    &newsize);
					break;
				}
				/* FALLTHROUGH */
			default:
				errx(1, "oid '%s' is type %d,"
					" cannot set that", name,
					kind & CTLTYPE);
		}

		i = show_var(mib, len);
		if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
			if (!i && !bflag)
				putchar('\n');
			switch (errno) {
			case EOPNOTSUPP:
				errx(1, "%s: value is not available", 
					string);
			case ENOTDIR:
				errx(1, "%s: specification is incomplete", 
					string);
			case ENOMEM:
				errx(1, "%s: type is unknown to this program", 
					string);
			default:
				warn("%s", string);
				return;
			}
		}
		if (!bflag)
			printf(" -> ");
		i = nflag;
		nflag = 1;
		j = show_var(mib, len);
		if (!j && !bflag)
			putchar('\n');
		nflag = i;
	}

	if (name_allocated != NULL)
		free(name_allocated);
}
예제 #15
0
/* assmble a litteral fix num */
void asm_lit_fixnum(buffer_type *buf, yyscan_t *scanner) {
    vm_int i = 0;
    
    i = strtoq(get_text(scanner), 0, 0);
    EMIT_LIT_FIXNUM(buf, i);
}
예제 #16
0
static void
set(char *t, NODE *ip)
{
	int type;
	char *kw, *val = NULL;
	struct group *gr;
	struct passwd *pw;
	mode_t *m;
	int value;
	char *ep;

	for (; (kw = strtok(t, "= \t\n")); t = NULL) {
		ip->flags |= type = parsekey(kw, &value);
		if (value && (val = strtok(NULL, " \t\n")) == NULL)
			errx(1, "line %d: missing value", lineno);
		switch(type) {
		case F_CKSUM:
			ip->cksum = strtoul(val, &ep, 10);
			if (*ep)
				errx(1, "line %d: invalid checksum %s",
				lineno, val);
			break;
		case F_MD5:
			ip->md5digest = strdup(val);
			if(!ip->md5digest) {
				errx(1, "strdup");
			}
			break;
		case F_SHA1:
			ip->sha1digest = strdup(val);
			if(!ip->sha1digest) {
				errx(1, "strdup");
			}
			break;
		case F_RMD160:
			ip->rmd160digest = strdup(val);
			if(!ip->rmd160digest) {
				errx(1, "strdup");
			}
			break;
		case F_FLAGS:
			if (strcmp("none", val) == 0)
				ip->st_flags = 0;
			else if (strtofflags(&val, &ip->st_flags, NULL) != 0)
				errx(1, "line %d: invalid flag %s",lineno, val);
 			break;
		case F_GID:
			ip->st_gid = strtoul(val, &ep, 10);
			if (*ep)
				errx(1, "line %d: invalid gid %s", lineno, val);
			break;
		case F_GNAME:
			if ((gr = getgrnam(val)) == NULL)
			    errx(1, "line %d: unknown group %s", lineno, val);
			ip->st_gid = gr->gr_gid;
			break;
		case F_IGN:
			/* just set flag bit */
			break;
		case F_MODE:
			if ((m = setmode(val)) == NULL)
				errx(1, "line %d: invalid file mode %s",
				lineno, val);
			ip->st_mode = getmode(m, 0);
			free(m);
			break;
		case F_NLINK:
			ip->st_nlink = strtoul(val, &ep, 10);
			if (*ep)
				errx(1, "line %d: invalid link count %s",
				lineno,  val);
			break;
		case F_SIZE:
			ip->st_size = strtoq(val, &ep, 10);
			if (*ep)
				errx(1, "line %d: invalid size %s",
				lineno, val);
			break;
		case F_SLINK:
			if ((ip->slink = strdup(val)) == NULL)
				errx(1, "strdup");
			break;
		case F_TIME:
			ip->st_mtimespec.tv_sec = strtoul(val, &ep, 10);
			if (*ep != '.')
				errx(1, "line %d: invalid time %s",
				lineno, val);
			val = ep + 1;
			ip->st_mtimespec.tv_nsec = strtoul(val, &ep, 10);
			if (*ep)
				errx(1, "line %d: invalid time %s",
				lineno, val);
			break;
		case F_TYPE:
			switch(*val) {
			case 'b':
				if (!strcmp(val, "block"))
					ip->type = F_BLOCK;
				break;
			case 'c':
				if (!strcmp(val, "char"))
					ip->type = F_CHAR;
				break;
			case 'd':
				if (!strcmp(val, "dir"))
					ip->type = F_DIR;
				break;
			case 'f':
				if (!strcmp(val, "file"))
					ip->type = F_FILE;
				if (!strcmp(val, "fifo"))
					ip->type = F_FIFO;
				break;
			case 'l':
				if (!strcmp(val, "link"))
					ip->type = F_LINK;
				break;
			case 's':
				if (!strcmp(val, "socket"))
					ip->type = F_SOCK;
				break;
			default:
				errx(1, "line %d: unknown file type %s",
				lineno, val);
			}
			break;
		case F_UID:
			ip->st_uid = strtoul(val, &ep, 10);
			if (*ep)
				errx(1, "line %d: invalid uid %s", lineno, val);
			break;
		case F_UNAME:
			if ((pw = getpwnam(val)) == NULL)
			    errx(1, "line %d: unknown user %s", lineno, val);
			ip->st_uid = pw->pw_uid;
			break;
		}
	}
}
예제 #17
0
static int
UnDosLine(	char *const line,
		const char *const curdir,
		size_t curdirlen,
		char *fname,
		size_t fnamesize,
		int *ftype,
		longest_int *fsize,
		time_t *ftime)
{
	char *cp;
	int hour, year;
	char *filestart;
	char *sizestart;
	struct tm ftm;

	/*
	 *
0123456789012345678901234567890123456789012345678901234567890123456789
04-27-99  10:32PM               270158 Game booklet.pdf
03-11-99  10:03PM       <DIR>          Get A3d Banner

We also try to parse the format from CMD.EXE, which is similar:

03/22/2001  06:23p              62,325 cls.pdf

	 *
	 */
	cp = line;
	if (
		isdigit((int) cp[0])
		&& isdigit((int) cp[1])
		&& ispunct((int) cp[2])
		&& isdigit((int) cp[3])
		&& isdigit((int) cp[4])
		&& ispunct((int) cp[5])
		&& isdigit((int) cp[6])
		&& isdigit((int) cp[7])
	) {
		(void) memset(&ftm, 0, sizeof(struct tm));
		ftm.tm_isdst = -1;
		cp[2] = '\0';
		ftm.tm_mon = atoi(cp + 0);
		if (ftm.tm_mon > 0)
			ftm.tm_mon -= 1;
		cp[5] = '\0';
		ftm.tm_mday = atoi(cp + 3);
		if ((isdigit((int) cp[8])) && (isdigit((int) cp[9]))) {
			/* Four-digit year */
			cp[10] = '\0';
			year = atoi(cp + 6);
			if (year > 1900)
				year -= 1900;
			ftm.tm_year = year;	/* years since 1900 */
			cp += 11;
		} else {
			/* Two-digit year */
			cp[8] = '\0';
			year = atoi(cp + 6);
			if (year < 98)
				year += 100;
			ftm.tm_year = year;	/* years since 1900 */
			cp += 9;
		}

		for (;;) {
			if (*cp == '\0')
				return (-1);
			if (isdigit((int) *cp))
				break;
			cp++;
		}

		cp[2] = '\0';
		hour = atoi(cp);
		if (((cp[5] == 'P') || (cp[5] == 'p')) && (hour < 12))
			hour += 12;
		else if (((cp[5] == 'A') || (cp[5] == 'a')) && (hour == 12))
			hour -= 12;
		ftm.tm_hour = hour;
		cp[5] = '\0';
		ftm.tm_min = atoi(cp + 3);
		*ftime = mktime(&ftm);
		if (*ftype == (time_t) -1)
			return (-1);

		cp += 6;
		*ftype = '-';
		for (;;) {
			if (*cp == '\0')
				return (-1);
			if ((*cp == '<') && (cp[1] == 'D')) {
				/* found <DIR> */
				*ftype = 'd';
				cp += 5;
				break;	/* size field will end up being empty string */
			} else if ((*cp == '<') && (cp[1] == 'J')) {
				/* found <JUNCTION>
				 *
				 * Will we ever really see this?
				 * IIS from Win2000sp1 sends <DIR>
				 * for FTP, but CMD.EXE prints
				 * <JUNCTION>.
				 */
				*ftype = 'd';
				cp += 10;
				break;
			} else if (isdigit((int) *cp)) {
				break;
			} else {
				cp++;
			}
		}

		sizestart = cp;
		for (;;) {
			if (*cp == '\0')
				return (-1);
#ifdef HAVE_MEMMOVE
			if (*cp == ',') {
				/* Yuck -- US Locale dependency */
				memmove(cp, cp + 1, strlen(cp + 1) + 1);
			}
#endif
			if (!isdigit((int) *cp)) {
				*cp++ = '\0';
				break;
			}
			cp++;
		}

		if (fsize != NULL) {
#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)
			if (*ftype == 'd')
				*fsize = 0;
			else
				(void) sscanf(sizestart, SCANF_LONG_LONG, fsize);
#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)
			if (*ftype == 'd')
				*fsize = 0;
			else
				*fsize = (longest_int) strtoq(sizestart, NULL, 0);
#else
			*fsize = (longest_int) 0;
			if (*ftype != 'd') {
				long fsize2 = 0L;

				(void) sscanf(sizestart, "%ld", &fsize2);
				*fsize = (longest_int) fsize2;
			}
#endif
		}

		for (;;) {
			if (*cp == '\0')
				return (-1);
			if (!isspace((int) *cp)) {
				break;
			}
			cp++;
		}

		filestart = cp;
		if (curdirlen == 0) {
			(void) Strncpy(fname, filestart, fnamesize);
		} else {
			(void) Strncpy(fname, curdir, fnamesize);
			(void) Strncat(fname, filestart, fnamesize);
		}

		return (0);
	}
	return (-1);
}	/* UnDosLine */
예제 #18
0
파일: date.c 프로젝트: edgar-pek/PerspicuOS
int
main(int argc, char *argv[])
{
	struct timezone tz;
	int ch, rflag;
	int jflag, nflag;
	const char *format;
	char buf[1024];
	char *endptr, *fmt;
	char *tmp;
	int set_timezone;
	struct vary *v;
	const struct vary *badv;
	struct tm lt;

	v = NULL;
	fmt = NULL;
	(void) setlocale(LC_TIME, "");
	tz.tz_dsttime = tz.tz_minuteswest = 0;
	rflag = 0;
	jflag = nflag = 0;
	set_timezone = 0;
	while ((ch = getopt(argc, argv, "d:f:jnr:t:uv:")) != -1)
		switch((char)ch) {
		case 'd':		/* daylight savings time */
			tz.tz_dsttime = strtol(optarg, &endptr, 10) ? 1 : 0;
			if (endptr == optarg || *endptr != '\0')
				usage();
			set_timezone = 1;
			break;
		case 'f':
			fmt = optarg;
			break;
		case 'j':
			jflag = 1;	/* don't set time */
			break;
		case 'n':		/* don't set network */
			nflag = 1;
			break;
		case 'r':		/* user specified seconds */
			rflag = 1;
			tval = strtoq(optarg, &tmp, 0);
			if (*tmp != 0)
				usage();
			break;
		case 't':		/* minutes west of UTC */
					/* error check; don't allow "PST" */
			tz.tz_minuteswest = strtol(optarg, &endptr, 10);
			if (endptr == optarg || *endptr != '\0')
				usage();
			set_timezone = 1;
			break;
		case 'u':		/* do everything in UTC */
			(void)setenv("TZ", "UTC0", 1);
			break;
		case 'v':
			v = vary_append(v, optarg);
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	/*
	 * If -d or -t, set the timezone or daylight savings time; this
	 * doesn't belong here; the kernel should not know about either.
	 */
	if (set_timezone && settimeofday((struct timeval *)NULL, &tz))
		err(1, "settimeofday (timezone)");

	if (!rflag && time(&tval) == -1)
		err(1, "time");

	format = "%+";

	/* allow the operands in any order */
	if (*argv && **argv == '+') {
		format = *argv + 1;
		++argv;
	}

	if (*argv) {
		setthetime(fmt, *argv, jflag, nflag);
		++argv;
	} else if (fmt != NULL)
		usage();

	if (*argv && **argv == '+')
		format = *argv + 1;

	lt = *localtime(&tval);
	badv = vary_apply(v, &lt);
	if (badv) {
		fprintf(stderr, "%s: Cannot apply date adjustment\n",
			badv->arg);
		vary_destroy(v);
		usage();
	}
	vary_destroy(v);
	(void)strftime(buf, sizeof(buf), format, &lt);
	(void)printf("%s\n", buf);
	if (fflush(stdout))
		err(1, "stdout");
	exit(retval);
}
예제 #19
0
int
UnMlsT(const FTPCIPtr UNUSED(cip), const char *const line0, const MLstItemPtr mlip)
{
	char *cp, *val, *fact;
	int ec;
	size_t len;
	char line[1024];

	LIBNCFTP_USE_VAR(cip);
	memset(mlip, 0, sizeof(MLstItem));
	mlip->mode = -1;
	mlip->fsize = kSizeUnknown;
	mlip->ftype = '-';
	mlip->ftime = kModTimeUnknown;

	len = strlen(line0);
	if (len > (sizeof(line) - 1))
		return (-1);	/* Line too long, sorry. */
	/* This should be re-coded so does not need to make a
	 * copy of the buffer; it could be done in place.
	 */
	memcpy(line, line0, len + 1);

	/* Skip leading whitespace. */
	for (cp = line; *cp != '\0'; cp++) {
		if (! isspace((int) *cp))
			break;
	}

	while (*cp != '\0') {
		for (fact = cp; ; cp++) {
			if ((*cp == '\0') || (*cp == ' ')) {
				/* protocol violation */
				return (-1);
			}
			if (*cp == '=') {
				/* End of fact name. */
				*cp++ = '\0';
				break;
			}
		}
		for (val = cp; ; cp++) {
			if (*cp == '\0') {
				/* protocol violation */
				return (-1);
			}
			if (*cp == ' ') {
				ec = ' ';
				*cp++ = '\0';
				break;
			} else if (*cp == ';') {
				if (cp[1] == ' ') {
					ec = ' ';
					*cp++ = '\0';
					*cp++ = '\0';
				} else {
					ec = ';';
					*cp++ = '\0';
				}
				break;
			}
		}
		if (ISTRNEQ(fact, "OS.", 3))
			fact += 3;
		if (ISTREQ(fact, "type")) {
			if (ISTREQ(val, "file")) {
				mlip->ftype = '-';
			} else if (ISTREQ(val, "dir")) {
				mlip->ftype = 'd';
			} else if (ISTREQ(val, "cdir")) {
				/* not supported: current directory */
				return (-2);
			} else if (ISTREQ(val, "pdir")) {
				/* not supported: parent directory */
				return (-2);
			} else {
				/* ? */
				return (-1);
			}
		} else if (ISTREQ(fact, "UNIX.mode")) {
			if (val[0] == '0')
				sscanf(val, "%o", &mlip->mode);
			else	
				sscanf(val, "%i", &mlip->mode);
			if (mlip->mode != (-1))
				mlip->mode &= 00777;
		} else if (ISTREQ(fact, "perm")) {
			STRNCPY(mlip->perm, val);
		} else if (ISTREQ(fact, "size")) {
#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)
			(void) sscanf(val, SCANF_LONG_LONG, &mlip->fsize);
#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)
			mlip->fsize = (longest_int) strtoq(val, NULL, 0);
#else
			{
				long fsize2 = 0L;

				(void) sscanf(val, "%ld", &fsize2);
				mlip->fsize = (longest_int) fsize2;
			}
#endif
		} else if (ISTREQ(fact, "modify")) {
			mlip->ftime = UnMDTMDate(val);
		} else if (ISTREQ(fact, "UNIX.owner")) {
			STRNCPY(mlip->owner, val);
		} else if (ISTREQ(fact, "UNIX.group")) {
			STRNCPY(mlip->group, val);
		} else if (ISTREQ(fact, "UNIX.uid")) {
			mlip->uid = atoi(val);
		} else if (ISTREQ(fact, "UNIX.gid")) {
			mlip->gid = atoi(val);
		} else if (ISTREQ(fact, "perm")) {
			STRNCPY(mlip->perm, val);
		}

		/* End of facts? */
		if (ec == ' ')
			break;
	}

	len = strlen(cp);
	if (len > (sizeof(mlip->fname) - 1)) {
		/* Filename too long */
		return (-1);
	}
	memcpy(mlip->fname, cp, len);

	/* also set linkto here if used */

	return (0);
}	/* UnMlsT */
예제 #20
0
static int
UnLslRLine(	char *const line,
		const char *const curdir,
		size_t curdirlen,
		char *fname,
		size_t fnamesize,
		char *linkto,
		size_t linktosize,
		int *ftype,
		longest_int *fsize,
		time_t *ftime,
		time_t now,
		int thisyear,
		int *plugend)
{
	char *cp;
	int mon = 0, day = 0, hr = 0, min = 0, year = 0, sec = 0;
	int haveIsoHHMMSS = -1;
	char *monstart, *daystart, *hrstart, *minstart, *yearstart, *secstart = NULL;
	char *linktostart, *filestart = NULL;
	char *sizestart;
	char *pe;
	struct tm ftm;

	*plugend = 0;
	*ftype = 0;
	if (ftime != NULL)
		*ftime = (time_t) -1;
	if (fsize != NULL)
		*fsize = (longest_int) -1;

	/*
	 * Look for the digit just before the space
	 * before the month name.
	 *
-rw-rw----   1 gleason  sysdev      33404 Mar 24 01:29 RCmd.o
-rw-rw-r--   1 gleason  sysdevzz     1829 Jul  7  1996 README
-rw-rw-r--   1 gleason  sysdevzz     1829 Jul 7   1996 README
-rw-rw-r--   1 gleason  sysdevzz     1829 Jul  7 1996  README
-rw-rw-r--   1 gleason  sysdevzz     1829 Jul 7  1996  README
drwxrwxrwx   1 pvr pvr              45056 Jan  1 2000 DataFiles
         *
	 *------------------------------^
	 *                              0123456789012345
	 *------plugend--------^
	 *                     9876543210
	 *
	 */
	for (cp = line; *cp != '\0'; cp++) {
		if (	(isdigit((int) *cp))
			&& (isspace((int) cp[1]))
			&& (isupper((int) cp[2]))
			&& (islower((int) cp[3]))
		/*	&& (islower((int) cp[4])) */
			&& (isspace((int) cp[5]))
			&& (
((isdigit((int) cp[6])) && (isdigit((int) cp[7])))
|| ((isdigit((int) cp[6])) && (isspace((int) cp[7])))
|| ((isspace((int) cp[6])) && (isdigit((int) cp[7])))
			)
			&& (isspace((int) cp[8]))
		) {
			monstart = cp + 2;
			daystart = cp + 6;
			if (	((isspace((int) cp[9])) || (isdigit((int) cp[9])))
				&& (isdigit((int) cp[10]))
				&& (isdigit((int) cp[11]))
				&& (isdigit((int) cp[12]))
				&& ((isdigit((int) cp[13])) || (isspace((int) cp[13])))
			) {
				/* "Mon DD  YYYY" form */
				yearstart = cp + 9;
				if (isspace((int) *yearstart))
					yearstart++;
				hrstart = NULL;
				minstart = NULL;
				filestart = cp + 15;
				cp[1] = '\0';	/* end size */
				cp[5] = '\0';	/* end mon */
				cp[8] = '\0';	/* end day */
				if (! isspace((int) filestart[-1])) {
					if (isspace((int) filestart[-2])) {
						filestart--;
					}
				}
				filestart[-1] = '\0';	/* end year */
				mon = LsMonthNameToNum(monstart);
				day = atoi(daystart);
				hr = 23;
				min = 59;
				sec = 59;
				year = atoi(yearstart);

				pe = cp;
				while (isdigit((int) *pe))
					pe--;
				while (isspace((int) *pe))
					pe--;
				*plugend = (int) (pe - line) + 1;
				break;
			} else if (	/*
					 * Windows NT does not 0 pad.
					(isdigit((int) cp[9])) &&
					 */
				(isdigit((int) cp[10]))
				&& (cp[11] == ':')
				&& (isdigit((int) cp[12]))
				&& (isdigit((int) cp[13]))
			) {
				/* "Mon DD HH:MM" form */
				yearstart = NULL;
				hrstart = cp + 9;
				minstart = cp + 12;
				filestart = cp + 15;
				cp[1] = '\0';	/* end size */
				cp[5] = '\0';	/* end mon */
				cp[8] = '\0';	/* end day */
				cp[11] = '\0';	/* end hr */
				cp[14] = '\0';	/* end min */
				mon = LsMonthNameToNum(monstart);
				day = atoi(daystart);
				hr = atoi(hrstart);
				min = atoi(minstart);
				sec = 0;
				year = 0;

				pe = cp;
				while (isdigit((int) *pe))
					pe--;
				while (isspace((int) *pe))
					pe--;
				*plugend = (int) (pe - line) + 1;
				break;
			}
		} else if (	(isdigit((int) *cp))
			&& (isspace((int) cp[1]))

			&& (isdigit((int) cp[2]))
			&& (isdigit((int) cp[3]))
			&& (isdigit((int) cp[4]))
			&& (isdigit((int) cp[5]))
			&& (cp[6] == '-')
			&& (isdigit((int) cp[7]))
			&& (isdigit((int) cp[8]))
			&& (cp[9] == '-')
			&& (isdigit((int) cp[10]))
			&& (isdigit((int) cp[11]))

			&& (isspace((int) cp[12]))

			&& (isdigit((int) cp[13]))
			&& (isdigit((int) cp[14]))
			&& (cp[15] == ':')
			&& (isdigit((int) cp[16]))
			&& (isdigit((int) cp[17]))

			&& (
				((haveIsoHHMMSS = isspace((int) cp[18]))) ||
				(
					   (isdigit((int) cp[19]))
					&& (isdigit((int) cp[20]))
					&& (isspace((int) cp[21]))
					&& ((haveIsoHHMMSS = (int) cp[18]) == ':')
				)

			)
		) {
			/* "YYYY-mm-dd HH:MM" or "YYYY-mm-dd HH:MM:SS" form */
/* drwxr-xr-x   4 ftpuser  ftpusers  136 2008-03-12 23:38 beta
                                       0123456789012345678901234567890123456789
*/
			yearstart = cp + 2;
			cp[6] = '\0';	/* end year */

			monstart = cp + 7;
			cp[9] = '\0';	/* end month */

			daystart = cp + 10;
			cp[12] = '\0';	/* end day */

			hrstart = cp + 13;
			cp[15] = '\0';	/* end hr */

			minstart = cp + 16;
			cp[18] = '\0';	/* end min */

			if (haveIsoHHMMSS == ':') {
				secstart = cp + 19;
				cp[21] = '\0';	/* end sec */
				sec = atoi(secstart);
				filestart = cp + 22;
			} else {
				filestart = cp + 19;
				sec = 0;
			}

			mon = atoi(monstart) - 1;
			day = atoi(daystart);
			hr = atoi(hrstart);
			min = atoi(minstart);
			year = atoi(yearstart);

			pe = cp;
			while (isdigit((int) *pe))
				pe--;
			while (isspace((int) *pe))
				pe--;
			*plugend = (int) (pe - line) + 1;
			break;
		}
	}

	if (*cp == '\0')
		return (-1);

	linktostart = strstr(filestart, " -> ");
	if (linktostart != NULL) {
		*linktostart = '\0';
		linktostart += 4;
		(void) Strncpy(linkto, linktostart, linktosize);
	} else {
		*linkto = '\0';
	}

	if (curdirlen == 0) {
		(void) Strncpy(fname, filestart, fnamesize);
	} else {
		(void) Strncpy(fname, curdir, fnamesize);
		(void) Strncat(fname, filestart, fnamesize);
	}

	if (ftime != NULL) {
		(void) memset(&ftm, 0, sizeof(struct tm));
		ftm.tm_mon = mon;
		ftm.tm_mday = day;
		ftm.tm_hour = hr;
		ftm.tm_min = min;
		ftm.tm_sec = sec;
		ftm.tm_isdst = -1;
		if (year == 0) {
			/* We guess the year, based on what the
			 * current year is.
			 *
			 * UNIX ls would always print the year
			 * if the file was older than 6 months,
			 * but many non-UNIX based servers do
			 * not honor that convention, so we
			 * now assume that if the year was not
			 * given it implies the current year,
			 * unless the file is up to two days 
			 * into the future.
			 */
			ftm.tm_year = thisyear - 1900;
			*ftime = mktime(&ftm);
			if (*ftime == (time_t) -1) {
				/* panic */
			} else if (*ftime > (now + (2 * 86400L))) {
				--ftm.tm_year;
				*ftime = mktime(&ftm);
			}
		} else {
			ftm.tm_year = year - 1900;
			*ftime = mktime(&ftm);
		}
	}

	if (fsize != NULL) {
		while ((cp > line) && (isdigit((int) *cp)))
			--cp;
		sizestart = cp + 1;
#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)
		(void) sscanf(sizestart, SCANF_LONG_LONG, fsize);
#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)
		*fsize = (longest_int) strtoq(sizestart, NULL, 0);
#else
		{
			long fsize2 = 0L;
			
			(void) sscanf(sizestart, "%ld", &fsize2);
			*fsize = (longest_int) fsize2;
		}
#endif
	}

	switch (line[0]) {
		case 'd':
		case 'l':
			*ftype = (int) line[0];
			break;
		case 'b':
		case 'c':
		case 's':
			*ftype = (int) line[0];
			return (-1);
		default:
			*ftype = '-';
	}

	return (0);
}	/* UnLslRLine */
예제 #21
0
파일: limits.c 프로젝트: 2asoft/freebsd
static rlim_t
resource_num(int which, int ch, const char *str)
{
    rlim_t res = RLIM_INFINITY;

    if (str != NULL &&
	!(strcasecmp(str, "inf") == 0 ||
	  strcasecmp(str, "infinity") == 0 ||
	  strcasecmp(str, "unlimit") == 0 ||
	  strcasecmp(str, "unlimited") == 0)) {
	const char * s = str;
	char *e;

	switch (which) {
	case RLIMIT_CPU:	/* time values */
	    errno = 0;
	    res = 0;
	    while (*s) {
		rlim_t tim = strtoq(s, &e, 0);
		if (e == NULL || e == s || errno)
		    break;
		switch (*e++) {
		case 0:		   	/* end of string */
		    e--;
		default:
		case 's': case 'S':	/* seconds */
		    break;
		case 'm': case 'M':	/* minutes */
		    tim *= 60L;
		    break;
		case 'h': case 'H':	/* hours */
		    tim *= (60L * 60L);
		    break;
		case 'd': case 'D':	/* days */
		    tim *= (60L * 60L * 24L);
		    break;
		case 'w': case 'W':	/* weeks */
		    tim *= (60L * 60L * 24L * 7L);
		case 'y': case 'Y':	/* Years */
		    tim *= (60L * 60L * 24L * 365L);
		}
		s = e;
		res += tim;
	    }
	    break;
	case RLIMIT_FSIZE: /* Size values */
	case RLIMIT_DATA:
	case RLIMIT_STACK:
	case RLIMIT_CORE:
	case RLIMIT_RSS:
	case RLIMIT_MEMLOCK:
	case RLIMIT_SBSIZE:
	case RLIMIT_VMEM:
	case RLIMIT_SWAP:
	    errno = 0;
	    res = 0;
	    while (*s) {
		rlim_t mult, tim = strtoq(s, &e, 0);
		if (e == NULL || e == s || errno)
		    break;
		switch (*e++) {
		case 0:	/* end of string */
		    e--;
		default:
		    mult = 1;
		    break;
		case 'b': case 'B':	/* 512-byte blocks */
		    mult = 512;
		    break;
		case 'k': case 'K':	/* 1024-byte Kilobytes */
		    mult = 1024;
		    break;
		case 'm': case 'M':	/* 1024-k kbytes */
		    mult = 1024 * 1024;
		    break;
		case 'g': case 'G':	/* 1Gbyte */
		    mult = 1024 * 1024 * 1024;
		    break;
		case 't': case 'T':	/* 1TBte */
		    mult = 1024LL * 1024LL * 1024LL * 1024LL;
		    break;
		}
		s = e;
		res += (tim * mult);
	    }
	    break;
	case RLIMIT_NPROC:
	case RLIMIT_NOFILE:
	case RLIMIT_NPTS:
	case RLIMIT_KQUEUES:
	case RLIMIT_UMTXP:
	    res = strtoq(s, &e, 0);
	    s = e;
	    break;
	}
	if (*s) {
	    warnx("invalid value -%c `%s'", ch, str);
	    usage();
	}
    }
    return res;
}
예제 #22
0
/*
 * Report a read error, logging how many bytes were trying to be read, which
 * sector they were being read from, and try to also find out what that sector
 * is used for.
 */
void
logreaderror(struct disk *dp, int nbytes) {
	quad_t secno;
	off_t saved_offset;
	char newdev[512];

#ifdef	DIOCGDINFO
	int fd, slice, part;
	struct dos_partition *dos;
	struct disklabel label;
	char buf[512];
#else	/* DIOCGDINFO */
	static size_t geomSize = 0;
	static char * geomConf = NULL;
	char * cp;
	static size_t partLen = 31;
	static char *part = NULL;
	quad_t relsec = -1;
	char *typefld = NULL;
#endif	/* DIOCGDINFO */

	saved_offset = dseek(dp, 0, SEEK_CUR);
	secno = (quad_t)saved_offset / dp->secsize;
	dp->errors++;

	syslog(LOG_NOTICE, "error reading %d bytes from sector " QD " on %s",
	    nbytes, secno, dp->device);

#ifdef	DIOCGDINFO
	/*
	 * First, find out which slice it's in.  To do this, we seek to the
	 * start of the disk, read the first sector, and go through the DOS
	 * slice table.
	 */
	if (dseek(dp, 0, SEEK_SET) == -1) {
		syslog(LOG_NOTICE, "could not seek to start of disk: %m");
		exit(EXIT_FAILURE);
	}

	if (read(dp->fd, buf, sizeof buf) != sizeof buf) {
		dseek(dp, saved_offset, SEEK_SET);
		return;
	}

	/* seek back to where we were */
	if (dseek(dp, saved_offset, SEEK_SET) == -1) {
		syslog(LOG_NOTICE,
		       "could not seek to previous position"
		       "after reading first sector: %m");
		exit(EXIT_FAILURE);
	}

	// TODO:  should validate DOS partition table (vs GPT or dedicated)
	dos = (struct dos_partition *)&buf[DOSPARTOFF];
	for (slice = 0; slice < NDOSPART; slice++)
		if (dos[slice].dp_start <= secno &&
		  secno < dos[slice].dp_start + dos[slice].dp_size)
			break;

	if (slice == NDOSPART) {
		syslog(LOG_NOTICE,
		  "sector " QD " on %s doesn't appear "
		  "to be within any DOS slice", secno, dp->device);
		return;
	}

	/* Make secno relative to this slice */
	secno -= dos[slice].dp_start;

	snprintf(newdev, sizeof newdev, "%ss%d", dp->device, slice + 1);
	syslog(LOG_DEBUG, "bad sector seems to be within %s", newdev);

	/* Check the type of that partition. */
	if (dos[slice].dp_typ != DOSPTYP_386BSD) {
		/* If not a BSD slice, we can't do much more. */
		syslog(LOG_NOTICE, "last bad sector is sector " QD
		    " on device %s, type %02x", secno, newdev,
		    dos[slice].dp_typ);
		return;
	}

	if ((fd = open(newdev, O_RDONLY)) < 0) {
		syslog(LOG_NOTICE, "open %s failure: %m", newdev);
		return;
	}

	/* Try to read the disklabel from that device. */
	if (ioctl(fd, DIOCGDINFO, &label) < 0) {
		syslog(LOG_NOTICE, "DIOCGDINFO on %s failed: %m",
		    newdev);
		return;
	}

	/* Check which partition this sector is in. */
	for (part = 0; part < MAXPARTITIONS; part++)
		if (part != 2 && /* skip 'c' partition */
		    label.d_partitions[part].p_offset <= secno &&
		    secno < label.d_partitions[part].p_offset +
		            label.d_partitions[part].p_size)
			break;

	if (part == MAXPARTITIONS) {
		syslog(LOG_NOTICE,
		  "sector " QD " on %s doesn't appear "
		  "to be within any BSD partition", secno, newdev);
		return;
	}

	secno -= label.d_partitions[part].p_offset;
	snprintf(newdev, sizeof newdev, "%ss%d%c",
	    dp->device, slice + 1, 'a' + part);
	syslog(LOG_DEBUG, "bad sector seems to be within %s", newdev);
	if (label.d_partitions[part].p_fstype != FS_BSDFFS) {
		/* Again, if not a BSD partition, can't do much. */
		syslog(LOG_NOTICE, "last bad sector is sector " QD
		    " on device %s, type %s", secno, newdev,
		    fstypename(label.d_partitions[part].p_fstype));
		return;
	}
#else	/* DIOCGDINFO */
	if (geomSize == 0) {
		sysctlbyname("kern.geom.conftxt", NULL, &geomSize, NULL, 0);
		if (geomSize <= 0) {
			printf("sysctlbyname() returned size = %d\n", geomSize);
			geomSize = 0;
			exit(EXIT_FAILURE);
		}
		geomConf = malloc(geomSize);
		if (geomConf == NULL) {
			printf("malloc(%d) returned NULL\n", geomSize);
			geomSize = 0;
			exit(EXIT_FAILURE);
		}
		if (sysctlbyname("kern.geom.conftxt", geomConf, &geomSize,
				 NULL, 0) != 0) {
			perror("sysctlbyname()");
			geomSize = 0;
			free(geomConf);
			geomConf = NULL;
			exit(EXIT_FAILURE);
		}
	}
	if (part == NULL)
		part = malloc(partLen + 1);

	for ( cp = geomConf ; *cp ; ++cp ) {
		// find line "0 DISK " matching current disk, using
		// strncmp because where cp points is not null-terminated
		// (All DISK lines, and only DISK lines, are at level 0.)
		// Magic numbers:  7 == strlen("0 DISK "); 5 == strlen("/dev/")
		if (strncmp(cp, "0 DISK ", 7) == 0
		 && strncmp(&cp[7], &dp->device[5], strlen(dp->device) - 5) == 0
		 && cp[7 + strlen(dp->device) - 5] == ' ') {
			for (;;) {
				// scan to end of line
				while (cp[1] && *cp != '\n')
					++cp;
				++cp;	// start of next line
				// Find PART line containing the failed sector;
				// must be on same disk => stop upon finding
				// another DISK line.  If more than one matching
				// PART -- due to nested geoms -- use the last
				// (innermost).
				if (*cp == '\0' || *cp == '0')
					break;	// end of current DISK's entries
				// scan to end of level number
				while (cp[1] && *cp != ' ')
					++cp;
				if (strncmp(cp, " PART ", 6) == 0) {
					char *pp = &cp[6];
					int pl = strchr(pp, ' ') - pp;
					quad_t mediasize, offset;
					long secsize;

					cp = pp + pl;	// cp -> mediasize
					mediasize = strtoq(cp, &cp, 10);
					secsize = strtol(cp, &cp, 10);
					mediasize /= secsize;
					cp = strchr(cp, 'o') + 1;
					offset = strtoq(cp, &cp, 10) / secsize;
					if (secno >= offset
					 && (secno - offset) < mediasize) {
						if (pl > partLen) {
							part = realloc(part,
									pl+1);
							partLen = pl;
						}
						strncpy(part, pp, pl);
						part[pl] = '\0';
						relsec = secno - offset;
						typefld = cp + 1;
					}
				}
			}
		}
		// scan to end of line
		while (cp[1] && *cp != '\n')
			++cp;
	}
////	printf("part %s, relsec %qd, typefld %p: %.27s\n",
////		part, relsec, typefld, typefld);
	secno = relsec;
	strncpy(newdev, part, sizeof(newdev) - 1);
	newdev[sizeof(newdev) - 1] = '\0';		// paranoia
#endif	/* DIOCGDINFO */

	syslog(LOG_NOTICE, "last bad sector is sector " QD
	  " on 4.2BSD filesystem %s", secno, newdev);

	/*
	 * XXX: todo: find out which file on the BSD filesystem uses this
	 * sector...
	 */
}
예제 #23
0
void http_got_header(struct connection *c, struct read_buffer *rb)
{
    int cf;
    int state = c->state != S_PROC ? S_GETH : S_PROC;
    unsigned char *head;
    unsigned char *cookie, *ch;
    int a, h, version;
    unsigned char *d;
    struct cache_entry *e;
    struct http_connection_info *info;
    unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);
    set_timeout(c);
    info = c->info;
    if (rb->close == 2) {
        unsigned char *h;
        if (!c->tries && (h = get_host_name(host))) {
            if (info->bl_flags & BL_NO_CHARSET) {
                del_blacklist_entry(h, BL_NO_CHARSET);
            } else {
                add_blacklist_entry(h, BL_NO_CHARSET);
                c->tries = -1;
            }
            mem_free(h);
        }
        setcstate(c, S_CANT_READ);
        retry_connection(c);
        return;
    }
    rb->close = 0;
again:
    if ((a = get_header(rb)) == -1) {
        setcstate(c, S_HTTP_ERROR);
        abort_connection(c);
        return;
    }
    if (!a) {
        read_from_socket(c, c->sock1, rb, http_got_header);
        setcstate(c, state);
        return;
    }
    if (a != -2) {
        head = mem_alloc(a + 1);
        memcpy(head, rb->data, a);
        head[a] = 0;
        kill_buffer_data(rb, a);
    } else {
        head = stracpy("HTTP/0.9 200 OK\r\nContent-Type: text/html\r\n\r\n");
    }
    if (get_http_code(head, &h, &version) || h == 101) {
        mem_free(head);
        setcstate(c, S_HTTP_ERROR);
        abort_connection(c);
        return;
    }
    if (check_http_server_bugs(host, c->info, head) && is_connection_restartable(c)) {
        mem_free(head);
        setcstate(c, S_RESTART);
        retry_connection(c);
        return;
    }
    ch = head;
    while ((cookie = parse_http_header(ch, "Set-Cookie", &ch))) {
        unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);
        set_cookie(NULL, host, cookie);
        mem_free(cookie);
    }
    if (h == 100) {
        mem_free(head);
        state = S_PROC;
        goto again;
    }
    if (h < 200) {
        mem_free(head);
        setcstate(c, S_HTTP_ERROR);
        abort_connection(c);
        return;
    }
    if (h == 204) {
        mem_free(head);
        setcstate(c, S_HTTP_204);
        http_end_request(c, 0);
        return;
    }
    if (h == 304) {
        mem_free(head);
        setcstate(c, S_OK);
        http_end_request(c, 1);
        return;
    }
    if ((h == 500 || h == 502 || h == 503 || h == 504) && http_bugs.retry_internal_errors && is_connection_restartable(c)) {
        /* !!! FIXME: wait some time ... */
        mem_free(head);
        setcstate(c, S_RESTART);
        retry_connection(c);
        return;
    }
    if (!c->cache && get_cache_entry(c->url, &c->cache)) {
        mem_free(head);
        setcstate(c, S_OUT_OF_MEM);
        abort_connection(c);
        return;
    }
    e = c->cache;
    e->http_code = h;
    if (e->head) mem_free(e->head);
    e->head = head;
    if ((d = parse_http_header(head, "Expires", NULL))) {
        time_t t = parse_http_date(d);
        if (t && e->expire_time != 1) e->expire_time = t;
        mem_free(d);
    }
    if ((d = parse_http_header(head, "Pragma", NULL))) {
        if (!casecmp(d, "no-cache", 8)) e->expire_time = 1;
        mem_free(d);
    }
    if ((d = parse_http_header(head, "Cache-Control", NULL))) {
        char *f = d;
        while (1) {
            while (*f && (*f == ' ' || *f == ',')) f++;
            if (!*f) break;
            if (!casecmp(f, "no-cache", 8) || !casecmp(f, "must-revalidate", 15)) {
                e->expire_time = 1;
            }
            if (!casecmp(f, "max-age=", 8)) {
                if (e->expire_time != 1) e->expire_time = time(NULL) + atoi(f + 8);
            }
            while (*f && *f != ',') f++;
        }
        mem_free(d);
    }
#ifdef HAVE_SSL
    if (c->ssl) {
        int l = 0;
        if (e->ssl_info) mem_free(e->ssl_info);
        e->ssl_info = init_str();
        add_num_to_str(&e->ssl_info, &l, SSL_get_cipher_bits(c->ssl, NULL));
        add_to_str(&e->ssl_info, &l, "-bit ");
        add_to_str(&e->ssl_info, &l, SSL_get_cipher_version(c->ssl));
        add_to_str(&e->ssl_info, &l, " ");
        add_to_str(&e->ssl_info, &l, (unsigned  char *)SSL_get_cipher_name(c->ssl));
    }
#endif
    if (e->redirect) mem_free(e->redirect), e->redirect = NULL;
    if (h == 301 || h == 302 || h == 303 || h == 307) {
        if ((h == 302 || h == 307) && !e->expire_time) e->expire_time = 1;
        if ((d = parse_http_header(e->head, "Location", NULL))) {
            unsigned char *user, *ins;
            unsigned char *newuser, *newpassword;
            if (!parse_url(d, NULL, &user, NULL, NULL, NULL, &ins, NULL, NULL, NULL, NULL, NULL, NULL) && !user && ins && (newuser = get_user_name(host))) {
                if (*newuser) {
                    int ins_off = ins - d;
                    newpassword = get_pass(host);
                    if (!newpassword) newpassword = stracpy("");
                    add_to_strn(&newuser, ":");
                    add_to_strn(&newuser, newpassword);
                    add_to_strn(&newuser, "@");
                    extend_str(&d, strlen(newuser));
                    ins = d + ins_off;
                    memmove(ins + strlen(newuser), ins, strlen(ins) + 1);
                    memcpy(ins, newuser, strlen(newuser));
                    mem_free(newpassword);
                }
                mem_free(newuser);
            }
            if (e->redirect) mem_free(e->redirect);
            e->redirect = d;
            e->redirect_get = h == 303;
        }
    }
    if (!e->expire_time && strchr(c->url, POST_CHAR)) e->expire_time = 1;
    info->close = 0;
    info->length = -1;
    info->version = version;
    if ((d = parse_http_header(e->head, "Connection", NULL)) || (d = parse_http_header(e->head, "Proxy-Connection", NULL))) {
        if (!strcasecmp(d, "close")) info->close = 1;
        mem_free(d);
    } else if (version < 11) info->close = 1;
    cf = c->from;
    c->from = 0;
    if ((d = parse_http_header(e->head, "Content-Range", NULL))) {
        if (strlen(d) > 6) {
            d[5] = 0;
            if (!(strcasecmp(d, "bytes")) && d[6] >= '0' && d[6] <= '9') {
#if defined(HAVE_STRTOLL)
                long long f = strtoll(d + 6, NULL, 10);
#elif defined(HAVE_STRTOQ)
                longlong f = strtoq(d + 6, NULL, 10);
#else
                long f = strtol(d + 6, NULL, 10);
                if (f == MAXLONG) f = -1;
#endif
                if (f >= 0 && (off_t)f >= 0 && (off_t)f == f) c->from = f;
            }
        }
        mem_free(d);
    }
    if (cf && !c->from && !c->unrestartable) c->unrestartable = 1;
    if (c->from > cf || c->from < 0) {
        setcstate(c, S_HTTP_ERROR);
        abort_connection(c);
        return;
    }
    if ((d = parse_http_header(e->head, "Content-Length", NULL))) {
        unsigned char *ep;
#if defined(HAVE_STRTOLL)
        long long l = strtoll(d, (char **)(void *)&ep, 10);
#elif defined(HAVE_STRTOQ)
        longlong l = strtoq(d, (char **)(void *)&ep, 10);
#else
        long l = strtol(d, (char **)(void *)&ep, 10);
        if (l == MAXLONG) l = -1;
#endif
        if (!*ep && l >= 0 && (off_t)l >= 0 && (off_t)l == l) {
            if (!info->close || version >= 11) info->length = l;
            if (c->from + l >= 0) c->est_length = c->from + l;
        }
        mem_free(d);
    }
    if ((d = parse_http_header(e->head, "Accept-Ranges", NULL))) {
        if (!strcasecmp(d, "none") && !c->unrestartable) c->unrestartable = 1;
        mem_free(d);
    } else {
        if (!c->unrestartable && !c->from) c->unrestartable = 1;
    }
    if (info->bl_flags & BL_NO_RANGE && !c->unrestartable) c->unrestartable = 1;
    if ((d = parse_http_header(e->head, "Transfer-Encoding", NULL))) {
        if (!strcasecmp(d, "chunked")) {
            info->length = -2;
            info->chunk_remaining = -1;
        }
        mem_free(d);
    }
    if (!info->close && info->length == -1) info->close = 1;
    if ((d = parse_http_header(e->head, "Last-Modified", NULL))) {
        if (e->last_modified && strcasecmp(e->last_modified, d)) {
            delete_entry_content(e);
            if (c->from) {
                c->from = 0;
                mem_free(d);
                setcstate(c, S_MODIFIED);
                retry_connection(c);
                return;
            }
        }
        if (!e->last_modified) e->last_modified = d;
        else mem_free(d);
    }
    if (!e->last_modified && (d = parse_http_header(e->head, "Date", NULL)))
        e->last_modified = d;
    if (info->length == -1 || (version < 11 && info->close)) rb->close = 1;
    read_http_data(c, rb);
}