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