summaryrefslogtreecommitdiff
path: root/usr/src/cmd/tail/tail.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/tail/tail.c')
-rw-r--r--usr/src/cmd/tail/tail.c114
1 files changed, 96 insertions, 18 deletions
diff --git a/usr/src/cmd/tail/tail.c b/usr/src/cmd/tail/tail.c
index c641cfa592..8e83ae4079 100644
--- a/usr/src/cmd/tail/tail.c
+++ b/usr/src/cmd/tail/tail.c
@@ -30,9 +30,14 @@
* SUCH DAMAGE.
*/
+/*
+ * Copyright 2017, Joyent, Inc.
+ */
+
#include <sys/types.h>
#include <sys/stat.h>
+#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
@@ -226,6 +231,24 @@ main(int argc, char *argv[])
exit(rval);
}
+static boolean_t
+iscount(const char *ap)
+{
+ char c;
+
+ if (ap == NULL) {
+ return (B_FALSE);
+ }
+
+ c = ap[0];
+
+ if (c == '+' || c == '-') {
+ c = ap[1];
+ }
+
+ return (isdigit(c) ? B_TRUE : B_FALSE);
+}
+
/*
* Convert the obsolete argument form into something that getopt can handle.
* This means that anything of the form [+-][0-9][0-9]*[lbc][Ffr] that isn't
@@ -293,28 +316,83 @@ obsolete(char *argv[])
/*
* Legacy Solaris tail supports "+c" "-c", "+l", "-l",
- * "+b", and "-b" with an default number of 10. Map
- * these arguments to an explicit +/-10 for FreeBSD.
- * New argument will be of the form -[bcn][+-]10
+ * "+b", and "-b" with a default value of 10. We need
+ * to determine here whether or not a count has been
+ * provided after the flag, and create a new, explicit
+ * argument as appropriate. [+-]l isn't allowed to have
+ * any numbers after it, but [+-][bc] can, potentially
+ * in the next command-line argument. We therefore
+ * handle them in two separate cases below.
*/
+ case 'l':
+ len = strlen(ap);
+ start = NULL;
+
+ if (len > 2) {
+ errx(1, "illegal option -- %s", *argv);
+ }
+
+ /* The only characters following should be flags */
+ if (len == 2 && !isalpha(ap[1])) {
+ errx(1, "illegal option -- %s", *argv);
+ }
+
+ if (asprintf(&start, "-%sn%c10",
+ ap + 1, *argv[0]) == -1) {
+ err(1, "asprintf");
+ }
+
+ *argv = start;
+
+ continue;
case 'b':
case 'c':
- case 'l':
- if ((start = p = malloc(6)) == NULL)
- err(1, "malloc");
- *p++ = '-';
- switch (ap[0]) {
- case 'c':
- *p++ = ap[0];
- break;
- case 'b':
- *p++ = ap[0];
- break;
- case 'l':
- *p++ = 'n';
- break;
+ len = strlen(ap);
+ start = NULL;
+
+ if (len == 1) {
+ /*
+ * The option is just the flag name. Check if
+ * the next argument is a count, so we know
+ * whether we need to default to 10.
+ */
+ if (iscount(argv[1])) {
+ ++argv;
+ continue;
+ } else {
+ if (asprintf(&start,
+ "-%c%c10", ap[0], *argv[0]) == -1) {
+ err(1, "asprintf");
+ }
+ }
+ } else {
+ /*
+ * The option has characters following the c/b.
+ * If the characters following the option are a
+ * count, then we use those. This invocation is
+ * only allowed when '-' is used.
+ *
+ * Otherwise, we need to honor the following
+ * flags, and default to 10.
+ */
+ if (iscount(ap + 1)) {
+ if (*argv[0] != '-') {
+ errx(1, "illegal option -- %s",
+ *argv);
+ }
+
+ if (asprintf(&start, "-%c%s",
+ ap[0], ap + 1) == -1) {
+ err(1, "asprintf");
+ }
+ } else {
+ if (asprintf(&start, "-%s%c%c10",
+ ap + 1, ap[0], *argv[0]) == -1) {
+ err(1, "asprintf");
+ }
+ }
}
- (void) snprintf(p, 6, "%c10", *argv[0]);
+
*argv = start;
continue;