Mercurial > hg
annotate contrib/chg/util.c @ 28788:57a78a64de44
chg: add util function abortmsgerrno to print error with errno
It's common to abortmsg with the errno information. Let's make a utility
function for it.
author | Jun Wu <quark@fb.com> |
---|---|
date | Tue, 05 Apr 2016 17:25:39 +0100 |
parents | ea86cdcd9b50 |
children | ddef14468952 |
rev | line source |
---|---|
28060 | 1 /* |
2 * Utility functions | |
3 * | |
4 * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> | |
5 * | |
6 * This software may be used and distributed according to the terms of the | |
7 * GNU General Public License version 2 or any later version. | |
8 */ | |
9 | |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
10 #include <errno.h> |
28060 | 11 #include <signal.h> |
12 #include <stdarg.h> | |
13 #include <stdio.h> | |
14 #include <stdlib.h> | |
28084
3fc45956c978
chg: initialize sigaction fields more reliably
Yuya Nishihara <yuya@tcha.org>
parents:
28060
diff
changeset
|
15 #include <string.h> |
28060 | 16 #include <sys/types.h> |
17 #include <sys/wait.h> | |
18 #include <unistd.h> | |
19 | |
20 #include "util.h" | |
21 | |
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
22 static int colorenabled = 0; |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
23 |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
24 static inline void fsetcolor(FILE *fp, const char *code) |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
25 { |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
26 if (!colorenabled) |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
27 return; |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
28 fprintf(fp, "\033[%sm", code); |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
29 } |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
30 |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
31 static void vabortmsgerrno(int no, const char *fmt, va_list args) |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
32 { |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
33 fsetcolor(stderr, "1;31"); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
34 fputs("chg: abort: ", stderr); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
35 vfprintf(stderr, fmt, args); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
36 if (no != 0) |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
37 fprintf(stderr, " (errno = %d, %s)", no, strerror(no)); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
38 fsetcolor(stderr, ""); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
39 fputc('\n', stderr); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
40 exit(255); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
41 } |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
42 |
28060 | 43 void abortmsg(const char *fmt, ...) |
44 { | |
45 va_list args; | |
46 va_start(args, fmt); | |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
47 vabortmsgerrno(0, fmt, args); |
28060 | 48 va_end(args); |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
49 } |
28060 | 50 |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
51 void abortmsgerrno(const char *fmt, ...) |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
52 { |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
53 int no = errno; |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
54 va_list args; |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
55 va_start(args, fmt); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
56 vabortmsgerrno(no, fmt, args); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
57 va_end(args); |
28060 | 58 } |
59 | |
60 static int debugmsgenabled = 0; | |
61 | |
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
62 void enablecolor(void) |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
63 { |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
64 colorenabled = 1; |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
65 } |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
66 |
28060 | 67 void enabledebugmsg(void) |
68 { | |
69 debugmsgenabled = 1; | |
70 } | |
71 | |
72 void debugmsg(const char *fmt, ...) | |
73 { | |
74 if (!debugmsgenabled) | |
75 return; | |
76 | |
77 va_list args; | |
78 va_start(args, fmt); | |
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
79 fsetcolor(stderr, "1;30"); |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
80 fputs("chg: debug: ", stderr); |
28060 | 81 vfprintf(stderr, fmt, args); |
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
82 fsetcolor(stderr, ""); |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
83 fputc('\n', stderr); |
28060 | 84 va_end(args); |
85 } | |
86 | |
28165
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
87 void *mallocx(size_t size) |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
88 { |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
89 void *result = malloc(size); |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
90 if (!result) |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
91 abortmsg("failed to malloc"); |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
92 return result; |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
93 } |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
94 |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
95 void *reallocx(void *ptr, size_t size) |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
96 { |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
97 void *result = realloc(ptr, size); |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
98 if (!result) |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
99 abortmsg("failed to realloc"); |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
100 return result; |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
101 } |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
102 |
28060 | 103 /* |
104 * Execute a shell command in mostly the same manner as system(), with the | |
105 * give environment variables, after chdir to the given cwd. Returns a status | |
106 * code compatible with the Python subprocess module. | |
107 */ | |
108 int runshellcmd(const char *cmd, const char *envp[], const char *cwd) | |
109 { | |
110 enum { F_SIGINT = 1, F_SIGQUIT = 2, F_SIGMASK = 4, F_WAITPID = 8 }; | |
111 unsigned int doneflags = 0; | |
112 int status = 0; | |
113 struct sigaction newsa, oldsaint, oldsaquit; | |
114 sigset_t oldmask; | |
115 | |
116 /* block or mask signals just as system() does */ | |
28084
3fc45956c978
chg: initialize sigaction fields more reliably
Yuya Nishihara <yuya@tcha.org>
parents:
28060
diff
changeset
|
117 memset(&newsa, 0, sizeof(newsa)); |
28060 | 118 newsa.sa_handler = SIG_IGN; |
119 newsa.sa_flags = 0; | |
120 if (sigemptyset(&newsa.sa_mask) < 0) | |
121 goto done; | |
122 if (sigaction(SIGINT, &newsa, &oldsaint) < 0) | |
123 goto done; | |
124 doneflags |= F_SIGINT; | |
125 if (sigaction(SIGQUIT, &newsa, &oldsaquit) < 0) | |
126 goto done; | |
127 doneflags |= F_SIGQUIT; | |
128 | |
129 if (sigaddset(&newsa.sa_mask, SIGCHLD) < 0) | |
130 goto done; | |
131 if (sigprocmask(SIG_BLOCK, &newsa.sa_mask, &oldmask) < 0) | |
132 goto done; | |
133 doneflags |= F_SIGMASK; | |
134 | |
135 pid_t pid = fork(); | |
136 if (pid < 0) | |
137 goto done; | |
138 if (pid == 0) { | |
139 sigaction(SIGINT, &oldsaint, NULL); | |
140 sigaction(SIGQUIT, &oldsaquit, NULL); | |
141 sigprocmask(SIG_SETMASK, &oldmask, NULL); | |
142 if (cwd && chdir(cwd) < 0) | |
143 _exit(127); | |
144 const char *argv[] = {"sh", "-c", cmd, NULL}; | |
145 if (envp) { | |
146 execve("/bin/sh", (char **)argv, (char **)envp); | |
147 } else { | |
148 execv("/bin/sh", (char **)argv); | |
149 } | |
150 _exit(127); | |
151 } else { | |
152 if (waitpid(pid, &status, 0) < 0) | |
153 goto done; | |
154 doneflags |= F_WAITPID; | |
155 } | |
156 | |
157 done: | |
158 if (doneflags & F_SIGINT) | |
159 sigaction(SIGINT, &oldsaint, NULL); | |
160 if (doneflags & F_SIGQUIT) | |
161 sigaction(SIGQUIT, &oldsaquit, NULL); | |
162 if (doneflags & F_SIGMASK) | |
163 sigprocmask(SIG_SETMASK, &oldmask, NULL); | |
164 | |
165 /* no way to report other errors, use 127 (= shell termination) */ | |
166 if (!(doneflags & F_WAITPID)) | |
167 return 127; | |
168 if (WIFEXITED(status)) | |
169 return WEXITSTATUS(status); | |
170 if (WIFSIGNALED(status)) | |
171 return -WTERMSIG(status); | |
172 return 127; | |
173 } |