Beispiel #1
0
static NORETURN void perror_on_device_and_die(const char *fmt)
{
	bb_perror_msg_and_die(fmt, G.device_name);
}
Beispiel #2
0
int expand_main(int argc UNUSED_PARAM, char **argv)
{
	/* Default 8 spaces for 1 tab */
	const char *opt_t = "8";
	FILE *file;
	unsigned tab_size;
	unsigned opt;
	int exit_status = EXIT_SUCCESS;

#if ENABLE_FEATURE_EXPAND_LONG_OPTIONS
	static const char expand_longopts[] ALIGN1 =
		/* name, has_arg, val */
		"initial\0"          No_argument       "i"
		"tabs\0"             Required_argument "t"
	;
#endif
#if ENABLE_FEATURE_UNEXPAND_LONG_OPTIONS
	static const char unexpand_longopts[] ALIGN1 =
		/* name, has_arg, val */
		"first-only\0"       No_argument       "i"
		"tabs\0"             Required_argument "t"
		"all\0"              No_argument       "a"
	;
#endif
	init_unicode();

	if (ENABLE_EXPAND && (!ENABLE_UNEXPAND || applet_name[0] == 'e')) {
		IF_FEATURE_EXPAND_LONG_OPTIONS(applet_long_options = expand_longopts);
		opt = getopt32(argv, "it:", &opt_t);
	} else {
		IF_FEATURE_UNEXPAND_LONG_OPTIONS(applet_long_options = unexpand_longopts);
		/* -t NUM sets also -a */
		opt_complementary = "ta";
		opt = getopt32(argv, "ft:a", &opt_t);
		/* -f --first-only is the default */
		if (!(opt & OPT_ALL)) opt |= OPT_INITIAL;
	}
	tab_size = xatou_range(opt_t, 1, UINT_MAX);

	argv += optind;

	if (!*argv) {
		*--argv = (char*)bb_msg_standard_input;
	}
	do {
		file = fopen_or_warn_stdin(*argv);
		if (!file) {
			exit_status = EXIT_FAILURE;
			continue;
		}

		if (ENABLE_EXPAND && (!ENABLE_UNEXPAND || applet_name[0] == 'e'))
			IF_EXPAND(expand(file, tab_size, opt));
		else
			IF_UNEXPAND(unexpand(file, tab_size, opt));

		/* Check and close the file */
		if (fclose_if_not_stdin(file)) {
			bb_simple_perror_msg(*argv);
			exit_status = EXIT_FAILURE;
		}
		/* If stdin also clear EOF */
		if (file == stdin)
			clearerr(file);
	} while (*++argv);

	/* Now close stdin also */
	/* (if we didn't read from it, it's a no-op) */
	if (fclose(stdin))
		bb_perror_msg_and_die(bb_msg_standard_input);

	fflush_stdout_and_exit(exit_status);
}
Beispiel #3
0
int arping_main(int argc UNUSED_PARAM, char **argv)
{
	const char *device = "eth0";
	char *source = NULL;
	char *target;
	unsigned char *packet;
	char *err_str;

	INIT_G();

	sock_fd = xsocket(AF_PACKET, SOCK_DGRAM, 0);

	// Drop suid root privileges
	// Need to remove SUID_NEVER from applets.h for this to work
	//xsetuid(getuid());

	err_str = xasprintf("interface %s %%s", device);
	{
		unsigned opt;
		char *str_timeout;

		/* Dad also sets quit_on_reply.
		 * Advert also sets unsolicited.
		 */
		opt_complementary = "=1:Df:AU:c+";
		opt = getopt32(argv, "DUAqfbc:w:I:s:",
				&count, &str_timeout, &device, &source);
		if (opt & 0x80) /* -w: timeout */
			timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000 + 500000;
		//if (opt & 0x200) /* -s: source */
		option_mask32 &= 0x3f; /* set respective flags */
	}

	target = argv[optind];

	xfunc_error_retval = 2;

	{
		struct ifreq ifr;

		memset(&ifr, 0, sizeof(ifr));
		strncpy_IFNAMSIZ(ifr.ifr_name, device);
		/* We use ifr.ifr_name in error msg so that problem
		 * with truncated name will be visible */
		ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, err_str, "not found");
		me.sll_ifindex = ifr.ifr_ifindex;

		xioctl(sock_fd, SIOCGIFFLAGS, (char *) &ifr);

		if (!(ifr.ifr_flags & IFF_UP)) {
			bb_error_msg_and_die(err_str, "is down");
		}
		if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {
			bb_error_msg(err_str, "is not ARPable");
			return (option_mask32 & DAD ? 0 : 2);
		}
	}

	/* if (!inet_aton(target, &dst)) - not needed */ {
		len_and_sockaddr *lsa;
		lsa = xhost_and_af2sockaddr(target, 0, AF_INET);
		dst = lsa->u.sin.sin_addr;
		if (ENABLE_FEATURE_CLEAN_UP)
			free(lsa);
	}

	if (source && !inet_aton(source, &src)) {
		bb_error_msg_and_die("invalid source address %s", source);
	}

	if ((option_mask32 & (DAD|UNSOLICITED)) == UNSOLICITED && src.s_addr == 0)
		src = dst;

	if (!(option_mask32 & DAD) || src.s_addr) {
		struct sockaddr_in saddr;
		int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);

		setsockopt_bindtodevice(probe_fd, device);
		memset(&saddr, 0, sizeof(saddr));
		saddr.sin_family = AF_INET;
		if (src.s_addr) {
			/* Check that this is indeed our IP */
			saddr.sin_addr = src;
			xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
		} else { /* !(option_mask32 & DAD) case */
			/* Find IP address on this iface */
			socklen_t alen = sizeof(saddr);

			saddr.sin_port = htons(1025);
			saddr.sin_addr = dst;

			if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1)
				bb_perror_msg("setsockopt(SO_DONTROUTE)");
			xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
			if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) {
				bb_perror_msg_and_die("getsockname");
			}
			if (saddr.sin_family != AF_INET)
				bb_error_msg_and_die("no IP address configured");
			src = saddr.sin_addr;
		}
		close(probe_fd);
	}

	me.sll_family = AF_PACKET;
	//me.sll_ifindex = ifindex; - done before
	me.sll_protocol = htons(ETH_P_ARP);
	xbind(sock_fd, (struct sockaddr *) &me, sizeof(me));

	{
		socklen_t alen = sizeof(me);

		if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) {
			bb_perror_msg_and_die("getsockname");
		}
	}
	if (me.sll_halen == 0) {
		bb_error_msg(err_str, "is not ARPable (no ll address)");
		return (option_mask32 & DAD ? 0 : 2);
	}
	he = me;
	memset(he.sll_addr, -1, he.sll_halen);

	if (!(option_mask32 & QUIET)) {
		/* inet_ntoa uses static storage, can't use in same printf */
		printf("ARPING to %s", inet_ntoa(dst));
		printf(" from %s via %s\n", inet_ntoa(src), device);
	}

	signal_SA_RESTART_empty_mask(SIGINT,  (void (*)(int))finish);
	signal_SA_RESTART_empty_mask(SIGALRM, (void (*)(int))catcher);

	catcher();

	packet = xmalloc(4096);
	while (1) {
		sigset_t sset, osset;
		struct sockaddr_ll from;
		socklen_t alen = sizeof(from);
		int cc;

		cc = recvfrom(sock_fd, packet, 4096, 0, (struct sockaddr *) &from, &alen);
		if (cc < 0) {
			bb_perror_msg("recvfrom");
			continue;
		}
		sigemptyset(&sset);
		sigaddset(&sset, SIGALRM);
		sigaddset(&sset, SIGINT);
		sigprocmask(SIG_BLOCK, &sset, &osset);
		recv_pack(packet, cc, &from);
		sigprocmask(SIG_SETMASK, &osset, NULL);
	}
}
Beispiel #4
0
int flashcp_main(int argc UNUSED_PARAM, char **argv)
{
	int fd_f, fd_d; /* input file and mtd device file descriptors */
	int i;
	uoff_t erase_count;
	struct mtd_info_user mtd;
	struct erase_info_user e;
	struct stat statb;
//	const char *filename, *devicename;
	RESERVE_CONFIG_UBUFFER(buf, BUFSIZE);
	RESERVE_CONFIG_UBUFFER(buf2, BUFSIZE);

	opt_complementary = "=2"; /* exactly 2 non-option args: file, dev */
	/*opts =*/ getopt32(argv, "v");
	argv += optind;
//	filename = *argv++;
//	devicename = *argv;
#define filename argv[0]
#define devicename argv[1]

	/* open input file and mtd device and do sanity checks */
	fd_f = xopen(filename, O_RDONLY);
	fstat(fd_f, &statb);
	fd_d = xopen(devicename, O_SYNC | O_RDWR);
#if !MTD_DEBUG
	if (ioctl(fd_d, MEMGETINFO, &mtd) < 0) {
		bb_error_msg_and_die("%s is not a MTD flash device", devicename);
	}
	if (statb.st_size > mtd.size) {
		bb_error_msg_and_die("%s bigger than %s", filename, devicename);
	}
#else
	mtd.erasesize = 64 * 1024;
#endif

	/* always erase a complete block */
	erase_count = (uoff_t)(statb.st_size + mtd.erasesize - 1) / mtd.erasesize;
	/* erase 1 block at a time to be able to give verbose output */
	e.length = mtd.erasesize;
#if 0
/* (1) bloat
 * (2) will it work for multi-gigabyte devices?
 * (3) worse wrt error detection granularity
 */
	/* optimization: if not verbose, erase in one go */
	if (!opts) { // if (!(opts & OPT_v))
		e.length = mtd.erasesize * erase_count;
		erase_count = 1;
	}
#endif
	e.start = 0;
	for (i = 1; i <= erase_count; i++) {
		progress(-1, i, erase_count);
#if !MTD_DEBUG
		if (ioctl(fd_d, MEMERASE, &e) < 0) {
			bb_perror_msg_and_die("erase error at 0x%llx on %s",
				(long long)e.start, devicename);
		}
#else
		usleep(100*1000);
#endif
		e.start += mtd.erasesize;
	}
	progress_newline();

	/* doing this outer loop gives significantly smaller code
	 * than doing two separate loops for writing and verifying */
	for (i = 0; i <= 1; i++) {
		uoff_t done;
		unsigned count;

		xlseek(fd_f, 0, SEEK_SET);
		xlseek(fd_d, 0, SEEK_SET);
		done = 0;
		count = BUFSIZE;
		while (1) {
			uoff_t rem;

			progress(i, done / 1024, (uoff_t)statb.st_size / 1024);
			rem = statb.st_size - done;
			if (rem == 0)
				break;
			if (rem < BUFSIZE)
				count = rem;
			xread(fd_f, buf, count);
			if (i == 0) {
				int ret;
				if (count < BUFSIZE)
					memset((char*)buf + count, 0, BUFSIZE - count);
				errno = 0;
				ret = full_write(fd_d, buf, BUFSIZE);
				if (ret != BUFSIZE) {
					bb_perror_msg_and_die("write error at 0x%"OFF_FMT"x on %s, "
						"write returned %d",
						done, devicename, ret);
				}
			} else { /* i == 1 */
				xread(fd_d, buf2, count);
				if (memcmp(buf, buf2, count) != 0) {
					bb_error_msg_and_die("verification mismatch at 0x%"OFF_FMT"x", done);
				}
			}

			done += count;
		}

		progress_newline();
	}
	/* we won't come here if there was an error */

	return EXIT_SUCCESS;
}
Beispiel #5
0
int fbset_main(int argc, char **argv)
#endif
{
	struct fb_var_screeninfo var, varset;
	int fh, i;
	char *fbdev = DEFAULTFBDEV;
	char *modefile = DEFAULTFBMODE;
	char *thisarg, *mode = NULL;

	memset(&varset, 0xFF, sizeof(varset));

	/* parse cmd args.... why do they have to make things so difficult? */
	argv++;
	argc--;
	for (; argc > 0 && (thisarg = *argv); argc--, argv++) {
		for (i = 0; g_cmdoptions[i].name; i++) {
			if (!strcmp(thisarg, g_cmdoptions[i].name)) {
				if (argc - 1 < g_cmdoptions[i].param_count)
					bb_show_usage();
				switch (g_cmdoptions[i].code) {
				case CMD_FB:
					fbdev = argv[1];
					break;
				case CMD_DB:
					modefile = argv[1];
					break;
				case CMD_GEOMETRY:
					varset.xres = strtoul(argv[1], 0, 0);
					varset.yres = strtoul(argv[2], 0, 0);
					varset.xres_virtual = strtoul(argv[3], 0, 0);
					varset.yres_virtual = strtoul(argv[4], 0, 0);
					varset.bits_per_pixel = strtoul(argv[5], 0, 0);
					break;
				case CMD_TIMING:
					varset.pixclock = strtoul(argv[1], 0, 0);
					varset.left_margin = strtoul(argv[2], 0, 0);
					varset.right_margin = strtoul(argv[3], 0, 0);
					varset.upper_margin = strtoul(argv[4], 0, 0);
					varset.lower_margin = strtoul(argv[5], 0, 0);
					varset.hsync_len = strtoul(argv[6], 0, 0);
					varset.vsync_len = strtoul(argv[7], 0, 0);
					break;
		case CMD_CHANGE:
		    g_options |= OPT_CHANGE;
		    break;
#ifdef CONFIG_FEATURE_FBSET_FANCY
				case CMD_XRES:
					varset.xres = strtoul(argv[1], 0, 0);
					break;
				case CMD_YRES:
					varset.yres = strtoul(argv[1], 0, 0);
					break;
			   case CMD_DEPTH:
					varset.bits_per_pixel = strtoul(argv[1], 0, 0);
					break;
#endif
				}
				argc -= g_cmdoptions[i].param_count;
				argv += g_cmdoptions[i].param_count;
				break;
			}
		}
		if (!g_cmdoptions[i].name) {
			if (argc == 1) {
				mode = *argv;
				g_options |= OPT_READMODE;
			} else {
				bb_show_usage();
			}
		}
	}

	if ((fh = open(fbdev, O_RDONLY)) < 0)
		bb_perror_msg_and_die("fbset(open)");
	if (ioctl(fh, FBIOGET_VSCREENINFO, &var))
		bb_perror_msg_and_die("fbset(ioctl)");
	if (g_options & OPT_READMODE) {
		if (!readmode(&var, modefile, mode)) {
			bb_error_msg("Unknown video mode `%s'", mode);
			return EXIT_FAILURE;
		}
	}

	setmode(&var, &varset);
	if (g_options & OPT_CHANGE)
		if (ioctl(fh, FBIOPUT_VSCREENINFO, &var))
			bb_perror_msg_and_die("fbset(ioctl)");
	showmode(&var);
	/* Don't close the file, as exiting will take care of that */
	/* close(fh); */

	return EXIT_SUCCESS;
}
Beispiel #6
0
static void INET_setroute(int action, char **args)
{
	struct rtentry rt;
	const char *netmask;
	int skfd, isnet, xflag;

	assert((action == RTACTION_ADD) || (action == RTACTION_DEL));

	/* Grab the -net or -host options.  Remember they were transformed. */
	xflag = kw_lookup(tbl_hash_net_host, &args);

	/* If we did grab -net or -host, make sure we still have an arg left. */
	if (*args == NULL) {
		bb_show_usage();
	}

	/* Clean out the RTREQ structure. */
	memset((char *) &rt, 0, sizeof(struct rtentry));

	{
		const char *target = *args++;

		/* Prefer hostname lookup is -host flag (xflag==1) was given. */
 		isnet = INET_resolve(target, (struct sockaddr_in *) &rt.rt_dst,
							 (xflag & HOST_FLAG));
		if (isnet < 0) {
			bb_error_msg_and_die("resolving %s", target);
		}

	}

	if (xflag) {		/* Reinit isnet if -net or -host was specified. */
		isnet = (xflag & NET_FLAG);
	}

	/* Fill in the other fields. */
	rt.rt_flags = ((isnet) ? RTF_UP : (RTF_UP | RTF_HOST));

	netmask = bb_INET_default;

	while (*args) {
		int k = kw_lookup(tbl_ipvx, &args);
		const char *args_m1 = args[-1];

		if (k & KW_IPVx_FLAG_ONLY) {
			rt.rt_flags |= flags_ipvx[k & 3];
			continue;
		}

#if HAVE_NEW_ADDRT
		if (k == KW_IPVx_METRIC) {
			rt.rt_metric = bb_xgetularg10(args_m1) + 1;
			continue;
		}
#endif

		if (k == KW_IPVx_NETMASK) {
			struct sockaddr mask;

			if (mask_in_addr(rt)) {
				bb_show_usage();
			}

			netmask = args_m1;
			isnet = INET_resolve(netmask, (struct sockaddr_in *) &mask, 0);
			if (isnet < 0) {
				bb_error_msg_and_die("resolving %s", netmask);
			}
			rt.rt_genmask = full_mask(mask);
			continue;
		}

		if (k == KW_IPVx_GATEWAY) {
			if (rt.rt_flags & RTF_GATEWAY) {
				bb_show_usage();
			}

			isnet = INET_resolve(args_m1,
								 (struct sockaddr_in *) &rt.rt_gateway, 1);
			rt.rt_flags |= RTF_GATEWAY;

			if (isnet) {
				if (isnet < 0) {
					bb_error_msg_and_die("resolving %s", args_m1);
				}
				bb_error_msg_and_die("gateway %s is a NETWORK", args_m1);
			}
			continue;
		}

		if (k == KW_IPVx_MSS) {	/* Check valid MSS bounds. */
			rt.rt_flags |= RTF_MSS;
			rt.rt_mss = bb_xgetularg10_bnd(args_m1, 64, 32768);
			continue;
		}

		if (k == KW_IPVx_WINDOW) {	/* Check valid window bounds. */
			rt.rt_flags |= RTF_WINDOW;
			rt.rt_window = bb_xgetularg10_bnd(args_m1, 128, INT_MAX);
			continue;
		}

#ifdef RTF_IRTT
		if (k == KW_IPVx_IRTT) {
			rt.rt_flags |= RTF_IRTT;
			rt.rt_irtt = bb_xgetularg10(args_m1);
			rt.rt_irtt *= (sysconf(_SC_CLK_TCK) / 100);	/* FIXME */
#if 0					/* FIXME: do we need to check anything of this? */
			if (rt.rt_irtt < 1 || rt.rt_irtt > (120 * HZ)) {
				bb_error_msg_and_die("bad irtt");
			}
#endif
			continue;
		}
#endif

		/* Device is special in that it can be the last arg specified
		 * and doesn't requre the dev/device keyword in that case. */
		if (!rt.rt_dev && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) {
			/* Don't use args_m1 here since args may have changed! */
			rt.rt_dev = args[-1];
			continue;
		}

		/* Nothing matched. */
		bb_show_usage();
	}

#ifdef RTF_REJECT
	if ((rt.rt_flags & RTF_REJECT) && !rt.rt_dev) {
		rt.rt_dev = "lo";
	}
#endif

	/* sanity checks.. */
	if (mask_in_addr(rt)) {
		unsigned long mask = mask_in_addr(rt);

		mask = ~ntohl(mask);
		if ((rt.rt_flags & RTF_HOST) && mask != 0xffffffff) {
			bb_error_msg_and_die("netmask %.8x and host route conflict",
								 (unsigned int) mask);
		}
		if (mask & (mask + 1)) {
			bb_error_msg_and_die("bogus netmask %s", netmask);
		}
		mask = ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr;
		if (mask & ~mask_in_addr(rt)) {
			bb_error_msg_and_die("netmask and route address conflict");
		}
	}

	/* Fill out netmask if still unset */
	if ((action == RTACTION_ADD) && (rt.rt_flags & RTF_HOST)) {
		mask_in_addr(rt) = 0xffffffff;
	}

	/* Create a socket to the INET kernel. */
	if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		bb_perror_msg_and_die("socket");
	}

	if (ioctl(skfd, ((action==RTACTION_ADD) ? SIOCADDRT : SIOCDELRT), &rt)<0) {
		bb_perror_msg_and_die("SIOC[ADD|DEL]RT");
	}

	/* Don't bother closing, as we're exiting after we return anyway. */
	/* close(skfd); */
}
Beispiel #7
0
int crond_main(int ac, char **av)
{
	unsigned long opt;
	char *lopt, *Lopt, *copt;

#ifdef FEATURE_DEBUG_OPT
	char *dopt;

	bb_opt_complementally = "f-b:b-f:S-L:L-S:d-l";
#else
	bb_opt_complementally = "f-b:b-f:S-L:L-S";
#endif

	opterr = 0;			/* disable getopt 'errors' message. */
	opt = bb_getopt_ulflags(ac, av, "l:L:fbSc:"
#ifdef FEATURE_DEBUG_OPT
							"d:"
#endif
							, &lopt, &Lopt, &copt
#ifdef FEATURE_DEBUG_OPT
							, &dopt
#endif
		);
	if (opt & 1) {
		LogLevel = atoi(lopt);
	}
	if (opt & 2) {
		if (*Lopt != 0) {
			LogFile = Lopt;
		}
	}
	if (opt & 32) {
		if (*copt != 0) {
			CDir = copt;
		}
	}
#ifdef FEATURE_DEBUG_OPT
	if (opt & 64) {
		DebugOpt = atoi(dopt);
		LogLevel = 0;
	}
#endif

	/*
	 * change directory
	 */

	if (chdir(CDir) != 0) {
		bb_perror_msg_and_die("%s", CDir);
	}
	signal(SIGHUP, SIG_IGN);	/* hmm.. but, if kill -HUP original
								 * version - his died. ;(
								 */
	/*
	 * close stdin and stdout, stderr.
	 * close unused descriptors -  don't need.
	 * optional detach from controlling terminal
	 */

	if (!(opt & 4)) {
#if defined(__uClinux__)
		/* reexec for vfork() do continue parent */
		vfork_daemon_rexec(1, 0, ac, av, "-f");
#else							/* uClinux */
		if (daemon(1, 0) < 0) {
			bb_perror_msg_and_die("daemon");
		}
#endif							/* uClinux */
	}

	(void) startlogger();	/* need if syslog mode selected */

	/*
	 * main loop - synchronize to 1 second after the minute, minimum sleep
	 *             of 1 second.
	 */

	crondlog("\011%s " VERSION " dillon, started, log level %d\n",
			 bb_applet_name, LogLevel);

	SynchronizeDir();

	{
		time_t t1 = time(NULL);
		time_t t2;
		long dt;
		short rescan = 60;
		short sleep_time = 60;

		for (;;) {
			sleep((sleep_time + 1) - (short) (time(NULL) % sleep_time));

			t2 = time(NULL);
			dt = t2 - t1;

			/*
			 * The file 'cron.update' is checked to determine new cron
			 * jobs.  The directory is rescanned once an hour to deal
			 * with any screwups.
			 *
			 * check for disparity.  Disparities over an hour either way
			 * result in resynchronization.  A reverse-indexed disparity
			 * less then an hour causes us to effectively sleep until we
			 * match the original time (i.e. no re-execution of jobs that
			 * have just been run).  A forward-indexed disparity less then
			 * an hour causes intermediate jobs to be run, but only once
			 * in the worst case.
			 *
			 * when running jobs, the inequality used is greater but not
			 * equal to t1, and less then or equal to t2.
			 */

			if (--rescan == 0) {
				rescan = 60;
				SynchronizeDir();
			}
			CheckUpdates();
#ifdef FEATURE_DEBUG_OPT
			if (DebugOpt)
				crondlog("\005Wakeup dt=%d\n", dt);
#endif
			if (dt < -60 * 60 || dt > 60 * 60) {
				t1 = t2;
				crondlog("\111time disparity of %d minutes detected\n", dt / 60);
			} else if (dt > 0) {
				TestJobs(t1, t2);
				RunJobs();
				sleep(5);
				if (CheckJobs() > 0) {
					sleep_time = 10;
				} else {
					sleep_time = 60;
				}
				t1 = t2;
			}
		}
	}
	/* not reached */
}
Beispiel #8
0
void xpipe(int filedes[2])
{
	if (pipe(filedes))
		bb_perror_msg_and_die("can't create pipe");
}
Beispiel #9
0
void xdup2(int from, int to)
{
	if (dup2(from, to) != to)
		bb_perror_msg_and_die("can't duplicate file descriptor");
}
Beispiel #10
0
void xunlink(const char *pathname)
{
	if (unlink(pathname))
		bb_perror_msg_and_die("can't remove file '%s'", pathname);
}
Beispiel #11
0
void xrename(const char *oldpath, const char *newpath)
{
	if (rename(oldpath, newpath))
		bb_perror_msg_and_die("can't move '%s' to '%s'", oldpath, newpath);
}
extern int ipaddr_list_or_flush(int argc, char **argv, int flush)
{
	const char *option[] = { "to", "scope", "up", "label", "dev", 0 };
	struct nlmsg_list *linfo = NULL;
	struct nlmsg_list *ainfo = NULL;
	struct nlmsg_list *l;
	struct rtnl_handle rth;
	char *filter_dev = NULL;
	int no_link = 0;

	ipaddr_reset_filter(oneline);
	filter.showqueue = 1;

	if (filter.family == AF_UNSPEC)
		filter.family = preferred_family;

	if (flush) {
		if (argc <= 0) {
			fprintf(stderr, "Flush requires arguments.\n");
			return -1;
		}
		if (filter.family == AF_PACKET) {
			fprintf(stderr, "Cannot flush link addresses.\n");
			return -1;
		}
	}

	while (argc > 0) {
		const unsigned short option_num = compare_string_array(option, *argv);
		switch (option_num) {
			case 0: /* to */
				NEXT_ARG();
				get_prefix(&filter.pfx, *argv, filter.family);
				if (filter.family == AF_UNSPEC) {
					filter.family = filter.pfx.family;
				}
				break;
			case 1: /* scope */
			{
				int scope = 0;
				NEXT_ARG();
				filter.scopemask = -1;
				if (rtnl_rtscope_a2n(&scope, *argv)) {
					if (strcmp(*argv, "all") != 0) {
						invarg("invalid \"scope\"\n", *argv);
					}
					scope = RT_SCOPE_NOWHERE;
					filter.scopemask = 0;
				}
				filter.scope = scope;
				break;
			}
			case 2: /* up */
				filter.up = 1;
				break;
			case 3: /* label */
				NEXT_ARG();
				filter.label = *argv;
				break;
			case 4: /* dev */
				NEXT_ARG();
			default:
				if (filter_dev) {
					duparg2("dev", *argv);
				}
				filter_dev = *argv;
		}
		argv++;
		argc--;
	}

	if (rtnl_open(&rth, 0) < 0)
		exit(1);

	if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
		bb_perror_msg_and_die("Cannot send dump request");
	}

	if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
		bb_error_msg_and_die("Dump terminated");
	}

	if (filter_dev) {
		filter.ifindex = ll_name_to_index(filter_dev);
		if (filter.ifindex <= 0) {
			bb_error_msg("Device \"%s\" does not exist.", filter_dev);
			return -1;
		}
	}

	if (flush) {
		int round = 0;
		char flushb[4096-512];

		filter.flushb = flushb;
		filter.flushp = 0;
		filter.flushe = sizeof(flushb);
		filter.rth = &rth;

		for (;;) {
			if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
				perror("Cannot send dump request");
				exit(1);
			}
			filter.flushed = 0;
			if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) {
				fprintf(stderr, "Flush terminated\n");
				exit(1);
			}
			if (filter.flushed == 0) {
#if 0
				if (round == 0)
					fprintf(stderr, "Nothing to flush.\n");
#endif
				fflush(stdout);
				return 0;
			}
			round++;
			if (flush_update() < 0)
				exit(1);
		}
	}

	if (filter.family != AF_PACKET) {
		if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
			bb_perror_msg_and_die("Cannot send dump request");
		}

		if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) {
			bb_error_msg_and_die("Dump terminated");
		}
	}


	if (filter.family && filter.family != AF_PACKET) {
		struct nlmsg_list **lp;
		lp=&linfo;

		if (filter.oneline)
			no_link = 1;

		while ((l=*lp)!=NULL) {
			int ok = 0;
			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
			struct nlmsg_list *a;

			for (a=ainfo; a; a=a->next) {
				struct nlmsghdr *n = &a->h;
				struct ifaddrmsg *ifa = NLMSG_DATA(n);

				if (ifa->ifa_index != ifi->ifi_index ||
				    (filter.family && filter.family != ifa->ifa_family))
					continue;
				if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
					continue;
				if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
					continue;
				if (filter.pfx.family || filter.label) {
					struct rtattr *tb[IFA_MAX+1];
					memset(tb, 0, sizeof(tb));
					parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
					if (!tb[IFA_LOCAL])
						tb[IFA_LOCAL] = tb[IFA_ADDRESS];

					if (filter.pfx.family && tb[IFA_LOCAL]) {
						inet_prefix dst;
						memset(&dst, 0, sizeof(dst));
						dst.family = ifa->ifa_family;
						memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
						if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
							continue;
					}
					if (filter.label) {
						SPRINT_BUF(b1);
						const char *label;
						if (tb[IFA_LABEL])
							label = RTA_DATA(tb[IFA_LABEL]);
						else
							label = ll_idx_n2a(ifa->ifa_index, b1);
						if (fnmatch(filter.label, label, 0) != 0)
							continue;
					}
				}

				ok = 1;
				break;
			}
			if (!ok)
				*lp = l->next;
			else
				lp = &l->next;
		}
	}

	for (l=linfo; l; l = l->next) {
		if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
			if (filter.family != AF_PACKET)
				print_selected_addrinfo(ifi->ifi_index, ainfo, stdout);
		}
		fflush(stdout);
	}

	exit(0);
}
Beispiel #13
0
void data_extract_all(archive_handle_t *archive_handle)
{
	file_header_t *file_header = archive_handle->file_header;
	int dst_fd;
	int res;

	if (archive_handle->flags & ARCHIVE_CREATE_LEADING_DIRS) {
		char *name = xstrdup(file_header->name);
		bb_make_directory(dirname(name), -1, FILEUTILS_RECUR);
		free(name);
	}

	/* Check if the file already exists */
	if (archive_handle->flags & ARCHIVE_EXTRACT_UNCONDITIONAL) {
		/* Remove the existing entry if it exists */
		if (((file_header->mode & S_IFMT) != S_IFDIR)
		 && (unlink(file_header->name) == -1)
		 && (errno != ENOENT)
		) {
			bb_perror_msg_and_die("cannot remove old file %s",
					file_header->name);
		}
	}
	else if (archive_handle->flags & ARCHIVE_EXTRACT_NEWER) {
		/* Remove the existing entry if its older than the extracted entry */
		struct stat statbuf;
		if (lstat(file_header->name, &statbuf) == -1) {
			if (errno != ENOENT) {
				bb_perror_msg_and_die("cannot stat old file");
			}
		}
		else if (statbuf.st_mtime <= file_header->mtime) {
			if (!(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
				bb_error_msg("%s not created: newer or "
					"same age file exists", file_header->name);
			}
			data_skip(archive_handle);
			return;
		}
		else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
			bb_perror_msg_and_die("cannot remove old file %s",
					file_header->name);
		}
	}

	/* Handle hard links separately
	 * We identified hard links as regular files of size 0 with a symlink */
	if (S_ISREG(file_header->mode) && (file_header->link_target)
	 && (file_header->size == 0)
	) {
		/* hard link */
		res = link(file_header->link_target, file_header->name);
		if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
			bb_perror_msg("cannot create %slink "
					"from %s to %s", "hard",
					file_header->name,
					file_header->link_target);
		}
	} else {
		/* Create the filesystem entry */
		switch (file_header->mode & S_IFMT) {
		case S_IFREG: {
			/* Regular file */
			dst_fd = xopen3(file_header->name, O_WRONLY | O_CREAT | O_EXCL,
							file_header->mode);
			bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
			close(dst_fd);
			break;
		}
		case S_IFDIR:
			res = mkdir(file_header->name, file_header->mode);
			if ((res == -1) && (errno != EISDIR)
			 && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("cannot make dir %s", file_header->name);
			}
			break;
		case S_IFLNK:
			/* Symlink */
			res = symlink(file_header->link_target, file_header->name);
			if ((res == -1)
			 && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("cannot create %slink "
					"from %s to %s", "sym",
					file_header->name,
					file_header->link_target);
			}
			break;
#ifndef _WIN32
		case S_IFSOCK:
		case S_IFBLK:
		case S_IFCHR:
		case S_IFIFO:
			res = mknod(file_header->name, file_header->mode, file_header->device);
			if ((res == -1)
			 && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("cannot create node %s", file_header->name);
			}
			break;
#endif
		default:
			bb_error_msg_and_die("unrecognized file type");
		}
	}

#ifndef _WIN32
	if (!(archive_handle->flags & ARCHIVE_NOPRESERVE_OWN)) {
#if ENABLE_FEATURE_TAR_UNAME_GNAME
		uid_t uid = file_header->uid;
		gid_t gid = file_header->gid;

		if (file_header->uname) {
			struct passwd *pwd = getpwnam(file_header->uname);
			if (pwd) uid = pwd->pw_uid;
		}
		if (file_header->gname) {
			struct group *grp = getgrnam(file_header->gname);
			if (grp) gid = grp->gr_gid;
		}
		lchown(file_header->name, uid, gid);
#else
		lchown(file_header->name, file_header->uid, file_header->gid);
#endif
	}
#endif
	if ((file_header->mode & S_IFMT) != S_IFLNK) {
		/* uclibc has no lchmod, glibc is even stranger -
		 * it has lchmod which seems to do nothing!
		 * so we use chmod... */
		if (!(archive_handle->flags & ARCHIVE_NOPRESERVE_PERM)) {
			chmod(file_header->name, file_header->mode);
		}
		/* same for utime */
		if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) {
			struct utimbuf t;
			t.actime = t.modtime = file_header->mtime;
			utime(file_header->name, &t);
		}
	}
}
int readprofile_main(int argc, char **argv)
{
	FILE *map;
	int proFd;
	const char *mapFile, *proFile, *mult=0;
	unsigned long len=0, indx=1;
	unsigned long long add0=0;
	unsigned int step;
	unsigned int *buf, total, fn_len;
	unsigned long long fn_add, next_add;          /* current and next address */
	char fn_name[S_LEN], next_name[S_LEN];   /* current and next name */
	char mode[8];
	int c;
	int optAll=0, optInfo=0, optReset=0, optVerbose=0, optNative=0;
	int optBins=0, optSub=0;
	char mapline[S_LEN];
	int maplineno=1;
	int header_printed;

#define next (current^1)

	proFile = defaultpro;
	mapFile = defaultmap;

	while ((c = getopt(argc, argv, "M:m:np:itvarVbs")) != -1) {
		switch(c) {
		case 'm':
			mapFile = optarg;
			break;
		case 'n':
			optNative++;
			break;
		case 'p':
			proFile = optarg;
			break;
		case 'a':
			optAll++;
			break;
		case 'b':
			optBins++;
			break;
		case 's':
			optSub++;
			break;
		case 'i':
			optInfo++;
			break;
		case 'M':
			mult = optarg;
			break;
		case 'r':
			optReset++;
			break;
		case 'v':
			optVerbose++;
			break;
		default:
			bb_show_usage();
		}
	}

	if (optReset || mult) {
		int multiplier, fd, to_write;

		/*
		 * When writing the multiplier, if the length of the write is
		 * not sizeof(int), the multiplier is not changed
		 */
		if (mult) {
			multiplier = strtoul(mult, 0, 10);
			to_write = sizeof(int);
		} else {
			multiplier = 0;
			to_write = 1;	/* sth different from sizeof(int) */
		}

		fd = bb_xopen(defaultpro,O_WRONLY);

		if (write(fd, &multiplier, to_write) != to_write)
			bb_perror_msg_and_die("error writing %s", defaultpro);

		close(fd);
		return EXIT_SUCCESS;
	}

	/*
	 * Use an fd for the profiling buffer, to skip stdio overhead
	 */

	proFd = bb_xopen(proFile,O_RDONLY);

	if (((int)(len=lseek(proFd,0,SEEK_END)) < 0)
	    || (lseek(proFd,0,SEEK_SET) < 0))
		bb_perror_msg_and_die(proFile);

	buf = xmalloc(len);

	if (read(proFd,buf,len) != len)
		bb_perror_msg_and_die(proFile);

	close(proFd);

	if (!optNative) {
		int entries = len/sizeof(*buf);
		int big = 0,small = 0,i;
		unsigned *p;

		for (p = buf+1; p < buf+entries; p++) {
			if (*p & ~0U << (sizeof(*buf)*4))
				big++;
			if (*p & ((1 << (sizeof(*buf)*4))-1))
				small++;
		}
		if (big > small) {
			bb_error_msg("Assuming reversed byte order. "
				"Use -n to force native byte order.");
			for (p = buf; p < buf+entries; p++)
				for (i = 0; i < sizeof(*buf)/2; i++) {
					unsigned char *b = (unsigned char *) p;
					unsigned char tmp;

					tmp = b[i];
					b[i] = b[sizeof(*buf)-i-1];
					b[sizeof(*buf)-i-1] = tmp;
				}
		}
	}

	step = buf[0];
	if (optInfo) {
		printf("Sampling_step: %i\n", step);
		return EXIT_SUCCESS;
	}

	total = 0;

	map = bb_xfopen(mapFile, "r");

	while (fgets(mapline,S_LEN,map)) {
		if (sscanf(mapline,"%llx %s %s",&fn_add,mode,fn_name) != 3)
			bb_error_msg_and_die("%s(%i): wrong map line",
					     mapFile, maplineno);

		if (!strcmp(fn_name,"_stext")) /* only elf works like this */ {
			add0 = fn_add;
			break;
		}
		maplineno++;
	}

	if (!add0)
		bb_error_msg_and_die("can't find \"_stext\" in %s", mapFile);

	/*
	 * Main loop.
	 */
	while (fgets(mapline,S_LEN,map)) {
		unsigned int this = 0;

		if (sscanf(mapline,"%llx %s %s",&next_add,mode,next_name) != 3)
			bb_error_msg_and_die("%s(%i): wrong map line",
					     mapFile, maplineno);

		header_printed = 0;

		/* ignore any LEADING (before a '[tT]' symbol is found)
		   Absolute symbols */
		if ((*mode == 'A' || *mode == '?') && total == 0) continue;
		if (*mode != 'T' && *mode != 't' &&
		    *mode != 'W' && *mode != 'w')
			break;	/* only text is profiled */

		if (indx >= len / sizeof(*buf))
			bb_error_msg_and_die("profile address out of range. "
					     "Wrong map file?");

		while (indx < (next_add-add0)/step) {
			if (optBins && (buf[indx] || optAll)) {
				if (!header_printed) {
					printf ("%s:\n", fn_name);
					header_printed = 1;
				}
				printf ("\t%llx\t%u\n", (indx - 1)*step + add0, buf[indx]);
			}
			this += buf[indx++];
		}
		total += this;

		if (optBins) {
			if (optVerbose || this > 0)
				printf ("  total\t\t\t\t%u\n", this);
		} else if ((this || optAll) &&
			   (fn_len = next_add-fn_add) != 0) {
			if (optVerbose)
				printf("%016llx %-40s %6i %8.4f\n", fn_add,
				       fn_name,this,this/(double)fn_len);
			else
				printf("%6i %-40s %8.4f\n",
				       this,fn_name,this/(double)fn_len);
			if (optSub) {
				unsigned long long scan;

				for (scan = (fn_add-add0)/step + 1;
				     scan < (next_add-add0)/step; scan++) {
					unsigned long long addr;

					addr = (scan - 1)*step + add0;
					printf("\t%#llx\t%s+%#llx\t%u\n",
					       addr, fn_name, addr - fn_add,
					       buf[scan]);
				}
			}
		}

		fn_add = next_add;
		strcpy(fn_name,next_name);

		maplineno++;
	}

	/* clock ticks, out of kernel text - probably modules */
	printf("%6i %s\n", buf[len/sizeof(*buf)-1], "*unknown*");

	/* trailer */
	if (optVerbose)
		printf("%016x %-40s %6i %8.4f\n",
		       0,"total",total,total/(double)(fn_add-add0));
	else
		printf("%6i %-40s %8.4f\n",
		       total,"total",total/(double)(fn_add-add0));

	fclose(map);
	free(buf);

	return EXIT_SUCCESS;
}
Beispiel #15
0
/*
 * Execute a particular fsck program, and link it into the list of
 * child processes we are waiting for.
 */
static int execute(const char *type, const char *device, const char *mntpt,
		   int interactive)
{
	char *s, *argv[80];
	char *prog;
	int  argc, i;
	struct fsck_instance *inst, *p;
	pid_t   pid;

	inst = malloc(sizeof(struct fsck_instance));
	if (!inst)
		return ENOMEM;
	memset(inst, 0, sizeof(struct fsck_instance));

	prog = xasprintf("fsck.%s", type);
	argv[0] = prog;
	argc = 1;

	for (i=0; i <num_args; i++)
		argv[argc++] = string_copy(args[i]);

	if (progress && !progress_active()) {
		if ((strcmp(type, "ext2") == 0) ||
		    (strcmp(type, "ext3") == 0)) {
			char tmp[80];
			snprintf(tmp, 80, "-C%d", progress_fd);
			argv[argc++] = string_copy(tmp);
			inst->flags |= FLAG_PROGRESS;
		}
	}

	argv[argc++] = string_copy(device);
	argv[argc] = 0;

	s = find_fsck(prog);
	if (s == NULL) {
		bb_error_msg("%s: not found", prog);
		return ENOENT;
	}

	if (verbose || noexecute) {
		printf("[%s (%d) -- %s] ", s, num_running,
		       mntpt ? mntpt : device);
		for (i=0; i < argc; i++)
			printf("%s ", argv[i]);
		puts("");
	}

	/* Fork and execute the correct program. */
	if (noexecute)
		pid = -1;
	else if ((pid = fork()) < 0) {
		perror("fork");
		return errno;
	} else if (pid == 0) {
		if (!interactive)
			close(0);
		(void) execv(s, argv);
		bb_perror_msg_and_die("%s", argv[0]);
	}

	for (i = 1; i < argc; i++)
		free(argv[i]);

	free(s);
	inst->pid = pid;
	inst->prog = prog;
	inst->type = string_copy(type);
	inst->device = string_copy(device);
	inst->base_device = base_device(device);
	inst->start_time = time(0);
	inst->next = NULL;

	/*
	 * Find the end of the list, so we add the instance on at the end.
	 */
	for (p = instance_list; p && p->next; p = p->next);

	if (p)
		p->next = inst;
	else
		instance_list = inst;

	return 0;
}
Beispiel #16
0
// Die with an error message if we have trouble flushing stdout.
void xfflush_stdout(void)
{
	if (fflush(stdout)) {
		bb_perror_msg_and_die(bb_msg_standard_output);
	}
}
Beispiel #17
0
void bb_xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
{
	if (bind(sockfd, my_addr, addrlen))
		bb_perror_msg_and_die("bind");
}
Beispiel #18
0
// Die with an error message if we can't set gid.  (Because resource limits may
// limit this user to a given number of processes, and if that fills up the
// setgid() will fail and we'll _still_be_root_, which is bad.)
void xsetgid(gid_t gid)
{
	if (setgid(gid)) bb_perror_msg_and_die("setgid");
}
Beispiel #19
0
static void INET6_setroute(int action, char **args)
{
	struct sockaddr_in6 sa6;
	struct in6_rtmsg rt;
	int prefix_len, skfd;
	const char *devname;

	assert((action == RTACTION_ADD) || (action == RTACTION_DEL));

	{
		/* We know args isn't NULL from the check in route_main. */
		const char *target = *args++;

		if (strcmp(target, "default") == 0) {
			prefix_len = 0;
			memset(&sa6, 0, sizeof(sa6));
		} else {
			char *cp;
			if ((cp = strchr(target, '/'))) { /* Yes... const to non is ok. */
				*cp = 0;
				prefix_len = bb_xgetularg10_bnd(cp+1, 0, 128);
			} else {
				prefix_len = 128;
			}
			if (INET6_resolve(target, (struct sockaddr_in6 *) &sa6) < 0) {
				bb_error_msg_and_die("resolving %s", target);
			}
		}
	}

	/* Clean out the RTREQ structure. */
	memset((char *) &rt, 0, sizeof(struct in6_rtmsg));

	memcpy(&rt.rtmsg_dst, sa6.sin6_addr.s6_addr, sizeof(struct in6_addr));

	/* Fill in the other fields. */
	rt.rtmsg_dst_len = prefix_len;
	rt.rtmsg_flags = ((prefix_len == 128) ? (RTF_UP|RTF_HOST) : RTF_UP);
	rt.rtmsg_metric = 1;

	devname = NULL;

	while (*args) {
		int k = kw_lookup(tbl_ipvx, &args);
		const char *args_m1 = args[-1];

		if ((k == KW_IPVx_MOD) || (k == KW_IPVx_DYN)) {
			rt.rtmsg_flags |= flags_ipvx[k & 3];
			continue;
		}

		if (k == KW_IPVx_METRIC) {
			rt.rtmsg_metric = bb_xgetularg10(args_m1);
			continue;
		}

		if (k == KW_IPVx_GATEWAY) {
			if (rt.rtmsg_flags & RTF_GATEWAY) {
				bb_show_usage();
			}

			if (INET6_resolve(args_m1, (struct sockaddr_in6 *) &sa6) < 0) {
				bb_error_msg_and_die("resolving %s", args_m1);
			}
			memcpy(&rt.rtmsg_gateway, sa6.sin6_addr.s6_addr,
				   sizeof(struct in6_addr));
			rt.rtmsg_flags |= RTF_GATEWAY;
			continue;
		}

		/* Device is special in that it can be the last arg specified
		 * and doesn't requre the dev/device keyword in that case. */
		if (!devname && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) {
			/* Don't use args_m1 here since args may have changed! */
			devname = args[-1];
			continue;
		}

		/* Nothing matched. */
		bb_show_usage();
	}

	/* Create a socket to the INET6 kernel. */
	if ((skfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
		bb_perror_msg_and_die("socket");
	}

	rt.rtmsg_ifindex = 0;

	if (devname) {
		struct ifreq ifr;
		memset(&ifr, 0, sizeof(ifr));
		strcpy(ifr.ifr_name, devname);

		if (ioctl(skfd, SIOGIFINDEX, &ifr) < 0) {
			bb_perror_msg_and_die("SIOGIFINDEX");
		}
		rt.rtmsg_ifindex = ifr.ifr_ifindex;
	}

	/* Tell the kernel to accept this route. */
	if (ioctl(skfd, ((action==RTACTION_ADD) ? SIOCADDRT : SIOCDELRT), &rt)<0) {
		bb_perror_msg_and_die("SIOC[ADD|DEL]RT");
	}

	/* Don't bother closing, as we're exiting after we return anyway. */
	/* close(skfd); */
}
Beispiel #20
0
// Die with an error message if we can't set uid.  (See xsetgid() for why.)
void xsetuid(uid_t uid)
{
	if (setuid(uid)) bb_perror_msg_and_die("setuid");
}
Beispiel #21
0
extern int unzip_main(int argc, char **argv)
{
	union {
		unsigned char raw[26];
		struct {
			unsigned short version;	/* 0-1 */
			unsigned short flags;	/* 2-3 */
			unsigned short method;	/* 4-5 */
			unsigned short modtime;	/* 6-7 */
			unsigned short moddate;	/* 8-9 */
			unsigned int crc32 __attribute__ ((packed));		/* 10-13 */
			unsigned int cmpsize __attribute__ ((packed));;	/* 14-17 */
			unsigned int ucmpsize __attribute__ ((packed));;	/* 18-21 */
			unsigned short filename_len;		/* 22-23 */
			unsigned short extra_len;		/* 24-25 */
		} formated __attribute__ ((packed));
	} zip_header;

	archive_handle_t *archive_handle;
	unsigned int total_size = 0;
	unsigned int total_entries = 0;
	char *base_dir = NULL;
	int opt = 0;

	/* Initialise */
	archive_handle = init_handle();
	archive_handle->action_data = NULL;
	archive_handle->action_header = header_list_unzip;

	while ((opt = getopt(argc, argv, "lnopqd:")) != -1) {
		switch (opt) {
			case 'l':	/* list */
				archive_handle->action_header = header_verbose_list_unzip;
				archive_handle->action_data = data_skip;
				break;
			case 'n':	/* never overwright existing files */
				break;
			case 'o':
				archive_handle->flags = ARCHIVE_EXTRACT_UNCONDITIONAL;
				break;
			case 'p':	/* extract files to stdout */
				archive_handle->action_data = data_extract_to_stdout;
				break;
			case 'q':	/* Extract files quietly */
				archive_handle->action_header = header_skip;
				break;
			case 'd':	/* Extract files to specified base directory*/
				base_dir = optarg;
				break;
#if 0
			case 'x':	/* Exclude the specified files */
				archive_handle->filter = filter_accept_reject_list;
				break;
#endif
			default:
				bb_show_usage();
		}
	}

	if (argc == optind) {
		bb_show_usage();
	}

	printf("Archive:  %s\n", argv[optind]);
	if (archive_handle->action_header == header_verbose_list_unzip) {
		printf("  Length     Date   Time    Name\n");
		printf(" --------    ----   ----    ----\n");
	}

	if (*argv[optind] == '-') {
		archive_handle->src_fd = fileno(stdin);
		archive_handle->seek = seek_by_char;
	} else {
		archive_handle->src_fd = bb_xopen(argv[optind++], O_RDONLY);
	}

	if ((base_dir) && (chdir(base_dir))) {
		bb_perror_msg_and_die("Couldnt chdir");
	}

	while (optind < argc) {
		archive_handle->filter = filter_accept_list;
		archive_handle->accept = llist_add_to(archive_handle->accept, argv[optind]);
		optind++;
	}

	while (1) {
		unsigned int magic;
		int dst_fd;

		/* TODO Endian issues */
		archive_xread_all(archive_handle, &magic, 4);
		archive_handle->offset += 4;

		if (magic == ZIP_CDS_MAGIC) {
			break;
		}
		else if (magic != ZIP_FILEHEADER_MAGIC) {
			bb_error_msg_and_die("Invlaide zip magic");
		}

		/* Read the file header */
		archive_xread_all(archive_handle, zip_header.raw, 26);
		archive_handle->offset += 26;
		archive_handle->file_header->mode = S_IFREG | 0777;

		if (zip_header.formated.method != 8) {
			bb_error_msg_and_die("Unsupported compression method %d\n", zip_header.formated.method);
		}

		/* Read filename */
		archive_handle->file_header->name = xmalloc(zip_header.formated.filename_len + 1);
		archive_xread_all(archive_handle, archive_handle->file_header->name, zip_header.formated.filename_len);
		archive_handle->offset += zip_header.formated.filename_len;
		archive_handle->file_header->name[zip_header.formated.filename_len] = '\0';

		/* Skip extra header bits */
		archive_handle->file_header->size = zip_header.formated.extra_len;
		data_skip(archive_handle);
		archive_handle->offset += zip_header.formated.extra_len;

		/* Handle directories */
		archive_handle->file_header->mode = S_IFREG | 0777;
		if (last_char_is(archive_handle->file_header->name, '/')) {
			archive_handle->file_header->mode ^= S_IFREG;
			archive_handle->file_header->mode |= S_IFDIR;
		}

		/* Data section */
		archive_handle->file_header->size = zip_header.formated.cmpsize;
		if (archive_handle->action_data) {
			archive_handle->action_data(archive_handle);
		} else {
			dst_fd = bb_xopen(archive_handle->file_header->name, O_WRONLY | O_CREAT);
			inflate(archive_handle->src_fd, dst_fd);
			close(dst_fd);
			chmod(archive_handle->file_header->name, archive_handle->file_header->mode);

			/* Validate decompression - crc */
			if (zip_header.formated.crc32 != (gunzip_crc ^ 0xffffffffL)) {
				bb_error_msg("Invalid compressed data--crc error");
			}

			/* Validate decompression - size */
			if (gunzip_bytes_out != zip_header.formated.ucmpsize) {
				bb_error_msg("Invalid compressed data--length error");
			}
		}

		/* local file descriptor section */
		archive_handle->offset += zip_header.formated.cmpsize;
		/* This ISNT unix time */
		archive_handle->file_header->mtime = zip_header.formated.modtime | (zip_header.formated.moddate << 16);
		archive_handle->file_header->size = zip_header.formated.ucmpsize;
		total_size += archive_handle->file_header->size;
		total_entries++;

		archive_handle->action_header(archive_handle->file_header);

		/* Data descriptor section */
		if (zip_header.formated.flags & 4) {
			/* skip over duplicate crc, compressed size and uncompressed size */
			unsigned short i;
			for (i = 0; i != 12; i++) {
				archive_xread_char(archive_handle);
			}
			archive_handle->offset += 12;
		}
	}
	/* Central directory section */

	if (archive_handle->action_header == header_verbose_list_unzip) {
		printf(" --------                   -------\n");
		printf("%9d                   %d files\n", total_size, total_entries);
	}

	return(EXIT_SUCCESS);
}
Beispiel #22
0
// Die if we can't chdir to a new path.
void xchdir(const char *path)
{
	if (chdir(path))
		bb_perror_msg_and_die("chdir(%s)", path);
}
Beispiel #23
0
int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
{
	unsigned opt;
	char *signame;
	char *startas;
	char *chuid;
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
//	char *retry_arg = NULL;
//	int retries = -1;
	char *opt_N;
#endif

	INIT_G();

	opt = GETOPT32(argv, "^"
		"KSbqtma:n:s:u:c:x:p:"
		IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:")
			/* -K or -S is required; they are mutually exclusive */
			/* -p is required if -m is given */
			/* -xpun (at least one) is required if -K is given */
			/* -xa (at least one) is required if -S is given */
			/* -q turns off -v */
			"\0"
			"K:S:K--S:S--K:m?p:K?xpun:S?xa"
			IF_FEATURE_START_STOP_DAEMON_FANCY("q-v"),
		LONGOPTS
		&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile
		IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N)
		/* We accept and ignore -R <param> / --retry <param> */
		IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL)
	);

	if (opt & OPT_s) {
		signal_nr = get_signum(signame);
		if (signal_nr < 0) bb_show_usage();
	}

	if (!(opt & OPT_a))
		startas = execname;
	if (!execname) /* in case -a is given and -x is not */
		execname = startas;
	if (execname) {
		G.execname_sizeof = strlen(execname) + 1;
		G.execname_cmpbuf = xmalloc(G.execname_sizeof + 1);
	}

//	IF_FEATURE_START_STOP_DAEMON_FANCY(
//		if (retry_arg)
//			retries = xatoi_positive(retry_arg);
//	)
	//argc -= optind;
	argv += optind;

	if (userspec) {
		user_id = bb_strtou(userspec, NULL, 10);
		if (errno)
			user_id = xuname2uid(userspec);
	}
	/* Both start and stop need to know current processes */
	do_procinit();

	if (opt & CTX_STOP) {
		int i = do_stop();
		return (opt & OPT_OKNODO) ? 0 : (i <= 0);
	}

	if (G.found_procs) {
		if (!QUIET)
			printf("%s is already running\n%u\n", execname, (unsigned)G.found_procs->pid);
		return !(opt & OPT_OKNODO);
	}

#ifdef OLDER_VERSION_OF_X
	if (execname)
		xstat(execname, &G.execstat);
#endif

	*--argv = startas;
	if (opt & OPT_BACKGROUND) {
#if BB_MMU
		bb_daemonize(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS + DAEMON_DOUBLE_FORK);
		/* DAEMON_DEVNULL_STDIO is superfluous -
		 * it's always done by bb_daemonize() */
#else
		/* Daemons usually call bb_daemonize_or_rexec(), but SSD can do
		 * without: SSD is not itself a daemon, it _execs_ a daemon.
		 * The usual NOMMU problem of "child can't run indefinitely,
		 * it must exec" does not bite us: we exec anyway.
		 */
		pid_t pid = xvfork();
		if (pid != 0) {
			/* parent */
			/* why _exit? the child may have changed the stack,
			 * so "return 0" may do bad things */
			_exit(EXIT_SUCCESS);
		}
		/* Child */
		setsid(); /* detach from controlling tty */
		/* Redirect stdio to /dev/null, close extra FDs */
		bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS);
#endif
	}
	if (opt & OPT_MAKEPID) {
		/* User wants _us_ to make the pidfile */
		write_pidfile(pidfile);
	}
	if (opt & OPT_c) {
		struct bb_uidgid_t ugid;
		parse_chown_usergroup_or_die(&ugid, chuid);
		if (ugid.uid != (uid_t) -1L) {
			struct passwd *pw = xgetpwuid(ugid.uid);
			if (ugid.gid != (gid_t) -1L)
				pw->pw_gid = ugid.gid;
			/* initgroups, setgid, setuid: */
			change_identity(pw);
		} else if (ugid.gid != (gid_t) -1L) {
			xsetgid(ugid.gid);
			setgroups(1, &ugid.gid);
		}
	}
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
	if (opt & OPT_NICELEVEL) {
		/* Set process priority */
		int prio = getpriority(PRIO_PROCESS, 0) + xatoi_range(opt_N, INT_MIN/2, INT_MAX/2);
		if (setpriority(PRIO_PROCESS, 0, prio) < 0) {
			bb_perror_msg_and_die("setpriority(%d)", prio);
		}
	}
#endif
	execvp(startas, argv);
	bb_perror_msg_and_die("can't execute '%s'", startas);
}
Beispiel #24
0
int fuser_main(int argc UNUSED_PARAM, char **argv)
{
	pid_list *plist;
	inode_list *ilist;
	char **pp;
	dev_t dev;
	ino_t inode;
	unsigned port;
	int opt;
	int success;
	int killsig;
/*
fuser [options] FILEs or PORT/PROTOs
Find processes which use FILEs or PORTs
        -m      Find processes which use same fs as FILEs
        -4      Search only IPv4 space
        -6      Search only IPv6 space
        -s      Silent: just exit with 0 if any processes are found
        -k      Kill found processes (otherwise display PIDs)
        -SIGNAL Signal to send (default: TERM)
*/
	/* Handle -SIGNAL. Oh my... */
	killsig = SIGTERM;
	pp = argv;
	while (*++pp) {
		char *arg = *pp;
		if (arg[0] != '-')
			continue;
		if (arg[1] == '-' && arg[2] == '\0') /* "--" */
			break;
		if ((arg[1] == '4' || arg[1] == '6') && arg[2] == '\0')
			continue; /* it's "-4" or "-6" */
		opt = get_signum(&arg[1]);
		if (opt < 0)
			continue;
		/* "-SIGNAL" option found. Remove it and bail out */
		killsig = opt;
		do {
			pp[0] = arg = pp[1];
			pp++;
		} while (arg);
		break;
	}

	opt = getopt32(argv, OPTION_STRING);
	argv += optind;

	ilist = NULL;
	pp = argv;
	while (*pp) {
		char *proto = parse_net_arg(*pp, &port);
		if (proto) { /* PORT/PROTO */
			ilist = scan_proc_net(proto, port, ilist);
			free(proto);
		} else { /* FILE */
			if (!file_to_dev_inode(*pp, &dev, &inode))
				bb_perror_msg_and_die("can't open %s", *pp);
			ilist = add_inode(ilist, dev, inode);
		}
		pp++;
	}

	plist = scan_proc_pids(ilist); /* changes dir to "/proc" */

	if (!plist)
		return EXIT_FAILURE;
	success = 1;
	if (opt & OPT_KILL) {
		success = kill_pid_list(plist, killsig);
	} else if (!(opt & OPT_SILENT)) {
		success = print_pid_list(plist);
	}
	return (success != 1); /* 0 == success */
}
Beispiel #25
0
int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
{
	FILE *orig_fp;
	char *orig_fn;
	char *new_fn;
	struct stat sb;

	sb.st_mode = 0666;

	argv++;

	orig_fn = xmalloc_follow_symlinks(SHELLS_FILE);
	if (!orig_fn)
		return EXIT_FAILURE;
	orig_fp = fopen_for_read(orig_fn);
	if (orig_fp)
		xfstat(fileno(orig_fp), &sb, orig_fn);

	new_fn = xasprintf("%s.tmp", orig_fn);
	/*
	 * O_TRUNC or O_EXCL? At the first glance, O_EXCL looks better,
	 * since it prevents races. But: (1) it requires a retry loop,
	 * (2) if /etc/shells.tmp is *stale*, then retry loop
	 * with O_EXCL will never succeed - it should have a timeout,
	 * after which it should revert to O_TRUNC.
	 * For now, I settle for O_TRUNC instead.
	 */
	xmove_fd(xopen3(new_fn, O_WRONLY | O_CREAT | O_TRUNC, sb.st_mode), STDOUT_FILENO);
	/* TODO?
	xfchown(STDOUT_FILENO, sb.st_uid, sb.st_gid);
	*/

	if (orig_fp) {
		/* Copy old file, possibly skipping removed shell names */
		char *line;
		while ((line = xmalloc_fgetline(orig_fp)) != NULL) {
			char **cpp = argv;
			while (*cpp) {
				if (*cpp != dont_add && strcmp(*cpp, line) == 0) {
					/* Old file has this shell name */
					if (REMOVE_SHELL) {
						/* we are remove-shell */
						/* delete this name by not copying it */
						goto next_line;
					}
					/* we are add-shell */
					/* mark this name as "do not add" */
					*cpp = dont_add;
				}
				cpp++;
			}
			/* copy shell name from old to new file */
			puts(line);
 next_line:
			free(line);
		}
		if (ENABLE_FEATURE_CLEAN_UP)
			fclose(orig_fp);
	}

	if (ADD_SHELL) {
		char **cpp = argv;
		while (*cpp) {
			if (*cpp != dont_add)
				puts(*cpp);
			cpp++;
		}
	}

	/* Ensure we wrote out everything */
	if (fclose(stdout) != 0) {
		xunlink(new_fn);
		bb_perror_msg_and_die("%s: write error", new_fn);
	}

	/* Small hole: if rename fails, /etc/shells.tmp is not removed */
	xrename(new_fn, orig_fn);

	if (ENABLE_FEATURE_CLEAN_UP) {
		free(orig_fn);
		free(new_fn);
	}

	return EXIT_SUCCESS;
}
Beispiel #26
0
static void fatal2_cannot(const char *m1, const char *m2)
{
	bb_perror_msg_and_die("%s: fatal: cannot %s%s", svdir, m1, m2);
	/* was exiting 100 */
}
Beispiel #27
0
int chrt_main(int argc, char **argv)
{
	pid_t pid = 0;
	unsigned opt;
	struct sched_param sp;
	char *p_opt = NULL, *priority = NULL;
	const char *state = "current\0new";
	int prio = 0, policy = SCHED_RR;

	opt_complementary = "r--fo:f--ro:r--fo"; /* only one policy accepted */
	opt = getopt32(argv, "+mp:rfo", &p_opt);
	if (opt & OPT_r)
		policy = SCHED_RR;
	if (opt & OPT_f)
		policy = SCHED_FIFO;
	if (opt & OPT_o)
		policy = SCHED_OTHER;

	if (opt & OPT_m) { /* print min/max */
		show_min_max(SCHED_FIFO);
		show_min_max(SCHED_RR);
		show_min_max(SCHED_OTHER);
		fflush_stdout_and_exit(EXIT_SUCCESS);
	}
	if (opt & OPT_p) {
		if (argc == optind+1) { /* -p <priority> <pid> */
			priority = p_opt;
			p_opt = argv[optind];
		}
		argv += optind; /* me -p <arg> */
		pid = xatoul_range(p_opt, 1, ULONG_MAX); /* -p <pid> */
	} else {
		argv += optind; /* me -p <arg> */
		priority = *argv;
	}
	if (priority) {
		/* from the manpage of sched_getscheduler:
		   [...] sched_priority can have a value
		   in the range 0 to 99.
		   [...] SCHED_OTHER or SCHED_BATCH  must  be  assigned
		   the  static  priority  0. [...] SCHED_FIFO  or
		   SCHED_RR can have a static priority in the range 1 to 99.
		 */
		prio = xstrtol_range(priority, 0, policy == SCHED_OTHER
													 ? 0 : 1, 99);
	}

	if (opt & OPT_p) {
		int pol = 0;
print_rt_info:
		pol = sched_getscheduler(pid);
		if (pol < 0)
			bb_perror_msg_and_die("failed to %cet pid %d's policy", 'g', pid);
		printf("pid %d's %s scheduling policy: %s\n",
				pid, state, policies[pol].name);
		if (sched_getparam(pid, &sp))
			bb_perror_msg_and_die("failed to get pid %d's attributes", pid);
		printf("pid %d's %s scheduling priority: %d\n",
				pid, state, sp.sched_priority);
		if (!*argv) /* no new prio given or we did print already, done. */
			return EXIT_SUCCESS;
	}

	sp.sched_priority = prio;
	if (sched_setscheduler(pid, policy, &sp) < 0)
		bb_perror_msg_and_die("failed to %cet pid %d's policy", 's', pid);
	if (opt & OPT_p) {
		state += 8;
		++argv;
		goto print_rt_info;
	}
	++argv;
	BB_EXECVP(*argv, argv);
	bb_simple_perror_msg_and_die(*argv);
}
Beispiel #28
0
static void PRS(int argc, char *argv[])
{
	int     i, j;
	char    *arg, *dev, *tmp = 0;
	char    options[128];
	int     opt = 0;
	int     opts_for_fsck = 0;
	struct sigaction        sa;

	/*
	 * Set up signal action
	 */
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_handler = signal_cancel;
	sigaction(SIGINT, &sa, 0);
	sigaction(SIGTERM, &sa, 0);

	num_devices = 0;
	num_args = 0;
	instance_list = 0;

	for (i=1; i < argc; i++) {
		arg = argv[i];
		if (!arg)
			continue;
		if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
			if (num_devices >= MAX_DEVICES) {
				bb_error_msg_and_die("too many devices");
			}
			dev = blkid_get_devname(cache, arg, NULL);
			if (!dev && strchr(arg, '=')) {
				/*
				 * Check to see if we failed because
				 * /proc/partitions isn't found.
				 */
				if (access("/proc/partitions", R_OK) < 0) {
					bb_perror_msg_and_die("cannot open /proc/partitions "
							"(is /proc mounted?)");
				}
				/*
				 * Check to see if this is because
				 * we're not running as root
				 */
				if (geteuid())
					bb_error_msg_and_die(
		"must be root to scan for matching filesystems: %s\n", arg);
				else
					bb_error_msg_and_die(
		"cannot find matching filesystem: %s", arg);
			}
			devices[num_devices++] = dev ? dev : string_copy(arg);
			continue;
		}
		if (arg[0] != '-' || opts_for_fsck) {
			if (num_args >= MAX_ARGS) {
				bb_error_msg_and_die("too many arguments");
			}
			args[num_args++] = string_copy(arg);
			continue;
		}
		for (j=1; arg[j]; j++) {
			if (opts_for_fsck) {
				options[++opt] = arg[j];
				continue;
			}
			switch (arg[j]) {
			case 'A':
				doall++;
				break;
			case 'C':
				progress++;
				if (arg[j+1]) {
					progress_fd = string_to_int(arg+j+1);
					if (progress_fd < 0)
						progress_fd = 0;
					else
						goto next_arg;
				} else if ((i+1) < argc
				 && argv[i+1][0] != '-') {
					progress_fd = string_to_int(argv[i]);
					if (progress_fd < 0)
						progress_fd = 0;
					else {
						goto next_arg;
						i++;
					}
				}
				break;
			case 'V':
				verbose++;
				break;
			case 'N':
				noexecute++;
				break;
			case 'R':
				skip_root++;
				break;
			case 'T':
				notitle++;
				break;
			case 'M':
				like_mount++;
				break;
			case 'P':
				parallel_root++;
				break;
			case 's':
				serialize++;
				break;
			case 't':
				tmp = 0;
				if (fstype)
					bb_show_usage();
				if (arg[j+1])
					tmp = arg+j+1;
				else if ((i+1) < argc)
					tmp = argv[++i];
				else
					bb_show_usage();
				fstype = string_copy(tmp);
				compile_fs_type(fstype, &fs_type_compiled);
				goto next_arg;
			case '-':
				opts_for_fsck++;
				break;
			case '?':
				bb_show_usage();
				break;
			default:
				options[++opt] = arg[j];
				break;
			}
		}
	next_arg:
		if (opt) {
			options[0] = '-';
			options[++opt] = '\0';
			if (num_args >= MAX_ARGS) {
				bb_error_msg("too many arguments");
			}
			args[num_args++] = string_copy(options);
			opt = 0;
		}
	}
	if (getenv("FSCK_FORCE_ALL_PARALLEL"))
		force_all_parallel++;
	if ((tmp = getenv("FSCK_MAX_INST")))
	    max_running = atoi(tmp);
}
Beispiel #29
0
/* Called only from main, once */
static int arp_del(char **args)
{
	char *host;
	struct arpreq req;
	struct sockaddr sa;
	int flags = 0;
	int err;

	memset(&req, 0, sizeof(req));

	/* Resolve the host name. */
	host = *args;
	if (ap->input(host, &sa) < 0) {
		bb_herror_msg_and_die("%s", host);
	}

	/* If a host has more than one address, use the correct one! */
	memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr));

	if (hw_set)
		req.arp_ha.sa_family = hw->type;

	req.arp_flags = ATF_PERM;
	args++;
	while (*args != NULL) {
		switch (index_in_strings(options, *args)) {
		case 0: /* "pub" */
			flags |= 1;
			args++;
			break;
		case 1: /* "priv" */
			flags |= 2;
			args++;
			break;
		case 2: /* "temp" */
			req.arp_flags &= ~ATF_PERM;
			args++;
			break;
		case 3: /* "trail" */
			req.arp_flags |= ATF_USETRAILERS;
			args++;
			break;
		case 4: /* "dontpub" */
#ifdef HAVE_ATF_DONTPUB
			req.arp_flags |= ATF_DONTPUB;
#else
			bb_error_msg("feature ATF_DONTPUB is not supported");
#endif
			args++;
			break;
		case 5: /* "auto" */
#ifdef HAVE_ATF_MAGIC
			req.arp_flags |= ATF_MAGIC;
#else
			bb_error_msg("feature ATF_MAGIC is not supported");
#endif
			args++;
			break;
		case 6: /* "dev" */
			if (*++args == NULL)
				bb_show_usage();
			device = *args;
			args++;
			break;
		case 7: /* "netmask" */
			if (*++args == NULL)
				bb_show_usage();
			if (strcmp(*args, "255.255.255.255") != 0) {
				host = *args;
				if (ap->input(host, &sa) < 0) {
					bb_herror_msg_and_die("%s", host);
				}
				memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr));
				req.arp_flags |= ATF_NETMASK;
			}
			args++;
			break;
		default:
			bb_show_usage();
			break;
		}
	}
	if (flags == 0)
		flags = 3;

	strncpy(req.arp_dev, device, sizeof(req.arp_dev));

	err = -1;

	/* Call the kernel. */
	if (flags & 2) {
		if (option_mask32 & ARP_OPT_v)
			bb_error_msg("SIOCDARP(nopub)");
		err = ioctl(sockfd, SIOCDARP, &req);
		if (err < 0) {
			if (errno == ENXIO) {
				if (flags & 1)
					goto nopub;
				printf("No ARP entry for %s\n", host);
				return -1;
			}
			bb_perror_msg_and_die("SIOCDARP(priv)");
		}
	}
	if ((flags & 1) && err) {
 nopub:
		req.arp_flags |= ATF_PUBL;
		if (option_mask32 & ARP_OPT_v)
			bb_error_msg("SIOCDARP(pub)");
		if (ioctl(sockfd, SIOCDARP, &req) < 0) {
			if (errno == ENXIO) {
				printf("No ARP entry for %s\n", host);
				return -1;
			}
			bb_perror_msg_and_die("SIOCDARP(pub)");
		}
	}
	return 0;
}
Beispiel #30
0
static void NOINLINE retrieve_file_data(FILE *dfp)
{
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
# if ENABLE_FEATURE_WGET_TIMEOUT
	unsigned second_cnt;
# endif
	struct pollfd polldata;

	polldata.fd = fileno(dfp);
	polldata.events = POLLIN | POLLPRI;
#endif
	progress_meter(PROGRESS_START);

	if (G.chunked)
		goto get_clen;

	/* Loops only if chunked */
	while (1) {

#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
		/* Must use nonblocking I/O, otherwise fread will loop
		 * and *block* until it reads full buffer,
		 * which messes up progress bar and/or timeout logic.
		 * Because of nonblocking I/O, we need to dance
		 * very carefully around EAGAIN. See explanation at
		 * clearerr() call.
		 */
		ndelay_on(polldata.fd);
#endif
		while (1) {
			int n;
			unsigned rdsz;

			rdsz = sizeof(G.wget_buf);
			if (G.got_clen) {
				if (G.content_len < (off_t)sizeof(G.wget_buf)) {
					if ((int)G.content_len <= 0)
						break;
					rdsz = (unsigned)G.content_len;
				}
			}

#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
# if ENABLE_FEATURE_WGET_TIMEOUT
			second_cnt = G.timeout_seconds;
# endif
			while (1) {
				if (safe_poll(&polldata, 1, 1000) != 0)
					break; /* error, EOF, or data is available */
# if ENABLE_FEATURE_WGET_TIMEOUT
				if (second_cnt != 0 && --second_cnt == 0) {
					progress_meter(PROGRESS_END);
					bb_error_msg_and_die("download timed out");
				}
# endif
				/* Needed for "stalled" indicator */
				progress_meter(PROGRESS_BUMP);
			}

			/* fread internally uses read loop, which in our case
			 * is usually exited when we get EAGAIN.
			 * In this case, libc sets error marker on the stream.
			 * Need to clear it before next fread to avoid possible
			 * rare false positive ferror below. Rare because usually
			 * fread gets more than zero bytes, and we don't fall
			 * into if (n <= 0) ...
			 */
			clearerr(dfp);
			errno = 0;
#endif
			n = fread(G.wget_buf, 1, rdsz, dfp);
			/* man fread:
			 * If error occurs, or EOF is reached, the return value
			 * is a short item count (or zero).
			 * fread does not distinguish between EOF and error.
			 */
			if (n <= 0) {
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
				if (errno == EAGAIN) /* poll lied, there is no data? */
					continue; /* yes */
#endif
				if (ferror(dfp))
					bb_perror_msg_and_die(bb_msg_read_error);
				break; /* EOF, not error */
			}

			xwrite(G.output_fd, G.wget_buf, n);

#if ENABLE_FEATURE_WGET_STATUSBAR
			G.transferred += n;
			progress_meter(PROGRESS_BUMP);
#endif
			if (G.got_clen) {
				G.content_len -= n;
				if (G.content_len == 0)
					break;
			}
		}
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
		clearerr(dfp);
		ndelay_off(polldata.fd); /* else fgets can get very unhappy */
#endif
		if (!G.chunked)
			break;

		fgets_and_trim(dfp); /* Eat empty line */
 get_clen:
		fgets_and_trim(dfp);
		G.content_len = STRTOOFF(G.wget_buf, NULL, 16);
		/* FIXME: error check? */
		if (G.content_len == 0)
			break; /* all done! */
		G.got_clen = 1;
	}

	/* If -c failed, we restart from the beginning,
	 * but we do not truncate file then, we do it only now, at the end.
	 * This lets user to ^C if his 99% complete 10 GB file download
	 * failed to restart *without* losing the almost complete file.
	 */
	{
		off_t pos = lseek(G.output_fd, 0, SEEK_CUR);
		if (pos != (off_t)-1)
			ftruncate(G.output_fd, pos);
	}

	/* Draw full bar and free its resources */
	G.chunked = 0;  /* makes it show 100% even for chunked download */
	G.got_clen = 1; /* makes it show 100% even for download of (formerly) unknown size */
	progress_meter(PROGRESS_END);
}