/* Misc. utility functions and C-library extensions for finit and its plugins * * Copyright (c) 2008-2010 Claudio Matsuoka * Copyright (c) 2008-2022 Joachim Wiberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef FINIT_HELPERS_H_ #define FINIT_HELPERS_H_ #include #include #include #include #include #include #include #include /* Not included by default in musl libc */ #include #ifdef _LIBITE_LITE # include #else # include #endif #include "log.h" #define PROGRESS_DEFAULT PROGRESS_MODERN typedef enum { PROGRESS_SILENT, PROGRESS_CLASSIC, PROGRESS_MODERN, } pstyle_t; char *console (void); void console_init (void); ssize_t cprintf (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); void tabstospaces (char *line); char *strip_line (char *line); void enable_progress (int onoff); void show_progress (pstyle_t style); char *release_heading (void); speed_t stty_parse_speed(char *baud); void stty (int fd, speed_t speed); void print_banner (const char *heading); void printv (const char *fmt, va_list ap); void print (int action, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); void print_desc (char *action, char *desc); int print_result (int fail); int getuser (char *username, char **home); int getgroup (char *group); int getcuser (char *buf, size_t len); int getcgroup (char *buf, size_t len); int mksubsys (const char *dir, mode_t mode, char *user, char *group); void set_hostname (char **hostname); void networking (int updown); int in_container (void); int complete (char *cmd, int pid); int run (char *cmd, char *log); int run_interactive (char *cmd, char *fmt, ...) __attribute__ ((format (printf, 2, 3))); int exec_runtask (char *cmd, char *args[]); pid_t run_getty (char *tty, char *cmd, char *args[], int noclear, int nowait, struct rlimit rlimit[]); pid_t run_sh (char *tty, int noclear, int nowait, struct rlimit rlimit[]); int run_parts (char *dir, char *cmd, const char *env[], int progress); /* * Defaults to user "root" and group "wheel" (root) if: * 1) the user is missing * 2) the group or the file /etc/group is missing */ static inline int create(char *path, mode_t mode, char *user, char *group) { int fd, uid, gid; if (!path) { errno = EINVAL; return -1; } uid = getuser(user, NULL); if (uid < 0) uid = 0; gid = getgroup(group); if (gid < 0) gid = 0; fd = creat(path, mode); if (fd == -1) { warn("Failed creating %s properly", path); return -1; } close(fd); if (chown(path, uid, gid)) { warn("Failed chowning %s properly", path); return -1; } return 0; } static inline int ln(const char *target, const char *linkpath) { if (!target || !linkpath) { errno = EINVAL; return -1; } if (symlink(target, linkpath)) { if (errno != EEXIST) warn("Failed creating %s -> %s symlink", target, linkpath); return -1; } return 0; } static inline int dprint(int fd, const char *s, size_t len) { size_t loop = 3; int rc = -1; if (!len) len = strlen(s); while (loop--) { rc = write(fd, s, len); if (rc == -1 && errno == EINTR) continue; break; } return rc; } static inline char *fgetval(char *line, const char *key, char *sep) { char *ptr, *str, *copy; size_t len; str = copy = strdup(line); if (!copy) return NULL; ptr = strsep(&str, sep); if (ptr && strcmp(ptr, key)) { fail: free(copy); return NULL; } /* * Check if we should strip optional separator, e.g., * 'foo = bar' => '= bar' should be stripped to 'bar' */ while (str && strchr(sep, str[0])) { ptr = strsep(&str, sep); if (!ptr) goto fail; } ptr = str; if (*ptr == '"' || *ptr == '\'') { char *end = &ptr[strlen(ptr) - 1]; char q = *ptr; while (end > ptr && isspace(*end)) *end-- = 0; if (*end == q) { *end = 0; ptr++; } } len = strlen(ptr) + 1; memmove(copy, ptr, len); return realloc(copy, len); } #endif /* FINIT_HELPERS_H_ */ /** * Local Variables: * indent-tabs-mode: t * c-file-style: "linux" * End: */