cpp

Coverage Report

Created: 2022-09-21 22:22

/home/andy/git/oilshell/oil/cpp/leaky_core.cc
Line
Count
Source (jump to first uncovered line)
1
// leaky_core.cc
2
3
// clang-format off
4
#include "mycpp/myerror.h"
5
// clang-format on
6
7
#include "cpp/leaky_core.h"
8
9
#include <errno.h>
10
#include <pwd.h>  // passwd
11
#include <signal.h>
12
#include <sys/resource.h>  // getrusage
13
#include <sys/times.h>     // tms / times()
14
#include <sys/utsname.h>   // uname
15
#include <sys/wait.h>      // waitpid()
16
#include <time.h>          // time()
17
#include <unistd.h>        // getuid(), environ
18
19
namespace pyos {
20
21
0
Tuple2<int, int> WaitPid() {
22
0
  int status;
23
0
  int result = ::waitpid(-1, &status, WUNTRACED);
24
0
  if (result < 0) {
25
0
    return Tuple2<int, int>(-1, errno);
26
0
  }
27
0
  return Tuple2<int, int>(result, status);
28
0
}
29
30
2
Tuple2<int, int> Read(int fd, int n, List<Str*>* chunks) {
31
2
  Str* s = OverAllocatedStr(n);  // Allocate enough for the result
32
33
2
  int length = ::read(fd, s->data(), n);
34
2
  if (length < 0) {
35
0
    return Tuple2<int, int>(-1, errno);
36
0
  }
37
2
  if (length == 0) {
38
1
    return Tuple2<int, int>(length, 0);
39
1
  }
40
41
  // Now we know how much data we got back
42
1
  s->SetObjLenFromStrLen(length);
43
1
  chunks->append(s);
44
45
1
  return Tuple2<int, int>(length, 0);
46
2
}
47
48
3
Tuple2<int, int> ReadByte(int fd) {
49
3
  unsigned char buf[1];
50
3
  ssize_t n = read(fd, &buf, 1);
51
3
  if (n < 0) {  // read error
52
0
    return Tuple2<int, int>(-1, errno);
53
3
  } else if (n == 0) {  // EOF
54
1
    return Tuple2<int, int>(EOF_SENTINEL, 0);
55
2
  } else {  // return character
56
2
    return Tuple2<int, int>(buf[0], 0);
57
2
  }
58
3
}
59
60
// for read --line
61
0
Str* ReadLine() {
62
0
  assert(0);  // Does this get called?
63
0
}
64
65
0
Dict<Str*, Str*>* Environ() {
66
0
  auto d = NewDict<Str*, Str*>();
67
68
0
  for (char** env = environ; *env; ++env) {
69
0
    char* pair = *env;
70
71
0
    char* eq = strchr(pair, '=');
72
0
    assert(eq != nullptr);  // must look like KEY=value
73
74
0
    int key_len = eq - pair;
75
0
    char* buf = static_cast<char*>(malloc(key_len + 1));
76
0
    memcpy(buf, pair, key_len);  // includes NUL terminator
77
0
    buf[key_len] = '\0';
78
79
0
    Str* key = StrFromC(buf, key_len);
80
81
0
    int len = strlen(pair);
82
0
    int val_len = len - key_len - 1;
83
0
    char* buf2 = static_cast<char*>(malloc(val_len + 1));
84
0
    memcpy(buf2, eq + 1, val_len);  // copy starting after =
85
0
    buf2[val_len] = '\0';
86
87
0
    Str* val = StrFromC(buf2, val_len);
88
89
0
    d->set(key, val);
90
0
  }
91
92
0
  return d;
93
0
}
94
95
0
int Chdir(Str* dest_dir) {
96
0
  if (chdir(dest_dir->data_) == 0) {
97
0
    return 0;  // success
98
0
  } else {
99
0
    return errno;
100
0
  }
101
0
}
102
103
0
Str* GetMyHomeDir() {
104
0
  uid_t uid = getuid();  // always succeeds
105
106
  // Don't free this.  (May return a pointer to a static area)
107
0
  struct passwd* entry = getpwuid(uid);
108
0
  if (entry == nullptr) {
109
0
    return nullptr;
110
0
  }
111
0
  return StrFromC(entry->pw_dir);
112
0
}
113
114
0
Str* GetHomeDir(Str* user_name) {
115
  // Don't free this.  (May return a pointer to a static area)
116
0
  struct passwd* entry = getpwnam(user_name->data_);
117
0
  if (entry == nullptr) {
118
0
    return nullptr;
119
0
  }
120
0
  return StrFromC(entry->pw_dir);
121
0
}
122
123
0
Str* GetUserName(int uid) {
124
0
  Str* result = kEmptyString;
125
126
0
  if (passwd* pw = getpwuid(uid)) {
127
0
    result = CopyBufferIntoNewStr(pw->pw_name);
128
0
  } else {
129
0
    throw Alloc<IOError>(errno);
130
0
  }
131
132
0
  return result;
133
0
}
134
135
0
Str* OsType() {
136
0
  Str* result = kEmptyString;
137
138
0
  utsname un = {};
139
0
  if (::uname(&un) == 0) {
140
0
    result = CopyBufferIntoNewStr(un.sysname);
141
0
  } else {
142
0
    throw Alloc<IOError>(errno);
143
0
  }
144
145
0
  return result;
146
0
}
147
148
0
Tuple3<double, double, double> Time() {
149
0
  rusage ru;  // NOTE(Jesse): Doesn't have to be cleared to 0.  The kernel
150
              // clears unused fields.
151
0
  if (::getrusage(RUSAGE_SELF, &ru) == -1) {
152
0
    throw Alloc<IOError>(errno);
153
0
  }
154
155
0
  time_t t = ::time(nullptr);
156
0
  auto result = Tuple3<double, double, double>(
157
0
      static_cast<double>(t), static_cast<double>(ru.ru_utime.tv_sec),
158
0
      static_cast<double>(ru.ru_stime.tv_sec));
159
0
  return result;
160
0
}
161
162
0
void PrintTimes() {
163
0
  tms t;
164
0
  if (times(&t) == -1) {
165
0
    throw Alloc<IOError>(errno);
166
0
  } else {
167
0
    {
168
0
      int user_minutes = t.tms_utime / 60;
169
0
      float user_seconds = t.tms_utime % 60;
170
0
      int system_minutes = t.tms_stime / 60;
171
0
      float system_seconds = t.tms_stime % 60;
172
0
      printf("%dm%1.3fs %dm%1.3fs", user_minutes, user_seconds, system_minutes,
173
0
             system_seconds);
174
0
    }
175
176
0
    {
177
0
      int child_user_minutes = t.tms_cutime / 60;
178
0
      float child_user_seconds = t.tms_cutime % 60;
179
0
      int child_system_minutes = t.tms_cstime / 60;
180
0
      float child_system_seconds = t.tms_cstime % 60;
181
0
      printf("%dm%1.3fs %dm%1.3fs", child_user_minutes, child_user_seconds,
182
0
             child_system_minutes, child_system_seconds);
183
0
    }
184
0
  }
185
0
}
186
187
0
bool InputAvailable(int fd) {
188
0
  NotImplemented();
189
0
}
190
191
0
void SignalState_AfterForkingChild() {
192
0
  signal(SIGQUIT, SIG_DFL);
193
0
  signal(SIGPIPE, SIG_DFL);
194
0
  signal(SIGTSTP, SIG_DFL);
195
0
}
196
197
}  // namespace pyos
198
199
namespace pyutil {
200
201
0
bool IsValidCharEscape(int c) {
202
0
  if (c == '/' || c == '.' || c == '-') {
203
0
    return false;
204
0
  }
205
0
  if (c == ' ') {  // foo\ bar is idiomatic
206
0
    return true;
207
0
  }
208
0
  return ispunct(c);
209
0
}
210
211
3
Str* ChArrayToString(List<int>* ch_array) {
212
3
  int n = len(ch_array);
213
3
  unsigned char* buf = static_cast<unsigned char*>(malloc(n + 1));
214
11
  for (int i = 0; i < n; ++i) {
215
8
    buf[i] = ch_array->index_(i);
216
8
  }
217
3
  buf[n] = '\0';
218
3
  return CopyBufferIntoNewStr(reinterpret_cast<char*>(buf), n);
219
3
}
220
221
0
Str* _ResourceLoader::Get(Str* path) {
222
  /* NotImplemented(); */
223
0
  return StrFromC("TODO");
224
0
}
225
226
0
_ResourceLoader* GetResourceLoader() {
227
0
  return Alloc<_ResourceLoader>();
228
0
}
229
230
0
void CopyFile(Str* in_path, Str* out_path) {
231
0
  assert(0);
232
0
}
233
234
0
Str* GetVersion(_ResourceLoader* loader) {
235
  /* NotImplemented(); */
236
0
  return StrFromC("TODO");
237
0
}
238
239
0
Str* ShowAppVersion(Str* app_name, _ResourceLoader* loader) {
240
0
  assert(0);
241
0
}
242
243
2
Str* BackslashEscape(Str* s, Str* meta_chars) {
244
2
  int upper_bound = len(s) * 2;
245
2
  char* buf = static_cast<char*>(malloc(upper_bound));
246
2
  char* p = buf;
247
248
11
  for (int i = 0; i < len(s); ++i) {
249
9
    char c = s->data_[i];
250
9
    if (memchr(meta_chars->data_, c, len(meta_chars))) {
251
3
      *p++ = '\\';
252
3
    }
253
9
    *p++ = c;
254
9
  }
255
2
  int len = p - buf;
256
2
  return CopyBufferIntoNewStr(buf, len);
257
2
}
258
259
// Hack so e->errno will work below
260
#undef errno
261
262
0
Str* strerror(_OSError* e) {
263
0
  return CopyBufferIntoNewStr(::strerror(e->errno));
264
0
}
265
266
}  // namespace pyutil