blob: 2d6dab8710e82a08a226f4381d1e66eba9280da5 [file] [log] [blame]
Brian Silverman66f079a2013-08-26 16:24:30 -07001#include "aos/atom_code/configuration.h"
2
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
23const char *const kAtomNetInterface = "eth0";
24const in_addr *DoGetOwnIPAddress() {
25 ifaddrs *addrs;
26 if (getifaddrs(&addrs) != 0) {
27 LOG(FATAL, "getifaddrs(%p) failed with %d: %s\n", &addrs,
28 errno, strerror(errno));
29 }
30 // Smart pointers don't work very well for iterating through a linked list,
31 // but it does do a very nice job of making sure that addrs gets freed.
32 unique_c_ptr<ifaddrs, freeifaddrs> addrs_deleter(addrs);
33
34 for (; addrs != NULL; addrs = addrs->ifa_next) {
35 if (addrs->ifa_addr->sa_family == AF_INET) {
36 if (strcmp(kAtomNetInterface, addrs->ifa_name) == 0) {
37 static const in_addr r =
Brian Silverman63cf2412013-11-17 05:44:36 -080038 reinterpret_cast<sockaddr_in *>(__builtin_assume_aligned(
39 addrs->ifa_addr, alignof(sockaddr_in)))->sin_addr;
Brian Silverman66f079a2013-08-26 16:24:30 -070040 return &r;
41 }
42 }
43 }
44 LOG(FATAL, "couldn't find an AF_INET interface named \"%s\"\n",
45 kAtomNetInterface);
46}
47
48const char *DoGetRootDirectory() {
49 ssize_t size = 0;
50 char *r = NULL;
51 while (true) {
52 if (r != NULL) delete r;
53 size += 256;
54 r = new char[size];
55
56 ssize_t ret = readlink("/proc/self/exe", r, size);
57 if (ret < 0) {
58 if (ret != -1) {
59 LOG(WARNING, "it returned %zd, not -1\n", ret);
60 }
61 LOG(FATAL, "readlink(\"/proc/self/exe\", %p, %zu) failed with %d: %s\n",
62 r, size, errno, strerror(errno));
63 }
64 if (ret < size) {
65 void *last_slash = memrchr(r, '/', size);
66 if (last_slash == NULL) {
67 r[ret] = '\0';
68 LOG(FATAL, "couldn't find a '/' in \"%s\"\n", r);
69 }
70 *static_cast<char *>(last_slash) = '\0';
71 LOG(INFO, "got a root dir of \"%s\"\n", r);
72 return r;
73 }
74 }
75}
76
77const char *DoGetLoggingDirectory() {
78 static const char kSuffix[] = "/../../tmp/robot_logs";
79 const char *root = GetRootDirectory();
80 char *r = new char[strlen(root) + sizeof(kSuffix)];
81 strcpy(r, root);
82 strcat(r, kSuffix);
83 return r;
84}
85
86} // namespace
87
88const char *GetRootDirectory() {
89 static aos::Once<const char> once(DoGetRootDirectory);
90 return once.Get();
91}
92
93const char *GetLoggingDirectory() {
94 static aos::Once<const char> once(DoGetLoggingDirectory);
95 return once.Get();
96}
97
98const in_addr &GetOwnIPAddress() {
99 static aos::Once<const in_addr> once(DoGetOwnIPAddress);
100 return *once.Get();
101}
102
103} // namespace configuration
104} // namespace aos