logcat: Add -T flag (-t w/o assumption of -d)

(cherry picked from commit de02546e3d7c9c307e3d87e0a7fe8bb39b363a72)

Change-Id: I49763e2db83755e0b7b12dfa3f83a3957c54d389
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index a54167e..3c33938 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -223,6 +223,7 @@
                     "  -c              clear (flush) the entire log and exit\n"
                     "  -d              dump the log and then exit (don't block)\n"
                     "  -t <count>      print only the most recent <count> lines (implies -d)\n"
+                    "  -T <count>      print only the most recent <count> lines (does not imply -d)\n"
                     "  -g              get the size of the log's ring buffer and exit\n"
                     "  -b <buffer>     Request alternate ring buffer, 'main', 'system', 'radio'\n"
                     "                  or 'events'. Multiple -b parameters are allowed and the\n"
@@ -302,7 +303,7 @@
     for (;;) {
         int ret;
 
-        ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:B");
+        ret = getopt(argc, argv, "cdt:T:gsQf:r::n:v:b:B");
 
         if (ret < 0) {
             break;
@@ -325,6 +326,8 @@
 
             case 't':
                 mode = O_RDONLY | O_NDELAY;
+                /* FALLTHRU */
+            case 'T':
                 tail_lines = atoi(optarg);
             break;
 
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index a4b796b..f963a3a 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -373,3 +373,71 @@
 
     ASSERT_EQ(1, signals);
 }
+
+static void caught_blocking_tail(int signum)
+{
+    unsigned long long v = 0xA55ADEADBEEF0000ULL;
+
+    v += getpid() & 0xFFFF;
+
+    LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
+}
+
+TEST(logcat, blocking_tail) {
+    FILE *fp;
+    unsigned long long v = 0xA55ADEADBEEF0000ULL;
+
+    pid_t pid = getpid();
+
+    v += pid & 0xFFFF;
+
+    ASSERT_EQ(0, NULL == (fp = popen(
+      "( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
+      " logcat -b events -T 5 2>&1",
+      "r")));
+
+    char buffer[5120];
+
+    int count = 0;
+
+    int signals = 0;
+
+    signal(SIGALRM, caught_blocking_tail);
+    alarm(2);
+    while (fgets(buffer, sizeof(buffer), fp)) {
+        alarm(2);
+
+        ++count;
+
+        if (!strncmp(buffer, "DONE", 4)) {
+            break;
+        }
+
+        int p;
+        unsigned long long l;
+
+        if ((2 != sscanf(buffer, "I/[0] ( %u): %lld", &p, &l))
+         || (p != pid)) {
+            continue;
+        }
+
+        if (l == v) {
+            if (count >= 5) {
+                ++signals;
+            }
+            break;
+        }
+    }
+    alarm(0);
+    signal(SIGALRM, SIG_DFL);
+
+    /* Generate SIGPIPE */
+    fclose(fp);
+    caught_blocking_tail(0);
+
+    pclose(fp);
+
+    ASSERT_LT(5, count);
+
+    ASSERT_EQ(1, signals);
+}