blob: 6c39a93aa4e8a8c33a9b42fd0c89953d4c7c588e [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>
4#include <errno.h>
5#include <stdlib.h>
6#include <sys/types.h>
7#include <netinet/in.h>
8#include <arpa/inet.h>
9#include <ifaddrs.h>
10#include <unistd.h>
11
12#include "aos/common/logging/logging.h"
13#include "aos/common/unique_malloc_ptr.h"
14#include "aos/common/once.h"
15
16namespace aos {
17namespace configuration {
18namespace {
19
20// Including the terminating '\0'.
21const size_t kMaxAddrLength = 18;
22
Brian Silverman14fd0fb2014-01-14 21:42:01 -080023// TODO(brians): Don't hard-code this.
24const char *const kLinuxNetInterface = "eth0";
Brian Silverman66f079a2013-08-26 16:24:30 -070025const in_addr *DoGetOwnIPAddress() {
26 ifaddrs *addrs;
27 if (getifaddrs(&addrs) != 0) {
28 LOG(FATAL, "getifaddrs(%p) failed with %d: %s\n", &addrs,
29 errno, strerror(errno));
30 }
31 // Smart pointers don't work very well for iterating through a linked list,
32 // but it does do a very nice job of making sure that addrs gets freed.
33 unique_c_ptr<ifaddrs, freeifaddrs> addrs_deleter(addrs);
34
35 for (; addrs != NULL; addrs = addrs->ifa_next) {
36 if (addrs->ifa_addr->sa_family == AF_INET) {
Brian Silverman14fd0fb2014-01-14 21:42:01 -080037 if (strcmp(kLinuxNetInterface, addrs->ifa_name) == 0) {
Brian Silverman66f079a2013-08-26 16:24:30 -070038 static const in_addr r =
Brian Silverman63cf2412013-11-17 05:44:36 -080039 reinterpret_cast<sockaddr_in *>(__builtin_assume_aligned(
40 addrs->ifa_addr, alignof(sockaddr_in)))->sin_addr;
Brian Silverman66f079a2013-08-26 16:24:30 -070041 return &r;
42 }
43 }
44 }
45 LOG(FATAL, "couldn't find an AF_INET interface named \"%s\"\n",
Brian Silverman14fd0fb2014-01-14 21:42:01 -080046 kLinuxNetInterface);
Brian Silverman66f079a2013-08-26 16:24:30 -070047}
48
49const char *DoGetRootDirectory() {
50 ssize_t size = 0;
51 char *r = NULL;
52 while (true) {
53 if (r != NULL) delete r;
54 size += 256;
55 r = new char[size];
56
57 ssize_t ret = readlink("/proc/self/exe", r, size);
58 if (ret < 0) {
59 if (ret != -1) {
60 LOG(WARNING, "it returned %zd, not -1\n", ret);
61 }
62 LOG(FATAL, "readlink(\"/proc/self/exe\", %p, %zu) failed with %d: %s\n",
63 r, size, errno, strerror(errno));
64 }
65 if (ret < size) {
66 void *last_slash = memrchr(r, '/', size);
67 if (last_slash == NULL) {
68 r[ret] = '\0';
69 LOG(FATAL, "couldn't find a '/' in \"%s\"\n", r);
70 }
71 *static_cast<char *>(last_slash) = '\0';
72 LOG(INFO, "got a root dir of \"%s\"\n", r);
73 return r;
74 }
75 }
76}
77
78const char *DoGetLoggingDirectory() {
79 static const char kSuffix[] = "/../../tmp/robot_logs";
80 const char *root = GetRootDirectory();
81 char *r = new char[strlen(root) + sizeof(kSuffix)];
82 strcpy(r, root);
83 strcat(r, kSuffix);
84 return r;
85}
86
87} // namespace
88
89const char *GetRootDirectory() {
90 static aos::Once<const char> once(DoGetRootDirectory);
91 return once.Get();
92}
93
94const char *GetLoggingDirectory() {
95 static aos::Once<const char> once(DoGetLoggingDirectory);
96 return once.Get();
97}
98
99const in_addr &GetOwnIPAddress() {
100 static aos::Once<const in_addr> once(DoGetOwnIPAddress);
101 return *once.Get();
102}
103
104} // namespace configuration
105} // namespace aos