int rtnl_rtprot_a2n(uint32_t *id, char *arg) { static const char *cache = NULL; static unsigned long res; int i; if (cache && strcmp(cache, arg) == 0) { *id = res; return 0; } rtnl_rtprot_initialize(); for (i = 0; i < 256; i++) { if (rtnl_rtprot_tab[i] && strcmp(rtnl_rtprot_tab[i], arg) == 0) { cache = rtnl_rtprot_tab[i]; res = i; *id = res; return 0; } } res = bb_strtoul(arg, NULL, 0); if (errno || res > 255) return -1; *id = res; return 0; }
static int remove_ids(type_id type, char **argv) { unsigned long id; int nb_errors = 0; union semun arg; arg.val = 0; while (argv[0]) { id = bb_strtoul(argv[0], NULL, 10); if (errno || id > INT_MAX) { bb_error_msg("invalid id: %s", argv[0]); nb_errors++; } else { int ret = 0; if (type == SEM) ret = semctl(id, 0, IPC_RMID, arg); else if (type == MSG) ret = msgctl(id, IPC_RMID, NULL); else if (type == SHM) ret = shmctl(id, IPC_RMID, NULL); if (ret) { bb_perror_msg("can't remove id %s", argv[0]); nb_errors++; } } argv++; } return nb_errors; }
unsigned long FAST_FUNC get_ug_id(const char *s, long FAST_FUNC (*xname2id)(const char *)) { unsigned long r; r = bb_strtoul(s, NULL, 10); if (errno) return xname2id(s); return r; }
static NOINLINE pid_t read_pid(const char *filename) { int len; char buf[128]; len = open_read_close(filename, buf, 127); if (len > 0) { buf[len] = '\0'; /* returns ULONG_MAX on error => -1 */ return bb_strtoul(buf, NULL, 10); } return 0; }
/* String to timespec: "NNNN[.NNNNN]" -> struct timespec. * Can be used for other fixed-point needs. * Returns pointer past last converted char, * and returns errno similar to bb_strtoXX functions. */ char* FAST_FUNC bb_str_to_ts(struct timespec *ts, const char *arg) { if (sizeof(ts->tv_sec) <= sizeof(int)) ts->tv_sec = bb_strtou(arg, &arg, 10); else if (sizeof(ts->tv_sec) <= sizeof(long)) ts->tv_sec = bb_strtoul(arg, &arg, 10); else ts->tv_sec = bb_strtoull(arg, &arg, 10); ts->tv_nsec = 0; if (*arg != '.') return arg; /* !EINVAL: number is not ok (alphanumeric ending, overflow etc) */ if (errno != EINVAL) return arg; if (!*++arg) /* "NNN." */ return arg; { /* "NNN.xxx" - parse xxx */ int ndigits; char *p; char buf[10]; /* we never use more than 9 digits */ /* Need to make a copy to avoid false overflow */ safe_strncpy(buf, arg, 10); ts->tv_nsec = bb_strtou(buf, &p, 10); ndigits = p - buf; arg += ndigits; /* normalize to nsec */ while (ndigits < 9) { ndigits++; ts->tv_nsec *= 10; } while (isdigit(*arg)) /* skip possible 10th plus digits */ arg++; } return arg; }
static void conv_strtoul(const char *arg, void *result) { *(unsigned long*)result = bb_strtoul(arg, NULL, 0); }
int FAST_FUNC shell_builtin_ulimit(char **argv) { unsigned opts; unsigned argc; /* We can't use getopt32: need to handle commands like * ulimit 123 -c2 -l 456 */ /* In case getopt was already called: * reset the libc getopt() function, which keeps internal state. */ #ifdef __GLIBC__ optind = 0; #else /* BSD style */ optind = 1; /* optreset = 1; */ #endif /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */ argc = 1; while (argv[argc]) argc++; opts = 0; while (1) { struct rlimit limit; const struct limits *l; int opt_char = getopt(argc, argv, ulimit_opt_string); if (opt_char == -1) break; if (opt_char == 'H') { opts |= OPT_hard; continue; } if (opt_char == 'S') { opts |= OPT_soft; continue; } if (opt_char == 'a') { for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) { getrlimit(l->cmd, &limit); printf("-%c: %-30s ", l->option, l->name); printlim(opts, &limit, l); } continue; } if (opt_char == 1) opt_char = 'f'; for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) { if (opt_char == l->option) { char *val_str; getrlimit(l->cmd, &limit); val_str = optarg; if (!val_str && argv[optind] && argv[optind][0] != '-') val_str = argv[optind++]; /* ++ skips NN in "-c NN" case */ if (val_str) { rlim_t val; if (strcmp(val_str, "unlimited") == 0) val = RLIM_INFINITY; else { if (sizeof(val) == sizeof(int)) val = bb_strtou(val_str, NULL, 10); else if (sizeof(val) == sizeof(long)) val = bb_strtoul(val_str, NULL, 10); else val = bb_strtoull(val_str, NULL, 10); if (errno) { bb_error_msg("invalid number '%s'", val_str); return EXIT_FAILURE; } val <<= l->factor_shift; } //bb_error_msg("opt %c val_str:'%s' val:%lld", opt_char, val_str, (long long)val); /* from man bash: "If neither -H nor -S * is specified, both the soft and hard * limits are set. */ if (!opts) opts = OPT_hard + OPT_soft; if (opts & OPT_hard) limit.rlim_max = val; if (opts & OPT_soft) limit.rlim_cur = val; //bb_error_msg("setrlimit(%d, %lld, %lld)", l->cmd, (long long)limit.rlim_cur, (long long)limit.rlim_max); if (setrlimit(l->cmd, &limit) < 0) { bb_perror_msg("error setting limit"); return EXIT_FAILURE; } } else { printlim(opts, &limit, l); } break; } } /* for (every possible opt) */ if (l == &limits_tbl[ARRAY_SIZE(limits_tbl)]) { /* bad option. getopt already complained. */ break; } } /* while (there are options) */ return 0; }