16dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn/* 26dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * Copyright (C) 2017 The Android Open Source Project 36dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * 46dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License"); 56dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * you may not use this file except in compliance with the License. 66dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * You may obtain a copy of the License at 76dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * 86dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * http://www.apache.org/licenses/LICENSE-2.0 96dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * 106dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * Unless required by applicable law or agreed to in writing, software 116dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS, 126dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * See the License for the specific language governing permissions and 146dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn * limitations under the License. 156dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn */ 166dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 176dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn#include <ctype.h> 1803d055d6ff38993c04fcc3ec24becda35b119a52Josh Gao#include <fcntl.h> 196dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn#include <stdio.h> 206dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn#include <string.h> 216dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn#include <unistd.h> 226dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 236dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn#include <string> 246dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn#include <vector> 256dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 266dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn#include <log/logcat.h> 276dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 286dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzynstatic std::string unquote(const char*& cp, const char*& delim) { 296dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if ((*cp == '\'') || (*cp == '"')) { 306dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn // KISS: Simple quotes. Do not handle the case 316dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn // of concatenation like "blah"foo'bar' 326dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn char quote = *cp++; 336dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn delim = strchr(cp, quote); 346dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (!delim) delim = cp + strlen(cp); 356dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::string str(cp, delim); 366dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (*delim) ++delim; 376dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn return str; 386dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 396dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn delim = strpbrk(cp, " \t\f\r\n"); 406dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (!delim) delim = cp + strlen(cp); 416dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn return std::string(cp, delim); 426dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn} 436dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 446dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzynstatic bool __android_logcat_parse(const char* command, 456dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<std::string>& args, 466dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<std::string>& envs) { 476dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn for (const char *delim, *cp = command; cp && *cp; cp = delim) { 486dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn while (isspace(*cp)) ++cp; 496dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if ((args.size() == 0) && (*cp != '=') && !isdigit(*cp)) { 506dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn const char* env = cp; 516dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn while (isalnum(*cp) || (*cp == '_')) ++cp; 526dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (cp && (*cp == '=')) { 536dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::string str(env, ++cp); 546dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn str += unquote(cp, delim); 556dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn envs.push_back(str); 566dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn continue; 576dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 586dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn cp = env; 596dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 606dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn args.push_back(unquote(cp, delim)); 616dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if ((args.size() == 1) && (args[0] != "logcat") && 626dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn (args[0] != "/system/bin/logcat")) { 636dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn return false; 646dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 656dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 666dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn return args.size() != 0; 676dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn} 686dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 696dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark SalyzynFILE* android_logcat_popen(android_logcat_context* ctx, const char* command) { 706dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn *ctx = NULL; 716dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 726dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<std::string> args; 736dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<std::string> envs; 746dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (!__android_logcat_parse(command, args, envs)) return NULL; 756dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 766dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<const char*> argv; 776dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn for (auto& str : args) { 786dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn argv.push_back(str.c_str()); 796dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 806dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn argv.push_back(NULL); 816dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 826dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<const char*> envp; 836dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn for (auto& str : envs) { 846dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn envp.push_back(str.c_str()); 856dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 866dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn envp.push_back(NULL); 876dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 886dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn *ctx = create_android_logcat(); 896dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (!*ctx) return NULL; 906dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 916dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn int fd = android_logcat_run_command_thread( 926dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn *ctx, argv.size() - 1, (char* const*)&argv[0], (char* const*)&envp[0]); 936dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn argv.clear(); 946dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn args.clear(); 956dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn envp.clear(); 966dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn envs.clear(); 976dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (fd < 0) { 986dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn android_logcat_destroy(ctx); 996dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn return NULL; 1006dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 1016dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 10203d055d6ff38993c04fcc3ec24becda35b119a52Josh Gao int duped = dup(fd); 10303d055d6ff38993c04fcc3ec24becda35b119a52Josh Gao FILE* retval = fdopen(duped, "reb"); 10403d055d6ff38993c04fcc3ec24becda35b119a52Josh Gao if (!retval) { 10503d055d6ff38993c04fcc3ec24becda35b119a52Josh Gao close(duped); 10603d055d6ff38993c04fcc3ec24becda35b119a52Josh Gao android_logcat_destroy(ctx); 10703d055d6ff38993c04fcc3ec24becda35b119a52Josh Gao } 1086dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn return retval; 1096dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn} 1106dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 1116dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzynint android_logcat_pclose(android_logcat_context* ctx, FILE* output) { 1126dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (*ctx) { 1136dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn static const useconds_t wait_sample = 20000; 1146dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn // Wait two seconds maximum 1156dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn for (size_t retry = ((2 * 1000000) + wait_sample - 1) / wait_sample; 1166dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn android_logcat_run_command_thread_running(*ctx) && retry; --retry) { 1176dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn usleep(wait_sample); 1186dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 1196dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 1206dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 1216dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (output) fclose(output); 1226dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn return android_logcat_destroy(ctx); 1236dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn} 1246dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 1256dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzynint android_logcat_system(const char* command) { 1266dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<std::string> args; 1276dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<std::string> envs; 1286dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (!__android_logcat_parse(command, args, envs)) return -1; 1296dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 1306dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<const char*> argv; 1316dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn for (auto& str : args) { 1326dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn argv.push_back(str.c_str()); 1336dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 1346dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn argv.push_back(NULL); 1356dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 1366dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn std::vector<const char*> envp; 1376dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn for (auto& str : envs) { 1386dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn envp.push_back(str.c_str()); 1396dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn } 1406dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn envp.push_back(NULL); 1416dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn 1426dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn android_logcat_context ctx = create_android_logcat(); 1436dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (!ctx) return -1; 1446dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn /* Command return value */ 1456dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn int retval = android_logcat_run_command(ctx, -1, -1, argv.size() - 1, 1466dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn (char* const*)&argv[0], 1476dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn (char* const*)&envp[0]); 1486dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn /* destroy return value */ 1496dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn int ret = android_logcat_destroy(&ctx); 1506dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn /* Paranoia merging any discrepancies between the two return values */ 1516dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn if (!ret) ret = retval; 1526dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn return ret; 1536dabc81a0b7eac772209e8eef70ff3b156e5cc6bMark Salyzyn} 154