1 /*
2 * Copyright (C) 2003 Sam Horrocks
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 */
19
20 #include "speedy.h"
21
22 static struct timeval saved_time;
23 static int my_euid = -1;
24 static int saved_pid;
25 #ifdef SPEEDY_DEBUG
26 static int savecore;
27 #endif
28
29 extern char **environ;
30
speedy_util_pref_fd(int oldfd,int newfd)31 int speedy_util_pref_fd(int oldfd, int newfd) {
32 if (newfd == oldfd || newfd == PREF_FD_DONTCARE || oldfd == -1)
33 return oldfd;
34 (void) dup2(oldfd, newfd);
35 (void) close(oldfd);
36 return newfd;
37 }
38
39 #ifdef SPEEDY_PROFILING
end_profiling(int dowrites)40 static void end_profiling(int dowrites) {
41 char *cwd;
42
43 if (dowrites)
44 cwd = getcwd(NULL, 0);
45
46 mkdir(SPEEDY_PROFILING, 0777);
47 chdir(SPEEDY_PROFILING);
48
49 if (dowrites) {
50 _mcleanup();
51 __bb_exit_func();
52 chdir(cwd);
53 free(cwd);
54 }
55 }
56 #endif
57
speedy_util_geteuid(void)58 SPEEDY_INLINE int speedy_util_geteuid(void) {
59 if (my_euid == -1)
60 my_euid = geteuid();
61 return my_euid;
62 }
63
64 #ifdef IAMSUID
speedy_util_seteuid(int id)65 int speedy_util_seteuid(int id) {
66 int retval = seteuid(id);
67 if (retval != -1)
68 my_euid = id;
69 return retval;
70 }
71 #endif
72
speedy_util_getuid(void)73 SPEEDY_INLINE int speedy_util_getuid(void) {
74 static int uid = -1;
75 if (uid == -1)
76 uid = getuid();
77 return uid;
78 }
79
80 #ifdef SPEEDY_BACKEND
speedy_util_argc(const char * const * argv)81 int speedy_util_argc(const char * const * argv) {
82 int retval;
83 for (retval = 0; *argv++; ++retval)
84 ;
85 return retval;
86 }
87 #endif
88
speedy_util_getpid(void)89 SPEEDY_INLINE int speedy_util_getpid(void) {
90 if (!saved_pid) saved_pid = getpid();
91 return saved_pid;
92 }
93
speedy_util_pid_invalidate(void)94 void speedy_util_pid_invalidate(void) {
95 saved_pid = 0;
96 }
97
just_die(const char * fmt,va_list ap)98 static void just_die(const char *fmt, va_list ap) {
99 char buf[2048];
100
101 sprintf(buf, "%s[%u]: ", SPEEDY_PROGNAME, (int)getpid());
102 vsprintf(buf + strlen(buf), fmt, ap);
103 if (errno) {
104 strcat(buf, ": ");
105 strcat(buf, strerror(errno));
106 }
107 strcat(buf, "\n");
108 # ifdef SPEEDY_DEBUG
109 savecore = 1;
110 # endif
111 speedy_abort(buf);
112 }
113
speedy_util_die(const char * fmt,...)114 void speedy_util_die(const char *fmt, ...) {
115 va_list ap;
116
117 va_start(ap, fmt);
118 just_die(fmt, ap);
119 va_end(ap);
120 }
121
speedy_util_die_quiet(const char * fmt,...)122 void speedy_util_die_quiet(const char *fmt, ...) {
123 va_list ap;
124
125 errno = 0;
126 va_start(ap, fmt);
127 just_die(fmt, ap);
128 va_end(ap);
129 }
130
speedy_util_execvp(const char * filename,const char * const * argv)131 int speedy_util_execvp(const char *filename, const char *const *argv) {
132
133 /* Get original argv */
134 environ = (char **)speedy_opt_exec_envp();
135
136 #ifdef SPEEDY_PROFILING
137 end_profiling(1);
138 #endif
139
140 /* Exec the backend */
141 return speedy_execvp(filename, argv);
142 }
143
speedy_util_strndup(const char * s,int len)144 char *speedy_util_strndup(const char *s, int len) {
145 char *buf;
146 speedy_new(buf, len+1, char);
147 speedy_memcpy(buf, s, len);
148 buf[len] = '\0';
149 return buf;
150 }
151
speedy_util_gettimeofday(struct timeval * tv)152 SPEEDY_INLINE void speedy_util_gettimeofday(struct timeval *tv) {
153 if (!saved_time.tv_sec)
154 gettimeofday(&saved_time, NULL);
155 *tv = saved_time;
156 }
157
speedy_util_time(void)158 SPEEDY_INLINE int speedy_util_time(void) {
159 struct timeval tv;
160 speedy_util_gettimeofday(&tv);
161 return tv.tv_sec;
162 }
163
speedy_util_time_invalidate(void)164 void speedy_util_time_invalidate(void) {
165 saved_time.tv_sec = 0;
166 }
167
speedy_util_fname(int num,char type)168 char *speedy_util_fname(int num, char type) {
169 char *fname;
170 int uid = speedy_util_getuid(), euid = speedy_util_geteuid();
171
172 speedy_new(fname, strlen(OPTVAL_TMPBASE) + 80, char);
173
174 if (euid == uid)
175 sprintf(fname, "%s.%x.%x.%c", OPTVAL_TMPBASE, num, euid, type);
176 else
177 sprintf(fname, "%s.%x.%x.%x.%c", OPTVAL_TMPBASE, num, euid, uid, type);
178
179 return fname;
180 }
181
speedy_util_getcwd(void)182 char *speedy_util_getcwd(void) {
183 char *buf, *cwd_ret;
184 int size = 512, too_small;
185
186 /* TEST - see if memory alloc works */
187 /* size = 10; */
188
189 while (1) {
190 speedy_new(buf, size, char);
191 cwd_ret = getcwd(buf, size);
192
193 /* TEST - simulate getcwd failure due to unreable directory */
194 /* cwd_ret = NULL; errno = EACCES; */
195
196 if (cwd_ret != NULL)
197 break;
198
199 /* Must test errno here in case speedy_free overwrites it */
200 too_small = (errno == ERANGE);
201
202 speedy_free(buf);
203
204 if (!too_small)
205 break;
206
207 size *= 2;
208 }
209 return cwd_ret;
210 }
211
speedy_util_mapout(SpeedyMapInfo * mi)212 void speedy_util_mapout(SpeedyMapInfo *mi) {
213 if (mi->addr) {
214 if (mi->is_mmaped)
215 (void) munmap(mi->addr, mi->maplen);
216 else
217 speedy_free(mi->addr);
218 mi->addr = NULL;
219 }
220 speedy_free(mi);
221 }
222
readall(int fd,void * addr,int len)223 static int readall(int fd, void *addr, int len) {
224 int numread, n;
225
226 for (numread = 0; len - numread; numread += n) {
227 n = read(fd, ((char*)addr) + numread, len - numread);
228 if (n == -1)
229 return -1;
230 if (n == 0)
231 break;
232 }
233 return numread;
234 }
235
speedy_util_mapin(int fd,int max_size,int file_size)236 SpeedyMapInfo *speedy_util_mapin(int fd, int max_size, int file_size)
237 {
238 SpeedyMapInfo *mi;
239
240 speedy_new(mi, 1, SpeedyMapInfo);
241
242 if (file_size) {
243 mi->maplen = max_size == -1 ? file_size : min(file_size, max_size);
244 mi->addr = mmap(0, mi->maplen, PROT_READ, MAP_SHARED, fd, 0);
245 mi->is_mmaped = (mi->addr != (void*)MAP_FAILED);
246
247 if (!mi->is_mmaped) {
248 speedy_new(mi->addr, mi->maplen, char);
249 lseek(fd, 0, SEEK_SET);
250 mi->maplen = readall(fd, mi->addr, mi->maplen);
251 if (mi->maplen == -1) {
252 speedy_util_mapout(mi);
253 return NULL;
254 }
255 }
256 } else {
257 mi->maplen = 0;
258 mi->addr = NULL;
259 mi->is_mmaped = 0;
260 }
261 return mi;
262 }
263
speedy_util_stat_devino(const struct stat * stbuf)264 SPEEDY_INLINE SpeedyDevIno speedy_util_stat_devino(const struct stat *stbuf) {
265 SpeedyDevIno retval;
266 retval.d = stbuf->st_dev;
267 retval.i = stbuf->st_ino;
268 return retval;
269 }
270
speedy_util_open_stat(const char * path,struct stat * stbuf)271 SPEEDY_INLINE int speedy_util_open_stat(const char *path, struct stat *stbuf)
272 {
273 int fd = open(path, O_RDONLY);
274 if (fd != -1 && fstat(fd, stbuf) == -1) {
275 close(fd);
276 fd = -1;
277 }
278 return fd;
279 }
280
speedy_util_exit(int status,int underbar_exit)281 void speedy_util_exit(int status, int underbar_exit) {
282
283 # ifdef SPEEDY_PROFILING
284 end_profiling(underbar_exit);
285 # endif
286
287 # ifdef SPEEDY_DEBUG
288 if (savecore) {
289 char buf[200];
290 struct timeval tv;
291
292 mkdir("/tmp/speedy_core", 0777);
293 gettimeofday(&tv, NULL);
294 sprintf(buf, "/tmp/speedy_core/%s.%d.%06d.%d", SPEEDY_PROGNAME, (int)tv.tv_sec, (int)tv.tv_usec, getpid());
295 mkdir(buf, 0777);
296 chdir(buf);
297 kill(getpid(), SIGFPE);
298 }
299 # endif
300
301 if (underbar_exit)
302 _exit(status);
303 else
304 exit(status);
305 }
306
speedy_util_kill(pid_t pid,int sig)307 int speedy_util_kill(pid_t pid, int sig) {
308 return pid
309 ? (pid == speedy_util_getpid() ? 0 : kill(pid, sig))
310 : -1;
311 }
312