void bb_debug_dump_packet(unsigned char *outpack, int pktsize) { int i; printf("packet dump:\n"); for (i = 0; i < pktsize; ++i) { printf("%2.2x ", outpack[i]); if (i % 20 == 19) bb_putchar('\n'); } printf("\n\n"); }
int getsebool_main(int argc, char **argv) { int i, rc = 0, active, pending, len = 0; char **names; unsigned opt; selinux_or_die(); opt = getopt32(argv, "a"); if (opt) { /* -a */ if (argc > 2) bb_show_usage(); rc = security_get_boolean_names(&names, &len); if (rc) bb_perror_msg_and_die("can't get boolean names"); if (!len) { puts("No booleans"); return 0; } } if (!len) { if (argc < 2) bb_show_usage(); len = argc - 1; names = xmalloc(sizeof(char *) * len); for (i = 0; i < len; i++) names[i] = xstrdup(argv[i + 1]); } for (i = 0; i < len; i++) { active = security_get_boolean_active(names[i]); if (active < 0) { bb_error_msg_and_die("error getting active value for %s", names[i]); } pending = security_get_boolean_pending(names[i]); if (pending < 0) { bb_error_msg_and_die("error getting pending value for %s", names[i]); } printf("%s --> %s", names[i], (active ? "on" : "off")); if (pending != active) printf(" pending: %s", (pending ? "on" : "off")); bb_putchar('\n'); } if (ENABLE_FEATURE_CLEAN_UP) { for (i = 0; i < len; i++) free(names[i]); free(names); } return rc; }
static void display_recoverable(const struct termios *mode, int UNUSED_PARAM dummy) { int i; printf("%lx:%lx:%lx:%lx", (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag, (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag); for (i = 0; i < NCCS; ++i) printf(":%x", (unsigned int) mode->c_cc[i]); bb_putchar('\n'); }
int mountpoint_main(int argc, char **argv) { struct stat st; char *arg; int opt = getopt32(argv, "qdx"); #define OPT_q (1) #define OPT_d (2) #define OPT_x (4) if (optind != argc - 1) bb_show_usage(); arg = argv[optind]; if ( (opt & OPT_x && stat(arg, &st) == 0) || (lstat(arg, &st) == 0) ) { if (opt & OPT_x) { if (S_ISBLK(st.st_mode)) { printf("%u:%u\n", major(st.st_rdev), minor(st.st_rdev)); return EXIT_SUCCESS; } else { if (opt & OPT_q) bb_putchar('\n'); else bb_error_msg("%s: not a block device", arg); } return EXIT_FAILURE; } else if (S_ISDIR(st.st_mode)) { dev_t st_dev = st.st_dev; ino_t st_ino = st.st_ino; char *p = xasprintf("%s/..", arg); if (stat(p, &st) == 0) { int ret = (st_dev != st.st_dev) || (st_dev == st.st_dev && st_ino == st.st_ino); if (opt & OPT_d) printf("%u:%u\n", major(st_dev), minor(st_dev)); else if (!(opt & OPT_q)) printf("%s is %sa mountpoint\n", arg, ret?"":"not "); return !ret; } } else { if (!(opt & OPT_q)) bb_error_msg("%s: not a directory", arg); return EXIT_FAILURE; } } if (!(opt & OPT_q)) bb_simple_perror_msg(arg); return EXIT_FAILURE; }
int dmesg_main(int argc, char **argv) { char *size, *level; int flags = getopt32(argv, "cs:n:", &size, &level); if (flags & 4) { if (klogctl(8, NULL, xatoul_range(level, 0, 10))) bb_perror_msg_and_die("klogctl"); } else { int len; char *buf; len = (flags & 2) ? xatoul_range(size, 2, INT_MAX) : 16384; buf = xmalloc(len); if (0 > (len = klogctl(3 + (flags & 1), buf, len))) bb_perror_msg_and_die("klogctl"); // Skip <#> at the start of lines, and make sure we end with a newline. if (ENABLE_FEATURE_DMESG_PRETTY) { int last = '\n'; int in; for (in = 0; in<len;) { if (last == '\n' && buf[in] == '<') in += 3; else bb_putchar(last = buf[in++]); } if (last != '\n') bb_putchar('\n'); } else { write(1,buf,len); if (len && buf[len-1]!='\n') bb_putchar('\n'); } if (ENABLE_FEATURE_CLEAN_UP) free(buf); } return 0; }
static int fuser_print_pid_list(pid_list *plist) { pid_list *curr = plist; if (plist == NULL) return 0; while (curr != NULL) { if (curr->pid > 0) printf("%d ", curr->pid); curr = curr->next; } bb_putchar('\n'); return 1; }
static void regex_process(void) { char *uncomp_regex, *err; /* Reset variables */ free(match_lines); match_lines = NULL; match_pos = 0; num_matches = 0; if (pattern_valid) { regfree(&pattern); pattern_valid = 0; } /* Get the uncompiled regular expression from the user */ clear_line(); bb_putchar((option_mask32 & LESS_STATE_MATCH_BACKWARDS) ? '?' : '/'); uncomp_regex = less_gets(1); if (!uncomp_regex[0]) { free(uncomp_regex); buffer_print(); return; } /* Compile the regex and check for errors */ err = regcomp_or_errmsg(&pattern, uncomp_regex, (option_mask32 & FLAG_I) ? REG_ICASE : 0); free(uncomp_regex); if (err) { print_statusline(err); free(err); return; } pattern_valid = 1; match_pos = 0; fill_match_lines(0); while (match_pos < num_matches) { if ((int)match_lines[match_pos] > cur_fline) break; match_pos++; } if (option_mask32 & LESS_STATE_MATCH_BACKWARDS) match_pos--; /* It's possible that no matches are found yet. * goto_match() will read input looking for match, * if needed */ goto_match(match_pos); }
static void cleanup(int code) { set_cursor(-1); // cursor on tcsetattr(G.kbd_fd, TCSANOW, &G.term_orig); if (ENABLE_FEATURE_CLEAN_UP) { close(G.kbd_fd); } // Reset attributes if (!BW) fputs("\033[0m", stdout); bb_putchar('\n'); if (code > 1) kill_myself_with_sig(code); exit(code); }
static void cleanup(int code) { set_cursor(CURSOR_ON); tcsetattr(G.kbd_fd, TCSANOW, &G.term_orig); if (ENABLE_FEATURE_CLEAN_UP) { close(G.kbd_fd); } // Reset attributes if (!BW) putcsi("0m"); bb_putchar('\n'); if (code > EXIT_FAILURE) kill_myself_with_sig(code); exit(code); }
/* lookup the default nameserver and display it */ static void server_print(void) { char *server; server = xmalloc_sockaddr2dotted_noport((struct sockaddr*)&_res.nsaddr_list[0]); /* I honestly don't know what to do if DNS server has _IPv6 address_. * Probably it is listed in * _res._u._ext_.nsaddrs[MAXNS] (of type "struct sockaddr_in6*" each) * but how to find out whether resolver uses * _res.nsaddr_list[] or _res._u._ext_.nsaddrs[], or both? * Looks like classic design from hell, BIND-grade. Hard to surpass. */ print_host(server, "Server:"); if (ENABLE_FEATURE_CLEAN_UP) free(server); bb_putchar('\n'); }
/* lookup the default nameserver and display it */ static void server_print(void) { char *server; struct sockaddr *sa; #if ENABLE_FEATURE_IPV6 sa = (struct sockaddr*)_res._u._ext.nsaddrs[0]; if (!sa) #endif sa = (struct sockaddr*)&_res.nsaddr_list[0]; server = xmalloc_sockaddr2dotted_noport(sa); print_host(server, "Server:"); if (ENABLE_FEATURE_CLEAN_UP) free(server); bb_putchar('\n'); }
static void print_sem(int semid) { struct semid_ds semds; struct ipc_perm *ipcp = &semds.sem_perm; union semun arg; unsigned int i; arg.buf = &semds; if (semctl(semid, 0, IPC_STAT, arg)) { bb_perror_msg("semctl"); return; } printf("\nSemaphore Array semid=%d\n" "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n" "mode=%#o, access_perms=%#o\n" "nsems = %ld\n" "otime = %-26.24s\n", semid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode, ipcp->mode & 0777, (long) semds.sem_nsems, semds.sem_otime ? ctime(&semds.sem_otime) : "Not set"); printf("ctime = %-26.24s\n" "%-10s %-10s %-10s %-10s %-10s\n", ctime(&semds.sem_ctime), "semnum", "value", "ncount", "zcount", "pid"); arg.val = 0; for (i = 0; i < semds.sem_nsems; i++) { int val, ncnt, zcnt, pid; val = semctl(semid, i, GETVAL, arg); ncnt = semctl(semid, i, GETNCNT, arg); zcnt = semctl(semid, i, GETZCNT, arg); pid = semctl(semid, i, GETPID, arg); if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) { bb_perror_msg_and_die("semctl"); } printf("%-10d %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid); } bb_putchar('\n'); }
static void flag_change(void) { int keypress; clear_line(); bb_putchar('-'); keypress = less_getch(1); switch (keypress) { case 'M': option_mask32 ^= FLAG_M; break; case 'm': option_mask32 ^= FLAG_m; break; case 'E': option_mask32 ^= FLAG_E; break; case '~': option_mask32 ^= FLAG_TILDE; break; } }
static void bsd_select(void) { #if !defined(__alpha__) int t, ss; struct partition *p; for (t = 0; t < 4; t++) { p = get_part_table(t); if (p && is_bsd_partition_type(p->sys_ind)) { xbsd_part = p; xbsd_part_index = t; ss = get_start_sect(xbsd_part); if (ss == 0) { printf("Partition %s has invalid starting sector 0\n", partname(disk_device, t+1, 0)); return; } printf("Reading disklabel of %s at sector %u\n", partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR); if (xbsd_readlabel(xbsd_part) == 0) { if (xbsd_create_disklabel() == 0) return; break; } } } if (t == 4) { printf("There is no *BSD partition on %s\n", disk_device); return; } #elif defined(__alpha__) if (xbsd_readlabel(NULL) == 0) if (xbsd_create_disklabel() == 0) exit(EXIT_SUCCESS); #endif while (1) { bb_putchar('\n'); switch (tolower(read_nonempty("BSD disklabel command (m for help): "))) { case 'd': xbsd_delete_part(); break; case 'e': xbsd_edit_disklabel(); break; case 'i': xbsd_write_bootstrap(); break; case 'l': xbsd_list_types(); break; case 'n': xbsd_new_part(); break; case 'p': xbsd_print_disklabel(0); break; case 'q': if (ENABLE_FEATURE_CLEAN_UP) close_dev_fd(); exit(EXIT_SUCCESS); case 'r': return; case 's': xbsd_print_disklabel(1); break; case 't': xbsd_change_fstype(); break; case 'u': change_units(); break; case 'w': xbsd_write_disklabel(); break; #if !defined(__alpha__) case 'x': xbsd_link_part(); break; #endif default: bsd_menu(); break; } } }
static void summarize(const char *fmt, char **command, resource_t *resp) { unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ unsigned cpu_ticks; /* Same, in "CPU ticks" */ unsigned pagesize = getpagesize(); /* Impossible: we do not use WUNTRACED flag in wait()... if (WIFSTOPPED(resp->waitstatus)) printf("Command stopped by signal %u\n", WSTOPSIG(resp->waitstatus)); else */ if (WIFSIGNALED(resp->waitstatus)) printf("Command terminated by signal %u\n", WTERMSIG(resp->waitstatus)); else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus)) printf("Command exited with non-zero status %u\n", WEXITSTATUS(resp->waitstatus)); vv_ms = (resp->ru.ru_utime.tv_sec + resp->ru.ru_stime.tv_sec) * 1000 + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000; #if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000 /* 1000 is exactly divisible by TICKS_PER_SEC (typical) */ cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC); #else cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000; #endif if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */ while (*fmt) { /* Handle leading literal part */ int n = strcspn(fmt, "%\\"); if (n) { printf("%.*s", n, fmt); fmt += n; continue; } switch (*fmt) { #ifdef NOT_NEEDED /* Handle literal char */ /* Usually we optimize for size, but there is a limit * for everything. With this we do a lot of 1-byte writes */ default: bb_putchar(*fmt); break; #endif case '%': switch (*++fmt) { #ifdef NOT_NEEDED_YET /* Our format strings do not have these */ /* and we do not take format str from user */ default: bb_putchar('%'); /*FALLTHROUGH*/ case '%': if (!*fmt) goto ret; bb_putchar(*fmt); break; #endif case 'C': /* The command that got timed. */ printargv(command); break; case 'D': /* Average unshared data size. */ printf("%lu", (ptok(pagesize, (UL) resp->ru.ru_idrss) + ptok(pagesize, (UL) resp->ru.ru_isrss)) / cpu_ticks); break; case 'E': { /* Elapsed real (wall clock) time. */ unsigned seconds = resp->elapsed_ms / 1000; if (seconds >= 3600) /* One hour -> h:m:s. */ printf("%uh %um %02us", seconds / 3600, (seconds % 3600) / 60, seconds % 60); else printf("%um %u.%02us", /* -> m:s. */ seconds / 60, seconds % 60, (unsigned)(resp->elapsed_ms / 10) % 100); break; } case 'F': /* Major page faults. */ printf("%lu", resp->ru.ru_majflt); break; case 'I': /* Inputs. */ printf("%lu", resp->ru.ru_inblock); break; case 'K': /* Average mem usage == data+stack+text. */ printf("%lu", (ptok(pagesize, (UL) resp->ru.ru_idrss) + ptok(pagesize, (UL) resp->ru.ru_isrss) + ptok(pagesize, (UL) resp->ru.ru_ixrss)) / cpu_ticks); break; case 'M': /* Maximum resident set size. */ printf("%lu", ptok(pagesize, (UL) resp->ru.ru_maxrss)); break; case 'O': /* Outputs. */ printf("%lu", resp->ru.ru_oublock); break; case 'P': /* Percent of CPU this job got. */ /* % cpu is (total cpu time)/(elapsed time). */ if (resp->elapsed_ms > 0) printf("%u%%", (unsigned)(vv_ms * 100 / resp->elapsed_ms)); else printf("?%%"); break; case 'R': /* Minor page faults (reclaims). */ printf("%lu", resp->ru.ru_minflt); break; case 'S': /* System time. */ printf("%u.%02u", (unsigned)resp->ru.ru_stime.tv_sec, (unsigned)(resp->ru.ru_stime.tv_usec / 10000)); break; case 'T': /* System time. */ if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */ printf("%uh %um %02us", (unsigned)(resp->ru.ru_stime.tv_sec / 3600), (unsigned)(resp->ru.ru_stime.tv_sec % 3600) / 60, (unsigned)(resp->ru.ru_stime.tv_sec % 60)); else printf("%um %u.%02us", /* -> m:s. */ (unsigned)(resp->ru.ru_stime.tv_sec / 60), (unsigned)(resp->ru.ru_stime.tv_sec % 60), (unsigned)(resp->ru.ru_stime.tv_usec / 10000)); break; case 'U': /* User time. */ printf("%u.%02u", (unsigned)resp->ru.ru_utime.tv_sec, (unsigned)(resp->ru.ru_utime.tv_usec / 10000)); break; case 'u': /* User time. */ if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */ printf("%uh %um %02us", (unsigned)(resp->ru.ru_utime.tv_sec / 3600), (unsigned)(resp->ru.ru_utime.tv_sec % 3600) / 60, (unsigned)(resp->ru.ru_utime.tv_sec % 60)); else printf("%um %u.%02us", /* -> m:s. */ (unsigned)(resp->ru.ru_utime.tv_sec / 60), (unsigned)(resp->ru.ru_utime.tv_sec % 60), (unsigned)(resp->ru.ru_utime.tv_usec / 10000)); break; case 'W': /* Times swapped out. */ printf("%lu", resp->ru.ru_nswap); break; case 'X': /* Average shared text size. */ printf("%lu", ptok(pagesize, (UL) resp->ru.ru_ixrss) / cpu_ticks); break; case 'Z': /* Page size. */ printf("%u", pagesize); break; case 'c': /* Involuntary context switches. */ printf("%lu", resp->ru.ru_nivcsw); break; case 'e': /* Elapsed real time in seconds. */ printf("%u.%02u", (unsigned)resp->elapsed_ms / 1000, (unsigned)(resp->elapsed_ms / 10) % 100); break; case 'k': /* Signals delivered. */ printf("%lu", resp->ru.ru_nsignals); break; case 'p': /* Average stack segment. */ printf("%lu", ptok(pagesize, (UL) resp->ru.ru_isrss) / cpu_ticks); break; case 'r': /* Incoming socket messages received. */ printf("%lu", resp->ru.ru_msgrcv); break; case 's': /* Outgoing socket messages sent. */ printf("%lu", resp->ru.ru_msgsnd); break; case 't': /* Average resident set size. */ printf("%lu", ptok(pagesize, (UL) resp->ru.ru_idrss) / cpu_ticks); break; case 'w': /* Voluntary context switches. */ printf("%lu", resp->ru.ru_nvcsw); break; case 'x': /* Exit status. */ printf("%u", WEXITSTATUS(resp->waitstatus)); break; } break; #ifdef NOT_NEEDED_YET case '\\': /* Format escape. */ switch (*++fmt) { default: bb_putchar('\\'); /*FALLTHROUGH*/ case '\\': if (!*fmt) goto ret; bb_putchar(*fmt); break; case 't': bb_putchar('\t'); break; case 'n': bb_putchar('\n'); break; } break; #endif } ++fmt; } /* ret: */ bb_putchar('\n'); }
static void progress_newline(void) { if (!option_mask32) //if (!(option_mask32 & OPT_v)) return; bb_putchar('\n'); }
int fuser_main(int argc UNUSED_PARAM, char **argv) { // changed for ofgwrite applet_name = argv[0]; char **pp; INIT_G(); /* Handle -SIGNAL. Oh my... */ pp = argv; while (*++pp) { int sig; 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" */ sig = get_signum(&arg[1]); if (sig < 0) continue; /* "-SIGNAL" option found. Remove it and bail out */ G.killsig = sig; do { pp[0] = arg = pp[1]; pp++; } while (arg); break; } opt_complementary = "-1"; /* at least one param */ getopt32(argv, OPTION_STRING); argv += optind; pp = argv; while (*pp) { /* parse net arg */ unsigned port; char path[sizeof("/proc/net/TCP6")]; strcpy(path, "/proc/net/"); if (sscanf(*pp, "%u/%4s", &port, path + sizeof("/proc/net/")-1) == 2 && access(path, R_OK) == 0 ) { /* PORT/PROTO */ scan_proc_net_or_maps(path, port); } else { /* FILE */ struct stat statbuf; xstat(*pp, &statbuf); add_inode(&statbuf); } pp++; } if (scan_recursive("/proc")) { if (!(option_mask32 & OPT_SILENT)) bb_putchar('\n'); return G.kill_failed; } return EXIT_FAILURE; }
int seq_main(int argc, char **argv) { enum { OPT_w = (1 << 0), OPT_s = (1 << 1), }; double first, last, increment, v; unsigned n; unsigned width; unsigned frac_part; const char *sep, *opt_s = "\n"; unsigned opt; #if ENABLE_LOCALE_SUPPORT /* Undo busybox.c: on input, we want to use dot * as fractional separator, regardless of current locale */ setlocale(LC_NUMERIC, "C"); #endif opt = getopt32(argv, "+ws:", &opt_s); argc -= optind; argv += optind; first = increment = 1; errno = 0; switch (argc) { char *pp; case 3: increment = strtod(argv[1], &pp); errno |= *pp; case 2: first = strtod(argv[0], &pp); errno |= *pp; case 1: last = strtod(argv[argc-1], &pp); if (!errno && *pp == '\0') break; default: bb_show_usage(); } #if ENABLE_LOCALE_SUPPORT setlocale(LC_NUMERIC, ""); #endif /* Last checked to be compatible with: coreutils-6.10 */ width = 0; frac_part = 0; while (1) { char *dot = strchrnul(*argv, '.'); int w = (dot - *argv); int f = strlen(dot); if (width < w) width = w; argv++; if (!*argv) break; /* Why do the above _before_ frac check below? * Try "seq 1 2.0" and "seq 1.0 2.0": * coreutils never pay attention to the number * of fractional digits in last arg. */ if (frac_part < f) frac_part = f; } if (frac_part) { frac_part--; if (frac_part) width += frac_part + 1; } if (!(opt & OPT_w)) width = 0; sep = ""; v = first; n = 0; while (increment >= 0 ? v <= last : v >= last) { if (printf("%s%0*.*f", sep, width, frac_part, v) < 0) break; /* I/O error, bail out (yes, this really happens) */ sep = opt_s; /* v += increment; - would accumulate floating point errors */ n++; v = first + n * increment; } if (n) /* if while loop executed at least once */ bb_putchar('\n'); return fflush_all(); }
/* Dump all but word data. */ static void dump_data(int bus_fd, int mode, unsigned first, unsigned last, int *block, int blen) { int i, j, res; puts(" 0 1 2 3 4 5 6 7 8 9 a b c d e f" " 0123456789abcdef"); for (i = 0; i < I2CDUMP_NUM_REGS; i += 0x10) { if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen) break; if (i/16 < first/16) continue; if (i/16 > last/16) break; printf("%02x: ", i); for (j = 0; j < 16; j++) { fflush_all(); /* Skip unwanted registers */ if (i+j < first || i+j > last) { printf(" "); if (mode == I2C_SMBUS_WORD_DATA) { printf(" "); j++; } continue; } switch (mode) { case I2C_SMBUS_BYTE_DATA: res = i2c_smbus_read_byte_data(bus_fd, i+j); block[i+j] = res; break; case I2C_SMBUS_WORD_DATA: res = i2c_smbus_read_word_data(bus_fd, i+j); if (res < 0) { block[i+j] = res; block[i+j+1] = res; } else { block[i+j] = res & 0xff; block[i+j+1] = res >> 8; } break; case I2C_SMBUS_BYTE: res = i2c_smbus_read_byte(bus_fd); block[i+j] = res; break; default: res = block[i+j]; } if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen) { printf(" "); } else if (res < 0) { printf("XX "); if (mode == I2C_SMBUS_WORD_DATA) printf("XX "); } else { printf("%02x ", block[i+j]); if (mode == I2C_SMBUS_WORD_DATA) printf("%02x ", block[i+j+1]); } if (mode == I2C_SMBUS_WORD_DATA) j++; } printf(" "); for (j = 0; j < 16; j++) { if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen) break; /* Skip unwanted registers */ if (i+j < first || i+j > last) { bb_putchar(' '); continue; } res = block[i+j]; if (res < 0) { bb_putchar('X'); } else if (res == 0x00 || res == 0xff) { bb_putchar('.'); } else if (res < 32 || res >= 127) { bb_putchar('?'); } else { bb_putchar(res); } } bb_putchar('\n'); } }
static void xbsd_print_disklabel(int show_all) { struct xbsd_disklabel *lp = &xbsd_dlabel; struct xbsd_partition *pp; int i, j; if (show_all) { static const int d_masks[] = { BSD_D_REMOVABLE, BSD_D_ECC, BSD_D_BADSECT }; #if defined(__alpha__) printf("# %s:\n", disk_device); #else printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0)); #endif if ((unsigned) lp->d_type < ARRAY_SIZE(xbsd_dktypenames)-1) printf("type: %s\n", xbsd_dktypenames[lp->d_type]); else printf("type: %u\n", lp->d_type); printf("disk: %.*s\n", (int) sizeof(lp->d_typename), lp->d_typename); printf("label: %.*s\n", (int) sizeof(lp->d_packname), lp->d_packname); printf("flags: "); print_flags_separated(d_masks, "removable\0""ecc\0""badsect\0", lp->d_flags, " "); bb_putchar('\n'); /* On various machines the fields of *lp are short/int/long */ /* In order to avoid problems, we cast them all to long. */ printf("bytes/sector: %lu\n", (long) lp->d_secsize); printf("sectors/track: %lu\n", (long) lp->d_nsectors); printf("tracks/cylinder: %lu\n", (long) lp->d_ntracks); printf("sectors/cylinder: %lu\n", (long) lp->d_secpercyl); printf("cylinders: %lu\n", (long) lp->d_ncylinders); printf("rpm: %u\n", lp->d_rpm); printf("interleave: %u\n", lp->d_interleave); printf("trackskew: %u\n", lp->d_trackskew); printf("cylinderskew: %u\n", lp->d_cylskew); printf("headswitch: %lu\t\t# milliseconds\n", (long) lp->d_headswitch); printf("track-to-track seek: %lu\t# milliseconds\n", (long) lp->d_trkseek); printf("drivedata: "); for (i = NDDATA - 1; i >= 0; i--) if (lp->d_drivedata[i]) break; if (i < 0) i = 0; for (j = 0; j <= i; j++) printf("%lu ", (long) lp->d_drivedata[j]); } printf("\n%u partitions:\n", lp->d_npartitions); printf("# start end size fstype [fsize bsize cpg]\n"); pp = lp->d_partitions; for (i = 0; i < lp->d_npartitions; i++, pp++) { if (pp->p_size) { if (display_in_cyl_units && lp->d_secpercyl) { printf(" %c: %8lu%c %8lu%c %8lu%c ", 'a' + i, (unsigned long) pp->p_offset / lp->d_secpercyl + 1, (pp->p_offset % lp->d_secpercyl) ? '*' : ' ', (unsigned long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl, ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ', (long) pp->p_size / lp->d_secpercyl, (pp->p_size % lp->d_secpercyl) ? '*' : ' ' ); } else { printf(" %c: %8lu %8lu %8lu ", 'a' + i, (long) pp->p_offset, (long) pp->p_offset + pp->p_size - 1, (long) pp->p_size ); } if ((unsigned) pp->p_fstype < ARRAY_SIZE(xbsd_fstypes)-1) printf("%8.8s", xbsd_fstypes[pp->p_fstype]); else printf("%8x", pp->p_fstype); switch (pp->p_fstype) { case BSD_FS_UNUSED: printf(" %5lu %5lu %5.5s ", (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, ""); break; case BSD_FS_BSDFFS: printf(" %5lu %5lu %5u ", (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg); break; default: printf("%22.22s", ""); break; } bb_putchar('\n'); } } }
int brctl_main(int argc UNUSED_PARAM, char **argv) { static const char keywords[] ALIGN1 = "addbr\0" "delbr\0" "addif\0" "delif\0" IF_FEATURE_BRCTL_FANCY( "stp\0" "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" "setpathcost\0" "setportprio\0" "setbridgeprio\0" ) IF_FEATURE_BRCTL_SHOW("show\0"); enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif IF_FEATURE_BRCTL_FANCY(, ARG_stp, ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio ) IF_FEATURE_BRCTL_SHOW(, 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_to, *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); puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces"); 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_IFNAMSIZ(ifr.ifr_name, brname); 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("%02x", 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 'addbr/delbr' need at least two arguments */ bb_show_usage(); strncpy_IFNAMSIZ(ifr.ifr_name, br); 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 */ static const char no_yes[] ALIGN1 = "0\0" "off\0" "n\0" "no\0" /* 0 .. 3 */ "1\0" "on\0" "y\0" "yes\0"; /* 4 .. 7 */ int onoff = index_in_strings(no_yes, *argv); if (onoff < 0) bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); onoff = (unsigned)onoff / 4; arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 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_to, *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_positive(*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; }
static void number_process(int first_digit) { unsigned i; int num; int keypress; char num_input[sizeof(int)*4]; /* more than enough */ num_input[0] = first_digit; /* Clear the current line, print a prompt, and then print the digit */ clear_line(); printf(":%c", first_digit); /* Receive input until a letter is given */ i = 1; while (i < sizeof(num_input)-1) { keypress = less_getch(i + 1); if ((unsigned)keypress > 255 || !isdigit(num_input[i])) break; num_input[i] = keypress; bb_putchar(keypress); i++; } num_input[i] = '\0'; num = bb_strtou(num_input, NULL, 10); /* on format error, num == -1 */ if (num < 1 || num > MAXLINES) { buffer_print(); return; } /* We now know the number and the letter entered, so we process them */ switch (keypress) { case KEYCODE_DOWN: case 'z': case 'd': case 'e': case ' ': case '\015': buffer_down(num); break; case KEYCODE_UP: case 'b': case 'w': case 'y': case 'u': buffer_up(num); break; case 'g': case '<': case 'G': case '>': cur_fline = num + max_displayed_line; read_lines(); buffer_line(num - 1); break; case 'p': case '%': num = num * (max_fline / 100); /* + max_fline / 2; */ cur_fline = num + max_displayed_line; read_lines(); buffer_line(num); break; #if ENABLE_FEATURE_LESS_REGEXP case 'n': goto_match(match_pos + num); break; case '/': option_mask32 &= ~LESS_STATE_MATCH_BACKWARDS; regex_process(); break; case '?': option_mask32 |= LESS_STATE_MATCH_BACKWARDS; regex_process(); break; #endif } }
int tunctl_main(int argc UNUSED_PARAM, char **argv) { struct ifreq ifr; int fd; const char *opt_name = "tap%d"; const char *opt_device = "/dev/net/tun"; #if ENABLE_FEATURE_TUNCTL_UG const char *opt_user, *opt_group; long user = -1, group = -1; #endif unsigned opts; enum { OPT_f = 1 << 0, // control device name (/dev/net/tun) OPT_t = 1 << 1, // create named interface OPT_d = 1 << 2, // delete named interface #if ENABLE_FEATURE_TUNCTL_UG OPT_u = 1 << 3, // set new interface owner OPT_g = 1 << 4, // set new interface group OPT_b = 1 << 5, // brief output #endif }; opt_complementary = "=0:t--d:d--t"; // no arguments; t ^ d opts = getopt32(argv, "f:t:d:" IF_FEATURE_TUNCTL_UG("u:g:b"), &opt_device, &opt_name, &opt_name IF_FEATURE_TUNCTL_UG(, &opt_user, &opt_group)); // select device memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strncpy_IFNAMSIZ(ifr.ifr_name, opt_name); // open device fd = xopen(opt_device, O_RDWR); IOCTL(fd, TUNSETIFF, (void *)&ifr); // delete? if (opts & OPT_d) { IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0); printf("Set '%s' nonpersistent\n", ifr.ifr_name); return EXIT_SUCCESS; } // create #if ENABLE_FEATURE_TUNCTL_UG if (opts & OPT_g) { group = xgroup2gid(opt_group); IOCTL(fd, TUNSETGROUP, (void *)(uintptr_t)group); } else user = geteuid(); if (opts & OPT_u) user = xuname2uid(opt_user); IOCTL(fd, TUNSETOWNER, (void *)(uintptr_t)user); #endif IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)1); // show info #if ENABLE_FEATURE_TUNCTL_UG if (opts & OPT_b) { puts(ifr.ifr_name); } else { printf("Set '%s' %spersistent", ifr.ifr_name, ""); printf(" and owned by uid %ld", user); if (group != -1) printf(" gid %ld", group); bb_putchar('\n'); } #else puts(ifr.ifr_name); #endif return EXIT_SUCCESS; }
int uname_main(int argc UNUSED_PARAM, char **argv) { #if ENABLE_LONG_OPTS static const char uname_longopts[] ALIGN1 = /* name, has_arg, val */ "all\0" No_argument "a" "kernel-name\0" No_argument "s" "nodename\0" No_argument "n" "kernel-release\0" No_argument "r" "release\0" No_argument "r" "kernel-version\0" No_argument "v" "machine\0" No_argument "m" "processor\0" No_argument "p" "hardware-platform\0" No_argument "i" "operating-system\0" No_argument "o" #ifdef MY_ABC_HERE "synology-unique\0" No_argument "u" #endif ; #endif uname_info_t uname_info; #if defined(__sparc__) && defined(__linux__) char *fake_sparc = getenv("FAKE_SPARC"); #endif const char *unknown_str = "unknown"; const char *fmt; const unsigned short *delta; unsigned toprint; IF_LONG_OPTS(applet_long_options = uname_longopts); toprint = getopt32(argv, options); if (argv[optind]) { /* coreutils-6.9 compat */ bb_show_usage(); } if (toprint & (1 << OPT_ALL_BIT)) { /* -a => all opts on */ toprint = (1 << OPT_ALL_BIT) - 1; unknown_str = ""; /* -a does not print unknown fields */ } if (toprint == 0) { /* no opts => -s (sysname) */ toprint = 1; } uname(&uname_info.name); /* never fails */ #if defined(__sparc__) && defined(__linux__) if (fake_sparc && (fake_sparc[0] | 0x20) == 'y') { strcpy(uname_info.name.machine, "sparc"); } #endif strcpy(uname_info.processor, unknown_str); strcpy(uname_info.platform, unknown_str); strcpy(uname_info.os, "GNU/Linux"); #ifdef MY_ABC_HERE if (1 != GetKeyValue("/etc.defaults/synoinfo.conf", "unique", uname_info.unique, sizeof(uname_info.unique))) { strcpy(uname_info.unique, unknown_str); } #endif #if 0 /* Fedora does something like this */ strcpy(uname_info.processor, uname_info.name.machine); strcpy(uname_info.platform, uname_info.name.machine); if (uname_info.platform[0] == 'i' && uname_info.platform[1] && uname_info.platform[2] == '8' && uname_info.platform[3] == '6' ) { uname_info.platform[1] = '3'; } #endif delta = utsname_offset; fmt = " %s" + 1; do { if (toprint & 1) { const char *p = (char *)(&uname_info) + *delta; if (p[0]) { printf(fmt, p); fmt = " %s"; } } ++delta; } while (toprint >>= 1); bb_putchar('\n'); fflush_stdout_and_exit(EXIT_SUCCESS); /* coreutils-6.9 compat */ }
int id_main(int argc UNUSED_PARAM, char **argv) { uid_t ruid; gid_t rgid; uid_t euid; gid_t egid; unsigned opt; int i; int status = EXIT_SUCCESS; const char *prefix; const char *username; #if ENABLE_SELINUX security_context_t scontext = NULL; #endif if (ENABLE_GROUPS && (!ENABLE_ID || applet_name[0] == 'g')) { /* TODO: coreutils groups prepend "USER : "******"") | JUST_ALL_GROUPS | NAME_NOT_NUMBER; } else { /* Don't allow -n -r -nr -ug -rug -nug -rnug -uZ -gZ -GZ*/ /* Don't allow more than one username */ opt = getopt32(argv, "^" "rnugG" IF_SELINUX("Z") "\0" "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG" IF_SELINUX(":u--Z:Z--u:g--Z:Z--g:G--Z:Z--G") ); } username = argv[optind]; if (username) { struct passwd *p = xgetpwnam(username); euid = ruid = p->pw_uid; egid = rgid = p->pw_gid; } else { egid = getegid(); rgid = getgid(); euid = geteuid(); ruid = getuid(); } /* JUST_ALL_GROUPS ignores -r PRINT_REAL flag even if man page for */ /* id says: print the real ID instead of the effective ID, with -ugG */ /* in fact in this case egid is always printed if egid != rgid */ if (!opt || (opt & JUST_ALL_GROUPS)) { gid_t *groups; int n; if (!opt) { /* Default Mode */ status |= print_user(ruid, "uid="); status |= print_group(rgid, " gid="); if (euid != ruid) status |= print_user(euid, " euid="); if (egid != rgid) status |= print_group(egid, " egid="); } else { /* JUST_ALL_GROUPS */ status |= print_group(rgid, NULL); if (egid != rgid) status |= print_group(egid, " "); } /* We are supplying largish buffer, trying * to not run get_groups() twice. That might be slow * ("user database in remote SQL server" case) */ groups = xmalloc(64 * sizeof(groups[0])); n = 64; if (get_groups(username, rgid, groups, &n) < 0) { /* Need bigger buffer after all */ groups = xrealloc(groups, n * sizeof(groups[0])); get_groups(username, rgid, groups, &n); } if (n > 0) { /* Print the list */ prefix = " groups="; for (i = 0; i < n; i++) { if (opt && (groups[i] == rgid || groups[i] == egid)) continue; status |= print_group(groups[i], opt ? " " : prefix); prefix = ","; } } else if (n < 0) { /* error in get_groups() */ if (ENABLE_DESKTOP) bb_error_msg_and_die("can't get groups"); return EXIT_FAILURE; } if (ENABLE_FEATURE_CLEAN_UP) free(groups); #if ENABLE_SELINUX if (is_selinux_enabled()) { if (getcon(&scontext) == 0) printf(" context=%s", scontext); } #endif } else if (opt & PRINT_REAL) { euid = ruid; egid = rgid; } if (opt & JUST_USER) status |= print_user(euid, NULL); else if (opt & JUST_GROUP) status |= print_group(egid, NULL); #if ENABLE_SELINUX else if (opt & JUST_CONTEXT) { selinux_or_die(); if (username || getcon(&scontext)) { bb_error_msg_and_die("can't get process context%s", username ? " for a different user" : ""); } fputs(scontext, stdout); } /* freecon(NULL) seems to be harmless */ if (ENABLE_FEATURE_CLEAN_UP) freecon(scontext); #endif bb_putchar('\n'); fflush_stdout_and_exit(status); }
char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) { /* Was static char[BIGNUM] */ enum { sizeof_passwd = 128 }; static char *passwd; char *ret; int i; struct sigaction sa, oldsa; struct termios tio, oldtio; tcgetattr(fd, &oldtio); tcflush(fd, TCIFLUSH); tio = oldtio; #ifndef IUCLC # define IUCLC 0 #endif tio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY); tio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP); tcsetattr(fd, TCSANOW, &tio); memset(&sa, 0, sizeof(sa)); /* sa.sa_flags = 0; - no SA_RESTART! */ /* SIGINT and SIGALRM will interrupt reads below */ sa.sa_handler = askpass_timeout; sigaction(SIGINT, &sa, &oldsa); if (timeout) { sigaction_set(SIGALRM, &sa); alarm(timeout); } fputs(prompt, stdout); fflush_all(); if (!passwd) passwd = xmalloc(sizeof_passwd); ret = passwd; i = 0; while (1) { int r = read(fd, &ret[i], 1); if (r < 0) { /* read is interrupted by timeout or ^C */ ret = NULL; break; } if (r == 0 /* EOF */ || ret[i] == '\r' || ret[i] == '\n' /* EOL */ || ++i == sizeof_passwd-1 /* line limit */ ) { ret[i] = '\0'; break; } } if (timeout) { alarm(0); } sigaction_set(SIGINT, &oldsa); tcsetattr(fd, TCSANOW, &oldtio); bb_putchar('\n'); fflush_all(); return ret; }
static int generate_output(char **argv, int argc, const char *optstr, const struct option *longopts) { int exit_code = 0; /* We assume everything will be OK */ int opt; #if ENABLE_FEATURE_GETOPT_LONG int longindex; #endif const char *charptr; if (quiet_errors) /* No error reporting from getopt(3) */ opterr = 0; /* We used it already in main() in getopt32(), * we *must* reset getopt(3): */ #ifdef __GLIBC__ optind = 0; #else /* BSD style */ optind = 1; /* optreset = 1; */ #endif while (1) { opt = #if ENABLE_FEATURE_GETOPT_LONG alternative ? getopt_long_only(argc, argv, optstr, longopts, &longindex) : getopt_long(argc, argv, optstr, longopts, &longindex); #else getopt(argc, argv, optstr); #endif if (opt == -1) break; if (opt == '?' || opt == ':' ) exit_code = 1; else if (!quiet_output) { #if ENABLE_FEATURE_GETOPT_LONG if (opt == LONG_OPT) { printf(" --%s", longopts[longindex].name); if (longopts[longindex].has_arg) printf(" %s", normalize(optarg ? optarg : "")); } else #endif if (opt == NON_OPT) printf(" %s", normalize(optarg)); else { printf(" -%c", opt); charptr = strchr(optstr, opt); if (charptr != NULL && *++charptr == ':') printf(" %s", normalize(optarg ? optarg : "")); } } } if (!quiet_output) { printf(" --"); while (optind < argc) printf(" %s", normalize(argv[optind++])); bb_putchar('\n'); } return exit_code; }
int sendmail_main(int argc UNUSED_PARAM, char **argv) { char *opt_connect = opt_connect; char *opt_from = NULL; char *s; llist_t *list = NULL; char *host = sane_address(safe_gethostname()); unsigned nheaders = 0; int code; enum { HDR_OTHER = 0, HDR_TOCC, HDR_BCC, } last_hdr = 0; int check_hdr; int has_to = 0; enum { //--- standard options OPT_t = 1 << 0, // read message for recipients, append them to those on cmdline OPT_f = 1 << 1, // sender address OPT_o = 1 << 2, // various options. -oi IMPLIED! others are IGNORED! OPT_i = 1 << 3, // IMPLIED! //--- BB specific options OPT_w = 1 << 4, // network timeout OPT_H = 1 << 5, // use external connection helper OPT_S = 1 << 6, // specify connection string OPT_a = 1 << 7, // authentication tokens OPT_v = 1 << 8, // verbosity }; // init global variables INIT_G(); // save initial stdin since body is piped! xdup2(STDIN_FILENO, 3); G.fp0 = xfdopen_for_read(3); // parse options // -v is a counter, -H and -S are mutually exclusive, -a is a list opt_complementary = "vv:w+:H--S:S--H:a::"; // N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect // -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility, // it is still under development. opts = getopt32(argv, "tf:o:iw:H:S:a::v", &opt_from, NULL, &timeout, &opt_connect, &opt_connect, &list, &verbose); //argc -= optind; argv += optind; // process -a[upm]<token> options if ((opts & OPT_a) && !list) bb_show_usage(); while (list) { char *a = (char *) llist_pop(&list); if ('u' == a[0]) G.user = xstrdup(a+1); if ('p' == a[0]) G.pass = xstrdup(a+1); // N.B. we support only AUTH LOGIN so far //if ('m' == a[0]) // G.method = xstrdup(a+1); } // N.B. list == NULL here //bb_info_msg("OPT[%x] AU[%s], AP[%s], AM[%s], ARGV[%s]", opts, au, ap, am, *argv); // connect to server // connection helper ordered? -> if (opts & OPT_H) { const char *args[] = { "sh", "-c", opt_connect, NULL }; // plug it in launch_helper(args); // Now: // our stdout will go to helper's stdin, // helper's stdout will be available on our stdin. // Wait for initial server message. // If helper (such as openssl) invokes STARTTLS, the initial 220 // is swallowed by helper (and not repeated after TLS is initiated). // We will send NOOP cmd to server and check the response. // We should get 220+250 on plain connection, 250 on STARTTLSed session. // // The problem here is some servers delay initial 220 message, // and consider client to be a spammer if it starts sending cmds // before 220 reached it. The code below is unsafe in this regard: // in non-STARTTLSed case, we potentially send NOOP before 220 // is sent by server. // Ideas? (--delay SECS opt? --assume-starttls-helper opt?) code = smtp_check("NOOP", -1); if (code == 220) // we got 220 - this is not STARTTLSed connection, // eat 250 response to our NOOP smtp_check(NULL, 250); else if (code != 250) bb_error_msg_and_die("SMTP init failed"); } else { // vanilla connection int fd; // host[:port] not explicitly specified? -> use $SMTPHOST // no $SMTPHOST? -> use localhost if (!(opts & OPT_S)) { opt_connect = getenv("SMTPHOST"); if (!opt_connect) opt_connect = (char *)"127.0.0.1"; } // do connect fd = create_and_connect_stream_or_die(opt_connect, 25); // and make ourselves a simple IO filter xmove_fd(fd, STDIN_FILENO); xdup2(STDIN_FILENO, STDOUT_FILENO); // Wait for initial server 220 message smtp_check(NULL, 220); } // we should start with modern EHLO if (250 != smtp_checkp("EHLO %s", host, -1)) smtp_checkp("HELO %s", host, 250); // perform authentication if (opts & OPT_a) { smtp_check("AUTH LOGIN", 334); // we must read credentials unless they are given via -a[up] options if (!G.user || !G.pass) get_cred_or_die(4); encode_base64(NULL, G.user, NULL); smtp_check("", 334); encode_base64(NULL, G.pass, NULL); smtp_check("", 235); } // set sender // N.B. we have here a very loosely defined algorythm // since sendmail historically offers no means to specify secrets on cmdline. // 1) server can require no authentication -> // we must just provide a (possibly fake) reply address. // 2) server can require AUTH -> // we must provide valid username and password along with a (possibly fake) reply address. // For the sake of security username and password are to be read either from console or from a secured file. // Since reading from console may defeat usability, the solution is either to read from a predefined // file descriptor (e.g. 4), or again from a secured file. // got no sender address? use auth name, then UID username as a last resort if (!opt_from) { opt_from = xasprintf("%s@%s", G.user ? G.user : xuid2uname(getuid()), xgethostbyname(host)->h_name); } free(host); smtp_checkp("MAIL FROM:<%s>", opt_from, 250); // process message // read recipients from message and add them to those given on cmdline. // this means we scan stdin for To:, Cc:, Bcc: lines until an empty line // and then use the rest of stdin as message body code = 0; // set "analyze headers" mode while ((s = xmalloc_fgetline(G.fp0)) != NULL) { dump: // put message lines doubling leading dots if (code) { // escape leading dots // N.B. this feature is implied even if no -i (-oi) switch given // N.B. we need to escape the leading dot regardless of // whether it is single or not character on the line if ('.' == s[0] /*&& '\0' == s[1] */) bb_putchar('.'); // dump read line send_r_n(s); free(s); continue; } // analyze headers // To: or Cc: headers add recipients check_hdr = (0 == strncasecmp("To:", s, 3)); has_to |= check_hdr; if (opts & OPT_t) { if (check_hdr || 0 == strncasecmp("Bcc:" + 1, s, 3)) { rcptto_list(s+3); last_hdr = HDR_TOCC; goto addheader; } // Bcc: header adds blind copy (hidden) recipient if (0 == strncasecmp("Bcc:", s, 4)) { rcptto_list(s+4); free(s); last_hdr = HDR_BCC; continue; // N.B. Bcc: vanishes from headers! } } check_hdr = (list && isspace(s[0])); if (strchr(s, ':') || check_hdr) { // other headers go verbatim // N.B. RFC2822 2.2.3 "Long Header Fields" allows for headers to occupy several lines. // Continuation is denoted by prefixing additional lines with whitespace(s). // Thanks (stefan.seyfried at googlemail.com) for pointing this out. if (check_hdr && last_hdr != HDR_OTHER) { rcptto_list(s+1); if (last_hdr == HDR_BCC) continue; // N.B. Bcc: vanishes from headers! } else { last_hdr = HDR_OTHER; } addheader: // N.B. we allow MAX_HEADERS generic headers at most to prevent attacks if (MAX_HEADERS && ++nheaders >= MAX_HEADERS) goto bail; llist_add_to_end(&list, s); } else { // a line without ":" (an empty line too, by definition) doesn't look like a valid header // so stop "analyze headers" mode reenter: // put recipients specified on cmdline check_hdr = 1; while (*argv) { char *t = sane_address(*argv); rcptto(t); //if (MAX_HEADERS && ++nheaders >= MAX_HEADERS) // goto bail; if (!has_to) { const char *hdr; if (check_hdr && argv[1]) hdr = "To: %s,"; else if (check_hdr) hdr = "To: %s"; else if (argv[1]) hdr = "To: %s," + 3; else hdr = "To: %s" + 3; llist_add_to_end(&list, xasprintf(hdr, t)); check_hdr = 0; } argv++; } // enter "put message" mode // N.B. DATA fails iff no recipients were accepted (or even provided) // in this case just bail out gracefully if (354 != smtp_check("DATA", -1)) goto bail; // dump the headers while (list) { send_r_n((char *) llist_pop(&list)); } // stop analyzing headers code++; // N.B. !s means: we read nothing, and nothing to be read in the future. // just dump empty line and break the loop if (!s) { send_r_n(""); break; } // go dump message body // N.B. "s" already contains the first non-header line, so pretend we read it from input goto dump; } } // odd case: we didn't stop "analyze headers" mode -> message body is empty. Reenter the loop // N.B. after reenter code will be > 0 if (!code) goto reenter; // finalize the message smtp_check(".", 250); bail: // ... and say goodbye smtp_check("QUIT", 221); // cleanup if (ENABLE_FEATURE_CLEAN_UP) fclose(G.fp0); return EXIT_SUCCESS; }
int cal_main(int argc, char **argv) { struct tm *local_time; struct tm zero_tm; time_t now; unsigned month, year, flags, i; char *month_names[12]; char day_headings[28]; /* 28 for julian, 21 for nonjulian */ char buf[40]; flags = getopt32(argv, "jy"); /* This sets julian = flags & 1: */ option_mask32 &= 1; month = 0; argv += optind; argc -= optind; if (argc > 2) { bb_show_usage(); } if (!argc) { time(&now); local_time = localtime(&now); year = local_time->tm_year + 1900; if (!(flags & 2)) { /* no -y */ month = local_time->tm_mon + 1; } } else { if (argc == 2) { month = xatou_range(*argv++, 1, 12); } year = xatou_range(*argv, 1, 9999); } blank_string(day_headings, sizeof(day_headings) - 7 + 7*julian); i = 0; do { zero_tm.tm_mon = i; strftime(buf, sizeof(buf), "%B", &zero_tm); month_names[i] = xstrdup(buf); if (i < 7) { zero_tm.tm_wday = i; strftime(buf, sizeof(buf), "%a", &zero_tm); strncpy(day_headings + i * (3+julian) + julian, buf, 2); } } while (++i < 12); if (month) { unsigned row, len, days[MAXDAYS]; unsigned *dp = days; char lineout[30]; day_array(month, year, dp); len = sprintf(lineout, "%s %d", month_names[month - 1], year); printf("%*s%s\n%s\n", ((7*julian + WEEK_LEN) - len) / 2, "", lineout, day_headings); for (row = 0; row < 6; row++) { build_row(lineout, dp)[0] = '\0'; dp += 7; trim_trailing_spaces_and_print(lineout); } } else { unsigned row, which_cal, week_len, days[12][MAXDAYS]; unsigned *dp; char lineout[80]; sprintf(lineout, "%d", year); center(lineout, (WEEK_LEN * 3 + HEAD_SEP * 2) + julian * (J_WEEK_LEN * 2 + HEAD_SEP - (WEEK_LEN * 3 + HEAD_SEP * 2)), 0); puts("\n"); /* two \n's */ for (i = 0; i < 12; i++) { day_array(i + 1, year, days[i]); } blank_string(lineout, sizeof(lineout)); week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN); for (month = 0; month < 12; month += 3-julian) { center(month_names[month], week_len, HEAD_SEP); if (!julian) { center(month_names[month + 1], week_len, HEAD_SEP); } center(month_names[month + 2 - julian], week_len, 0); printf("\n%s%*s%s", day_headings, HEAD_SEP, "", day_headings); if (!julian) { printf("%*s%s", HEAD_SEP, "", day_headings); } bb_putchar('\n'); for (row = 0; row < (6*7); row += 7) { for (which_cal = 0; which_cal < 3-julian; which_cal++) { dp = days[month + which_cal] + row; build_row(lineout + which_cal * (week_len + 2), dp); } /* blank_string took care of nul termination. */ trim_trailing_spaces_and_print(lineout); } } } fflush_stdout_and_exit(EXIT_SUCCESS); }
int hostname_main(int argc UNUSED_PARAM, char **argv) { enum { OPT_d = 0x1, OPT_f = 0x2, OPT_i = 0x4, OPT_s = 0x8, OPT_F = 0x10, OPT_dfi = 0x7, }; unsigned opts; char *buf; char *hostname_str; #if ENABLE_LONG_OPTS applet_long_options = "domain\0" No_argument "d" "fqdn\0" No_argument "f" //Enable if seen in active use in some distro: // "long\0" No_argument "f" // "ip-address\0" No_argument "i" // "short\0" No_argument "s" // "verbose\0" No_argument "v" "file\0" No_argument "F" ; #endif /* dnsdomainname from net-tools 1.60, hostname 1.100 (2001-04-14), * supports hostname's options too (not just -v as manpage says) */ opts = getopt32(argv, "dfisF:v", &hostname_str); argv += optind; buf = safe_gethostname(); if (applet_name[0] == 'd') /* dnsdomainname? */ opts = OPT_d; if (opts & OPT_dfi) { /* Cases when we need full hostname (or its part) */ struct hostent *hp; char *p; hp = xgethostbyname(buf); p = strchrnul(hp->h_name, '.'); if (opts & OPT_f) { puts(hp->h_name); } else if (opts & OPT_s) { *p = '\0'; puts(hp->h_name); } else if (opts & OPT_d) { if (*p) puts(p + 1); } else /*if (opts & OPT_i)*/ { if (hp->h_length == sizeof(struct in_addr)) { struct in_addr **h_addr_list = (struct in_addr **)hp->h_addr_list; while (*h_addr_list) { printf(h_addr_list[1] ? "%s " : "%s", inet_ntoa(**h_addr_list)); h_addr_list++; } bb_putchar('\n'); } } } else if (opts & OPT_s) { strchrnul(buf, '.')[0] = '\0'; puts(buf); } else if (opts & OPT_F) { /* Set the hostname */ do_sethostname(hostname_str, 1); } else if (argv[0]) { /* Set the hostname */ do_sethostname(argv[0], 0); } else { /* Just print the current hostname */ puts(buf); } if (ENABLE_FEATURE_CLEAN_UP) free(buf); return EXIT_SUCCESS; }