VERSION = 1
PATCHLEVEL = 10
-SUBLEVEL = 0
+SUBLEVEL = 1
EXTRAVERSION =
NAME = Unnamed
fmt = header_fmt + 1; /* Skip header leading newline on first output. */
i = 0;
do {
- off_t current;
-
if (nfiles > header_threshhold) {
tail_xprint_header(fmt, argv[i]);
fmt = header_fmt;
/* Optimizing count-bytes case if the file is seekable.
* Beware of backing up too far.
* Also we exclude files with size 0 (because of /proc/xxx) */
- current = lseek(fds[i], 0, SEEK_END);
- if (current > 0) {
- if (!from_top) {
+ if (COUNT_BYTES && !from_top) {
+ off_t current = lseek(fds[i], 0, SEEK_END);
+ if (current > 0) {
if (count == 0)
continue; /* showing zero lines is easy :) */
- if (COUNT_BYTES) {
- current -= count;
- if (current < 0)
- current = 0;
- xlseek(fds[i], current, SEEK_SET);
- bb_copyfd_size(fds[i], STDOUT_FILENO, count);
- continue;
- }
+ current -= count;
+ if (current < 0)
+ current = 0;
+ xlseek(fds[i], current, SEEK_SET);
+ bb_copyfd_size(fds[i], STDOUT_FILENO, count);
+ continue;
}
}
#endif
/* Allowed init action types */
-#define SYSINIT 0x001
-#define RESPAWN 0x002
-#define ASKFIRST 0x004
-#define WAIT 0x008
-#define ONCE 0x010
-#define CTRLALTDEL 0x020
-#define SHUTDOWN 0x040
-#define RESTART 0x080
+#define SYSINIT 0x01
+#define RESPAWN 0x02
+/* like respawn, but wait for <Enter> to be pressed on tty: */
+#define ASKFIRST 0x04
+#define WAIT 0x08
+#define ONCE 0x10
+#define CTRLALTDEL 0x20
+#define SHUTDOWN 0x40
+#define RESTART 0x80
#define STR_SYSINIT "\x01"
#define STR_RESPAWN "\x02"
sigemptyset(&nmask);
sigaddset(&nmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &nmask, &omask);
- pid = vfork();
+ if (BB_MMU && (a->action_type & ASKFIRST))
+ pid = fork();
+ else
+ pid = vfork();
sigprocmask(SIG_SETMASK, &omask, NULL);
if (pid < 0)
}
#endif
- /* NB: on NOMMU we can't wait for input in child */
+ /* NB: on NOMMU we can't wait for input in child, so
+ * "askfirst" will work the same as "respawn". */
if (BB_MMU && (a->action_type & ASKFIRST)) {
static const char press_enter[] ALIGN1 =
#ifdef CUSTOMIZED_BANNER
for (a = init_action_list; a; a = tmp) {
tmp = a->next;
- if (a->action_type == action_type) {
+ if (a->action_type & action_type) {
// Pointless: run() will error out if open of device fails.
///* a->terminal of "" means "init's console" */
//if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
fclose(file);
}
+#if ENABLE_FEATURE_USE_INITTAB
static void reload_signal(int sig ATTRIBUTE_UNUSED)
{
struct init_action *a, *tmp;
delete_init_action(a);
}
}
- run_actions(RESPAWN);
+ run_actions(RESPAWN | ASKFIRST);
}
+#endif
int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int init_main(int argc ATTRIBUTE_UNUSED, char **argv)
run_actions(ONCE);
/* Redefine SIGHUP to reread /etc/inittab */
- if (ENABLE_FEATURE_USE_INITTAB)
- signal(SIGHUP, reload_signal);
- else
- signal(SIGHUP, SIG_IGN);
+#if ENABLE_FEATURE_USE_INITTAB
+ signal(SIGHUP, reload_signal);
+#else
+ signal(SIGHUP, SIG_IGN);
+#endif
/* Now run the looping stuff for the rest of forever */
while (1) {
- /* run the respawn stuff */
- run_actions(RESPAWN);
-
- /* run the askfirst stuff */
- run_actions(ASKFIRST);
+ /* run the respawn/askfirst stuff */
+ run_actions(RESPAWN | ASKFIRST);
/* Don't consume all CPU time -- sleep a bit */
sleep(1);
linepos = 0;
} /* end of "read lines until we reach cur_fline" loop */
fill_match_lines(old_max_fline);
+#if ENABLE_FEATURE_LESS_REGEXP
+ /* prevent us from being stuck in search for a match */
+ wanted_match = -1;
+#endif
#undef readbuf
}
match = 0;
/* Try to find next match if eof isn't reached yet */
if (match >= num_matches && eof_error > 0) {
- wanted_match = match;
+ wanted_match = match; /* "I want to read until I see N'th match" */
read_lines();
- if (wanted_match >= num_matches) {
- /* We still failed to find it. Prevent future
- * read_lines() from trying... */
- wanted_match = num_matches - 1;
- }
}
if (num_matches) {
normalize_match_pos(match);
char *pid_str;
char *aff = aff; /* for compiler */
+ /* NB: we mimic util-linux's taskset: -p does not take
+ * an argument, i.e., "-pN" is NOT valid, only "-p N"!
+ * Indeed, util-linux-2.13-pre7 uses:
+ * getopt_long(argc, argv, "+pchV", ...), not "...p:..." */
+
opt_complementary = "-1"; /* at least 1 arg */
opt_p = getopt32(argv, "+p");
argv += optind;
* Written 2000 by Andi Kleen.
* Busybox port 2002 by Nick Fedchik <nick@fedchik.org.ua>
* Glenn McGrath
+ * Extended matching support 2008 by Nico Erfurth <masta@perlgolf.de>
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
found_selector++;
} else {
#endif
- lmac = ether_aton(selector + (strncmp(selector, "mac=", 4) == 0 ? 4 : 0));
- /* Check ascii selector, convert and copy to *mac */
- if (lmac == NULL)
+ lmac = xmalloc(ETH_ALEN);
+ ch->mac = ether_aton_r(selector + (strncmp(selector, "mac=", 4) ? 0 : 4), lmac);
+ if (ch->mac == NULL)
bb_error_msg_and_die("cannot parse %s", selector);
- ch->mac = xmalloc(ETH_ALEN);
- memcpy(ch->mac, lmac, ETH_ALEN);
#if ENABLE_FEATURE_NAMEIF_EXTENDED
found_selector++;
};
if (strlen(ifname) >= IF_NAMESIZE)
bb_error_msg_and_die("interface name '%s' too long", ifname);
ch = xzalloc(sizeof(*ch));
- ch->ifname = ifname;
+ ch->ifname = xstrdup(ifname);
nameif_parse_selector(ch, selector);
ch->next = *clist;
if (*clist)
*clist = ch;
}
+#if ENABLE_FEATURE_CLEAN_UP
+static void delete_eth_table(ethtable_t *ch)
+{
+ free(ch->ifname);
+#if ENABLE_FEATURE_NAMEIF_EXTENDED
+ free(ch->bus_info);
+ free(ch->driver);
+#endif
+ free(ch->mac);
+ free(ch);
+};
+#else
+void delete_eth_table(ethtable_t *ch);
+#endif
+
int nameif_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int nameif_main(int argc, char **argv)
{
char *next;
line_ptr = skip_whitespace(line);
- if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) {
- free(line);
- continue;
- }
+ if ((line_ptr[0] == '#') || (line_ptr[0] == '\n'))
+ goto read_next_line;
next = skip_non_whitespace(line_ptr);
if (*next)
*next++ = '\0';
prepend_new_eth_table(&clist, line_ptr, next);
+ read_next_line:
free(line);
}
fclose(ifh);
/* Find the current interface name and copy it to ifr.ifr_name */
line_ptr = skip_whitespace(line);
- *skip_non_whitespace(line_ptr) = '\0';
+ *strpbrk(line_ptr, " \t\n:") = '\0';
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, line_ptr, sizeof(ifr.ifr_name));
else
clist = ch->next;
if (ch->next != NULL)
- ch->next->prev = ch->prev;
- if (ENABLE_FEATURE_CLEAN_UP) {
- free(ch->ifname);
- free(ch->mac);
- free(ch);
- }
+ ch->next->prev = ch->prev;
+ if (ENABLE_FEATURE_CLEAN_UP)
+ delete_eth_table(ch);
next_line:
free(line);
}
if (ENABLE_FEATURE_CLEAN_UP) {
+ for (ch = clist; ch; ch = ch->next)
+ delete_eth_table(ch);
fclose(ifh);
};
* - don't know how to retrieve ORIGDST for udp.
*/
-#include <limits.h>
-#include <linux/netfilter_ipv4.h> /* wants <limits.h> */
-
#include "libbb.h"
+/* Wants <limits.h> etc, thus included after libbb.h: */
+#include <linux/netfilter_ipv4.h>
+
// TODO: move into this file:
#include "tcpudp_perhost.h"
*/
#include <features.h>
+#include <asm/types.h>
#if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION)
#include <netpacket/packet.h>
#include <net/ethernet.h>
#else
-#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#endif
static char *parse_net_arg(const char *arg, unsigned *port)
{
- char path[12], tproto[5];
+ char path[20], tproto[5];
if (sscanf(arg, "%u/%4s", port, tproto) != 2)
return NULL;
- sprintf(path, "net/%s", tproto);
+ sprintf(path, "/proc/net/%s", tproto);
if (access(path, R_OK) != 0)
return NULL;
return xstrdup(tproto);
static inode_list *scan_proc_net(const char *proto,
unsigned port, inode_list *ilist)
{
- char path[12], line[MAX_LINE + 1];
+ char path[20], line[MAX_LINE + 1];
char addr[128];
ino_t tmp_inode;
dev_t tmp_dev;
tmp_dev = find_socket_dev();
- sprintf(path, "net/%s", proto);
+ sprintf(path, "/proc/net/%s", proto);
f = fopen(path, "r");
if (!f)
return ilist;
opt = getopt32(argv, OPTION_STRING);
argv += optind;
- xchdir("/proc");
-
ilist = NULL;
pp = argv;
while (*pp) {
#else
qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0]));
#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
- } else { /* TOPMEM */
+ }
+#if ENABLE_FEATURE_TOPMEM
+ else { /* TOPMEM */
qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort);
}
+#endif
count = lines;
if (OPT_BATCH_MODE || count > ntop) {
count = ntop;
}
if (scan_mask == TOP_MASK)
display_process_list(count, col);
+#if ENABLE_FEATURE_TOPMEM
else
display_topmem_process_list(count, col);
+#endif
clearmems();
if (iterations >= 0 && !--iterations)
break;
-[ -n "$d" ] || d=..
-tail -n 2 "$d/README" > logfile.gnu
-busybox tail -n 2 "$d/README" > logfile.bb
-cmp logfile.gnu logfile.bb
+echo -ne "abc\ndef\n123\n" >input
+echo -ne "def\n123\n" >logfile.ok
+busybox tail -n 2 input > logfile.bb
+cmp logfile.ok logfile.bb
-[ -n "$d" ] || d=..
-tail -n 2 "$d/README" > logfile.gnu
-busybox tail -n 2 "$d/README" > logfile.bb
-cmp logfile.gnu logfile.bb
+echo -ne "abc\ndef\n123\n" >input
+echo -ne "def\n123\n" >logfile.ok
+busybox tail -2 input > logfile.bb
+cmp logfile.ok logfile.bb
a="taskset"
# testing "test name" "opts" "expected result" "file inp" "stdin"
-testing "taskset (get from pid 1)" "$a -p1 >/dev/null;echo \$?" "0\n" "" ""
-testing "taskset (invalid pid)" "$a -p0 >/dev/null 2>&1;echo \$?" "1\n" "" ""
+testing "taskset (get from pid 1)" "$a -p 1 >/dev/null;echo \$?" "0\n" "" ""
+testing "taskset (invalid pid)" "$a -p 0 >/dev/null 2>&1;echo \$?" "1\n" "" ""
testing "taskset (set_aff, needs CAP_SYS_NICE)" \
"$a 0x1 $SHELL -c $a\ -p\ \$$\|grep\ \"current\ affinity\ mask:\ 1\" >/dev/null;echo \$?" \
"0\n" "" ""