landley | cd9dfc3 | 2006-10-18 18:38:16 -0400 | [diff] [blame^] | 1 | /* vi: set sw=4 ts=4 :*/ |
landley | 4f344e3 | 2006-10-05 16:18:03 -0400 | [diff] [blame] | 2 | /* functions.c - reusable stuff. |
| 3 | * |
landley | cd9dfc3 | 2006-10-18 18:38:16 -0400 | [diff] [blame^] | 4 | * Functions with the x prefix are wrappers for library functions. They either |
| 5 | * succeed or kill the program with an error message, but never return failure. |
| 6 | * They usually have the same arguments and return value as the function they |
| 7 | * wrap. |
landley | 4f344e3 | 2006-10-05 16:18:03 -0400 | [diff] [blame] | 8 | */ |
| 9 | |
| 10 | #include "toys.h" |
| 11 | |
| 12 | // Die with an error message. |
| 13 | void error_exit(char *msg, ...) |
| 14 | { |
| 15 | va_list args; |
| 16 | |
| 17 | va_start(args, msg); |
| 18 | fprintf(stderr, "%s: ", toys.which->name); |
| 19 | vfprintf(stderr, msg, args); |
| 20 | va_end(args); |
| 21 | exit(toys.exitval); |
| 22 | } |
| 23 | |
landley | cd9dfc3 | 2006-10-18 18:38:16 -0400 | [diff] [blame^] | 24 | // Like strncpy but always null terminated. |
landley | 4f344e3 | 2006-10-05 16:18:03 -0400 | [diff] [blame] | 25 | void strlcpy(char *dest, char *src, size_t size) |
| 26 | { |
| 27 | strncpy(dest,src,size); |
| 28 | dest[size-1] = 0; |
| 29 | } |
| 30 | |
| 31 | // Die unless we can allocate memory. |
| 32 | void *xmalloc(size_t size) |
| 33 | { |
| 34 | void *ret = malloc(size); |
| 35 | if (!ret) error_exit("xmalloc"); |
landley | cd9dfc3 | 2006-10-18 18:38:16 -0400 | [diff] [blame^] | 36 | |
| 37 | return ret; |
landley | 4f344e3 | 2006-10-05 16:18:03 -0400 | [diff] [blame] | 38 | } |
| 39 | |
landley | cd9dfc3 | 2006-10-18 18:38:16 -0400 | [diff] [blame^] | 40 | // Die unless we can allocate prezeroed memory. |
| 41 | void *xzalloc(size_t size) |
| 42 | { |
| 43 | void *ret = xmalloc(size); |
| 44 | bzero(ret,size); |
| 45 | return ret; |
| 46 | } |
| 47 | |
| 48 | // Die unless we can change the size of an existing allocation, possibly |
| 49 | // moving it. (Notice different arguments from libc function.) |
| 50 | void xrealloc(void **ptr, size_t size) |
| 51 | { |
| 52 | *ptr = realloc(*ptr, size); |
| 53 | if (!*ptr) error_exit("xrealloc"); |
| 54 | } |
| 55 | |
| 56 | // Die unless we can allocate a copy of this string. |
landley | 4f344e3 | 2006-10-05 16:18:03 -0400 | [diff] [blame] | 57 | void *xstrndup(char *s, size_t n) |
| 58 | { |
| 59 | void *ret = xmalloc(++n); |
| 60 | strlcpy(ret, s, n); |
| 61 | |
| 62 | return ret; |
| 63 | } |
| 64 | |
landley | cd9dfc3 | 2006-10-18 18:38:16 -0400 | [diff] [blame^] | 65 | // Die unless we can exec argv[] (or run builtin command). Note that anything |
| 66 | // with a path isn't a builtin, so /bin/sh won't match the builtin sh. |
landley | 4f344e3 | 2006-10-05 16:18:03 -0400 | [diff] [blame] | 67 | void *xexec(char **argv) |
| 68 | { |
landley | cd9dfc3 | 2006-10-18 18:38:16 -0400 | [diff] [blame^] | 69 | toy_exec(argv); |
landley | 4f344e3 | 2006-10-05 16:18:03 -0400 | [diff] [blame] | 70 | execvp(argv[0], argv); |
| 71 | error_exit("No %s", argv[0]); |
| 72 | } |
| 73 | |
| 74 | // Die unless we can open/create a file, returning file descriptor. |
| 75 | int xopen(char *path, int flags, int mode) |
| 76 | { |
| 77 | int fd = open(path, flags, mode); |
| 78 | if (fd == -1) error_exit("No file %s\n", path); |
| 79 | return fd; |
| 80 | } |
| 81 | |
| 82 | // Die unless we can open/create a file, returning FILE *. |
| 83 | FILE *xfopen(char *path, char *mode) |
| 84 | { |
| 85 | FILE *f = fopen(path, mode); |
| 86 | if (!f) error_exit("No file %s\n", path); |
| 87 | return f; |
| 88 | } |