1d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley/* xwrap.c - wrappers around existing library functions. 2d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * 3d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * Functions with the x prefix are wrappers that either succeed or kill the 4d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * program with an error message, but never return failure. They usually have 5d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * the same arguments and return value as the function they wrap. 6d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * 7d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * Copyright 2006 Rob Landley <rob@landley.net> 8d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley */ 9d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 10d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley#include "toys.h" 11d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 122fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley// strcpy and strncat with size checking. Size is the total space in "dest", 132fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley// including null terminator. Exit if there's not enough space for the string 142fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley// (including space for the null terminator), because silently truncating is 152fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley// still broken behavior. (And leaving the string unterminated is INSANE.) 16d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xstrncpy(char *dest, char *src, size_t size) 17d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 183704f826b42d65e9d1da3c4f4084902d32eaba3aRob Landley if (strlen(src)+1 > size) error_exit("'%s' > %ld bytes", src, (long)size); 19d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley strcpy(dest, src); 20d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 21d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 222fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landleyvoid xstrncat(char *dest, char *src, size_t size) 232fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley{ 242fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley long len = strlen(src); 252fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley 262fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley if (len+strlen(dest)+1 > size) 2770a84a356b1c56743618362867b9300007d11998Rob Landley error_exit("'%s%s' > %ld bytes", dest, src, (long)size); 282fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley strcpy(dest+len, src); 292fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley} 302fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley 31d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xexit(void) 32d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 33aad492fd87d689c443e87561c23abc2e12b785a9Rob Landley if (fflush(NULL) || ferror(stdout)) 34aad492fd87d689c443e87561c23abc2e12b785a9Rob Landley if (!toys.exitval) perror_msg("write"); 35d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (toys.rebound) longjmp(*toys.rebound, 1); 36d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley else exit(toys.exitval); 37d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 38d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 39d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate memory. 40d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid *xmalloc(size_t size) 41d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 42d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley void *ret = malloc(size); 43d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!ret) error_exit("xmalloc"); 44d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 45d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 46d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 47d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 48d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate prezeroed memory. 49d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid *xzalloc(size_t size) 50d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 51d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley void *ret = xmalloc(size); 52d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley memset(ret, 0, size); 53d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 54d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 55d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 56d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can change the size of an existing allocation, possibly 57d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// moving it. (Notice different arguments from libc function.) 58d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid *xrealloc(void *ptr, size_t size) 59d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 60d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ptr = realloc(ptr, size); 61d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!ptr) error_exit("xrealloc"); 62d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 63d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ptr; 64d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 65d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 66d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate a copy of this many bytes of string. 67d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xstrndup(char *s, size_t n) 68d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 692fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley char *ret = strndup(s, ++n); 702fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley 712fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley if (!ret) error_exit("xstrndup"); 722fb85a3588bf2271e0506c5ab3bcb6a84bf77255Rob Landley ret[--n] = 0; 73d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 74d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 75d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 76d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 77d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate a copy of this string. 78d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xstrdup(char *s) 79d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 80d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return xstrndup(s, strlen(s)); 81d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 82d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 83d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate enough space to sprintf() into. 8459d85e2bb065a3bdc27868acb7a65f89d872c7faRob Landleychar *xmprintf(char *format, ...) 85d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 86d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_list va, va2; 87d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int len; 88d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *ret; 89d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 90d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_start(va, format); 91d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_copy(va2, va); 92d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 93d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // How long is it? 94d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley len = vsnprintf(0, 0, format, va); 95d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley len++; 96d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_end(va); 97d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 98d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Allocate and do the sprintf() 99d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ret = xmalloc(len); 100d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley vsnprintf(ret, len, format, va2); 101d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_end(va2); 102d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 103d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 104d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 105d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 106d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xprintf(char *format, ...) 107d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 108d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_list va; 109d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_start(va, format); 110d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 111d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley vprintf(format, va); 11221f3c8db00f0d4a3f0989559847d2564f4c73a11Rob Landley va_end(va); 113ddbaa718dbe3370786eae97000f4c1e8bb259a61Rob Landley if (fflush(stdout) || ferror(stdout)) perror_exit("write"); 114d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 115d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 116d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xputs(char *s) 117d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 118ddbaa718dbe3370786eae97000f4c1e8bb259a61Rob Landley if (EOF == puts(s) || fflush(stdout) || ferror(stdout)) perror_exit("write"); 119d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 120d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 121d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xputc(char c) 122d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 123ddbaa718dbe3370786eae97000f4c1e8bb259a61Rob Landley if (EOF == fputc(c, stdout) || fflush(stdout) || ferror(stdout)) 124ddbaa718dbe3370786eae97000f4c1e8bb259a61Rob Landley perror_exit("write"); 125d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 126d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 127d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xflush(void) 128d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 129ddbaa718dbe3370786eae97000f4c1e8bb259a61Rob Landley if (fflush(stdout) || ferror(stdout)) perror_exit("write");; 130d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 131d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 132d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can exec argv[] (or run builtin command). Note that anything 133d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// with a path isn't a builtin, so /bin/sh won't match the builtin sh. 134d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xexec(char **argv) 135d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 136977e48e1626b3e3f1f1f9b14f05ffc11e252455fRob Landley if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE) toy_exec(argv); 137d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley execvp(argv[0], argv); 138d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 139d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley perror_exit("exec %s", argv[0]); 140d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 141d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 14244e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley// Spawn child process, capturing stdin/stdout. 14344e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley// argv[]: command to exec. If null, child returns to original program. 144360d57f843f5435a75270e54583430dcb8f62546Rob Landley// pipes[2]: stdin, stdout of new process. If -1 will not have pipe allocated. 14544e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley// return: pid of child process 146360d57f843f5435a75270e54583430dcb8f62546Rob Landleypid_t xpopen_both(char **argv, int *pipes) 14744e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley{ 14844e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley int cestnepasun[4], pid; 14944e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley 150360d57f843f5435a75270e54583430dcb8f62546Rob Landley // Make the pipes? Not this won't set either pipe to 0 because if fds are 151360d57f843f5435a75270e54583430dcb8f62546Rob Landley // allocated in order and if fd0 was free it would go to cestnepasun[0] 15244e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley if (pipes) { 153360d57f843f5435a75270e54583430dcb8f62546Rob Landley for (pid = 0; pid < 2; pid++) { 154360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (pipes[pid] == -1) continue; 155360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (pipe(cestnepasun+(2*pid))) perror_exit("pipe"); 156360d57f843f5435a75270e54583430dcb8f62546Rob Landley pipes[pid] = cestnepasun[pid+1]; 157360d57f843f5435a75270e54583430dcb8f62546Rob Landley } 15844e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley } 15944e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley 16044e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley // Child process 16144e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley if (!(pid = xfork())) { 16244e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley // Dance of the stdin/stdout redirection. 16344e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley if (pipes) { 164360d57f843f5435a75270e54583430dcb8f62546Rob Landley // if we had no stdin/out, pipe handles could overlap, so test for it 165360d57f843f5435a75270e54583430dcb8f62546Rob Landley // and free up potentially overlapping pipe handles before reuse 166360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (pipes[1] != -1) close(cestnepasun[2]); 167360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (pipes[0] != -1) { 168360d57f843f5435a75270e54583430dcb8f62546Rob Landley close(cestnepasun[1]); 169360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (cestnepasun[0]) { 170360d57f843f5435a75270e54583430dcb8f62546Rob Landley dup2(cestnepasun[0], 0); 171360d57f843f5435a75270e54583430dcb8f62546Rob Landley close(cestnepasun[0]); 172360d57f843f5435a75270e54583430dcb8f62546Rob Landley } 173360d57f843f5435a75270e54583430dcb8f62546Rob Landley } 174360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (pipes[1] != -1) { 175360d57f843f5435a75270e54583430dcb8f62546Rob Landley dup2(cestnepasun[3], 1); 176360d57f843f5435a75270e54583430dcb8f62546Rob Landley dup2(cestnepasun[3], 2); 177360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (cestnepasun[3] > 2 || !cestnepasun[3]) close(cestnepasun[3]); 17844e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley } 17944e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley } 18044e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley if (argv) { 18144e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley if (CFG_TOYBOX) toy_exec(argv); 18244e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley execvp(argv[0], argv); 18344e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley _exit(127); 18444e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley } 18544e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley return 0; 18644e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley 187360d57f843f5435a75270e54583430dcb8f62546Rob Landley } 18844e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley 189360d57f843f5435a75270e54583430dcb8f62546Rob Landley // Parent process 190360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (pipes) { 191360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (pipes[0] != -1) close(cestnepasun[0]); 192360d57f843f5435a75270e54583430dcb8f62546Rob Landley if (pipes[1] != -1) close(cestnepasun[3]); 19344e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley } 194360d57f843f5435a75270e54583430dcb8f62546Rob Landley 195360d57f843f5435a75270e54583430dcb8f62546Rob Landley return pid; 19644e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley} 19744e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley 198360d57f843f5435a75270e54583430dcb8f62546Rob Landleyint xpclose_both(pid_t pid, int *pipes) 19944e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley{ 20044e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley int rc = 127; 20144e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley 20244e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley if (pipes) { 20344e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley close(pipes[0]); 20444e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley close(pipes[1]); 20544e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley } 20644e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley waitpid(pid, &rc, 0); 20744e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley 20844e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley return WIFEXITED(rc) ? WEXITSTATUS(rc) : WTERMSIG(rc) + 127; 20944e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley} 21044e68a1bec9b342c01e2f4e6ccf9f1e7a3ee8081Rob Landley 211360d57f843f5435a75270e54583430dcb8f62546Rob Landley// Wrapper to xpopen with a pipe for just one of stdin/stdout 212360d57f843f5435a75270e54583430dcb8f62546Rob Landleypid_t xpopen(char **argv, int *pipe, int stdout) 213360d57f843f5435a75270e54583430dcb8f62546Rob Landley{ 2148a9907119bf22f2279470be40cf40027dc37018cRob Landley int pipes[2], pid; 215360d57f843f5435a75270e54583430dcb8f62546Rob Landley 2168a9907119bf22f2279470be40cf40027dc37018cRob Landley pipes[!stdout] = -1; 2178a9907119bf22f2279470be40cf40027dc37018cRob Landley pipes[!!stdout] = 0; 2188a9907119bf22f2279470be40cf40027dc37018cRob Landley pid = xpopen_both(argv, pipes); 2198a9907119bf22f2279470be40cf40027dc37018cRob Landley *pipe = pid ? pipes[!!stdout] : -1; 220360d57f843f5435a75270e54583430dcb8f62546Rob Landley 2218a9907119bf22f2279470be40cf40027dc37018cRob Landley return pid; 222360d57f843f5435a75270e54583430dcb8f62546Rob Landley} 223360d57f843f5435a75270e54583430dcb8f62546Rob Landley 224360d57f843f5435a75270e54583430dcb8f62546Rob Landleyint xpclose(pid_t pid, int pipe) 225360d57f843f5435a75270e54583430dcb8f62546Rob Landley{ 226360d57f843f5435a75270e54583430dcb8f62546Rob Landley close(pipe); 227360d57f843f5435a75270e54583430dcb8f62546Rob Landley 228360d57f843f5435a75270e54583430dcb8f62546Rob Landley return xpclose_both(pid, 0); 229360d57f843f5435a75270e54583430dcb8f62546Rob Landley} 230360d57f843f5435a75270e54583430dcb8f62546Rob Landley 231360d57f843f5435a75270e54583430dcb8f62546Rob Landley// Call xpopen and wait for it to finish, keeping existing stdin/stdout. 232360d57f843f5435a75270e54583430dcb8f62546Rob Landleyint xrun(char **argv) 233360d57f843f5435a75270e54583430dcb8f62546Rob Landley{ 234360d57f843f5435a75270e54583430dcb8f62546Rob Landley return xpclose_both(xpopen_both(argv, 0), 0); 235360d57f843f5435a75270e54583430dcb8f62546Rob Landley} 236360d57f843f5435a75270e54583430dcb8f62546Rob Landley 237d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xaccess(char *path, int flags) 238d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 239d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (access(path, flags)) perror_exit("Can't access '%s'", path); 240d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 241d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 242d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can delete a file. (File must exist to be deleted.) 243d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xunlink(char *path) 244d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 245d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (unlink(path)) perror_exit("unlink '%s'", path); 246d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 247d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 248d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can open/create a file, returning file descriptor. 249d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyint xcreate(char *path, int flags, int mode) 250d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 251ccb73f8bf9191c01c90975958a210c47175bd98cRob Landley int fd = open(path, flags^O_CLOEXEC, mode); 252d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd == -1) perror_exit("%s", path); 253d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return fd; 254d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 255d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 256d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can open a file, returning file descriptor. 257d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyint xopen(char *path, int flags) 258d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 259d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return xcreate(path, flags, 0); 260d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 261d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 262d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xclose(int fd) 263d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 264d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (close(fd)) perror_exit("xclose"); 265d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 266d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 267d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyint xdup(int fd) 268d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 269d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd != -1) { 270d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley fd = dup(fd); 271d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd == -1) perror_exit("xdup"); 272d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 273d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return fd; 274d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 275d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 2761aa75118c46c8fbe0eeead18974d25e5f13274d5Rob LandleyFILE *xfdopen(int fd, char *mode) 2771aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley{ 2781aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley FILE *f = fdopen(fd, mode); 2791aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley 2801aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley if (!f) perror_exit("xfdopen"); 2811aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley 2821aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley return f; 2831aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley} 2841aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley 285d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can open/create a file, returning FILE *. 286d390493d76c4cda76c1c6d21897b0f246857e588Rob LandleyFILE *xfopen(char *path, char *mode) 287d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 288d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley FILE *f = fopen(path, mode); 289d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!f) perror_exit("No file %s", path); 290d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return f; 291d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 292d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 293d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die if there's an error other than EOF. 294d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleysize_t xread(int fd, void *buf, size_t len) 295d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 296d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ssize_t ret = read(fd, buf, len); 297d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (ret < 0) perror_exit("xread"); 298d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 299d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 300d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 301d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 302d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xreadall(int fd, void *buf, size_t len) 303d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 304d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len != readall(fd, buf, len)) perror_exit("xreadall"); 305d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 306d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 307d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// There's no xwriteall(), just xwrite(). When we read, there may or may not 308d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// be more data waiting. When we write, there is data and it had better go 309d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// somewhere. 310d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 311d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xwrite(int fd, void *buf, size_t len) 312d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 313d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len != writeall(fd, buf, len)) perror_exit("xwrite"); 314d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 315d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 316d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die if lseek fails, probably due to being called on a pipe. 317d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 318d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyoff_t xlseek(int fd, off_t offset, int whence) 319d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 320d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley offset = lseek(fd, offset, whence); 321d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (offset<0) perror_exit("lseek"); 322d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 323d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return offset; 324d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 325d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 326d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xgetcwd(void) 327d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 328d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *buf = getcwd(NULL, 0); 329d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!buf) perror_exit("xgetcwd"); 330d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 331d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return buf; 332d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 333d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 334d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xstat(char *path, struct stat *st) 335d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 336d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if(stat(path, st)) perror_exit("Can't stat %s", path); 337d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 338d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 339d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Cannonicalize path, even to file with one or more missing components at end. 340d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// if exact, require last path component to exist 3412c1cf4a02783e2a570ddf7b7ea968c7bed781f91Rob Landleychar *xabspath(char *path, int exact) 342d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 343d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley struct string_list *todo, *done = 0; 344d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int try = 9999, dirfd = open("/", 0);; 345d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char buf[4096], *ret; 346d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 347d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // If this isn't an absolute path, start with cwd. 348d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (*path != '/') { 349d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *temp = xgetcwd(); 350d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 351d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley splitpath(path, splitpath(temp, &todo)); 352d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(temp); 353d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } else splitpath(path, &todo); 354d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 355d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Iterate through path components 356d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley while (todo) { 357d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley struct string_list *new = llist_pop(&todo), **tail; 358d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ssize_t len; 359d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 360d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!try--) { 361d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley errno = ELOOP; 362d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley goto error; 363d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 364d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 365d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Removable path componenents. 366d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!strcmp(new->str, ".") || !strcmp(new->str, "..")) { 367d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int x = new->str[1]; 368d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 369d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(new); 370d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (x) { 371d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (done) free(llist_pop(&done)); 372d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley len = 0; 373d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } else continue; 374d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 375d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Is this a symlink? 376d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } else len=readlinkat(dirfd, new->str, buf, 4096); 377d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 378d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len>4095) goto error; 379d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len<1) { 380d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int fd; 381d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *s = ".."; 382d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 383d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // For .. just move dirfd 384d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len) { 385d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Not a symlink: add to linked list, move dirfd, fail if error 386d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if ((exact || todo) && errno != EINVAL) goto error; 387d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley new->next = done; 388d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley done = new; 389d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (errno == EINVAL && !todo) break; 390d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley s = new->str; 391d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 392d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley fd = openat(dirfd, s, 0); 393d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd == -1 && (exact || todo || errno != ENOENT)) goto error; 394d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(dirfd); 395d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley dirfd = fd; 396d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley continue; 397d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 398d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 399d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // If this symlink is to an absolute path, discard existing resolved path 400d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley buf[len] = 0; 401d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (*buf == '/') { 402d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley llist_traverse(done, free); 403d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley done=0; 404d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(dirfd); 405d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley dirfd = open("/", 0); 406d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 407d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(new); 408d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 409d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // prepend components of new path. Note symlink to "/" will leave new NULL 410d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley tail = splitpath(buf, &new); 411d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 412d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // symlink to "/" will return null and leave tail alone 413d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (new) { 414d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley *tail = todo; 415d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley todo = new; 416d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 417d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 418d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(dirfd); 419d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 420d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // At this point done has the path, in reverse order. Reverse list while 421d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // calculating buffer length. 422d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 423d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley try = 2; 424d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley while (done) { 425d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley struct string_list *temp = llist_pop(&done);; 426d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 427d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (todo) try++; 428d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley try += strlen(temp->str); 429d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley temp->next = todo; 430d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley todo = temp; 431d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 432d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 433d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Assemble return buffer 434d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 435d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ret = xmalloc(try); 436d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley *ret = '/'; 437d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ret [try = 1] = 0; 438d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley while (todo) { 439d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (try>1) ret[try++] = '/'; 440d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley try = stpcpy(ret+try, todo->str) - ret; 441d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(llist_pop(&todo)); 442d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 443d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 444d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 445d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 446d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyerror: 447d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(dirfd); 448d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley llist_traverse(todo, free); 449d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley llist_traverse(done, free); 450d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 451d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return NULL; 452d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 453d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 454d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xchdir(char *path) 455d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 456d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (chdir(path)) error_exit("chdir '%s'", path); 457d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 458d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 459afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landleyvoid xchroot(char *path) 460afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley{ 461afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley if (chroot(path)) error_exit("chroot '%s'", path); 462afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley xchdir("/"); 463afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley} 464afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley 4659e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landleystruct passwd *xgetpwuid(uid_t uid) 4669e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley{ 4679e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley struct passwd *pwd = getpwuid(uid); 4685ec4ab3113dcc813b6040d7ded38e297df99dc0eRob Landley if (!pwd) error_exit("bad uid %ld", (long)uid); 4699e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley return pwd; 4709e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley} 4719e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley 4729e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landleystruct group *xgetgrgid(gid_t gid) 4739e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley{ 4749e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley struct group *group = getgrgid(gid); 4754fd07e0f6698cdb873aab0113369eb36c81853a9Rob Landley 4764fd07e0f6698cdb873aab0113369eb36c81853a9Rob Landley if (!group) perror_exit("gid %ld", (long)gid); 4779e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley return group; 4789e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley} 4799e44a5841f0ab9bc03cefb5631c80f3e4e5a60feRob Landley 480b8140d18800e7094cdacb0a61526f46181dc132dRob Landleystruct passwd *xgetpwnamid(char *user) 481b8140d18800e7094cdacb0a61526f46181dc132dRob Landley{ 482b8140d18800e7094cdacb0a61526f46181dc132dRob Landley struct passwd *up = getpwnam(user); 483b8140d18800e7094cdacb0a61526f46181dc132dRob Landley uid_t uid; 484b8140d18800e7094cdacb0a61526f46181dc132dRob Landley 485b8140d18800e7094cdacb0a61526f46181dc132dRob Landley if (!up) { 486b8140d18800e7094cdacb0a61526f46181dc132dRob Landley char *s = 0; 487b8140d18800e7094cdacb0a61526f46181dc132dRob Landley 488b8140d18800e7094cdacb0a61526f46181dc132dRob Landley uid = estrtol(user, &s, 10); 489b8140d18800e7094cdacb0a61526f46181dc132dRob Landley if (!errno && s && !*s) up = getpwuid(uid); 490b8140d18800e7094cdacb0a61526f46181dc132dRob Landley } 491b8140d18800e7094cdacb0a61526f46181dc132dRob Landley if (!up) perror_exit("user '%s'", user); 492b8140d18800e7094cdacb0a61526f46181dc132dRob Landley 493b8140d18800e7094cdacb0a61526f46181dc132dRob Landley return up; 494b8140d18800e7094cdacb0a61526f46181dc132dRob Landley} 495b8140d18800e7094cdacb0a61526f46181dc132dRob Landley 496b8140d18800e7094cdacb0a61526f46181dc132dRob Landleystruct group *xgetgrnamid(char *group) 497b8140d18800e7094cdacb0a61526f46181dc132dRob Landley{ 498b8140d18800e7094cdacb0a61526f46181dc132dRob Landley struct group *gr = getgrnam(group); 499b8140d18800e7094cdacb0a61526f46181dc132dRob Landley gid_t gid; 500b8140d18800e7094cdacb0a61526f46181dc132dRob Landley 501b8140d18800e7094cdacb0a61526f46181dc132dRob Landley if (!gr) { 502b8140d18800e7094cdacb0a61526f46181dc132dRob Landley char *s = 0; 503b8140d18800e7094cdacb0a61526f46181dc132dRob Landley 504b8140d18800e7094cdacb0a61526f46181dc132dRob Landley gid = estrtol(group, &s, 10); 505b8140d18800e7094cdacb0a61526f46181dc132dRob Landley if (!errno && s && !*s) gr = getgrgid(gid); 506b8140d18800e7094cdacb0a61526f46181dc132dRob Landley } 507b8140d18800e7094cdacb0a61526f46181dc132dRob Landley if (!gr) perror_exit("group '%s'", group); 508b8140d18800e7094cdacb0a61526f46181dc132dRob Landley 509b8140d18800e7094cdacb0a61526f46181dc132dRob Landley return gr; 510b8140d18800e7094cdacb0a61526f46181dc132dRob Landley} 511b8140d18800e7094cdacb0a61526f46181dc132dRob Landley 5125ec4ab3113dcc813b6040d7ded38e297df99dc0eRob Landleystruct passwd *xgetpwnam(char *name) 5135ec4ab3113dcc813b6040d7ded38e297df99dc0eRob Landley{ 5145ec4ab3113dcc813b6040d7ded38e297df99dc0eRob Landley struct passwd *up = getpwnam(name); 5154fd07e0f6698cdb873aab0113369eb36c81853a9Rob Landley 5164fd07e0f6698cdb873aab0113369eb36c81853a9Rob Landley if (!up) perror_exit("user '%s'", name); 5175ec4ab3113dcc813b6040d7ded38e297df99dc0eRob Landley return up; 5185ec4ab3113dcc813b6040d7ded38e297df99dc0eRob Landley} 5195ec4ab3113dcc813b6040d7ded38e297df99dc0eRob Landley 52060c35c486a2ea1c6ea8920c599abf992b27542c5Rob Landleystruct group *xgetgrnam(char *name) 52160c35c486a2ea1c6ea8920c599abf992b27542c5Rob Landley{ 52260c35c486a2ea1c6ea8920c599abf992b27542c5Rob Landley struct group *gr = getgrnam(name); 52360c35c486a2ea1c6ea8920c599abf992b27542c5Rob Landley 52460c35c486a2ea1c6ea8920c599abf992b27542c5Rob Landley if (!gr) perror_exit("group '%s'", name); 52560c35c486a2ea1c6ea8920c599abf992b27542c5Rob Landley return gr; 52660c35c486a2ea1c6ea8920c599abf992b27542c5Rob Landley} 52760c35c486a2ea1c6ea8920c599abf992b27542c5Rob Landley 528afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley// setuid() can fail (for example, too many processes belonging to that user), 529afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley// which opens a security hole if the process continues as the original user. 530afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley 531afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landleyvoid xsetuser(struct passwd *pwd) 532afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley{ 533afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley if (initgroups(pwd->pw_name, pwd->pw_gid) || setgid(pwd->pw_uid) 534afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley || setuid(pwd->pw_uid)) perror_exit("xsetuser '%s'", pwd->pw_name); 535afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley} 536afba5b8efdf1bac2c02ca787840a2be053c800f7Rob Landley 537d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// This can return null (meaning file not found). It just won't return null 538d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// for memory allocation reasons. 539d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xreadlink(char *name) 540d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 541d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int len, size = 0; 542d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *buf = 0; 543d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 544d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Grow by 64 byte chunks until it's big enough. 545d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley for(;;) { 546d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley size +=64; 547d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley buf = xrealloc(buf, size); 548d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley len = readlink(name, buf, size); 549d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 550d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len<0) { 551d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(buf); 552d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return 0; 553d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 554d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len<size) { 555d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley buf[len]=0; 556d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return buf; 557d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 558d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 559d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 560d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 561dc3731783ead154d5a0d8d318566468474b43013Rob Landleychar *xreadfile(char *name, char *buf, off_t len) 562d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 563dc3731783ead154d5a0d8d318566468474b43013Rob Landley if (!(buf = readfile(name, buf, len))) perror_exit("Bad '%s'", name); 564dc3731783ead154d5a0d8d318566468474b43013Rob Landley 565d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return buf; 566d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 567d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 568d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyint xioctl(int fd, int request, void *data) 569d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 570d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int rc; 571d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 572d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley errno = 0; 573d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley rc = ioctl(fd, request, data); 574d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (rc == -1 && errno) perror_exit("ioctl %x", request); 575d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 576d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return rc; 577d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 578d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 579d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Open a /var/run/NAME.pid file, dying if we can't write it or if it currently 580d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// exists and is this executable. 581d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xpidfile(char *name) 582d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 583d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char pidfile[256], spid[32]; 584d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int i, fd; 585d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley pid_t pid; 586d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 587d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley sprintf(pidfile, "/var/run/%s.pid", name); 588d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Try three times to open the sucker. 589d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley for (i=0; i<3; i++) { 590dccfb2a9c156d03b6399120ae3dd4b23ff00b43fFelix Janda <felix.janda at fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644); 591d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd != -1) break; 592d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 593d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // If it already existed, read it. Loop for race condition. 594d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley fd = open(pidfile, O_RDONLY); 595d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd == -1) continue; 596d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 597d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Is the old program still there? 598d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley spid[xread(fd, spid, sizeof(spid)-1)] = 0; 599d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(fd); 600d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley pid = atoi(spid); 60146e8e1dcb3f616a675bf33c83531ee05a4dd8374Rob Landley if (pid < 1 || (kill(pid, 0) && errno == ESRCH)) unlink(pidfile); 602d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 603d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // An else with more sanity checking might be nice here. 604d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 605d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 606d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (i == 3) error_exit("xpidfile %s", name); 607d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 608d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley xwrite(fd, spid, sprintf(spid, "%ld\n", (long)getpid())); 609d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(fd); 610d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 611d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 612d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Copy the rest of in to out and close both files. 613d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 614d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xsendfile(int in, int out) 615d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 616d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley long len; 617d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 618d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (in<0) return; 619d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley for (;;) { 6206d28370f22aa6b7c97a57a434339fa57ce322c8bRob Landley len = xread(in, libbuf, sizeof(libbuf)); 621d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len<1) break; 6226d28370f22aa6b7c97a57a434339fa57ce322c8bRob Landley xwrite(out, libbuf, len); 623d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 624d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 62572756670274dac9562b869761c50c59ed57b7295Rob Landley 62672756670274dac9562b869761c50c59ed57b7295Rob Landley// parse fractional seconds with optional s/m/h/d suffix 62772756670274dac9562b869761c50c59ed57b7295Rob Landleylong xparsetime(char *arg, long units, long *fraction) 62872756670274dac9562b869761c50c59ed57b7295Rob Landley{ 62972756670274dac9562b869761c50c59ed57b7295Rob Landley double d; 63072756670274dac9562b869761c50c59ed57b7295Rob Landley long l; 63172756670274dac9562b869761c50c59ed57b7295Rob Landley 63272756670274dac9562b869761c50c59ed57b7295Rob Landley if (CFG_TOYBOX_FLOAT) d = strtod(arg, &arg); 63372756670274dac9562b869761c50c59ed57b7295Rob Landley else l = strtoul(arg, &arg, 10); 6342c1cf4a02783e2a570ddf7b7ea968c7bed781f91Rob Landley 63572756670274dac9562b869761c50c59ed57b7295Rob Landley // Parse suffix 63672756670274dac9562b869761c50c59ed57b7295Rob Landley if (*arg) { 63772756670274dac9562b869761c50c59ed57b7295Rob Landley int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *arg); 63872756670274dac9562b869761c50c59ed57b7295Rob Landley 63972756670274dac9562b869761c50c59ed57b7295Rob Landley if (i == -1) error_exit("Unknown suffix '%c'", *arg); 64072756670274dac9562b869761c50c59ed57b7295Rob Landley if (CFG_TOYBOX_FLOAT) d *= ismhd[i]; 64172756670274dac9562b869761c50c59ed57b7295Rob Landley else l *= ismhd[i]; 64272756670274dac9562b869761c50c59ed57b7295Rob Landley } 64372756670274dac9562b869761c50c59ed57b7295Rob Landley 64472756670274dac9562b869761c50c59ed57b7295Rob Landley if (CFG_TOYBOX_FLOAT) { 64572756670274dac9562b869761c50c59ed57b7295Rob Landley l = (long)d; 64672756670274dac9562b869761c50c59ed57b7295Rob Landley if (fraction) *fraction = units*(d-l); 64772756670274dac9562b869761c50c59ed57b7295Rob Landley } else if (fraction) *fraction = 0; 64872756670274dac9562b869761c50c59ed57b7295Rob Landley 64972756670274dac9562b869761c50c59ed57b7295Rob Landley return l; 65072756670274dac9562b869761c50c59ed57b7295Rob Landley} 6515b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley 6525b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley// Compile a regular expression into a regex_t 6535b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landleyvoid xregcomp(regex_t *preg, char *regex, int cflags) 6545b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley{ 6555b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley int rc = regcomp(preg, regex, cflags); 6565b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley 6575b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley if (rc) { 6585b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley regerror(rc, preg, libbuf, sizeof(libbuf)); 6595b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley error_exit("xregcomp: %s", libbuf); 6605b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley } 6615b405827a2fa4c928c488f3e7b0197dfec60dcc2Rob Landley} 662c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley 663c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landleychar *xtzset(char *new) 664c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley{ 665c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley char *tz = getenv("TZ"); 666c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley 667c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley if (tz) tz = xstrdup(tz); 668c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley if (setenv("TZ", new, 1)) perror_exit("setenv"); 669c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley tzset(); 670c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley 671c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley return tz; 672c277f347bba2417106b32212d9d40aceb4a88fb5Rob Landley} 673e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley 674e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley// Set a signal handler 675e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landleyvoid xsignal(int signal, void *handler) 676e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley{ 677e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley struct sigaction *sa = (void *)libbuf; 678e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley 679e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley memset(sa, 0, sizeof(struct sigaction)); 680e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley sa->sa_handler = handler; 681e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley 682e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley if (sigaction(signal, sa, 0)) perror_exit("xsignal %d", signal); 683e6abb61e057d55a08c263a48648aaf7b776dfceeRob Landley} 684