1 /*============================================================================ 2 epub2txt v2 3 util.c 4 Copyright (c)2022 Marco Bonelli, Kevin Boone, GPL v3.0 5 ============================================================================*/ 6 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include "util.h" 15 #include "log.h" 16 17 /*========================================================================== 18 run_command 19 Run an helper command through fork + execvp, wait for it to finish and return 20 its status. Log execvp errors, and abort execution if abort_on_error is TRUE. 21 (Marco Bonelli) 22 *==========================================================================*/ 23 int run_command (const char *const argv[], BOOL abort_on_error) 24 { 25 int status; 26 int pid = fork(); 27 28 if (pid == 0) 29 { 30 execvp(argv[0], (char **const)argv); 31 log_error ("Can't execute command \"%s\": %s", argv[0], strerror (errno)); 32 33 if (abort_on_error) 34 { 35 kill (getppid(), SIGTERM); 36 _exit (-1); 37 } 38 39 _exit (0); 40 } 41 42 waitpid (pid, &status, 0); 43 return status; 44 } 45 46 /*========================================================================== 47 Decode %xx in URL-type strings. The caller must free the resulting 48 string, which will be no longer than the input. 49 (Kevin Boone) 50 *==========================================================================*/ 51 char *decode_url (const char *url) 52 { 53 char *ret = malloc (strlen (url) + 2); 54 55 int len = 0; 56 for (; *url; len++) 57 { 58 if (*url == '%' && url[1] && url[2] && 59 isxdigit(url[1]) && isxdigit(url[2])) 60 { 61 char url1 = url[1]; 62 char url2 = url[2]; 63 url1 -= url1 <= '9' ? '0' : (url1 <= 'F' ? 'A' : 'a')-10; 64 url2 -= url2 <= '9' ? '0' : (url2 <= 'F' ? 'A' : 'a')-10; 65 ret[len] = 16 * url1 + url2; 66 url += 3; 67 continue; 68 } 69 else if (*url == '+') 70 { 71 /* I have not tested this piece of the function, because I have not 72 seen any instances of '+' (meaning space) in a spine href */ 73 url += 1; 74 ret[len] = ' '; 75 } 76 ret[len] = *url++; 77 } 78 ret[len] = '\0'; 79 80 return ret; 81 } 82 83 /*========================================================================== 84 is_subpath 85 Determine whether path is a subpath of root; or in other words, whether path 86 points to a file/directory inside root. Both root and path are assumed to be 87 in canonical form, therefore the caller should make sure of this using e.g. 88 canonicalize_file_name(path) or realpath(path, NULL). 89 (Marco Bonelli) 90 *==========================================================================*/ 91 BOOL is_subpath (const char *root, const char *path) 92 { 93 size_t root_len = strlen (root); 94 size_t path_len = strlen (path); 95 return path_len > root_len && !strncmp (root, path, root_len) 96 && path[root_len] == '/'; 97 }