int __parsespent(char *s, struct spwd *sp) { sp->sp_namp = s; if (!(s = strchr(s, ':'))) return -1; *s = 0; sp->sp_pwdp = ++s; if (!(s = strchr(s, ':'))) return -1; *s = 0; s++; sp->sp_lstchg = xatol(&s); if (*s != ':') return -1; s++; sp->sp_min = xatol(&s); if (*s != ':') return -1; s++; sp->sp_max = xatol(&s); if (*s != ':') return -1; s++; sp->sp_warn = xatol(&s); if (*s != ':') return -1; s++; sp->sp_inact = xatol(&s); if (*s != ':') return -1; s++; sp->sp_expire = xatol(&s); if (*s != ':') return -1; s++; sp->sp_flag = xatol(&s); if (*s != '\n') return -1; return 0; }
int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct spwd **res) { char path[20+NAME_MAX]; FILE *f = 0; int rv = 0; int fd; size_t k, l = strlen(name); char *s; int skip = 0; int cs; *res = 0; /* Disallow potentially-malicious user names */ if (*name=='.' || strchr(name, '/') || !l) return EINVAL; /* Buffer size must at least be able to hold name, plus some.. */ if (size < l+100) return ERANGE; /* Protect against truncation */ if (snprintf(path, sizeof path, "/etc/tcb/%s/shadow", name) >= sizeof path) return EINVAL; fd = open(path, O_RDONLY|O_NOFOLLOW|O_NONBLOCK); if (fd >= 0) { struct stat st = { 0 }; errno = EINVAL; if (fstat(fd, &st) || !S_ISREG(st.st_mode) || !(f = fdopen(fd, "rb"))) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); close(fd); pthread_setcancelstate(cs, 0); return errno; } } else { f = fopen("/etc/shadow", "rb"); if (!f) return errno; } pthread_cleanup_push(cleanup, f); while (fgets(buf, size, f) && (k=strlen(buf))>0) { if (skip || strncmp(name, buf, l)) { skip = buf[k-1] != '\n'; continue; } if (buf[k-1] != '\n') { rv = ERANGE; break; } buf[k-1] = 0; s = buf; sp->sp_namp = s; if (!(s = strchr(s, ':'))) continue; *s++ = 0; sp->sp_pwdp = s; if (!(s = strchr(s, ':'))) continue; *s++ = 0; sp->sp_lstchg = xatol(s); if (!(s = strchr(s, ':'))) continue; *s++ = 0; sp->sp_min = xatol(s); if (!(s = strchr(s, ':'))) continue; *s++ = 0; sp->sp_max = xatol(s); if (!(s = strchr(s, ':'))) continue; *s++ = 0; sp->sp_warn = xatol(s); if (!(s = strchr(s, ':'))) continue; *s++ = 0; sp->sp_inact = xatol(s); if (!(s = strchr(s, ':'))) continue; *s++ = 0; sp->sp_expire = xatol(s); if (!(s = strchr(s, ':'))) continue; *s++ = 0; sp->sp_flag = xatol(s); *res = sp; break; } pthread_cleanup_pop(1); return rv; }
int rtcwake_main(int argc UNUSED_PARAM, char **argv) { time_t rtc_time; unsigned opt; const char *rtcname = NULL; const char *suspend; const char *opt_seconds; const char *opt_time; time_t sys_time; time_t alarm_time = 0; unsigned seconds = 0; int utc = -1; int fd; #if ENABLE_LONG_OPTS static const char rtcwake_longopts[] ALIGN1 = "auto\0" No_argument "a" "local\0" No_argument "l" "utc\0" No_argument "u" "device\0" Required_argument "d" "mode\0" Required_argument "m" "seconds\0" Required_argument "s" "time\0" Required_argument "t" ; applet_long_options = rtcwake_longopts; #endif opt = getopt32(argv, "alud:m:s:t:", &rtcname, &suspend, &opt_seconds, &opt_time); /* this is the default if (opt & RTCWAKE_OPT_AUTO) utc = -1; */ if (opt & (RTCWAKE_OPT_UTC | RTCWAKE_OPT_LOCAL)) utc = opt & RTCWAKE_OPT_UTC; if (!(opt & RTCWAKE_OPT_SUSPEND_MODE)) suspend = DEFAULT_MODE; if (opt & RTCWAKE_OPT_SECONDS) /* alarm time, seconds-to-sleep (relative) */ seconds = xatoi(opt_seconds); if (opt & RTCWAKE_OPT_TIME) /* alarm time, time_t (absolute, seconds since 1/1 1970 UTC) */ alarm_time = xatol(opt_time); if (!alarm_time && !seconds) bb_error_msg_and_die("must provide wake time"); if (utc == -1) utc = rtc_adjtime_is_utc(); /* the rtcname is relative to /dev */ xchdir("/dev"); /* this RTC must exist and (if we'll sleep) be wakeup-enabled */ fd = rtc_xopen(&rtcname, O_RDONLY); if (strcmp(suspend, "on") && !may_wakeup(rtcname)) bb_error_msg_and_die("%s not enabled for wakeup events", rtcname); /* relative or absolute alarm time, normalized to time_t */ sys_time = time(NULL); { struct tm tm_time; rtc_read_tm(&tm_time, fd); rtc_time = rtc_tm2time(&tm_time, utc); } if (alarm_time) { if (alarm_time < sys_time) bb_error_msg_and_die("time doesn't go backward to %s", ctime(&alarm_time)); alarm_time += sys_time - rtc_time; } else alarm_time = rtc_time + seconds + 1; setup_alarm(fd, &alarm_time, rtc_time); sync(); printf("wakeup from \"%s\" at %s", suspend, ctime(&alarm_time)); fflush_all(); usleep(10 * 1000); if (strcmp(suspend, "on")) xopen_xwrite_close(SYS_POWER_PATH, suspend); else { /* "fake" suspend ... we'll do the delay ourselves */ unsigned long data; do { ssize_t ret = safe_read(fd, &data, sizeof(data)); if (ret < 0) { bb_perror_msg("rtc read"); break; } } while (!(data & RTC_AF)); } xioctl(fd, RTC_AIE_OFF, 0); if (ENABLE_FEATURE_CLEAN_UP) close(fd); return EXIT_SUCCESS; }
int rtcwake_main(int argc UNUSED_PARAM, char **argv) { unsigned opt; const char *rtcname = NULL; const char *suspend = "standby"; const char *opt_seconds; const char *opt_time; time_t rtc_time; time_t sys_time; time_t alarm_time = alarm_time; unsigned seconds = seconds; /* for compiler */ int utc = -1; int fd; #if ENABLE_LONG_OPTS static const char rtcwake_longopts[] ALIGN1 = "auto\0" No_argument "a" "local\0" No_argument "l" "utc\0" No_argument "u" "device\0" Required_argument "d" "mode\0" Required_argument "m" "seconds\0" Required_argument "s" "time\0" Required_argument "t" ; #endif opt = getopt32long(argv, /* Must have -s or -t, exclusive */ "^alud:m:s:t:" "\0" "s:t:s--t:t--s", rtcwake_longopts, &rtcname, &suspend, &opt_seconds, &opt_time); /* this is the default if (opt & RTCWAKE_OPT_AUTO) utc = -1; */ if (opt & (RTCWAKE_OPT_UTC | RTCWAKE_OPT_LOCAL)) utc = opt & RTCWAKE_OPT_UTC; if (opt & RTCWAKE_OPT_SECONDS) { /* alarm time, seconds-to-sleep (relative) */ seconds = xatou(opt_seconds); } else { /* RTCWAKE_OPT_TIME */ /* alarm time, time_t (absolute, seconds since 1/1 1970 UTC) */ if (sizeof(alarm_time) <= sizeof(long)) alarm_time = xatol(opt_time); else alarm_time = xatoll(opt_time); } if (utc == -1) utc = rtc_adjtime_is_utc(); /* the rtcname is relative to /dev */ xchdir("/dev"); /* this RTC must exist and (if we'll sleep) be wakeup-enabled */ fd = rtc_xopen(&rtcname, O_RDONLY); if (strcmp(suspend, "on") != 0) if (!may_wakeup(rtcname)) bb_error_msg_and_die("%s not enabled for wakeup events", rtcname); /* relative or absolute alarm time, normalized to time_t */ sys_time = time(NULL); { struct tm tm_time; rtc_read_tm(&tm_time, fd); rtc_time = rtc_tm2time(&tm_time, utc); } if (opt & RTCWAKE_OPT_TIME) { /* Correct for RTC<->system clock difference */ alarm_time += rtc_time - sys_time; if (alarm_time < rtc_time) /* * Compat message text. * I'd say "RTC time is already ahead of ..." instead. */ bb_error_msg_and_die("time doesn't go backward to %s", ctime(&alarm_time)); } else alarm_time = rtc_time + seconds + 1; setup_alarm(fd, &alarm_time, rtc_time); sync(); #if 0 /*debug*/ printf("sys_time: %s", ctime(&sys_time)); printf("rtc_time: %s", ctime(&rtc_time)); #endif printf("wakeup from \"%s\" at %s", suspend, ctime(&alarm_time)); fflush_all(); usleep(10 * 1000); if (strcmp(suspend, "on") != 0) xopen_xwrite_close(SYS_POWER_PATH, suspend); else { /* "fake" suspend ... we'll do the delay ourselves */ unsigned long data; do { ssize_t ret = safe_read(fd, &data, sizeof(data)); if (ret < 0) { bb_perror_msg("rtc read"); break; } } while (!(data & RTC_AF)); } xioctl(fd, RTC_AIE_OFF, 0); if (ENABLE_FEATURE_CLEAN_UP) close(fd); return EXIT_SUCCESS; }
int adjtimex_main(int argc UNUSED_PARAM, char **argv) { enum { OPT_quiet = 0x1 }; unsigned opt; char *opt_o, *opt_f, *opt_p, *opt_t; struct timex txc; int i, ret; const char *descript; opt_complementary = "=0"; /* no valid non-option parameters */ opt = getopt32(argv, "qo:f:p:t:", &opt_o, &opt_f, &opt_p, &opt_t); txc.modes = 0; //if (opt & 0x1) // -q if (opt & 0x2) { // -o txc.offset = xatol(opt_o); txc.modes |= ADJ_OFFSET_SINGLESHOT; } if (opt & 0x4) { // -f txc.freq = xatol(opt_f); txc.modes |= ADJ_FREQUENCY; } if (opt & 0x8) { // -p txc.constant = xatol(opt_p); txc.modes |= ADJ_TIMECONST; } if (opt & 0x10) { // -t txc.tick = xatol(opt_t); txc.modes |= ADJ_TICK; } ret = adjtimex(&txc); if (ret < 0) { bb_perror_nomsg_and_die(); } if (!(opt & OPT_quiet)) { int sep; const char *name; printf( " mode: %d\n" "-o offset: %ld\n" "-f frequency: %ld\n" " maxerror: %ld\n" " esterror: %ld\n" " status: %d (", txc.modes, txc.offset, txc.freq, txc.maxerror, txc.esterror, txc.status); /* representative output of next code fragment: "PLL | PPSTIME" */ name = statlist_name; sep = 0; for (i = 0; statlist_bit[i]; i++) { if (txc.status & statlist_bit[i]) { if (sep) fputs(" | ", stdout); fputs(name, stdout); sep = 1; } name += strlen(name) + 1; } descript = "error"; if (ret <= 5) descript = nth_string(ret_code_descript, ret); printf(")\n" "-p timeconstant: %ld\n" " precision: %ld\n" " tolerance: %ld\n" "-t tick: %ld\n" " time.tv_sec: %ld\n" " time.tv_usec: %ld\n" " return value: %d (%s)\n", txc.constant, txc.precision, txc.tolerance, txc.tick, (long)txc.time.tv_sec, (long)txc.time.tv_usec, ret, descript); } return 0; }
int adjtimex_main(int argc UNUSED_PARAM, char **argv) { enum { OPT_quiet = 0x1 }; unsigned opt; char *opt_o, *opt_f, *opt_p, *opt_t; struct timex txc; int ret; const char *descript; memset(&txc, 0, sizeof(txc)); opt = getopt32(argv, "^" "qo:f:p:t:" "\0" "=0"/*no valid non-option args*/, &opt_o, &opt_f, &opt_p, &opt_t ); //if (opt & 0x1) // -q if (opt & 0x2) { // -o txc.offset = xatol(opt_o); txc.modes |= ADJ_OFFSET_SINGLESHOT; } if (opt & 0x4) { // -f txc.freq = xatol(opt_f); txc.modes |= ADJ_FREQUENCY; } if (opt & 0x8) { // -p txc.constant = xatol(opt_p); txc.modes |= ADJ_TIMECONST; } if (opt & 0x10) { // -t txc.tick = xatol(opt_t); txc.modes |= ADJ_TICK; } /* It's NOFORK applet because the code is very simple: * just some printf. No opens, no allocs. * If you need to make it more complex, feel free to downgrade to NOEXEC */ ret = adjtimex(&txc); if (ret < 0) bb_perror_nomsg_and_die(); if (!(opt & OPT_quiet)) { const char *sep; const char *name; int i; printf( " mode: %d\n" "-o offset: %ld us\n" "-f freq.adjust: %ld (65536 = 1ppm)\n" " maxerror: %ld\n" " esterror: %ld\n" " status: %d (", txc.modes, txc.offset, txc.freq, txc.maxerror, txc.esterror, txc.status ); /* representative output of next code fragment: * "PLL | PPSTIME" */ name = statlist_name; sep = ""; for (i = 0; statlist_bit[i]; i++) { if (txc.status & statlist_bit[i]) { printf("%s%s", sep, name); sep = " | "; } name += strlen(name) + 1; } descript = "error"; if (ret <= 5) descript = nth_string(ret_code_descript, ret); printf(")\n" "-p timeconstant: %ld\n" " precision: %ld us\n" " tolerance: %ld\n" "-t tick: %ld us\n" " time.tv_sec: %ld\n" " time.tv_usec: %ld\n" " return value: %d (%s)\n", txc.constant, txc.precision, txc.tolerance, txc.tick, (long)txc.time.tv_sec, (long)txc.time.tv_usec, ret, descript ); } return 0; }
int adjtimex_main(int argc, char **argv) { enum { OPT_quiet = 0x1 }; unsigned opt; char *opt_o, *opt_f, *opt_p, *opt_t; struct timex txc; int i, ret, sep; const char *descript; txc.modes=0; opt = getopt32(argv, "qo:f:p:t:", &opt_o, &opt_f, &opt_p, &opt_t); //if (opt & 0x1) // -q if (opt & 0x2) { // -o txc.offset = xatol(opt_o); txc.modes |= ADJ_OFFSET_SINGLESHOT; } if (opt & 0x4) { // -f txc.freq = xatol(opt_f); txc.modes |= ADJ_FREQUENCY; } if (opt & 0x8) { // -p txc.constant = xatol(opt_p); txc.modes |= ADJ_TIMECONST; } if (opt & 0x10) { // -t txc.tick = xatol(opt_t); txc.modes |= ADJ_TICK; } if (argc != optind) { /* no valid non-option parameters */ bb_show_usage(); } ret = adjtimex(&txc); if (ret < 0) perror("adjtimex"); if (!(opt & OPT_quiet) && ret>=0) { printf( " mode: %d\n" "-o offset: %ld\n" "-f frequency: %ld\n" " maxerror: %ld\n" " esterror: %ld\n" " status: %d ( ", txc.modes, txc.offset, txc.freq, txc.maxerror, txc.esterror, txc.status); /* representative output of next code fragment: "PLL | PPSTIME" */ sep=0; for (i=0; statlist[i].name; i++) { if (txc.status & statlist[i].bit) { if (sep) fputs(" | ",stdout); fputs(statlist[i].name,stdout); sep=1; } } descript = "error"; if (ret >= 0 && ret <= 5) descript = ret_code_descript[ret]; printf(" )\n" "-p timeconstant: %ld\n" " precision: %ld\n" " tolerance: %ld\n" "-t tick: %ld\n" " time.tv_sec: %ld\n" " time.tv_usec: %ld\n" " return value: %d (%s)\n", txc.constant, txc.precision, txc.tolerance, txc.tick, (long)txc.time.tv_sec, (long)txc.time.tv_usec, ret, descript); } return (ret<0); }