int makedevs_main(int argc, char **argv) { mode_t mode; char *basedev, *type, *nodname, *buf; int Smajor, Sminor, S, E; if (argc < 7 || argv[1][0] == '-') bb_show_usage(); basedev = argv[1]; buf = xasprintf("%s%u", argv[1], (unsigned)-1); type = argv[2]; Smajor = xatoi_u(argv[3]); Sminor = xatoi_u(argv[4]); S = xatoi_u(argv[5]); E = xatoi_u(argv[6]); nodname = argv[7] ? basedev : buf; mode = 0660; switch (type[0]) { case 'c': mode |= S_IFCHR; break; case 'b': mode |= S_IFBLK; break; case 'f': mode |= S_IFIFO; break; default: bb_show_usage(); } while (S <= E) { sprintf(buf, "%s%u", basedev, S); /* if mode != S_IFCHR and != S_IFBLK, * third param in mknod() ignored */ if (mknod(nodname, mode, makedev(Smajor, Sminor))) bb_perror_msg("can't create '%s'", nodname); /*if (nodname == basedev)*/ /* ex. /dev/hda - to /dev/hda1 ... */ nodname = buf; S++; Sminor++; } return 0; }
static int ftpcmd(const char *s1, const char *s2, FILE *fp, char *buf) { int result; if (s1) { if (!s2) s2 = ""; fprintf(fp, "%s%s\r\n", s1, s2); fflush(fp); } do { char *buf_ptr; if (fgets(buf, 510, fp) == NULL) { bb_perror_msg_and_die("error getting response"); } buf_ptr = strstr(buf, "\r\n"); if (buf_ptr) { *buf_ptr = '\0'; } } while (!isdigit(buf[0]) || buf[3] != ' '); buf[3] = '\0'; result = xatoi_u(buf); buf[3] = ' '; return result; }
int mt_main(int argc, char **argv) { const char *file = "/dev/tape"; struct mtop op; struct mtpos position; int fd, mode, idx; if (argc < 2) { bb_show_usage(); } if (strcmp(argv[1], "-f") == 0) { if (argc < 4) { bb_show_usage(); } file = argv[2]; argv += 2; argc -= 2; } idx = index_in_strings(opcode_name, argv[1]); if (idx < 0) bb_error_msg_and_die("unrecognized opcode %s", argv[1]); op.mt_op = opcode_value[idx]; if (argc >= 3) op.mt_count = xatoi_u(argv[2]); else op.mt_count = 1; /* One, not zero, right? */ switch (opcode_value[idx]) { case MTWEOF: case MTERASE: case MTWSM: case MTSETDRVBUFFER: mode = O_WRONLY; break; default: mode = O_RDONLY; break; } fd = xopen(file, mode); switch (opcode_value[idx]) { case MTTELL: ioctl_or_perror_and_die(fd, MTIOCPOS, &position, "%s", file); printf("At block %d\n", (int) position.mt_blkno); break; default: ioctl_or_perror_and_die(fd, MTIOCTOP, &op, "%s", file); break; } return EXIT_SUCCESS; }
int hexdump_main(int argc, char **argv) { const char *p; int ch; bb_dump_vflag = FIRST; bb_dump_length = -1; while ((ch = getopt(argc, argv, hexdump_opts)) > 0) { p = strchr(hexdump_opts, ch); if (!p) bb_show_usage(); if ((p - hexdump_opts) < 5) { bb_dump_add(add_first); bb_dump_add(add_strings[(int)(p - hexdump_opts)]); } else if (ch == 'C') { bb_dump_add("\"%08.8_Ax\n\""); bb_dump_add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" "); bb_dump_add("\" |\" 16/1 \"%_p\" \"|\\n\""); } else { /* Save a little bit of space below by omitting the 'else's. */ if (ch == 'e') { bb_dump_add(optarg); } /* else */ if (ch == 'f') { bb_dump_addfile(optarg); } /* else */ if (ch == 'n') { bb_dump_length = xatoi_u(optarg); } /* else */ if (ch == 's') { bb_dump_skip = xatoul_range_sfx(optarg, 0, LONG_MAX, suffixes); } /* else */ if (ch == 'v') { bb_dump_vflag = ALL; } } } if (!bb_dump_fshead) { bb_dump_add(add_first); bb_dump_add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\""); } argv += optind; return bb_dump_dump(argv); }
int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv) { static const char keywords[] ALIGN1 = "addbr\0" "delbr\0" "addif\0" "delif\0" USE_FEATURE_BRCTL_FANCY( "stp\0" "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" "setpathcost\0" "setportprio\0" "setbridgeprio\0" ) USE_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif USE_FEATURE_BRCTL_FANCY(, ARG_stp, ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio ) USE_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) }; int fd; smallint key; struct ifreq ifr; char *br, *brif; argv++; while (*argv) { #if ENABLE_FEATURE_BRCTL_FANCY int ifidx[MAX_PORTS]; unsigned long args[4]; ifr.ifr_data = (char *) &args; #endif key = index_in_strings(keywords, *argv); if (key == -1) /* no match found in keywords array, bail out. */ bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); argv++; fd = xsocket(AF_INET, SOCK_STREAM, 0); #if ENABLE_FEATURE_BRCTL_SHOW if (key == ARG_show) { /* show */ char brname[IFNAMSIZ]; int bridx[MAX_PORTS]; int i, num; arm_ioctl(args, BRCTL_GET_BRIDGES, (unsigned long) bridx, MAX_PORTS); num = xioctl(fd, SIOCGIFBR, args); printf("bridge name\tbridge id\t\tSTP enabled\tinterfaces\n"); for (i = 0; i < num; i++) { char ifname[IFNAMSIZ]; int j, tabs; struct __bridge_info bi; unsigned char *x; if (!if_indextoname(bridx[i], brname)) bb_perror_msg_and_die("can't get bridge name for index %d", i); strncpy(ifr.ifr_name, brname, IFNAMSIZ); arm_ioctl(args, BRCTL_GET_BRIDGE_INFO, (unsigned long) &bi, 0); xioctl(fd, SIOCDEVPRIVATE, &ifr); printf("%s\t\t", brname); /* print bridge id */ x = (unsigned char *) &bi.bridge_id; for (j = 0; j < 8; j++) { printf("%.2x", x[j]); if (j == 1) bb_putchar('.'); } printf(bi.stp_enabled ? "\tyes" : "\tno"); /* print interface list */ arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long) ifidx, MAX_PORTS); xioctl(fd, SIOCDEVPRIVATE, &ifr); tabs = 0; for (j = 0; j < MAX_PORTS; j++) { if (!ifidx[j]) continue; if (!if_indextoname(ifidx[j], ifname)) bb_perror_msg_and_die("can't get interface name for index %d", j); if (tabs) printf("\t\t\t\t\t"); else tabs = 1; printf("\t\t%s\n", ifname); } if (!tabs) /* bridge has no interfaces */ bb_putchar('\n'); } goto done; } #endif if (!*argv) /* all but 'show' need at least one argument */ bb_show_usage(); br = *argv++; if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */ ioctl_or_perror_and_die(fd, key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, br, "bridge %s", br); goto done; } if (!*argv) /* all but 'addif/delif' need at least two arguments */ bb_show_usage(); strncpy(ifr.ifr_name, br, IFNAMSIZ); if (key == ARG_addif || key == ARG_delif) { /* addif or delif */ brif = *argv; ifr.ifr_ifindex = if_nametoindex(brif); if (!ifr.ifr_ifindex) { bb_perror_msg_and_die("iface %s", brif); } ioctl_or_perror_and_die(fd, key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, &ifr, "bridge %s", br); goto done_next_argv; } #if ENABLE_FEATURE_BRCTL_FANCY if (key == ARG_stp) { /* stp */ /* FIXME: parsing yes/y/on/1 versus no/n/off/0 is too involved */ arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, (unsigned)(**argv - '0'), 0); goto fire; } if ((unsigned)(key - ARG_setageing) < 4) { /* time related ops */ static const uint8_t ops[] ALIGN1 = { BRCTL_SET_AGEING_TIME, /* ARG_setageing */ BRCTL_SET_BRIDGE_FORWARD_DELAY, /* ARG_setfd */ BRCTL_SET_BRIDGE_HELLO_TIME, /* ARG_sethello */ BRCTL_SET_BRIDGE_MAX_AGE /* ARG_setmaxage */ }; arm_ioctl(args, ops[key - ARG_setageing], str_to_jiffies(*argv), 0); goto fire; } if (key == ARG_setpathcost || key == ARG_setportprio || key == ARG_setbridgeprio ) { static const uint8_t ops[] ALIGN1 = { BRCTL_SET_PATH_COST, /* ARG_setpathcost */ BRCTL_SET_PORT_PRIORITY, /* ARG_setportprio */ BRCTL_SET_BRIDGE_PRIORITY /* ARG_setbridgeprio */ }; int port = -1; unsigned arg1, arg2; if (key != ARG_setbridgeprio) { /* get portnum */ unsigned i; port = if_nametoindex(*argv++); if (!port) bb_error_msg_and_die(bb_msg_invalid_arg, *argv, "port"); memset(ifidx, 0, sizeof ifidx); arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx, MAX_PORTS); xioctl(fd, SIOCDEVPRIVATE, &ifr); for (i = 0; i < MAX_PORTS; i++) { if (ifidx[i] == port) { port = i; break; } } } arg1 = port; arg2 = xatoi_u(*argv); if (key == ARG_setbridgeprio) { arg1 = arg2; arg2 = 0; } arm_ioctl(args, ops[key - ARG_setpathcost], arg1, arg2); } fire: /* Execute the previously set command */ xioctl(fd, SIOCDEVPRIVATE, &ifr); #endif done_next_argv: argv++; done: close(fd); } return EXIT_SUCCESS; }
int sulogin_main(int argc, char **argv) { char *cp; int timeout = 0; char *timeout_arg; const char * const *p; struct passwd *pwd; const char *shell; #if ENABLE_FEATURE_SHADOWPASSWDS /* Using _r function to avoid pulling in static buffers */ char buffer[256]; struct spwd spw; struct spwd *result; #endif logmode = LOGMODE_BOTH; openlog(applet_name, 0, LOG_AUTH); if (getopt32(argc, argv, "t:", &timeout_arg)) { timeout = xatoi_u(timeout_arg); } if (argv[optind]) { close(0); close(1); dup(xopen(argv[optind], O_RDWR)); close(2); dup(0); } if (!isatty(0) || !isatty(1) || !isatty(2)) { logmode = LOGMODE_SYSLOG; bb_error_msg_and_die("not a tty"); } /* Clear out anything dangerous from the environment */ for (p = forbid; *p; p++) unsetenv(*p); signal(SIGALRM, catchalarm); pwd = getpwuid(0); if (!pwd) { goto auth_error; } #if ENABLE_FEATURE_SHADOWPASSWDS if (getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result)) { goto auth_error; } pwd->pw_passwd = spw.sp_pwdp; #endif while (1) { /* cp points to a static buffer that is zeroed every time */ cp = bb_askpass(timeout, "Give root password for system maintenance\n" "(or type Control-D for normal startup):"); if (!cp || !*cp) { bb_info_msg("Normal startup"); return 0; } if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) { break; } bb_do_delay(FAIL_DELAY); bb_error_msg("login incorrect"); } memset(cp, 0, strlen(cp)); signal(SIGALRM, SIG_DFL); bb_info_msg("System Maintenance Mode"); USE_SELINUX(renew_current_security_context()); shell = getenv("SUSHELL"); if (!shell) shell = getenv("sushell"); if (!shell) { shell = "/bin/sh"; if (pwd->pw_shell[0]) shell = pwd->pw_shell; } run_shell(shell, 1, 0, 0); /* never returns */ auth_error: bb_error_msg_and_die("no password entry for 'root'"); }
// NB: mp->xxx fields may be trashed on exit static int nfsmount(struct mntent *mp, int vfsflags, char *filteropts) { CLIENT *mclient; char *hostname; char *pathname; char *mounthost; struct nfs_mount_data data; char *opt; struct hostent *hp; struct sockaddr_in server_addr; struct sockaddr_in mount_server_addr; int msock, fsock; union { struct fhstatus nfsv2; struct mountres3 nfsv3; } status; int daemonized; char *s; int port; int mountport; int proto; int bg; int soft; int intr; int posix; int nocto; int noac; int nolock; int retry; int tcp; int mountprog; int mountvers; int nfsprog; int nfsvers; int retval; find_kernel_nfs_mount_version(); daemonized = 0; mounthost = NULL; retval = ETIMEDOUT; msock = fsock = -1; mclient = NULL; /* NB: hostname, mounthost, filteropts must be free()d prior to return */ filteropts = xstrdup(filteropts); /* going to trash it later... */ hostname = xstrdup(mp->mnt_fsname); /* mount_main() guarantees that ':' is there */ s = strchr(hostname, ':'); pathname = s + 1; *s = '\0'; /* Ignore all but first hostname in replicated mounts until they can be fully supported. ([email protected]) */ s = strchr(hostname, ','); if (s) { *s = '\0'; bb_error_msg("warning: multiple hostnames not supported"); } server_addr.sin_family = AF_INET; if (!inet_aton(hostname, &server_addr.sin_addr)) { hp = gethostbyname(hostname); if (hp == NULL) { bb_herror_msg("%s", hostname); goto fail; } if (hp->h_length > sizeof(struct in_addr)) { bb_error_msg("got bad hp->h_length"); hp->h_length = sizeof(struct in_addr); } memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); } memcpy(&mount_server_addr, &server_addr, sizeof(mount_server_addr)); /* add IP address to mtab options for use when unmounting */ if (!mp->mnt_opts) { /* TODO: actually mp->mnt_opts is never NULL */ mp->mnt_opts = xasprintf("addr=%s", inet_ntoa(server_addr.sin_addr)); } else { char *tmp = xasprintf("%s%saddr=%s", mp->mnt_opts, mp->mnt_opts[0] ? "," : "", inet_ntoa(server_addr.sin_addr)); free(mp->mnt_opts); mp->mnt_opts = tmp; } /* Set default options. * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to * let the kernel decide. * timeo is filled in after we know whether it'll be TCP or UDP. */ memset(&data, 0, sizeof(data)); data.retrans = 3; data.acregmin = 3; data.acregmax = 60; data.acdirmin = 30; data.acdirmax = 60; data.namlen = NAME_MAX; bg = 0; soft = 0; intr = 0; posix = 0; nocto = 0; nolock = 0; noac = 0; retry = 10000; /* 10000 minutes ~ 1 week */ tcp = 0; mountprog = MOUNTPROG; mountvers = 0; port = 0; mountport = 0; nfsprog = 100003; nfsvers = 0; /* parse options */ if (filteropts) for (opt = strtok(filteropts, ","); opt; opt = strtok(NULL, ",")) { char *opteq = strchr(opt, '='); if (opteq) { static const char *const options[] = { /* 0 */ "rsize", /* 1 */ "wsize", /* 2 */ "timeo", /* 3 */ "retrans", /* 4 */ "acregmin", /* 5 */ "acregmax", /* 6 */ "acdirmin", /* 7 */ "acdirmax", /* 8 */ "actimeo", /* 9 */ "retry", /* 10 */ "port", /* 11 */ "mountport", /* 12 */ "mounthost", /* 13 */ "mountprog", /* 14 */ "mountvers", /* 15 */ "nfsprog", /* 16 */ "nfsvers", /* 17 */ "vers", /* 18 */ "proto", /* 19 */ "namlen", /* 20 */ "addr", NULL }; int val = xatoi_u(opteq + 1); *opteq = '\0'; switch (index_in_str_array(options, opt)) { case 0: // "rsize" data.rsize = val; break; case 1: // "wsize" data.wsize = val; break; case 2: // "timeo" data.timeo = val; break; case 3: // "retrans" data.retrans = val; break; case 4: // "acregmin" data.acregmin = val; break; case 5: // "acregmax" data.acregmax = val; break; case 6: // "acdirmin" data.acdirmin = val; break; case 7: // "acdirmax" data.acdirmax = val; break; case 8: // "actimeo" data.acregmin = val; data.acregmax = val; data.acdirmin = val; data.acdirmax = val; break; case 9: // "retry" retry = val; break; case 10: // "port" port = val; break; case 11: // "mountport" mountport = val; break; case 12: // "mounthost" mounthost = xstrndup(opteq+1, strcspn(opteq+1," \t\n\r,")); break; case 13: // "mountprog" mountprog = val; break; case 14: // "mountvers" mountvers = val; break; case 15: // "nfsprog" nfsprog = val; break; case 16: // "nfsvers" case 17: // "vers" nfsvers = val; break; case 18: // "proto" if (!strncmp(opteq+1, "tcp", 3)) tcp = 1; else if (!strncmp(opteq+1, "udp", 3)) tcp = 0; else bb_error_msg("warning: unrecognized proto= option"); break; case 19: // "namlen" if (nfs_mount_version >= 2) data.namlen = val; else bb_error_msg("warning: option namlen is not supported\n"); break; case 20: // "addr" - ignore break; default: bb_error_msg("unknown nfs mount parameter: %s=%d", opt, val); goto fail; } } else { static const char *const options[] = { "bg", "fg", "soft", "hard", "intr", "posix", "cto", "ac", "tcp", "udp", "lock", NULL }; int val = 1; if (!strncmp(opt, "no", 2)) { val = 0; opt += 2; } switch (index_in_str_array(options, opt)) { case 0: // "bg" bg = val; break; case 1: // "fg" bg = !val; break; case 2: // "soft" soft = val; break; case 3: // "hard" soft = !val; break; case 4: // "intr" intr = val; break; case 5: // "posix" posix = val; break; case 6: // "cto" nocto = !val; break; case 7: // "ac" noac = !val; break; case 8: // "tcp" tcp = val; break; case 9: // "udp" tcp = !val; break; case 10: // "lock" if (nfs_mount_version >= 3) nolock = !val; else bb_error_msg("warning: option nolock is not supported"); break; default: bb_error_msg("unknown nfs mount option: %s%s", val ? "" : "no", opt); goto fail; } } } proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP; data.flags = (soft ? NFS_MOUNT_SOFT : 0) | (intr ? NFS_MOUNT_INTR : 0) | (posix ? NFS_MOUNT_POSIX : 0) | (nocto ? NFS_MOUNT_NOCTO : 0) | (noac ? NFS_MOUNT_NOAC : 0); if (nfs_mount_version >= 2) data.flags |= (tcp ? NFS_MOUNT_TCP : 0); if (nfs_mount_version >= 3) data.flags |= (nolock ? NFS_MOUNT_NONLM : 0); if (nfsvers > MAX_NFSPROT || mountvers > MAX_NFSPROT) { bb_error_msg("NFSv%d not supported", nfsvers); goto fail; } if (nfsvers && !mountvers) mountvers = (nfsvers < 3) ? 1 : nfsvers; if (nfsvers && nfsvers < mountvers) { mountvers = nfsvers; } /* Adjust options if none specified */ if (!data.timeo) data.timeo = tcp ? 70 : 7; data.version = nfs_mount_version; if (vfsflags & MS_REMOUNT) goto do_mount; /* * If the previous mount operation on the same host was * backgrounded, and the "bg" for this mount is also set, * give up immediately, to avoid the initial timeout. */ if (bg && we_saw_this_host_before(hostname)) { daemonized = daemonize(); /* parent or error */ if (daemonized <= 0) { /* parent or error */ retval = -daemonized; goto ret; } } /* create mount daemon client */ /* See if the nfs host = mount host. */ if (mounthost) { if (mounthost[0] >= '0' && mounthost[0] <= '9') { mount_server_addr.sin_family = AF_INET; mount_server_addr.sin_addr.s_addr = inet_addr(hostname); } else { hp = gethostbyname(mounthost); if (hp == NULL) { bb_herror_msg("%s", mounthost); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { bb_error_msg("got bad hp->h_length?"); hp->h_length = sizeof(struct in_addr); } mount_server_addr.sin_family = AF_INET; memcpy(&mount_server_addr.sin_addr, hp->h_addr, hp->h_length); } } } /* * The following loop implements the mount retries. When the mount * times out, and the "bg" option is set, we background ourself * and continue trying. * * The case where the mount point is not present and the "bg" * option is set, is treated as a timeout. This is done to * support nested mounts. * * The "retry" count specified by the user is the number of * minutes to retry before giving up. */ { struct timeval total_timeout; struct timeval retry_timeout; struct pmap* pm_mnt; time_t t; time_t prevt; time_t timeout; retry_timeout.tv_sec = 3; retry_timeout.tv_usec = 0; total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; timeout = time(NULL) + 60 * retry; prevt = 0; t = 30; retry: /* be careful not to use too many CPU cycles */ if (t - prevt < 30) sleep(30); pm_mnt = get_mountport(&mount_server_addr, mountprog, mountvers, proto, mountport); nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers; /* contact the mount daemon via TCP */ mount_server_addr.sin_port = htons(pm_mnt->pm_port); msock = RPC_ANYSOCK; switch (pm_mnt->pm_prot) { case IPPROTO_UDP: mclient = clntudp_create(&mount_server_addr, pm_mnt->pm_prog, pm_mnt->pm_vers, retry_timeout, &msock); if (mclient) break; mount_server_addr.sin_port = htons(pm_mnt->pm_port); msock = RPC_ANYSOCK; case IPPROTO_TCP: mclient = clnttcp_create(&mount_server_addr, pm_mnt->pm_prog, pm_mnt->pm_vers, &msock, 0, 0); break; default: mclient = 0; } if (!mclient) { if (!daemonized && prevt == 0) error_msg_rpc(clnt_spcreateerror(" ")); } else { enum clnt_stat clnt_stat; /* try to mount hostname:pathname */ mclient->cl_auth = authunix_create_default(); /* make pointers in xdr_mountres3 NULL so * that xdr_array allocates memory for us */ memset(&status, 0, sizeof(status)); if (pm_mnt->pm_vers == 3) clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) &pathname, (xdrproc_t) xdr_mountres3, (caddr_t) &status, total_timeout); else clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) &pathname, (xdrproc_t) xdr_fhstatus, (caddr_t) &status, total_timeout); if (clnt_stat == RPC_SUCCESS) goto prepare_kernel_data; /* we're done */ if (errno != ECONNREFUSED) { error_msg_rpc(clnt_sperror(mclient, " ")); goto fail; /* don't retry */ } /* Connection refused */ if (!daemonized && prevt == 0) /* print just once */ error_msg_rpc(clnt_sperror(mclient, " ")); auth_destroy(mclient->cl_auth); clnt_destroy(mclient); mclient = 0; close(msock); } /* Timeout. We are going to retry... maybe */ if (!bg) goto fail; if (!daemonized) { daemonized = daemonize(); if (daemonized <= 0) { /* parent or error */ retval = -daemonized; goto ret; } } prevt = t; t = time(NULL); if (t >= timeout) /* TODO error message */ goto fail; goto retry; } prepare_kernel_data: if (nfsvers == 2) { if (status.nfsv2.fhs_status != 0) { bb_error_msg("%s:%s failed, reason given by server: %s", hostname, pathname, nfs_strerror(status.nfsv2.fhs_status)); goto fail; } memcpy(data.root.data, (char *) status.nfsv2.fhstatus_u.fhs_fhandle, NFS_FHSIZE); data.root.size = NFS_FHSIZE; memcpy(data.old_root.data, (char *) status.nfsv2.fhstatus_u.fhs_fhandle, NFS_FHSIZE); } else { fhandle3 *my_fhandle; if (status.nfsv3.fhs_status != 0) { bb_error_msg("%s:%s failed, reason given by server: %s", hostname, pathname, nfs_strerror(status.nfsv3.fhs_status)); goto fail; } my_fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle; memset(data.old_root.data, 0, NFS_FHSIZE); memset(&data.root, 0, sizeof(data.root)); data.root.size = my_fhandle->fhandle3_len; memcpy(data.root.data, (char *) my_fhandle->fhandle3_val, my_fhandle->fhandle3_len); data.flags |= NFS_MOUNT_VER3; } /* create nfs socket for kernel */ if (tcp) { if (nfs_mount_version < 3) { bb_error_msg("NFS over TCP is not supported"); goto fail; } fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } else fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fsock < 0) { bb_perror_msg("nfs socket"); goto fail; } if (bindresvport(fsock, 0) < 0) { bb_perror_msg("nfs bindresvport"); goto fail; } if (port == 0) { server_addr.sin_port = PMAPPORT; port = pmap_getport(&server_addr, nfsprog, nfsvers, tcp ? IPPROTO_TCP : IPPROTO_UDP); if (port == 0) port = NFS_PORT; } server_addr.sin_port = htons(port); /* prepare data structure for kernel */ data.fd = fsock; memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); strncpy(data.hostname, hostname, sizeof(data.hostname)); /* clean up */ auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); if (bg) { /* We must wait until mount directory is available */ struct stat statbuf; int delay = 1; while (stat(mp->mnt_dir, &statbuf) == -1) { if (!daemonized) { daemonized = daemonize(); if (daemonized <= 0) { /* parent or error */ retval = -daemonized; goto ret; } } sleep(delay); /* 1, 2, 4, 8, 16, 30, ... */ delay *= 2; if (delay > 30) delay = 30; } } do_mount: /* perform actual mount */ mp->mnt_type = (char*)"nfs"; retval = mount_it_now(mp, vfsflags, (char*)&data); goto ret; fail: /* abort */ if (msock != -1) { if (mclient) { auth_destroy(mclient->cl_auth); clnt_destroy(mclient); } close(msock); } if (fsock != -1) close(fsock); ret: free(hostname); free(mounthost); free(filteropts); return retval; }
int du_main(int argc, char **argv) { long total; int slink_depth_save; int print_final_total; char *smax_print_depth; unsigned opt; #if ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K if (getenv("POSIXLY_CORRECT")) { /* TODO - a new libbb function? */ #if ENABLE_FEATURE_HUMAN_READABLE disp_hr = 512; #else disp_k = 0; #endif } #endif /* Note: SUSv3 specifies that -a and -s options cannot be used together * in strictly conforming applications. However, it also says that some * du implementations may produce output when -a and -s are used together. * gnu du exits with an error code in this case. We choose to simply * ignore -a. This is consistent with -s being equivalent to -d 0. */ #if ENABLE_FEATURE_HUMAN_READABLE opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s"; opt = getopt32(argc, argv, "aHkLsx" "d:" "lc" "hm", &smax_print_depth); if (opt & (1 << 9)) { /* -h opt */ disp_hr = 0; } if (opt & (1 << 10)) { /* -m opt */ disp_hr = 1024*1024; } if (opt & (1 << 2)) { /* -k opt */ disp_hr = 1024; } #else opt_complementary = "H-L:L-H:s-d:d-s"; opt = getopt32(argc, argv, "aHkLsx" "d:" "lc", &smax_print_depth); #if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K if (opt & (1 << 2)) { /* -k opt */ disp_k = 1; } #endif #endif if (opt & (1 << 0)) { /* -a opt */ print_files = INT_MAX; } if (opt & (1 << 1)) { /* -H opt */ slink_depth = 1; } if (opt & (1 << 3)) { /* -L opt */ slink_depth = INT_MAX; } if (opt & (1 << 4)) { /* -s opt */ max_print_depth = 0; } one_file_system = opt & (1 << 5); /* -x opt */ if (opt & (1 << 6)) { /* -d opt */ max_print_depth = xatoi_u(smax_print_depth); } if (opt & (1 << 7)) { /* -l opt */ count_hardlinks = MAXINT(nlink_t); } print_final_total = opt & (1 << 8); /* -c opt */ /* go through remaining args (if any) */ argv += optind; if (optind >= argc) { *--argv = (char*)"."; if (slink_depth == 1) { slink_depth = 0; } } slink_depth_save = slink_depth; total = 0; do { total += du(*argv); slink_depth = slink_depth_save; } while (*++argv); if (ENABLE_FEATURE_CLEAN_UP) reset_ino_dev_hashtable(); if (print_final_total) { print(total, "total"); } fflush_stdout_and_exit(status); }
int cut_main(int argc, char **argv) { char *sopt, *ltok; opt_complementary = "b--bcf:c--bcf:f--bcf"; getopt32(argc, argv, optstring, &sopt, &sopt, &sopt, <ok); // argc -= optind; argv += optind; if (!(option_mask32 & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS))) bb_error_msg_and_die("expected a list of bytes, characters, or fields"); if (option_mask32 & BB_GETOPT_ERROR) bb_error_msg_and_die("only one type of list may be specified"); if (option_mask32 & CUT_OPT_DELIM_FLGS) { if (strlen(ltok) > 1) { bb_error_msg_and_die("the delimiter must be a single character"); } delim = ltok[0]; } /* non-field (char or byte) cutting has some special handling */ if (!(option_mask32 & CUT_OPT_FIELDS_FLGS)) { if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) { bb_error_msg_and_die ("suppressing non-delimited lines makes sense%s", _op_on_field); } if (delim != '\t') { bb_error_msg_and_die ("a delimiter may be specified%s", _op_on_field); } } /* * parse list and put values into startpos and endpos. * valid list formats: N, N-, N-M, -M * more than one list can be separated by commas */ { char *ntok; int s = 0, e = 0; /* take apart the lists, one by one (they are separated with commas */ while ((ltok = strsep(&sopt, ",")) != NULL) { /* it's actually legal to pass an empty list */ if (strlen(ltok) == 0) continue; /* get the start pos */ ntok = strsep(<ok, "-"); if (ntok == NULL) { bb_error_msg ("internal error: ntok is null for start pos!?\n"); } else if (strlen(ntok) == 0) { s = BOL; } else { s = xatoi_u(ntok); /* account for the fact that arrays are zero based, while * the user expects the first char on the line to be char #1 */ if (s != 0) s--; } /* get the end pos */ ntok = strsep(<ok, "-"); if (ntok == NULL) { e = NON_RANGE; } else if (strlen(ntok) == 0) { e = EOL; } else { e = xatoi_u(ntok); /* if the user specified and end position of 0, that means "til the * end of the line */ if (e == 0) e = EOL; e--; /* again, arrays are zero based, lines are 1 based */ if (e == s) e = NON_RANGE; } /* if there's something left to tokenize, the user passed * an invalid list */ if (ltok) bb_error_msg_and_die("invalid byte or field list"); /* add the new list */ cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists)); cut_lists[nlists-1].startpos = s; cut_lists[nlists-1].endpos = e; } /* make sure we got some cut positions out of all that */ if (nlists == 0) bb_error_msg_and_die("missing list of positions"); /* now that the lists are parsed, we need to sort them to make life * easier on us when it comes time to print the chars / fields / lines */ qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc); } /* argv[0..argc-1] should be names of file to process. If no * files were specified or '-' was specified, take input from stdin. * Otherwise, we process all the files specified. */ if (argv[0] == NULL || LONE_DASH(argv[0])) { cut_file(stdin); } else { FILE *file; do { file = fopen_or_warn(argv[0], "r"); if (file) { cut_file(file); fclose(file); } } while (*++argv); } if (ENABLE_FEATURE_CLEAN_UP) free(cut_lists); return EXIT_SUCCESS; }
int udhcpc_main(int argc, char **argv) { uint8_t *temp, *message; char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_t; unsigned long t1 = 0, t2 = 0, xid = 0; unsigned long start = 0, lease = 0; long now; unsigned opt; int max_fd; int sig; int retval; int len; int no_clientid = 0; fd_set rfds; struct timeval tv; struct dhcpMessage packet; struct in_addr temp_addr; enum { OPT_c = 1 << 0, OPT_C = 1 << 1, OPT_V = 1 << 2, OPT_f = 1 << 3, OPT_b = 1 << 4, OPT_H = 1 << 5, OPT_h = 1 << 6, OPT_F = 1 << 7, OPT_i = 1 << 8, OPT_n = 1 << 9, OPT_p = 1 << 10, OPT_q = 1 << 11, OPT_R = 1 << 12, OPT_r = 1 << 13, OPT_s = 1 << 14, OPT_T = 1 << 15, OPT_t = 1 << 16, OPT_v = 1 << 17, }; #if ENABLE_GETOPT_LONG static const struct option arg_options[] = { { "clientid", required_argument, 0, 'c' }, { "clientid-none", no_argument, 0, 'C' }, { "vendorclass", required_argument, 0, 'V' }, { "foreground", no_argument, 0, 'f' }, { "background", no_argument, 0, 'b' }, { "hostname", required_argument, 0, 'H' }, { "hostname", required_argument, 0, 'h' }, { "fqdn", required_argument, 0, 'F' }, { "interface", required_argument, 0, 'i' }, { "now", no_argument, 0, 'n' }, { "pidfile", required_argument, 0, 'p' }, { "quit", no_argument, 0, 'q' }, { "release", no_argument, 0, 'R' }, { "request", required_argument, 0, 'r' }, { "script", required_argument, 0, 's' }, { "timeout", required_argument, 0, 'T' }, { "version", no_argument, 0, 'v' }, { "retries", required_argument, 0, 't' }, { 0, 0, 0, 0 } }; #endif /* Default options. */ client_config.interface = "eth0"; client_config.script = DEFAULT_SCRIPT; client_config.retries = 3; client_config.timeout = 3; /* Parse command line */ opt_complementary = "?:c--C:C--c" // mutually exclusive ":hH:Hh"; // -h and -H are the same #if ENABLE_GETOPT_LONG applet_long_options = arg_options; #endif opt = getopt32(argc, argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:v", &str_c, &str_V, &str_h, &str_h, &str_F, &client_config.interface, &client_config.pidfile, &str_r, &client_config.script, &str_T, &str_t ); if (opt & OPT_c) client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0); if (opt & OPT_C) no_clientid = 1; if (opt & OPT_V) client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); if (opt & OPT_f) client_config.foreground = 1; if (opt & OPT_b) client_config.background_if_no_lease = 1; if (opt & OPT_h) client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); if (opt & OPT_F) { client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3); /* Flags: 0000NEOS S: 1 => Client requests Server to update A RR in DNS as well as PTR O: 1 => Server indicates to client that DNS has been updated regardless E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com" N: 1 => Client requests Server to not update DNS */ client_config.fqdn[OPT_DATA + 0] = 0x1; /* client_config.fqdn[OPT_DATA + 1] = 0; - redundant */ /* client_config.fqdn[OPT_DATA + 2] = 0; - redundant */ } // if (opt & OPT_i) client_config.interface = ... if (opt & OPT_n) client_config.abort_if_no_lease = 1; // if (opt & OPT_p) client_config.pidfile = ... if (opt & OPT_q) client_config.quit_after_lease = 1; if (opt & OPT_R) client_config.release_on_quit = 1; if (opt & OPT_r) requested_ip = inet_addr(str_r); // if (opt & OPT_s) client_config.script = ... if (opt & OPT_T) client_config.timeout = xatoi_u(str_T); if (opt & OPT_t) client_config.retries = xatoi_u(str_t); if (opt & OPT_v) { printf("version %s\n\n", BB_VER); return 0; } if (ENABLE_FEATURE_UDHCP_SYSLOG) { openlog(applet_name, LOG_PID, LOG_LOCAL0); logmode |= LOGMODE_SYSLOG; } if (read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.arp) < 0) return 1; /* Sanitize fd's and write pidfile */ udhcp_make_pidfile(client_config.pidfile); /* if not set, and not suppressed, setup the default client ID */ if (!client_config.clientid && !no_clientid) { client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); client_config.clientid[OPT_DATA] = 1; memcpy(client_config.clientid + OPT_DATA+1, client_config.arp, 6); } if (!client_config.vendorclass) client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0); /* setup the signal pipe */ udhcp_sp_setup(); state = INIT_SELECTING; udhcp_run_script(NULL, "deconfig"); change_mode(LISTEN_RAW); for (;;) { tv.tv_sec = timeout - uptime(); tv.tv_usec = 0; if (listen_mode != LISTEN_NONE && sockfd < 0) { if (listen_mode == LISTEN_KERNEL) sockfd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface); else sockfd = raw_socket(client_config.ifindex); } max_fd = udhcp_sp_fd_set(&rfds, sockfd); if (tv.tv_sec > 0) { DEBUG("Waiting on select..."); retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); } else retval = 0; /* If we already timed out, fall through */ now = uptime(); if (retval == 0) { /* timeout dropped to zero */ switch (state) { case INIT_SELECTING: if (packet_num < client_config.retries) { if (packet_num == 0) xid = random_xid(); /* send discover packet */ send_discover(xid, requested_ip); /* broadcast */ timeout = now + client_config.timeout; packet_num++; } else { udhcp_run_script(NULL, "leasefail"); if (client_config.background_if_no_lease) { bb_info_msg("No lease, forking to background"); client_background(); } else if (client_config.abort_if_no_lease) { bb_info_msg("No lease, failing"); retval = 1; goto ret; } /* wait to try again */ packet_num = 0; timeout = now + 60; } break; case RENEW_REQUESTED: case REQUESTING: if (packet_num < client_config.retries) { /* send request packet */ if (state == RENEW_REQUESTED) send_renew(xid, server_addr, requested_ip); /* unicast */ else send_selecting(xid, server_addr, requested_ip); /* broadcast */ timeout = now + ((packet_num == 2) ? 10 : 2); packet_num++; } else { /* timed out, go back to init state */ if (state == RENEW_REQUESTED) udhcp_run_script(NULL, "deconfig"); state = INIT_SELECTING; timeout = now; packet_num = 0; change_mode(LISTEN_RAW); } break; case BOUND: /* Lease is starting to run out, time to enter renewing state */ state = RENEWING; change_mode(LISTEN_KERNEL); DEBUG("Entering renew state"); /* fall right through */ case RENEWING: /* Either set a new T1, or enter REBINDING state */ if ((t2 - t1) <= (lease / 14400 + 1)) { /* timed out, enter rebinding state */ state = REBINDING; timeout = now + (t2 - t1); DEBUG("Entering rebinding state"); } else { /* send a request packet */ send_renew(xid, server_addr, requested_ip); /* unicast */ t1 = (t2 - t1) / 2 + t1; timeout = t1 + start; } break; case REBINDING: /* Either set a new T2, or enter INIT state */ if ((lease - t2) <= (lease / 14400 + 1)) { /* timed out, enter init state */ state = INIT_SELECTING; bb_info_msg("Lease lost, entering init state"); udhcp_run_script(NULL, "deconfig"); timeout = now; packet_num = 0; change_mode(LISTEN_RAW); } else { /* send a request packet */ send_renew(xid, 0, requested_ip); /* broadcast */ t2 = (lease - t2) / 2 + t2; timeout = t2 + start; } break; case RELEASED: /* yah, I know, *you* say it would never happen */ timeout = 0x7fffffff; break; } } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) { /* a packet is ready, read it */ if (listen_mode == LISTEN_KERNEL) len = udhcp_get_packet(&packet, sockfd); else len = get_raw_packet(&packet, sockfd); if (len == -1 && errno != EINTR) { DEBUG("error on read, %s, reopening socket", strerror(errno)); change_mode(listen_mode); /* just close and reopen */ } if (len < 0) continue; if (packet.xid != xid) { DEBUG("Ignoring XID %lx (our xid is %lx)", (unsigned long) packet.xid, xid); continue; } /* Ignore packets that aren't for us */ if (memcmp(packet.chaddr, client_config.arp, 6)) { DEBUG("Packet does not have our chaddr - ignoring"); continue; } message = get_option(&packet, DHCP_MESSAGE_TYPE); if (message == NULL) { bb_error_msg("cannot get option from packet - ignoring"); continue; } switch (state) { case INIT_SELECTING: /* Must be a DHCPOFFER to one of our xid's */ if (*message == DHCPOFFER) { temp = get_option(&packet, DHCP_SERVER_ID); if (temp) { /* can be misaligned, thus memcpy */ memcpy(&server_addr, temp, 4); xid = packet.xid; requested_ip = packet.yiaddr; /* enter requesting state */ state = REQUESTING; timeout = now; packet_num = 0; } else { bb_error_msg("no server ID in message"); } } break; case RENEW_REQUESTED: case REQUESTING: case RENEWING: case REBINDING: if (*message == DHCPACK) { temp = get_option(&packet, DHCP_LEASE_TIME); if (!temp) { bb_error_msg("no lease time with ACK, using 1 hour lease"); lease = 60 * 60; } else { /* can be misaligned, thus memcpy */ memcpy(&lease, temp, 4); lease = ntohl(lease); } /* enter bound state */ t1 = lease / 2; /* little fixed point for n * .875 */ t2 = (lease * 0x7) >> 3; temp_addr.s_addr = packet.yiaddr; bb_info_msg("Lease of %s obtained, lease time %ld", inet_ntoa(temp_addr), lease); start = now; timeout = t1 + start; requested_ip = packet.yiaddr; udhcp_run_script(&packet, ((state == RENEWING || state == REBINDING) ? "renew" : "bound")); state = BOUND; change_mode(LISTEN_NONE); if (client_config.quit_after_lease) { if (client_config.release_on_quit) perform_release(); goto ret0; } if (!client_config.foreground) client_background(); } else if (*message == DHCPNAK) { /* return to init state */ bb_info_msg("Received DHCP NAK"); udhcp_run_script(&packet, "nak"); if (state != REQUESTING) udhcp_run_script(NULL, "deconfig"); state = INIT_SELECTING; timeout = now; requested_ip = 0; packet_num = 0; change_mode(LISTEN_RAW); sleep(3); /* avoid excessive network traffic */ } break; /* case BOUND, RELEASED: - ignore all packets */ } } else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) {
int cut_main(int argc ATTRIBUTE_UNUSED, char **argv) { char delim = '\t'; /* delimiter, default is tab */ char *sopt, *ltok; opt_complementary = "b--bcf:c--bcf:f--bcf"; getopt32(argv, optstring, &sopt, &sopt, &sopt, <ok); // argc -= optind; argv += optind; if (!(option_mask32 & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS))) bb_error_msg_and_die("expected a list of bytes, characters, or fields"); if (option_mask32 & CUT_OPT_DELIM_FLGS) { if (ltok[0] && ltok[1]) { /* more than 1 char? */ bb_error_msg_and_die("the delimiter must be a single character"); } delim = ltok[0]; } /* non-field (char or byte) cutting has some special handling */ if (!(option_mask32 & CUT_OPT_FIELDS_FLGS)) { static const char _op_on_field[] ALIGN1 = " only when operating on fields"; if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) { bb_error_msg_and_die ("suppressing non-delimited lines makes sense%s", _op_on_field); } if (delim != '\t') { bb_error_msg_and_die ("a delimiter may be specified%s", _op_on_field); } } /* * parse list and put values into startpos and endpos. * valid list formats: N, N-, N-M, -M * more than one list can be separated by commas */ { char *ntok; int s = 0, e = 0; /* take apart the lists, one by one (they are separated with commas) */ while ((ltok = strsep(&sopt, ",")) != NULL) { /* it's actually legal to pass an empty list */ if (!ltok[0]) continue; /* get the start pos */ ntok = strsep(<ok, "-"); if (!ntok[0]) { s = BOL; } else { s = xatoi_u(ntok); /* account for the fact that arrays are zero based, while * the user expects the first char on the line to be char #1 */ if (s != 0) s--; } /* get the end pos */ if (ltok == NULL) { e = NON_RANGE; } else if (!ltok[0]) { e = EOL; } else { e = xatoi_u(ltok); /* if the user specified and end position of 0, that means "til the * end of the line */ if (e == 0) e = EOL; e--; /* again, arrays are zero based, lines are 1 based */ if (e == s) e = NON_RANGE; } /* add the new list */ cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists)); cut_lists[nlists-1].startpos = s; cut_lists[nlists-1].endpos = e; } /* make sure we got some cut positions out of all that */ if (nlists == 0) bb_error_msg_and_die("missing list of positions"); /* now that the lists are parsed, we need to sort them to make life * easier on us when it comes time to print the chars / fields / lines */ qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc); } { int retval = EXIT_SUCCESS; if (!*argv) *--argv = (char *)"-"; do { FILE *file = fopen_or_warn_stdin(*argv); if (!file) { retval = EXIT_FAILURE; continue; } cut_file(file, delim); fclose_if_not_stdin(file); } while (*++argv); if (ENABLE_FEATURE_CLEAN_UP) free(cut_lists); fflush_stdout_and_exit(retval); } }
int grep_main(int argc, char **argv) { FILE *file; int matched; llist_t *fopt = NULL; /* do normal option parsing */ #if ENABLE_FEATURE_GREP_CONTEXT char *slines_after; char *slines_before; char *Copt; opt_complementary = "H-h:e::f::C-AB"; getopt32(argc, argv, GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP, &pattern_head, &fopt, &slines_after, &slines_before, &Copt); if (option_mask32 & GREP_OPT_C) { /* -C unsets prev -A and -B, but following -A or -B may override it */ if (!(option_mask32 & GREP_OPT_A)) /* not overridden */ slines_after = Copt; if (!(option_mask32 & GREP_OPT_B)) /* not overridden */ slines_before = Copt; option_mask32 |= GREP_OPT_A|GREP_OPT_B; /* for parser */ } if (option_mask32 & GREP_OPT_A) { lines_after = xatoi_u(slines_after); } if (option_mask32 & GREP_OPT_B) { lines_before = xatoi_u(slines_before); } /* sanity checks */ if (option_mask32 & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L)) { option_mask32 &= ~GREP_OPT_n; lines_before = 0; lines_after = 0; } else if (lines_before > 0) before_buf = xzalloc(lines_before * sizeof(char *)); #else /* with auto sanity checks */ opt_complementary = "H-h:e::f::c-n:q-n:l-n"; getopt32(argc, argv, GREP_OPTS OPT_EGREP, &pattern_head, &fopt); #endif invert_search = ((option_mask32 & GREP_OPT_v) != 0); /* 0 | 1 */ if (pattern_head != NULL) { /* convert char *argv[] to grep_list_data_t */ llist_t *cur; for (cur = pattern_head; cur; cur = cur->link) cur->data = new_grep_list_data(cur->data, 0); } if (option_mask32 & GREP_OPT_f) load_regexes_from_file(fopt); if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f') option_mask32 |= GREP_OPT_F; if (!(option_mask32 & GREP_OPT_o)) reflags = REG_NOSUB; if (ENABLE_FEATURE_GREP_EGREP_ALIAS && (applet_name[0] == 'e' || (option_mask32 & GREP_OPT_E))) reflags |= REG_EXTENDED; if (option_mask32 & GREP_OPT_i) reflags |= REG_ICASE; argv += optind; argc -= optind; /* if we didn't get a pattern from a -e and no command file was specified, * argv[optind] should be the pattern. no pattern, no worky */ if (pattern_head == NULL) { if (*argv == NULL) bb_show_usage(); else { char *pattern = new_grep_list_data(*argv++, 0); llist_add_to(&pattern_head, pattern); argc--; } } /* argv[(optind)..(argc-1)] should be names of file to grep through. If * there is more than one file to grep, we will print the filenames. */ if (argc > 1) print_filename = 1; /* -H / -h of course override */ if (option_mask32 & GREP_OPT_H) print_filename = 1; if (option_mask32 & GREP_OPT_h) print_filename = 0; /* If no files were specified, or '-' was specified, take input from * stdin. Otherwise, we grep through all the files specified. */ if (argc == 0) argc++; matched = 0; while (argc--) { cur_file = *argv++; file = stdin; if (!cur_file || (*cur_file == '-' && !cur_file[1])) { cur_file = "(standard input)"; } else { if (option_mask32 & GREP_OPT_r) { struct stat st; if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) { if (!(option_mask32 & GREP_OPT_h)) print_filename = 1; matched += grep_dir(cur_file); goto grep_done; } } /* else: fopen(dir) will succeed, but reading won't */ file = fopen(cur_file, "r"); if (file == NULL) { if (!SUPPRESS_ERR_MSGS) bb_perror_msg("%s", cur_file); open_errors = 1; continue; } } matched += grep_file(file); fclose_if_not_stdin(file); grep_done: if (matched < 0) { /* we found a match but were told to be quiet, stop here and * return success */ break; } } /* destroy all the elments in the pattern list */ if (ENABLE_FEATURE_CLEAN_UP) { while (pattern_head) { llist_t *pattern_head_ptr = pattern_head; grep_list_data_t *gl = (grep_list_data_t *)pattern_head_ptr->data; pattern_head = pattern_head->link; if ((gl->flg_mem_alocated_compiled & PATTERN_MEM_A)) free(gl->pattern); if ((gl->flg_mem_alocated_compiled & COMPILED)) regfree(&(gl->preg)); free(pattern_head_ptr); } } /* 0 = success, 1 = failed, 2 = error */ /* If the -q option is specified, the exit status shall be zero * if an input line is selected, even if an error was detected. */ if (BE_QUIET && matched) return 0; if (open_errors) return 2; return !matched; /* invert return value 0 = success, 1 = failed */ }
int hexdump_main(int argc, char **argv) { const char *p; int ch; #if ENABLE_FEATURE_HEXDUMP_REVERSE FILE *fp; smallint rdump = 0; #endif bb_dump_vflag = FIRST; bb_dump_length = -1; if (ENABLE_HD && !applet_name[2]) { /* we are "hd" */ ch = 'C'; goto hd_applet; } /* We cannot use getopt32: in hexdump options are cumulative. * E.g. "hexdump -C -C file" should dump each line twice */ while ((ch = getopt(argc, argv, hexdump_opts)) > 0) { p = strchr(hexdump_opts, ch); if (!p) bb_show_usage(); if ((p - hexdump_opts) < 5) { bb_dump_add(add_first); bb_dump_add(add_strings[(int)(p - hexdump_opts)]); } /* Save a little bit of space below by omitting the 'else's. */ if (ch == 'C') { hd_applet: bb_dump_add("\"%08.8_Ax\n\""); bb_dump_add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" "); bb_dump_add("\" |\" 16/1 \"%_p\" \"|\\n\""); } if (ch == 'e') { bb_dump_add(optarg); } /* else */ if (ch == 'f') { bb_dump_addfile(optarg); } /* else */ if (ch == 'n') { bb_dump_length = xatoi_u(optarg); } /* else */ if (ch == 's') { bb_dump_skip = xatoul_range_sfx(optarg, 0, LONG_MAX, suffixes); } /* else */ if (ch == 'v') { bb_dump_vflag = ALL; } #if ENABLE_FEATURE_HEXDUMP_REVERSE if (ch == 'R') { rdump = 1; } #endif } if (!bb_dump_fshead) { bb_dump_add(add_first); bb_dump_add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\""); } argv += optind; #if !ENABLE_FEATURE_HEXDUMP_REVERSE return bb_dump_dump(argv); #else if (!rdump) { return bb_dump_dump(argv); } /* -R: reverse of 'hexdump -Cv' */ fp = stdin; if (!*argv) { argv--; goto jump_in; } do { char *buf; fp = xfopen(*argv, "r"); jump_in: while ((buf = xmalloc_getline(fp)) != NULL) { p = buf; while (1) { /* skip address or previous byte */ while (isxdigit(*p)) p++; while (*p == ' ') p++; /* '|' char will break the line */ if (!isxdigit(*p) || sscanf(p, "%x ", &ch) != 1) break; putchar(ch); } free(buf); } fclose(fp); } while (*++argv); fflush_stdout_and_exit(EXIT_SUCCESS); #endif }
int sulogin_main(int argc, char **argv) { char *cp; int timeout = 0; char *timeout_arg; struct passwd *pwd; const char *shell; #if ENABLE_FEATURE_SHADOWPASSWDS /* Using _r function to avoid pulling in static buffers */ char buffer[256]; struct spwd spw; #endif logmode = LOGMODE_BOTH; openlog(applet_name, 0, LOG_AUTH); if (getopt32(argv, "t:", &timeout_arg)) { timeout = xatoi_u(timeout_arg); } if (argv[optind]) { close(0); close(1); dup(xopen(argv[optind], O_RDWR)); close(2); dup(0); } if (!isatty(0) || !isatty(1) || !isatty(2)) { logmode = LOGMODE_SYSLOG; bb_error_msg_and_die("not a tty"); } /* Clear dangerous stuff, set PATH */ sanitize_env_for_suid(); // bb_askpass() already handles this // signal(SIGALRM, catchalarm); pwd = getpwuid(0); if (!pwd) { goto auth_error; } #if ENABLE_FEATURE_SHADOWPASSWDS { /* getspnam_r may return 0 yet set result to NULL. * At least glibc 2.4 does this. Be extra paranoid here. */ struct spwd *result = NULL; int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result); if (r || !result) { goto auth_error; } pwd->pw_passwd = result->sp_pwdp; } #endif while (1) { /* cp points to a static buffer that is zeroed every time */ cp = bb_askpass(timeout, "Give root password for system maintenance\n" "(or type Control-D for normal startup):"); if (!cp || !*cp) { bb_info_msg("Normal startup"); return 0; } if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) { break; } bb_do_delay(FAIL_DELAY); bb_error_msg("login incorrect"); } memset(cp, 0, strlen(cp)); // signal(SIGALRM, SIG_DFL); bb_info_msg("System Maintenance Mode"); USE_SELINUX(renew_current_security_context()); shell = getenv("SUSHELL"); if (!shell) shell = getenv("sushell"); if (!shell) { shell = "/bin/sh"; if (pwd->pw_shell[0]) shell = pwd->pw_shell; } /* Exec login shell with no additional parameters. Never returns. */ run_shell(shell, 1, NULL, NULL); auth_error: bb_error_msg_and_die("no password entry for root"); }