1 /*
2  * Copyright (C) 2018 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 "common/libs/utils/environment.h"
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <iostream>
22 
23 namespace cvd {
24 
StringFromEnv(const std::string & varname,const std::string & defval)25 std::string StringFromEnv(const std::string& varname,
26                           const std::string& defval) {
27   const char* const valstr = getenv(varname.c_str());
28   if (!valstr) {
29     return defval;
30   }
31   return valstr;
32 }
33 
34 /**
35  * at runtime, return the arch of the host: e.g. aarch64, x86_64, etc
36  *
37  * uses "`which uname` -m"
38  *
39  * @return arch string on success, "" on failure
40  */
HostArch()41 std::string HostArch() {
42   static std::string arch;
43   static bool cached = false;
44 
45   if (cached) {
46     return arch;
47   }
48   cached = true;
49 
50   // good to check if uname exists and is executable
51   // or, guarantee uname is availabe by dependency list
52   FILE* pip = popen("uname -m", "r");
53   if (!pip) {
54     return std::string{};
55   }
56 
57   auto read_from_file =
58       [](FILE* fp, size_t len) {
59         /*
60          * to see if input is longer than len,
61          * we read up to len+1. If the length is len+1,
62          * then the input is too long
63          */
64         decltype(len) upper = len + 1;
65         std::string format("%");
66         format.append(std::to_string(upper)).append("s");
67         std::shared_ptr<char> buf(new char[upper],
68                                   std::default_delete<char[]>());
69         if (fscanf(fp, format.c_str(), buf.get()) == EOF) {
70           return std::string{};
71         }
72         std::string result(buf.get());
73         return (result.length() < upper) ? result : std::string{};
74       };
75   arch = read_from_file(pip, 20);
76   pclose(pip);
77 
78   // l and r trim on arch
79   static const char* whitespace = "\t\n\r\f\v ";
80   arch.erase(arch.find_last_not_of(whitespace) + 1); // r trim
81   arch.erase(0, arch.find_first_not_of(whitespace)); // l trim
82   return arch;
83 }
84 
85 }  // namespace cvd
86