diff options
Diffstat (limited to 'build/misc.c')
-rw-r--r-- | build/misc.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/build/misc.c b/build/misc.c new file mode 100644 index 000000000..7437f3d2a --- /dev/null +++ b/build/misc.c @@ -0,0 +1,202 @@ +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> + +#include "misc.h" +#include "spec.h" +#include "rpmlib.h" +#include "header.h" +#include "popt/popt.h" + +void addOrAppendListEntry(Header h, int_32 tag, char *line) +{ + int argc; + char **argv; + + poptParseArgvString(line, &argc, &argv); + if (argc) { + headerAddOrAppendEntry(h, tag, RPM_STRING_ARRAY_TYPE, argv, argc); + } + FREE(argv); +} + +/* Parse a simple part line that only take -n <pkg> or <pkg> */ +/* <pkg> is return in name as a pointer into a static buffer */ + +int parseSimplePart(char *line, char **name, int *flag) +{ + char *tok; + char linebuf[BUFSIZ]; + static char buf[BUFSIZ]; + + strcpy(linebuf, line); + + /* Throw away the first token (the %xxxx) */ + strtok(linebuf, " \t\n"); + + if (!(tok = strtok(NULL, " \t\n"))) { + *name = NULL; + return 0; + } + + if (!strcmp(tok, "-n")) { + if (!(tok = strtok(NULL, " \t\n"))) { + return 1; + } + *flag = PART_NAME; + } else { + *flag = PART_SUBNAME; + } + strcpy(buf, tok); + *name = buf; + + return (strtok(NULL, " \t\n")) ? 1 : 0; +} + +int parseYesNo(char *s) +{ + if (!s || (s[0] == 'n' || s[0] == 'N') || + !strcasecmp(s, "false") || + !strcasecmp(s, "off") || + !strcmp(s, "0")) { + return 0; + } + + return 1; +} + +char *findLastChar(char *s) +{ + char *res = s; + + while (*s) { + if (! isspace(*s)) { + res = s; + } + s++; + } + + return res; +} + +int parseNum(char *line, int *res) +{ + char *s1; + + s1 = NULL; + *res = strtoul(line, &s1, 10); + if ((*s1) || (s1 == line) || (*res == ULONG_MAX)) { + return 1; + } + + return 0; +} + +StringBuf getOutputFrom(char *dir, char *argv[], + char *writePtr, int writeBytesLeft, + int failNonZero) +{ + int progPID; + int progDead; + int toProg[2]; + int fromProg[2]; + int status; + void *oldhandler; + int bytesWritten; + StringBuf readBuff; + int bytes; + unsigned char buf[8193]; + + oldhandler = signal(SIGPIPE, SIG_IGN); + + pipe(toProg); + pipe(fromProg); + + if (!(progPID = fork())) { + close(toProg[1]); + close(fromProg[0]); + + dup2(toProg[0], 0); /* Make stdin the in pipe */ + dup2(fromProg[1], 1); /* Make stdout the out pipe */ + + close(toProg[0]); + close(fromProg[1]); + + if (dir) { + chdir(dir); + } + + execvp(argv[0], argv); + rpmError(RPMERR_EXEC, "Couldn't exec %s", argv[0]); + _exit(RPMERR_EXEC); + } + if (progPID < 0) { + rpmError(RPMERR_FORK, "Couldn't fork %s", argv[0]); + return NULL; + } + + close(toProg[0]); + close(fromProg[1]); + + /* Do not block reading or writing from/to prog. */ + fcntl(fromProg[0], F_SETFL, O_NONBLOCK); + fcntl(toProg[1], F_SETFL, O_NONBLOCK); + + readBuff = newStringBuf(); + + progDead = 0; + do { + if (waitpid(progPID, &status, WNOHANG)) { + progDead = 1; + } + + /* Write some stuff to the process if possible */ + if (writeBytesLeft) { + if ((bytesWritten = + write(toProg[1], writePtr, + (1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) { + if (errno != EAGAIN) { + perror("getOutputFrom()"); + exit(1); + } + bytesWritten = 0; + } + writeBytesLeft -= bytesWritten; + writePtr += bytesWritten; + } else { + close(toProg[1]); + } + + /* Read any data from prog */ + bytes = read(fromProg[0], buf, sizeof(buf)-1); + while (bytes > 0) { + buf[bytes] = '\0'; + appendStringBuf(readBuff, buf); + bytes = read(fromProg[0], buf, sizeof(buf)-1); + } + + /* terminate when prog dies */ + } while (!progDead); + + close(toProg[1]); + close(fromProg[0]); + signal(SIGPIPE, oldhandler); + + if (writeBytesLeft) { + rpmError(RPMERR_EXEC, "failed to write all data to %s", argv[0]); + return NULL; + } + waitpid(progPID, &status, 0); + if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) { + rpmError(RPMERR_EXEC, "%s failed", argv[0]); + return NULL; + } + + return readBuff; +} |