1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <fstream>
18 #include <iostream>
19 #include <string>
20 #include <vector>
21 
22 #include <errno.h>
23 #include <time.h>
24 #include <unistd.h>
25 
26 using std::cerr;
27 using std::cout;
28 using std::endl;
29 using std::getline;
30 using std::ifstream;
31 using std::string;
32 using std::vector;
33 
34 namespace {
35 
ReadLines(const string & input_file_path,vector<string> * lines)36 bool ReadLines(const string& input_file_path, vector<string>* lines) {
37   ifstream watched_file(input_file_path);
38   if (!watched_file.is_open()) {
39     cerr << "Unable to open input file: " << input_file_path << endl;
40     return false;
41   }
42 
43   string line;
44   while (getline(watched_file, line)) {
45     lines->push_back(line);
46   }
47   watched_file.close();
48   return true;
49 }
50 
HasSentinel(const vector<string> & lines,const string & sentinel)51 bool HasSentinel(const vector<string>& lines, const string& sentinel) {
52   for (const auto& line : lines) {
53     if (line.find(sentinel) != string::npos) {
54       return true;
55     }
56   }
57   return false;
58 }
59 
60 }  // namespace
61 
main(int argc,const char * argv[])62 int main(int argc, const char* argv[]) {
63   if (argc != 5) {
64     cerr << "Invalid usage." << endl;
65     cerr << argv[0]
66          << " <timeout in seconds>"
67          << " <input file path>"
68          << " <success sentinel>"
69          << " <failure sentinel>" << endl;
70     return -EINVAL;
71   }
72   const string timeout_as_str = argv[1];
73   const string input_file_path = argv[2];
74   const string success_sentinel = argv[3];
75   const string failure_sentinel = argv[4];
76 
77   const int timeout_seconds = atoi(timeout_as_str.c_str());
78   if (timeout_seconds <= 0) {
79     cerr << "Invalid timeout value (in seconds): " << timeout_as_str << endl;
80     return -EINVAL;
81   }
82 
83   int exit_code = 1;
84   const time_t start_time = time(nullptr);
85   vector<string> lines;
86   while (true) {
87     sleep(1);
88     if (time(nullptr) - start_time > timeout_seconds) {
89       cerr << "Timed out waiting for success/failure sentinel." << endl;
90       break;
91     }
92     // Ignore errors when reading lines.  The file may not immediately exist
93     // because it takes the Java process some time to create it.
94     lines.clear();
95     ReadLines(input_file_path, &lines);
96 
97     if (HasSentinel(lines, success_sentinel)) {
98       exit_code = 0;
99       break;
100     }
101     if (HasSentinel(lines, failure_sentinel)) {
102       break;
103     }
104   }
105 
106   cout << "Found output:" << endl;
107   for (const auto& line : lines) {
108     cout << "  " << line << endl;
109   }
110   return exit_code;
111 }
112