blob: a5dd4eeda1d6b8dde3f55ebab633280842908246 [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 =
38 reinterpret_cast<sockaddr_in *>(addrs->ifa_addr)->sin_addr;
39 return &r;
40 }
41 }
42 }
43 LOG(FATAL, "couldn't find an AF_INET interface named \"%s\"\n",
44 kAtomNetInterface);
45}
46
47const char *DoGetRootDirectory() {
48 ssize_t size = 0;
49 char *r = NULL;
50 while (true) {
51 if (r != NULL) delete r;
52 size += 256;
53 r = new char[size];
54
55 ssize_t ret = readlink("/proc/self/exe", r, size);
56 if (ret < 0) {
57 if (ret != -1) {
58 LOG(WARNING, "it returned %zd, not -1\n", ret);
59 }
60 LOG(FATAL, "readlink(\"/proc/self/exe\", %p, %zu) failed with %d: %s\n",
61 r, size, errno, strerror(errno));
62 }
63 if (ret < size) {
64 void *last_slash = memrchr(r, '/', size);
65 if (last_slash == NULL) {
66 r[ret] = '\0';
67 LOG(FATAL, "couldn't find a '/' in \"%s\"\n", r);
68 }
69 *static_cast<char *>(last_slash) = '\0';
70 LOG(INFO, "got a root dir of \"%s\"\n", r);
71 return r;
72 }
73 }
74}
75
76const char *DoGetLoggingDirectory() {
77 static const char kSuffix[] = "/../../tmp/robot_logs";
78 const char *root = GetRootDirectory();
79 char *r = new char[strlen(root) + sizeof(kSuffix)];
80 strcpy(r, root);
81 strcat(r, kSuffix);
82 return r;
83}
84
85} // namespace
86
87const char *GetRootDirectory() {
88 static aos::Once<const char> once(DoGetRootDirectory);
89 return once.Get();
90}
91
92const char *GetLoggingDirectory() {
93 static aos::Once<const char> once(DoGetLoggingDirectory);
94 return once.Get();
95}
96
97const in_addr &GetOwnIPAddress() {
98 static aos::Once<const in_addr> once(DoGetOwnIPAddress);
99 return *once.Get();
100}
101
102} // namespace configuration
103} // namespace aos