static NORETURN void perror_on_device_and_die(const char *fmt) { bb_perror_msg_and_die(fmt, G.device_name); }
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); }
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); } }
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; }
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; }
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); */ }
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 */ }
void xpipe(int filedes[2]) { if (pipe(filedes)) bb_perror_msg_and_die("can't create pipe"); }
void xdup2(int from, int to) { if (dup2(from, to) != to) bb_perror_msg_and_die("can't duplicate file descriptor"); }
void xunlink(const char *pathname) { if (unlink(pathname)) bb_perror_msg_and_die("can't remove file '%s'", pathname); }
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); }
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; }
/* * 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; }
// 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); } }
void bb_xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) { if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind"); }
// 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"); }
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); */ }
// 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"); }
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); }
// 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); }
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); }
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 */ }
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; }
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 */ }
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); }
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); }
/* 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; }
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); }