1 /*
2  * Copyright (C) 2019 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 <signal.h>
18 
19 #include <gflags/gflags.h>
20 #include <android-base/logging.h>
21 
22 #include "common/libs/fs/shared_buf.h"
23 #include "common/libs/fs/shared_fd.h"
24 #include "host/libs/config/cuttlefish_config.h"
25 #include "host/libs/config/logging.h"
26 
27 DEFINE_int32(log_pipe_fd, -1,
28              "A file descriptor representing a (UNIX) socket from which to "
29              "read the logs. If -1 is given the socket is created according to "
30              "the instance configuration");
31 
main(int argc,char ** argv)32 int main(int argc, char** argv) {
33   cuttlefish::DefaultSubprocessLogging(argv);
34   google::ParseCommandLineFlags(&argc, &argv, true);
35 
36   auto config = cuttlefish::CuttlefishConfig::Get();
37 
38   CHECK(config) << "Could not open cuttlefish config";
39 
40   auto instance = config->ForDefaultInstance();
41 
42   // Disable default handling of SIGPIPE
43   struct sigaction new_action {
44   }, old_action{};
45   new_action.sa_handler = SIG_IGN;
46   sigaction(SIGPIPE, &new_action, &old_action);
47 
48   cuttlefish::SharedFD pipe;
49 
50   if (FLAGS_log_pipe_fd < 0) {
51     auto log_name = instance.logcat_pipe_name();
52     pipe = cuttlefish::SharedFD::Open(log_name.c_str(), O_RDONLY);
53   } else {
54     pipe = cuttlefish::SharedFD::Dup(FLAGS_log_pipe_fd);
55     close(FLAGS_log_pipe_fd);
56   }
57 
58   if (!pipe->IsOpen()) {
59     LOG(ERROR) << "Error opening log pipe: " << pipe->StrError();
60     return 2;
61   }
62 
63   auto path = instance.logcat_path();
64   auto logcat_file =
65       cuttlefish::SharedFD::Open(path.c_str(), O_CREAT | O_APPEND | O_WRONLY, 0666);
66 
67   // Server loop
68   while (true) {
69     char buff[1024];
70     auto read = pipe->Read(buff, sizeof(buff));
71     if (read < 0) {
72       LOG(ERROR) << "Could not read logcat: " << pipe->StrError();
73       break;
74     }
75     auto written = cuttlefish::WriteAll(logcat_file, buff, read);
76     CHECK(written == read) << "Error writing to log file: "
77                            << logcat_file->StrError()
78                            << ". This is unrecoverable.";
79   }
80 
81   logcat_file->Close();
82   pipe->Close();
83   return 0;
84 }
85