示例#1
0
int readahead_main(int argc UNUSED_PARAM, char **argv)
{
	int retval = EXIT_SUCCESS;

	if (!argv[1]) {
		bb_show_usage();
	}

	while (*++argv) {
		int fd = open_or_warn(*argv, O_RDONLY);
		if (fd >= 0) {
			off_t len;
			int r;

			/* fdlength was reported to be unreliable - use seek */
			len = xlseek(fd, 0, SEEK_END);
			xlseek(fd, 0, SEEK_SET);
			r = readahead(fd, 0, len);
			close(fd);
			if (r >= 0)
				continue;
		}
		retval = EXIT_FAILURE;
	}

	return retval;
}
示例#2
0
int fsync_main(int argc UNUSED_PARAM, char **argv)
{
	int status;
	int opts;

	opts = getopt32(argv, "d"); /* fdatasync */
	argv += optind;
	if (!*argv) {
		bb_show_usage();
	}

	status = EXIT_SUCCESS;
	do {
		int fd = open_or_warn(*argv, O_NOATIME | O_NOCTTY | O_RDONLY);

		if (fd == -1) {
			status = EXIT_FAILURE;
			continue;
		}
		if ((opts ? fdatasync(fd) : fsync(fd))) {
			//status = EXIT_FAILURE; - do we want this?
			bb_simple_perror_msg(*argv);
		}
		close(fd);
	} while (*++argv);

	return status;
}
示例#3
0
static void reopen_logfile_to_stderr(void)
{
	if (G.log_filename) {
		int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND);
		if (logfd >= 0)
			xmove_fd(logfd, STDERR_FILENO);
	}
}
示例#4
0
void FAST_FUNC read_leases(const char *file)
{
	struct dyn_lease lease;
	int64_t written_at, time_passed;
	int fd;
#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
	unsigned i = 0;
#endif

	fd = open_or_warn(file, O_RDONLY);
	if (fd < 0)
		return;

	if (full_read(fd, &written_at, sizeof(written_at)) != sizeof(written_at))
		goto ret;
	written_at = SWAP_BE64(written_at);

	time_passed = time(NULL) - written_at;
	/* Strange written_at, or lease file from old version of udhcpd
	 * which had no "written_at" field? */
	if ((uint64_t)time_passed > 12 * 60 * 60)
		goto ret;

	while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
//FIXME: what if it matches some static lease?
		uint32_t y = ntohl(lease.lease_nip);
		if (y >= server_config.start_ip && y <= server_config.end_ip) {
			signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed;
			if (expires <= 0)
				continue;
			/* NB: add_lease takes "relative time", IOW,
			 * lease duration, not lease deadline. */
			if (add_lease(lease.lease_mac, lease.lease_nip,
					expires,
					lease.hostname, sizeof(lease.hostname)
				) == 0
			) {
				bb_error_msg("too many leases while loading %s", file);
				break;
			}
#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
			i++;
#endif
		}
	}
	log1("Read %d leases", i);
 ret:
	close(fd);
}
示例#5
0
void FAST_FUNC write_leases(void)
{
	int fd;
	unsigned i;
	leasetime_t curr;
	int64_t written_at;

	fd = open_or_warn(server_config.lease_file, O_WRONLY|O_CREAT|O_TRUNC);
	if (fd < 0)
		return;

	curr = written_at = time(NULL);

	written_at = SWAP_BE64(written_at);
	full_write(fd, &written_at, sizeof(written_at));

	for (i = 0; i < server_config.max_leases; i++) {
		leasetime_t tmp_time;

		if (g_leases[i].lease_nip == 0)
			continue;

		/* Screw with the time in the struct, for easier writing */
		tmp_time = g_leases[i].expires;

		g_leases[i].expires -= curr;
		if ((signed_leasetime_t) g_leases[i].expires < 0)
			g_leases[i].expires = 0;
		g_leases[i].expires = htonl(g_leases[i].expires);

		/* No error check. If the file gets truncated,
		 * we lose some leases on restart. Oh well. */
		full_write(fd, &g_leases[i], sizeof(g_leases[i]));

		/* Then restore it when done */
		g_leases[i].expires = tmp_time;
	}
	close(fd);

	if (server_config.notify_file) {
		char *argv[3];
		argv[0] = server_config.notify_file;
		argv[1] = server_config.lease_file;
		argv[2] = NULL;
		spawn_and_wait(argv);
	}
}
int readahead_main(int argc, char **argv)
{
	int retval = EXIT_SUCCESS;

	if (argc == 1) bb_show_usage();

	while (*++argv) {
		int fd = open_or_warn(*argv, O_RDONLY);
		if (fd >= 0) {
			int r = readahead(fd, 0, fdlength(fd));
			close(fd);
			if (r >= 0) continue;
		}
		retval = EXIT_FAILURE;
	}

	return retval;
}
示例#7
0
static int
xbsd_get_bootstrap(char *path, void *ptr, int size)
{
    int fdb;

    fdb = open_or_warn(path, O_RDONLY);
    if (fdb < 0) {
        return 0;
    }
    if (full_read(fdb, ptr, size) < 0) {
        bb_simple_perror_msg(path);
        close(fdb);
        return 0;
    }
    printf(" ... %s\n", path);
    close(fdb);
    return 1;
}
示例#8
0
/* Return:
 * -1 error, copy not made
 *  0 copy is made or user answered "no" in interactive mode
 *    (failures to preserve mode/owner/times are not reported in exit code)
 */
int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
{
	/* This is a recursive function, try to minimize stack usage */
	/* NB: each struct stat is ~100 bytes */
	struct stat source_stat;
	struct stat dest_stat;
	smallint retval = 0;
	smallint dest_exists = 0;
	smallint ovr;

/* Inverse of cp -d ("cp without -d") */
#define FLAGS_DEREF (flags & (FILEUTILS_DEREFERENCE + FILEUTILS_DEREFERENCE_L0))

	if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) {
		/* This may be a dangling symlink.
		 * Making [sym]links to dangling symlinks works, so... */
		if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK))
			goto make_links;
		bb_perror_msg("can't stat '%s'", source);
		return -1;
	}

	if (lstat(dest, &dest_stat) < 0) {
		if (errno != ENOENT) {
			bb_perror_msg("can't stat '%s'", dest);
			return -1;
		}
	} else {
		if (source_stat.st_dev == dest_stat.st_dev
		 && source_stat.st_ino == dest_stat.st_ino
		) {
			bb_error_msg("'%s' and '%s' are the same file", source, dest);
			return -1;
		}
		dest_exists = 1;
	}

#if ENABLE_SELINUX
	if ((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) && is_selinux_enabled() > 0) {
		security_context_t con;
		if (lgetfilecon(source, &con) >= 0) {
			if (setfscreatecon(con) < 0) {
				bb_perror_msg("can't set setfscreatecon %s", con);
				freecon(con);
				return -1;
			}
		} else if (errno == ENOTSUP || errno == ENODATA) {
			setfscreatecon_or_die(NULL);
		} else {
			bb_perror_msg("can't lgetfilecon %s", source);
			return -1;
		}
	}
#endif

	if (S_ISDIR(source_stat.st_mode)) {
		DIR *dp;
		const char *tp;
		struct dirent *d;
		mode_t saved_umask = 0;

		if (!(flags & FILEUTILS_RECUR)) {
			bb_error_msg("omitting directory '%s'", source);
			return -1;
		}

		/* Did we ever create source ourself before? */
		tp = is_in_ino_dev_hashtable(&source_stat);
		if (tp) {
			/* We did! it's a recursion! man the lifeboats... */
			bb_error_msg("recursion detected, omitting directory '%s'",
					source);
			return -1;
		}

		if (dest_exists) {
			if (!S_ISDIR(dest_stat.st_mode)) {
				bb_error_msg("target '%s' is not a directory", dest);
				return -1;
			}
			/* race here: user can substitute a symlink between
			 * this check and actual creation of files inside dest */
		} else {
			/* Create DEST */
			mode_t mode;
			saved_umask = umask(0);

			mode = source_stat.st_mode;
			if (!(flags & FILEUTILS_PRESERVE_STATUS))
				mode = source_stat.st_mode & ~saved_umask;
			/* Allow owner to access new dir (at least for now) */
			mode |= S_IRWXU;
			if (mkdir(dest, mode) < 0) {
				umask(saved_umask);
				bb_perror_msg("can't create directory '%s'", dest);
				return -1;
			}
			umask(saved_umask);
			/* need stat info for add_to_ino_dev_hashtable */
			if (lstat(dest, &dest_stat) < 0) {
				bb_perror_msg("can't stat '%s'", dest);
				return -1;
			}
		}
		/* remember (dev,inode) of each created dir.
		 * NULL: name is not remembered */
		add_to_ino_dev_hashtable(&dest_stat, NULL);

		/* Recursively copy files in SOURCE */
		dp = opendir(source);
		if (dp == NULL) {
			retval = -1;
			goto preserve_mode_ugid_time;
		}

		while ((d = readdir(dp)) != NULL) {
			char *new_source, *new_dest;

			new_source = concat_subpath_file(source, d->d_name);
			if (new_source == NULL)
				continue;
			new_dest = concat_path_file(dest, d->d_name);
			if (copy_file(new_source, new_dest, flags & ~FILEUTILS_DEREFERENCE_L0) < 0)
				retval = -1;
			free(new_source);
			free(new_dest);
		}
		closedir(dp);

		if (!dest_exists
		 && chmod(dest, source_stat.st_mode & ~saved_umask) < 0
		) {
			bb_perror_msg("can't preserve %s of '%s'", "permissions", dest);
			/* retval = -1; - WRONG! copy *WAS* made */
		}
		goto preserve_mode_ugid_time;
	}

	if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) {
		int (*lf)(const char *oldpath, const char *newpath);
 make_links:
		/* Hmm... maybe
		 * if (DEREF && MAKE_SOFTLINK) source = realpath(source) ?
		 * (but realpath returns NULL on dangling symlinks...) */
		lf = (flags & FILEUTILS_MAKE_SOFTLINK) ? symlink : link;
		if (lf(source, dest) < 0) {
			ovr = ask_and_unlink(dest, flags);
			if (ovr <= 0)
				return ovr;
			if (lf(source, dest) < 0) {
				bb_perror_msg("can't create link '%s'", dest);
				return -1;
			}
		}
		/* _Not_ jumping to preserve_mode_ugid_time:
		 * (sym)links don't have those */
		return 0;
	}

	if (/* "cp thing1 thing2" without -R: just open and read() from thing1 */
	    !(flags & FILEUTILS_RECUR)
	    /* "cp [-opts] regular_file thing2" */
	 || S_ISREG(source_stat.st_mode)
	 /* DEREF uses stat, which never returns S_ISLNK() == true.
	  * So the below is never true: */
	 /* || (FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) */
	) {
		int src_fd;
		int dst_fd;
		mode_t new_mode;

		if (!FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) {
			/* "cp -d symlink dst": create a link */
			goto dont_cat;
		}

		if (ENABLE_FEATURE_PRESERVE_HARDLINKS && !FLAGS_DEREF) {
			const char *link_target;
			link_target = is_in_ino_dev_hashtable(&source_stat);
			if (link_target) {
				if (link(link_target, dest) < 0) {
					ovr = ask_and_unlink(dest, flags);
					if (ovr <= 0)
						return ovr;
					if (link(link_target, dest) < 0) {
						bb_perror_msg("can't create link '%s'", dest);
						return -1;
					}
				}
				return 0;
			}
			add_to_ino_dev_hashtable(&source_stat, dest);
		}

		src_fd = open_or_warn(source, O_RDONLY);
		if (src_fd < 0)
			return -1;

		/* Do not try to open with weird mode fields */
		new_mode = source_stat.st_mode;
		if (!S_ISREG(source_stat.st_mode))
			new_mode = 0666;

		// POSIX way is a security problem versus (sym)link attacks
		if (!ENABLE_FEATURE_NON_POSIX_CP) {
			dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode);
		} else { /* safe way: */
			dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode);
		}
		if (dst_fd == -1) {
			ovr = ask_and_unlink(dest, flags);
			if (ovr <= 0) {
				close(src_fd);
				return ovr;
			}
			/* It shouldn't exist. If it exists, do not open (symlink attack?) */
			dst_fd = open3_or_warn(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode);
			if (dst_fd < 0) {
				close(src_fd);
				return -1;
			}
		}

#if ENABLE_SELINUX
		if ((flags & (FILEUTILS_PRESERVE_SECURITY_CONTEXT|FILEUTILS_SET_SECURITY_CONTEXT))
		 && is_selinux_enabled() > 0
		) {
			security_context_t con;
			if (getfscreatecon(&con) == -1) {
				bb_perror_msg("getfscreatecon");
				return -1;
			}
			if (con) {
				if (setfilecon(dest, con) == -1) {
					bb_perror_msg("setfilecon:%s,%s", dest, con);
					freecon(con);
					return -1;
				}
				freecon(con);
			}
		}
#endif

		if (bb_copyfd_eof(src_fd, dst_fd) == -1)
			retval = -1;
		/* Careful with writing... */
		if (close(dst_fd) < 0) {
			bb_perror_msg("error writing to '%s'", dest);
			retval = -1;
		}
		/* ...but read size is already checked by bb_copyfd_eof */
		close(src_fd);
		/* "cp /dev/something new_file" should not
		 * copy mode of /dev/something */
		if (!S_ISREG(source_stat.st_mode))
			return retval;
		goto preserve_mode_ugid_time;
	}
 dont_cat:

	/* Source is a symlink or a special file */
	/* We are lazy here, a bit lax with races... */
	if (dest_exists) {
		errno = EEXIST;
		ovr = ask_and_unlink(dest, flags);
		if (ovr <= 0)
			return ovr;
	}
	if (S_ISLNK(source_stat.st_mode)) {
		char *lpath = xmalloc_readlink_or_warn(source);
		if (lpath) {
			int r = symlink(lpath, dest);
			free(lpath);
			if (r < 0) {
				bb_perror_msg("can't create symlink '%s'", dest);
				return -1;
			}
			if (flags & FILEUTILS_PRESERVE_STATUS)
				if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0)
					bb_perror_msg("can't preserve %s of '%s'", "ownership", dest);
		}
		/* _Not_ jumping to preserve_mode_ugid_time:
		 * symlinks don't have those */
		return 0;
	}
	if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode)
	 || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode)
	) {
		if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) {
			bb_perror_msg("can't create '%s'", dest);
			return -1;
		}
	} else {
		bb_error_msg("unrecognized file '%s' with mode %x", source, source_stat.st_mode);
		return -1;
	}

 preserve_mode_ugid_time:

	if (flags & FILEUTILS_PRESERVE_STATUS
	/* Cannot happen: */
	/* && !(flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) */
	) {
		struct timeval times[2];

		times[1].tv_sec = times[0].tv_sec = source_stat.st_mtime;
		times[1].tv_usec = times[0].tv_usec = 0;
		/* BTW, utimes sets usec-precision time - just FYI */
		if (utimes(dest, times) < 0)
			bb_perror_msg("can't preserve %s of '%s'", "times", dest);
		if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) {
			source_stat.st_mode &= ~(S_ISUID | S_ISGID);
			bb_perror_msg("can't preserve %s of '%s'", "ownership", dest);
		}
#if ENABLE_XATTR
		/* Preserve extended attributes. We must copy it after chown()
		 * because it resets capabilities. */
		if (copy_file_attr(source, dest) == -1)
			bb_perror_msg("can't preserve %s of '%s'",
				      "extended attributes", dest);
#endif
		if (chmod(dest, source_stat.st_mode) < 0)
			bb_perror_msg("can't preserve %s of '%s'", "permissions", dest);
	}

	return retval;
}
示例#9
0
static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statbuf,
			void *userData, int depth UNUSED_PARAM)
{
	struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData;
	const char *header_name;
	int inputFileFd = -1;

	/* Strip leading '/' (must be before memorizing hardlink's name) */
	header_name = fileName;
	while (header_name[0] == '/') {
		static smallint warned;

		if (!warned) {
			bb_error_msg("removing leading '/' from member names");
			warned = 1;
		}
		header_name++;
	}

	if (header_name[0] == '\0')
		return TRUE;

	/* It is against the rules to archive a socket */
	if (S_ISSOCK(statbuf->st_mode)) {
		bb_error_msg("%s: socket ignored", fileName);
		return TRUE;
	}

	/*
	 * Check to see if we are dealing with a hard link.
	 * If so -
	 * Treat the first occurance of a given dev/inode as a file while
	 * treating any additional occurances as hard links.  This is done
	 * by adding the file information to the HardLinkInfo linked list.
	 */
	tbInfo->hlInfo = NULL;
	if (statbuf->st_nlink > 1) {
		tbInfo->hlInfo = findHardLinkInfo(tbInfo->hlInfoHead, statbuf);
		if (tbInfo->hlInfo == NULL)
			addHardLinkInfo(&tbInfo->hlInfoHead, statbuf, header_name);
	}

	/* It is a bad idea to store the archive we are in the process of creating,
	 * so check the device and inode to be sure that this particular file isn't
	 * the new tarball */
	if (tbInfo->statBuf.st_dev == statbuf->st_dev
	 && tbInfo->statBuf.st_ino == statbuf->st_ino
	) {
		bb_error_msg("%s: file is the archive; skipping", fileName);
		return TRUE;
	}

	if (exclude_file(tbInfo->excludeList, header_name))
		return SKIP;

#if !ENABLE_FEATURE_TAR_GNU_EXTENSIONS
	if (strlen(header_name) >= NAME_SIZE) {
		bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported");
		return TRUE;
	}
#endif

	/* Is this a regular file? */
	if (tbInfo->hlInfo == NULL && S_ISREG(statbuf->st_mode)) {
		/* open the file we want to archive, and make sure all is well */
		inputFileFd = open_or_warn(fileName, O_RDONLY);
		if (inputFileFd < 0) {
			return FALSE;
		}
	}

	/* Add an entry to the tarball */
	if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) {
		return FALSE;
	}

	/* If it was a regular file, write out the body */
	if (inputFileFd >= 0) {
		size_t readSize;
		/* Write the file to the archive. */
		/* We record size into header first, */
		/* and then write out file. If file shrinks in between, */
		/* tar will be corrupted. So we don't allow for that. */
		/* NB: GNU tar 1.16 warns and pads with zeroes */
		/* or even seeks back and updates header */
		bb_copyfd_exact_size(inputFileFd, tbInfo->tarFd, statbuf->st_size);
		////off_t readSize;
		////readSize = bb_copyfd_size(inputFileFd, tbInfo->tarFd, statbuf->st_size);
		////if (readSize != statbuf->st_size && readSize >= 0) {
		////	bb_error_msg_and_die("short read from %s, aborting", fileName);
		////}

		/* Check that file did not grow in between? */
		/* if (safe_read(inputFileFd, 1) == 1) warn but continue? */

		close(inputFileFd);

		/* Pad the file up to the tar block size */
		/* (a few tricks here in the name of code size) */
		readSize = (-(int)statbuf->st_size) & (TAR_BLOCK_SIZE-1);
		memset(block_buf, 0, readSize);
		xwrite(tbInfo->tarFd, block_buf, readSize);
	}

	return TRUE;
}
示例#10
0
int microcom_main(int argc UNUSED_PARAM, char **argv)
{
	int sfd;
	int nfd;
	struct pollfd pfd[2];
	struct termios tio0, tiosfd, tio;
	char *device_lock_file;
	enum {
		OPT_X = 1 << 0, // do not respect Ctrl-X, Ctrl-@
		OPT_s = 1 << 1, // baudrate
		OPT_d = 1 << 2, // wait for device response, ms
		OPT_t = 1 << 3, // timeout, ms
	};
	speed_t speed = 9600;
	int delay = -1;
	int timeout = -1;
	unsigned opts;

	// fetch options
	opt_complementary = "=1:s+:d+:t+"; // exactly one arg, numeric options
	opts = getopt32(argv, "Xs:d:t:", &speed, &delay, &timeout);
//	argc -= optind;
	argv += optind;

	// try to create lock file in /var/lock
	device_lock_file = (char *)bb_basename(argv[0]);
	device_lock_file = xasprintf("/var/lock/LCK..%s", device_lock_file);
	sfd = open(device_lock_file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644);
	if (sfd < 0) {
		// device already locked -> bail out
		if (errno == EEXIST)
			bb_perror_msg_and_die("can't create %s", device_lock_file);
		// can't create lock -> don't care
		if (ENABLE_FEATURE_CLEAN_UP)
			free(device_lock_file);
		device_lock_file = NULL;
	} else {
		// %4d to make concurrent mgetty (if any) happy.
		// Mgetty treats 4-bytes lock files as binary,
		// not text, PID. Making 5+ char file. Brrr...
		fdprintf(sfd, "%4d\n", getpid());
		close(sfd);
	}

	// setup signals
	bb_signals(0
		+ (1 << SIGHUP)
		+ (1 << SIGINT)
		+ (1 << SIGTERM)
		+ (1 << SIGPIPE)
		, signal_handler);

	// error exit code if we fail to open the device
	signalled = 1;

	// open device
	sfd = open_or_warn(argv[0], O_RDWR | O_NOCTTY | O_NONBLOCK);
	if (sfd < 0)
		goto done;
	fcntl(sfd, F_SETFL, 0);

	// put device to "raw mode"
	xget1(sfd, &tio, &tiosfd);
	// set device speed
	cfsetspeed(&tio, tty_value_to_baud(speed));
	if (xset1(sfd, &tio, argv[0]))
		goto done;

	// put stdin to "raw mode" (if stdin is a TTY),
	// handle one character at a time
	if (isatty(STDIN_FILENO)) {
		xget1(STDIN_FILENO, &tio, &tio0);
		if (xset1(STDIN_FILENO, &tio, "stdin"))
			goto done;
	}

	// main loop: check with poll(), then read/write bytes across
	pfd[0].fd = sfd;
	pfd[0].events = POLLIN;
	pfd[1].fd = STDIN_FILENO;
	pfd[1].events = POLLIN;

	signalled = 0;
	nfd = 2;
	while (!signalled && safe_poll(pfd, nfd, timeout) > 0) {
		if (nfd > 1 && pfd[1].revents) {
			char c;
			// read from stdin -> write to device
			if (safe_read(STDIN_FILENO, &c, 1) < 1) {
				// don't poll stdin anymore if we got EOF/error
				nfd--;
				goto skip_write;
			}
			// do we need special processing?
			if (!(opts & OPT_X)) {
				// ^@ sends Break
				if (VINTR == c) {
					tcsendbreak(sfd, 0);
					goto skip_write;
				}
				// ^X exits
				if (24 == c)
					break;
			}
			write(sfd, &c, 1);
			if (delay >= 0)
				safe_poll(pfd, 1, delay);
skip_write: ;
		}
		if (pfd[0].revents) {
#define iobuf bb_common_bufsiz1
			ssize_t len;
			// read from device -> write to stdout
			len = safe_read(sfd, iobuf, sizeof(iobuf));
			if (len > 0)
				full_write(STDOUT_FILENO, iobuf, len);
			else {
				// EOF/error -> bail out
				signalled = SIGHUP;
				break;
			}
		}
	}

	// restore device mode
	tcsetattr(sfd, TCSAFLUSH, &tiosfd);

	if (isatty(STDIN_FILENO))
		tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);

done:
	if (device_lock_file)
		unlink(device_lock_file);

	return signalled;
}
示例#11
0
void FAST_FUNC read_leases(const char *file)
{
	struct dyn_lease lease;
	int64_t written_at, time_passed;
	int fd;
#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
	unsigned i = 0;
#endif

	fd = open_or_warn(file, O_RDONLY);
	if (fd < 0)
		return;

	if (full_read(fd, &written_at, sizeof(written_at)) != sizeof(written_at))
		goto ret;
	written_at = SWAP_BE64(written_at);

	time_passed = time(NULL) - written_at;
	/* Strange written_at, or lease file from old version of udhcpd
	 * which had no "written_at" field? */
	if ((uint64_t)time_passed > 12 * 60 * 60)
		goto ret;

	while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
		uint32_t y = ntohl(lease.lease_nip);
		if (y >= server_config.start_ip && y <= server_config.end_ip) {
			signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed;
			uint32_t static_nip;

			if (expires <= 0)
				/* We keep expired leases: add_lease() will add
				 * a lease with 0 seconds remaining.
				 * Fewer IP address changes this way for mass reboot scenario.
				 */
				expires = 0;

			/* Check if there is a different static lease for this IP or MAC */
			static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac);
			if (static_nip) {
				/* NB: we do not add lease even if static_nip == lease.lease_nip.
				 */
				continue;
			}
			if (is_nip_reserved(server_config.static_leases, lease.lease_nip))
				continue;

			/* NB: add_lease takes "relative time", IOW,
			 * lease duration, not lease deadline. */
			if (add_lease(lease.lease_mac, lease.lease_nip,
					expires,
					lease.hostname, sizeof(lease.hostname)
				) == 0
			) {
				bb_error_msg("too many leases while loading %s", file);
				break;
			}
#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
			i++;
#endif
		}
	}
	log1("read %d leases", i);
 ret:
	close(fd);
}
示例#12
0
int catv_main(int argc, char **argv)
{
    int retval = EXIT_SUCCESS;
    int fd;
    unsigned flags;

    flags = getopt32(argv, "etv");
#define CATV_OPT_e (1<<0)
#define CATV_OPT_t (1<<1)
#define CATV_OPT_v (1<<2)
    flags ^= CATV_OPT_v;
    argv += optind;

    /* Read from stdin if there's nothing else to do. */
    fd = 0;
    if (!argv[0]) {
        argv--;
        goto jump_in;
    }
    do {
        fd = open_or_warn(*argv, O_RDONLY);
        if (fd < 0) {
            retval = EXIT_FAILURE;
            continue;
        }
jump_in:
        for (;;) {
            int i, res;

#define read_buf bb_common_bufsiz1
            res = read(fd, read_buf, COMMON_BUFSIZE);
            if (res < 0)
                retval = EXIT_FAILURE;
            if (res < 1)
                break;
            for (i = 0; i < res; i++) {
                unsigned char c = read_buf[i];

                if (c > 126 && (flags & CATV_OPT_v)) {
                    if (c == 127) {
                        printf("^?");
                        continue;
                    }
                    printf("M-");
                    c -= 128;
                }
                if (c < 32) {
                    if (c == 10) {
                        if (flags & CATV_OPT_e)
                            bb_putchar('$');
                    } else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) {
                        printf("^%c", c+'@');
                        continue;
                    }
                }
                bb_putchar(c);
            }
        }
        if (ENABLE_FEATURE_CLEAN_UP && fd)
            close(fd);
    } while (*++argv);

    fflush_stdout_and_exit(retval);
}