blob: 55fff8454b27e1fe8d0a12310f92e5d776664f63 [file] [log] [blame]
Brian Silverman14fd0fb2014-01-14 21:42:01 -08001#include "aos/linux_code/configuration.h"
Brian Silverman66f079a2013-08-26 16:24:30 -07002
3#include <string.h>
Brian Silverman66f079a2013-08-26 16:24:30 -07004#include <stdlib.h>
5#include <sys/types.h>
6#include <netinet/in.h>
7#include <arpa/inet.h>
8#include <ifaddrs.h>
9#include <unistd.h>
10
11#include "aos/common/logging/logging.h"
12#include "aos/common/unique_malloc_ptr.h"
13#include "aos/common/once.h"
14
15namespace aos {
16namespace configuration {
17namespace {
18
Austin Schuh629821e2014-02-10 21:18:27 -080019// TODO(brians): This shouldn't be necesary for running tests. Provide a way to
20// set the IP address when running tests from the test.
Brian Silverman14fd0fb2014-01-14 21:42:01 -080021const char *const kLinuxNetInterface = "eth0";
Brian Silverman66f079a2013-08-26 16:24:30 -070022const in_addr *DoGetOwnIPAddress() {
Brian Silverman01be0002014-05-10 15:44:38 -070023 static const char *kOverrideVariable = "FRC971_IP_OVERRIDE";
24 const char *override_ip = getenv(kOverrideVariable);
25 if (override_ip != NULL) {
26 LOG(INFO, "Override IP is %s\n", override_ip);
27 static in_addr r;
28 if (inet_aton(override_ip, &r) != 0) {
29 return &r;
joe3779d0c2014-02-15 19:41:22 -080030 } else {
Brian Silverman01be0002014-05-10 15:44:38 -070031 LOG(WARNING, "error parsing %s value '%s'\n",
32 kOverrideVariable, override_ip);
joe3779d0c2014-02-15 19:41:22 -080033 }
Brian Silverman01be0002014-05-10 15:44:38 -070034 } else {
35 LOG(INFO, "Couldn't get environmental variable.\n");
36 }
joe3779d0c2014-02-15 19:41:22 -080037
Brian Silverman66f079a2013-08-26 16:24:30 -070038 ifaddrs *addrs;
39 if (getifaddrs(&addrs) != 0) {
Brian Silverman01be0002014-05-10 15:44:38 -070040 PLOG(FATAL, "getifaddrs(%p) failed", &addrs);
Brian Silverman66f079a2013-08-26 16:24:30 -070041 }
42 // Smart pointers don't work very well for iterating through a linked list,
43 // but it does do a very nice job of making sure that addrs gets freed.
44 unique_c_ptr<ifaddrs, freeifaddrs> addrs_deleter(addrs);
45
Austin Schuh629821e2014-02-10 21:18:27 -080046 for (; addrs != nullptr; addrs = addrs->ifa_next) {
47 if (addrs->ifa_addr != nullptr && addrs->ifa_addr->sa_family == AF_INET) {
Brian Silverman14fd0fb2014-01-14 21:42:01 -080048 if (strcmp(kLinuxNetInterface, addrs->ifa_name) == 0) {
Brian Silverman66f079a2013-08-26 16:24:30 -070049 static const in_addr r =
Brian Silverman63cf2412013-11-17 05:44:36 -080050 reinterpret_cast<sockaddr_in *>(__builtin_assume_aligned(
51 addrs->ifa_addr, alignof(sockaddr_in)))->sin_addr;
Brian Silverman66f079a2013-08-26 16:24:30 -070052 return &r;
53 }
54 }
55 }
56 LOG(FATAL, "couldn't find an AF_INET interface named \"%s\"\n",
Brian Silverman14fd0fb2014-01-14 21:42:01 -080057 kLinuxNetInterface);
Brian Silverman66f079a2013-08-26 16:24:30 -070058}
59
60const char *DoGetRootDirectory() {
61 ssize_t size = 0;
62 char *r = NULL;
63 while (true) {
64 if (r != NULL) delete r;
65 size += 256;
66 r = new char[size];
67
68 ssize_t ret = readlink("/proc/self/exe", r, size);
69 if (ret < 0) {
70 if (ret != -1) {
71 LOG(WARNING, "it returned %zd, not -1\n", ret);
72 }
Brian Silverman01be0002014-05-10 15:44:38 -070073 PLOG(FATAL, "readlink(\"/proc/self/exe\", %p, %zu) failed", r, size);
Brian Silverman66f079a2013-08-26 16:24:30 -070074 }
75 if (ret < size) {
Brian Silvermane6335e42014-02-20 20:53:06 -080076 void *last_slash = memrchr(r, '/', ret);
Brian Silverman66f079a2013-08-26 16:24:30 -070077 if (last_slash == NULL) {
78 r[ret] = '\0';
79 LOG(FATAL, "couldn't find a '/' in \"%s\"\n", r);
80 }
81 *static_cast<char *>(last_slash) = '\0';
82 LOG(INFO, "got a root dir of \"%s\"\n", r);
83 return r;
84 }
85 }
86}
87
88const char *DoGetLoggingDirectory() {
89 static const char kSuffix[] = "/../../tmp/robot_logs";
90 const char *root = GetRootDirectory();
91 char *r = new char[strlen(root) + sizeof(kSuffix)];
92 strcpy(r, root);
93 strcat(r, kSuffix);
94 return r;
95}
96
97} // namespace
98
99const char *GetRootDirectory() {
100 static aos::Once<const char> once(DoGetRootDirectory);
101 return once.Get();
102}
103
104const char *GetLoggingDirectory() {
105 static aos::Once<const char> once(DoGetLoggingDirectory);
106 return once.Get();
107}
108
109const in_addr &GetOwnIPAddress() {
110 static aos::Once<const in_addr> once(DoGetOwnIPAddress);
111 return *once.Get();
112}
113
114} // namespace configuration
115} // namespace aos