daemon: Support SHA-512 hashes.
[jackhill/guix/guix.git] / nix / libutil / util.cc
1 #include "config.h"
2
3 #include "util.hh"
4 #include "affinity.hh"
5
6 #include <iostream>
7 #include <cerrno>
8 #include <cstdio>
9 #include <cstdlib>
10 #include <sstream>
11 #include <cstring>
12
13 #include <sys/wait.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16 #include <limits.h>
17
18 #ifdef __APPLE__
19 #include <sys/syscall.h>
20 #endif
21
22 #ifdef __linux__
23 #include <sys/prctl.h>
24 #endif
25
26
27 extern char * * environ;
28
29
30 namespace nix {
31
32
33 BaseError::BaseError(const FormatOrString & fs, unsigned int status)
34 : status(status)
35 {
36 err = fs.s;
37 }
38
39
40 BaseError & BaseError::addPrefix(const FormatOrString & fs)
41 {
42 prefix_ = fs.s + prefix_;
43 return *this;
44 }
45
46
47 SysError::SysError(const FormatOrString & fs)
48 : Error(format("%1%: %2%") % fs.s % strerror(errno))
49 , errNo(errno)
50 {
51 }
52
53
54 string getEnv(const string & key, const string & def)
55 {
56 char * value = getenv(key.c_str());
57 return value ? string(value) : def;
58 }
59
60
61 Path absPath(Path path, Path dir)
62 {
63 if (path[0] != '/') {
64 if (dir == "") {
65 #ifdef __GNU__
66 /* GNU (aka. GNU/Hurd) doesn't have any limitation on path
67 lengths and doesn't define `PATH_MAX'. */
68 char *buf = getcwd(NULL, 0);
69 if (buf == NULL)
70 #else
71 char buf[PATH_MAX];
72 if (!getcwd(buf, sizeof(buf)))
73 #endif
74 throw SysError("cannot get cwd");
75 dir = buf;
76 #ifdef __GNU__
77 free(buf);
78 #endif
79 }
80 path = dir + "/" + path;
81 }
82 return canonPath(path);
83 }
84
85
86 Path canonPath(const Path & path, bool resolveSymlinks)
87 {
88 string s;
89
90 if (path[0] != '/')
91 throw Error(format("not an absolute path: `%1%'") % path);
92
93 string::const_iterator i = path.begin(), end = path.end();
94 string temp;
95
96 /* Count the number of times we follow a symlink and stop at some
97 arbitrary (but high) limit to prevent infinite loops. */
98 unsigned int followCount = 0, maxFollow = 1024;
99
100 while (1) {
101
102 /* Skip slashes. */
103 while (i != end && *i == '/') i++;
104 if (i == end) break;
105
106 /* Ignore `.'. */
107 if (*i == '.' && (i + 1 == end || i[1] == '/'))
108 i++;
109
110 /* If `..', delete the last component. */
111 else if (*i == '.' && i + 1 < end && i[1] == '.' &&
112 (i + 2 == end || i[2] == '/'))
113 {
114 if (!s.empty()) s.erase(s.rfind('/'));
115 i += 2;
116 }
117
118 /* Normal component; copy it. */
119 else {
120 s += '/';
121 while (i != end && *i != '/') s += *i++;
122
123 /* If s points to a symlink, resolve it and restart (since
124 the symlink target might contain new symlinks). */
125 if (resolveSymlinks && isLink(s)) {
126 if (++followCount >= maxFollow)
127 throw Error(format("infinite symlink recursion in path `%1%'") % path);
128 temp = absPath(readLink(s), dirOf(s))
129 + string(i, end);
130 i = temp.begin(); /* restart */
131 end = temp.end();
132 s = "";
133 }
134 }
135 }
136
137 return s.empty() ? "/" : s;
138 }
139
140
141 Path dirOf(const Path & path)
142 {
143 Path::size_type pos = path.rfind('/');
144 if (pos == string::npos)
145 throw Error(format("invalid file name `%1%'") % path);
146 return pos == 0 ? "/" : Path(path, 0, pos);
147 }
148
149
150 string baseNameOf(const Path & path)
151 {
152 Path::size_type pos = path.rfind('/');
153 if (pos == string::npos)
154 throw Error(format("invalid file name `%1%'") % path);
155 return string(path, pos + 1);
156 }
157
158
159 bool isInDir(const Path & path, const Path & dir)
160 {
161 return path[0] == '/'
162 && string(path, 0, dir.size()) == dir
163 && path.size() >= dir.size() + 2
164 && path[dir.size()] == '/';
165 }
166
167
168 struct stat lstat(const Path & path)
169 {
170 struct stat st;
171 if (lstat(path.c_str(), &st))
172 throw SysError(format("getting status of `%1%'") % path);
173 return st;
174 }
175
176
177 bool pathExists(const Path & path)
178 {
179 int res;
180 struct stat st;
181 res = lstat(path.c_str(), &st);
182 if (!res) return true;
183 if (errno != ENOENT && errno != ENOTDIR)
184 throw SysError(format("getting status of %1%") % path);
185 return false;
186 }
187
188
189 Path readLink(const Path & path)
190 {
191 checkInterrupt();
192 struct stat st = lstat(path);
193 if (!S_ISLNK(st.st_mode))
194 throw Error(format("`%1%' is not a symlink") % path);
195 char buf[st.st_size];
196 ssize_t rlsize = readlink(path.c_str(), buf, st.st_size);
197 if (rlsize == -1)
198 throw SysError(format("reading symbolic link '%1%'") % path);
199 else if (rlsize > st.st_size)
200 throw Error(format("symbolic link ‘%1%’ size overflow %2% > %3%")
201 % path % rlsize % st.st_size);
202 return string(buf, st.st_size);
203 }
204
205
206 bool isLink(const Path & path)
207 {
208 struct stat st = lstat(path);
209 return S_ISLNK(st.st_mode);
210 }
211
212
213 DirEntries readDirectory(const Path & path)
214 {
215 DirEntries entries;
216 entries.reserve(64);
217
218 AutoCloseDir dir = opendir(path.c_str());
219 if (!dir) throw SysError(format("opening directory `%1%'") % path);
220
221 struct dirent * dirent;
222 while (errno = 0, dirent = readdir(dir)) { /* sic */
223 checkInterrupt();
224 string name = dirent->d_name;
225 if (name == "." || name == "..") continue;
226 entries.emplace_back(name, dirent->d_ino, dirent->d_type);
227 }
228 if (errno) throw SysError(format("reading directory `%1%'") % path);
229
230 return entries;
231 }
232
233
234 unsigned char getFileType(const Path & path)
235 {
236 struct stat st = lstat(path);
237 if (S_ISDIR(st.st_mode)) return DT_DIR;
238 if (S_ISLNK(st.st_mode)) return DT_LNK;
239 if (S_ISREG(st.st_mode)) return DT_REG;
240 return DT_UNKNOWN;
241 }
242
243
244 string readFile(int fd)
245 {
246 struct stat st;
247 if (fstat(fd, &st) == -1)
248 throw SysError("statting file");
249
250 unsigned char * buf = new unsigned char[st.st_size];
251 AutoDeleteArray<unsigned char> d(buf);
252 readFull(fd, buf, st.st_size);
253
254 return string((char *) buf, st.st_size);
255 }
256
257
258 string readFile(const Path & path, bool drain)
259 {
260 AutoCloseFD fd = open(path.c_str(), O_RDONLY);
261 if (fd == -1)
262 throw SysError(format("opening file `%1%'") % path);
263 return drain ? drainFD(fd) : readFile(fd);
264 }
265
266
267 void writeFile(const Path & path, const string & s)
268 {
269 AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666);
270 if (fd == -1)
271 throw SysError(format("opening file '%1%'") % path);
272 writeFull(fd, s);
273 }
274
275
276 string readLine(int fd)
277 {
278 string s;
279 while (1) {
280 checkInterrupt();
281 char ch;
282 ssize_t rd = read(fd, &ch, 1);
283 if (rd == -1) {
284 if (errno != EINTR)
285 throw SysError("reading a line");
286 } else if (rd == 0)
287 throw EndOfFile("unexpected EOF reading a line");
288 else {
289 if (ch == '\n') return s;
290 s += ch;
291 }
292 }
293 }
294
295
296 void writeLine(int fd, string s)
297 {
298 s += '\n';
299 writeFull(fd, s);
300 }
301
302
303 static void _deletePath(const Path & path, unsigned long long & bytesFreed)
304 {
305 checkInterrupt();
306
307 printMsg(lvlVomit, format("%1%") % path);
308
309 struct stat st = lstat(path);
310
311 if (!S_ISDIR(st.st_mode) && st.st_nlink == 1)
312 bytesFreed += st.st_blocks * 512;
313
314 if (S_ISDIR(st.st_mode)) {
315 /* Make the directory writable. */
316 if (!(st.st_mode & S_IWUSR)) {
317 if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
318 throw SysError(format("making `%1%' writable") % path);
319 }
320
321 for (auto & i : readDirectory(path))
322 _deletePath(path + "/" + i.name, bytesFreed);
323 }
324
325 if (remove(path.c_str()) == -1)
326 throw SysError(format("cannot unlink `%1%'") % path);
327 }
328
329
330 void deletePath(const Path & path)
331 {
332 unsigned long long dummy;
333 deletePath(path, dummy);
334 }
335
336
337 void deletePath(const Path & path, unsigned long long & bytesFreed)
338 {
339 startNest(nest, lvlDebug,
340 format("recursively deleting path `%1%'") % path);
341 bytesFreed = 0;
342 _deletePath(path, bytesFreed);
343 }
344
345
346 static Path tempName(Path tmpRoot, const Path & prefix, bool includePid,
347 int & counter)
348 {
349 tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot, true);
350 if (includePid)
351 return (format("%1%/%2%-%3%-%4%") % tmpRoot % prefix % getpid() % counter++).str();
352 else
353 return (format("%1%/%2%-%3%") % tmpRoot % prefix % counter++).str();
354 }
355
356
357 Path createTempDir(const Path & tmpRoot, const Path & prefix,
358 bool includePid, bool useGlobalCounter, mode_t mode)
359 {
360 static int globalCounter = 0;
361 int localCounter = 0;
362 int & counter(useGlobalCounter ? globalCounter : localCounter);
363
364 while (1) {
365 checkInterrupt();
366 Path tmpDir = tempName(tmpRoot, prefix, includePid, counter);
367 if (mkdir(tmpDir.c_str(), mode) == 0) {
368 /* Explicitly set the group of the directory. This is to
369 work around around problems caused by BSD's group
370 ownership semantics (directories inherit the group of
371 the parent). For instance, the group of /tmp on
372 FreeBSD is "wheel", so all directories created in /tmp
373 will be owned by "wheel"; but if the user is not in
374 "wheel", then "tar" will fail to unpack archives that
375 have the setgid bit set on directories. */
376 if (chown(tmpDir.c_str(), (uid_t) -1, getegid()) != 0)
377 throw SysError(format("setting group of directory `%1%'") % tmpDir);
378 return tmpDir;
379 }
380 if (errno != EEXIST)
381 throw SysError(format("creating directory `%1%'") % tmpDir);
382 }
383 }
384
385
386 Paths createDirs(const Path & path)
387 {
388 Paths created;
389 if (path == "/") return created;
390
391 struct stat st;
392 if (lstat(path.c_str(), &st) == -1) {
393 created = createDirs(dirOf(path));
394 if (mkdir(path.c_str(), 0777) == -1 && errno != EEXIST)
395 throw SysError(format("creating directory `%1%'") % path);
396 st = lstat(path);
397 created.push_back(path);
398 }
399
400 if (S_ISLNK(st.st_mode) && stat(path.c_str(), &st) == -1)
401 throw SysError(format("statting symlink `%1%'") % path);
402
403 if (!S_ISDIR(st.st_mode)) throw Error(format("`%1%' is not a directory") % path);
404
405 return created;
406 }
407
408
409 void createSymlink(const Path & target, const Path & link)
410 {
411 if (symlink(target.c_str(), link.c_str()))
412 throw SysError(format("creating symlink from `%1%' to `%2%'") % link % target);
413 }
414
415
416 LogType logType = ltPretty;
417 Verbosity verbosity = lvlInfo;
418
419 static int nestingLevel = 0;
420
421
422 Nest::Nest()
423 {
424 nest = false;
425 }
426
427
428 Nest::~Nest()
429 {
430 close();
431 }
432
433
434 static string escVerbosity(Verbosity level)
435 {
436 return std::to_string((int) level);
437 }
438
439
440 void Nest::open(Verbosity level, const FormatOrString & fs)
441 {
442 if (level <= verbosity) {
443 if (logType == ltEscapes)
444 std::cerr << "\033[" << escVerbosity(level) << "p"
445 << fs.s << "\n";
446 else
447 printMsg_(level, fs);
448 nest = true;
449 nestingLevel++;
450 }
451 }
452
453
454 void Nest::close()
455 {
456 if (nest) {
457 nestingLevel--;
458 if (logType == ltEscapes)
459 std::cerr << "\033[q";
460 nest = false;
461 }
462 }
463
464
465 void printMsg_(Verbosity level, const FormatOrString & fs)
466 {
467 checkInterrupt();
468 if (level > verbosity) return;
469 string prefix;
470 if (logType == ltPretty)
471 for (int i = 0; i < nestingLevel; i++)
472 prefix += "| ";
473 else if (logType == ltEscapes && level != lvlInfo)
474 prefix = "\033[" + escVerbosity(level) + "s";
475 string s = (format("%1%%2%\n") % prefix % fs.s).str();
476 writeToStderr(s);
477 }
478
479
480 void warnOnce(bool & haveWarned, const FormatOrString & fs)
481 {
482 if (!haveWarned) {
483 printMsg(lvlError, format("warning: %1%") % fs.s);
484 haveWarned = true;
485 }
486 }
487
488
489 void writeToStderr(const string & s)
490 {
491 try {
492 if (_writeToStderr)
493 _writeToStderr((const unsigned char *) s.data(), s.size());
494 else
495 writeFull(STDERR_FILENO, s);
496 } catch (SysError & e) {
497 /* Ignore failing writes to stderr if we're in an exception
498 handler, otherwise throw an exception. We need to ignore
499 write errors in exception handlers to ensure that cleanup
500 code runs to completion if the other side of stderr has
501 been closed unexpectedly. */
502 if (!std::uncaught_exception()) throw;
503 }
504 }
505
506
507 void (*_writeToStderr) (const unsigned char * buf, size_t count) = 0;
508
509
510 void readFull(int fd, unsigned char * buf, size_t count)
511 {
512 while (count) {
513 checkInterrupt();
514 ssize_t res = read(fd, (char *) buf, count);
515 if (res == -1) {
516 if (errno == EINTR) continue;
517 throw SysError("reading from file");
518 }
519 if (res == 0) throw EndOfFile("unexpected end-of-file");
520 count -= res;
521 buf += res;
522 }
523 }
524
525
526 void writeFull(int fd, const unsigned char * buf, size_t count)
527 {
528 while (count) {
529 checkInterrupt();
530 ssize_t res = write(fd, (char *) buf, count);
531 if (res == -1) {
532 if (errno == EINTR) continue;
533 throw SysError("writing to file");
534 }
535 count -= res;
536 buf += res;
537 }
538 }
539
540
541 void writeFull(int fd, const string & s)
542 {
543 writeFull(fd, (const unsigned char *) s.data(), s.size());
544 }
545
546
547 string drainFD(int fd)
548 {
549 string result;
550 unsigned char buffer[4096];
551 while (1) {
552 checkInterrupt();
553 ssize_t rd = read(fd, buffer, sizeof buffer);
554 if (rd == -1) {
555 if (errno != EINTR)
556 throw SysError("reading from file");
557 }
558 else if (rd == 0) break;
559 else result.append((char *) buffer, rd);
560 }
561 return result;
562 }
563
564
565
566 //////////////////////////////////////////////////////////////////////
567
568
569 AutoDelete::AutoDelete(const string & p, bool recursive) : path(p)
570 {
571 del = true;
572 this->recursive = recursive;
573 }
574
575 AutoDelete::~AutoDelete()
576 {
577 try {
578 if (del) {
579 if (recursive)
580 deletePath(path);
581 else {
582 if (remove(path.c_str()) == -1)
583 throw SysError(format("cannot unlink `%1%'") % path);
584 }
585 }
586 } catch (...) {
587 ignoreException();
588 }
589 }
590
591 void AutoDelete::cancel()
592 {
593 del = false;
594 }
595
596
597
598 //////////////////////////////////////////////////////////////////////
599
600
601 AutoCloseFD::AutoCloseFD()
602 {
603 fd = -1;
604 }
605
606
607 AutoCloseFD::AutoCloseFD(int fd)
608 {
609 this->fd = fd;
610 }
611
612
613 AutoCloseFD::AutoCloseFD(const AutoCloseFD & fd)
614 {
615 /* Copying an AutoCloseFD isn't allowed (who should get to close
616 it?). But as an edge case, allow copying of closed
617 AutoCloseFDs. This is necessary due to tiresome reasons
618 involving copy constructor use on default object values in STL
619 containers (like when you do `map[value]' where value isn't in
620 the map yet). */
621 this->fd = fd.fd;
622 if (this->fd != -1) abort();
623 }
624
625
626 AutoCloseFD::~AutoCloseFD()
627 {
628 try {
629 close();
630 } catch (...) {
631 ignoreException();
632 }
633 }
634
635
636 void AutoCloseFD::operator =(int fd)
637 {
638 if (this->fd != fd) close();
639 this->fd = fd;
640 }
641
642
643 AutoCloseFD::operator int() const
644 {
645 return fd;
646 }
647
648
649 void AutoCloseFD::close()
650 {
651 if (fd != -1) {
652 if (::close(fd) == -1)
653 /* This should never happen. */
654 throw SysError(format("closing file descriptor %1%") % fd);
655 fd = -1;
656 }
657 }
658
659
660 bool AutoCloseFD::isOpen()
661 {
662 return fd != -1;
663 }
664
665
666 /* Pass responsibility for closing this fd to the caller. */
667 int AutoCloseFD::borrow()
668 {
669 int oldFD = fd;
670 fd = -1;
671 return oldFD;
672 }
673
674
675 void Pipe::create()
676 {
677 int fds[2];
678 if (pipe(fds) != 0) throw SysError("creating pipe");
679 readSide = fds[0];
680 writeSide = fds[1];
681 closeOnExec(readSide);
682 closeOnExec(writeSide);
683 }
684
685
686
687 //////////////////////////////////////////////////////////////////////
688
689
690 AutoCloseDir::AutoCloseDir()
691 {
692 dir = 0;
693 }
694
695
696 AutoCloseDir::AutoCloseDir(DIR * dir)
697 {
698 this->dir = dir;
699 }
700
701
702 AutoCloseDir::~AutoCloseDir()
703 {
704 close();
705 }
706
707
708 void AutoCloseDir::operator =(DIR * dir)
709 {
710 this->dir = dir;
711 }
712
713
714 AutoCloseDir::operator DIR *()
715 {
716 return dir;
717 }
718
719
720 void AutoCloseDir::close()
721 {
722 if (dir) {
723 closedir(dir);
724 dir = 0;
725 }
726 }
727
728
729 //////////////////////////////////////////////////////////////////////
730
731
732 Pid::Pid()
733 : pid(-1), separatePG(false), killSignal(SIGKILL)
734 {
735 }
736
737
738 Pid::Pid(pid_t pid)
739 : pid(pid), separatePG(false), killSignal(SIGKILL)
740 {
741 }
742
743
744 Pid::~Pid()
745 {
746 kill();
747 }
748
749
750 void Pid::operator =(pid_t pid)
751 {
752 if (this->pid != pid) kill();
753 this->pid = pid;
754 killSignal = SIGKILL; // reset signal to default
755 }
756
757
758 Pid::operator pid_t()
759 {
760 return pid;
761 }
762
763
764 void Pid::kill(bool quiet)
765 {
766 if (pid == -1 || pid == 0) return;
767
768 if (!quiet)
769 printMsg(lvlError, format("killing process %1%") % pid);
770
771 /* Send the requested signal to the child. If it has its own
772 process group, send the signal to every process in the child
773 process group (which hopefully includes *all* its children). */
774 if (::kill(separatePG ? -pid : pid, killSignal) != 0)
775 printMsg(lvlError, (SysError(format("killing process %1%") % pid).msg()));
776
777 /* Wait until the child dies, disregarding the exit status. */
778 int status;
779 while (waitpid(pid, &status, 0) == -1) {
780 checkInterrupt();
781 if (errno != EINTR) {
782 printMsg(lvlError,
783 (SysError(format("waiting for process %1%") % pid).msg()));
784 break;
785 }
786 }
787
788 pid = -1;
789 }
790
791
792 int Pid::wait(bool block)
793 {
794 assert(pid != -1);
795 while (1) {
796 int status;
797 int res = waitpid(pid, &status, block ? 0 : WNOHANG);
798 if (res == pid) {
799 pid = -1;
800 return status;
801 }
802 if (res == 0 && !block) return -1;
803 if (errno != EINTR)
804 throw SysError("cannot get child exit status");
805 checkInterrupt();
806 }
807 }
808
809
810 void Pid::setSeparatePG(bool separatePG)
811 {
812 this->separatePG = separatePG;
813 }
814
815
816 void Pid::setKillSignal(int signal)
817 {
818 this->killSignal = signal;
819 }
820
821
822 void killUser(uid_t uid)
823 {
824 debug(format("killing all processes running under uid `%1%'") % uid);
825
826 assert(uid != 0); /* just to be safe... */
827
828 /* The system call kill(-1, sig) sends the signal `sig' to all
829 users to which the current process can send signals. So we
830 fork a process, switch to uid, and send a mass kill. */
831
832 Pid pid = startProcess([&]() {
833
834 if (setuid(uid) == -1)
835 throw SysError("setting uid");
836
837 while (true) {
838 #ifdef __APPLE__
839 /* OSX's kill syscall takes a third parameter that, among
840 other things, determines if kill(-1, signo) affects the
841 calling process. In the OSX libc, it's set to true,
842 which means "follow POSIX", which we don't want here
843 */
844 if (syscall(SYS_kill, -1, SIGKILL, false) == 0) break;
845 #else
846 if (kill(-1, SIGKILL) == 0) break;
847 #endif
848 if (errno == ESRCH) break; /* no more processes */
849 if (errno != EINTR)
850 throw SysError(format("cannot kill processes for uid `%1%'") % uid);
851 }
852
853 _exit(0);
854 });
855
856 int status = pid.wait(true);
857 if (status != 0)
858 throw Error(format("cannot kill processes for uid `%1%': %2%") % uid % statusToString(status));
859
860 /* !!! We should really do some check to make sure that there are
861 no processes left running under `uid', but there is no portable
862 way to do so (I think). The most reliable way may be `ps -eo
863 uid | grep -q $uid'. */
864 }
865
866
867 //////////////////////////////////////////////////////////////////////
868
869
870 pid_t startProcess(std::function<void()> fun,
871 bool dieWithParent, const string & errorPrefix, bool runExitHandlers)
872 {
873 pid_t pid = fork();
874 if (pid == -1) throw SysError("unable to fork");
875
876 if (pid == 0) {
877 _writeToStderr = 0;
878 try {
879 #if __linux__
880 if (dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1)
881 throw SysError("setting death signal");
882 #endif
883 restoreAffinity();
884 fun();
885 } catch (std::exception & e) {
886 try {
887 std::cerr << errorPrefix << e.what() << "\n";
888 } catch (...) { }
889 } catch (...) { }
890 if (runExitHandlers)
891 exit(1);
892 else
893 _exit(1);
894 }
895
896 return pid;
897 }
898
899
900 std::vector<char *> stringsToCharPtrs(const Strings & ss)
901 {
902 std::vector<char *> res;
903 for (auto & s : ss) res.push_back((char *) s.c_str());
904 res.push_back(0);
905 return res;
906 }
907
908
909 string runProgram(Path program, bool searchPath, const Strings & args)
910 {
911 checkInterrupt();
912
913 /* Create a pipe. */
914 Pipe pipe;
915 pipe.create();
916
917 /* Fork. */
918 Pid pid = startProcess([&]() {
919 if (dup2(pipe.writeSide, STDOUT_FILENO) == -1)
920 throw SysError("dupping stdout");
921
922 Strings args_(args);
923 args_.push_front(program);
924
925 if (searchPath)
926 execvp(program.c_str(), stringsToCharPtrs(args_).data());
927 else
928 execv(program.c_str(), stringsToCharPtrs(args_).data());
929
930 throw SysError(format("executing `%1%'") % program);
931 });
932
933 pipe.writeSide.close();
934
935 string result = drainFD(pipe.readSide);
936
937 /* Wait for the child to finish. */
938 int status = pid.wait(true);
939 if (!statusOk(status))
940 throw ExecError(format("program `%1%' %2%")
941 % program % statusToString(status));
942
943 return result;
944 }
945
946
947 void closeMostFDs(const set<int> & exceptions)
948 {
949 int maxFD = 0;
950 maxFD = sysconf(_SC_OPEN_MAX);
951 for (int fd = 0; fd < maxFD; ++fd)
952 if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO
953 && exceptions.find(fd) == exceptions.end())
954 close(fd); /* ignore result */
955 }
956
957
958 void closeOnExec(int fd)
959 {
960 int prev;
961 if ((prev = fcntl(fd, F_GETFD, 0)) == -1 ||
962 fcntl(fd, F_SETFD, prev | FD_CLOEXEC) == -1)
963 throw SysError("setting close-on-exec flag");
964 }
965
966
967 //////////////////////////////////////////////////////////////////////
968
969
970 volatile sig_atomic_t _isInterrupted = 0;
971
972 void _interrupted()
973 {
974 /* Block user interrupts while an exception is being handled.
975 Throwing an exception while another exception is being handled
976 kills the program! */
977 if (!std::uncaught_exception()) {
978 _isInterrupted = 0;
979 throw Interrupted("interrupted by the user");
980 }
981 }
982
983
984
985 //////////////////////////////////////////////////////////////////////
986
987
988 template<class C> C tokenizeString(const string & s, const string & separators)
989 {
990 C result;
991 string::size_type pos = s.find_first_not_of(separators, 0);
992 while (pos != string::npos) {
993 string::size_type end = s.find_first_of(separators, pos + 1);
994 if (end == string::npos) end = s.size();
995 string token(s, pos, end - pos);
996 result.insert(result.end(), token);
997 pos = s.find_first_not_of(separators, end);
998 }
999 return result;
1000 }
1001
1002 template Strings tokenizeString(const string & s, const string & separators);
1003 template StringSet tokenizeString(const string & s, const string & separators);
1004 template vector<string> tokenizeString(const string & s, const string & separators);
1005
1006
1007 string concatStringsSep(const string & sep, const Strings & ss)
1008 {
1009 string s;
1010 foreach (Strings::const_iterator, i, ss) {
1011 if (s.size() != 0) s += sep;
1012 s += *i;
1013 }
1014 return s;
1015 }
1016
1017
1018 string concatStringsSep(const string & sep, const StringSet & ss)
1019 {
1020 string s;
1021 foreach (StringSet::const_iterator, i, ss) {
1022 if (s.size() != 0) s += sep;
1023 s += *i;
1024 }
1025 return s;
1026 }
1027
1028
1029 string chomp(const string & s)
1030 {
1031 size_t i = s.find_last_not_of(" \n\r\t");
1032 return i == string::npos ? "" : string(s, 0, i + 1);
1033 }
1034
1035
1036 string statusToString(int status)
1037 {
1038 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
1039 if (WIFEXITED(status))
1040 return (format("failed with exit code %1%") % WEXITSTATUS(status)).str();
1041 else if (WIFSIGNALED(status)) {
1042 int sig = WTERMSIG(status);
1043 #if HAVE_STRSIGNAL
1044 const char * description = strsignal(sig);
1045 return (format("failed due to signal %1% (%2%)") % sig % description).str();
1046 #else
1047 return (format("failed due to signal %1%") % sig).str();
1048 #endif
1049 }
1050 else
1051 return "died abnormally";
1052 } else return "succeeded";
1053 }
1054
1055
1056 bool statusOk(int status)
1057 {
1058 return WIFEXITED(status) && WEXITSTATUS(status) == 0;
1059 }
1060
1061
1062 bool hasSuffix(const string & s, const string & suffix)
1063 {
1064 return s.size() >= suffix.size() && string(s, s.size() - suffix.size()) == suffix;
1065 }
1066
1067
1068 void expect(std::istream & str, const string & s)
1069 {
1070 char s2[s.size()];
1071 str.read(s2, s.size());
1072 if (string(s2, s.size()) != s)
1073 throw FormatError(format("expected string `%1%'") % s);
1074 }
1075
1076
1077 string parseString(std::istream & str)
1078 {
1079 string res;
1080 expect(str, "\"");
1081 int c;
1082 while ((c = str.get()) != '"')
1083 if (c == '\\') {
1084 c = str.get();
1085 if (c == 'n') res += '\n';
1086 else if (c == 'r') res += '\r';
1087 else if (c == 't') res += '\t';
1088 else res += c;
1089 }
1090 else res += c;
1091 return res;
1092 }
1093
1094
1095 bool endOfList(std::istream & str)
1096 {
1097 if (str.peek() == ',') {
1098 str.get();
1099 return false;
1100 }
1101 if (str.peek() == ']') {
1102 str.get();
1103 return true;
1104 }
1105 return false;
1106 }
1107
1108
1109 string decodeOctalEscaped(const string & s)
1110 {
1111 string r;
1112 for (string::const_iterator i = s.begin(); i != s.end(); ) {
1113 if (*i != '\\') { r += *i++; continue; }
1114 unsigned char c = 0;
1115 ++i;
1116 while (i != s.end() && *i >= '0' && *i < '8')
1117 c = c * 8 + (*i++ - '0');
1118 r += c;
1119 }
1120 return r;
1121 }
1122
1123
1124 void ignoreException()
1125 {
1126 try {
1127 throw;
1128 } catch (std::exception & e) {
1129 printMsg(lvlError, format("error (ignored): %1%") % e.what());
1130 }
1131 }
1132
1133
1134 }