tech-pkg archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Wrappers don't transform @file syntax
I stumbled upon a problem where wrappers don't transform @file syntax
accepted by tools like gcc, ld, and ar. Missing dependencies went
unnoticed because GHC used it to link libraries and executables:
> [*] cc '@/tmp/ghc23632_0/ghc_1.rsp'
> <.> /usr/pkgsrc/devel/hs-either/work/.gcc/bin/gcc -m64
'@/tmp/ghc3079_0/ghc_20.rsp' -D_FORTIFY_SOURCE=2 ...
The attached patch expands @file, possibly recursively, before applying
transformations. I originally planned to turn arguments back to @file
after transformations by writing them to a temporary file, but since it
invokes execvp(3) I couldn't come up with a way to delete it afterwards.
joerg@, could you review it please?
? files/test/Atffile
Index: files/bin/base-wrapper.c
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/cwrappers/files/bin/base-wrapper.c,v
retrieving revision 1.6
diff -u -r1.6 base-wrapper.c
--- files/bin/base-wrapper.c 27 Oct 2017 20:59:59 -0000 1.6
+++ files/bin/base-wrapper.c 10 Jan 2020 12:17:18 -0000
@@ -136,6 +136,7 @@
operation_mode_cc(&args);
#endif
arglist_apply_config(&args);
+ arglist_expand_atfile(&args);
#if defined(WRAPPER_LD)
normalise_ld(&args);
#else
Index: files/bin/common.c
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/cwrappers/files/bin/common.c,v
retrieving revision 1.10
diff -u -r1.10 common.c
--- files/bin/common.c 25 Mar 2018 20:45:25 -0000 1.10
+++ files/bin/common.c 10 Jan 2020 12:17:18 -0000
@@ -173,6 +173,34 @@
}
}
+static void
+arglist_insert_list(struct arglist *args, struct arglist *inserts, struct argument *before)
+{
+ struct argument *insert;
+
+ TAILQ_FOREACH(insert, inserts, link) {
+ struct argument *arg;
+
+ arg = argument_copy(insert->val);
+ if (before != NULL)
+ TAILQ_INSERT_BEFORE(before, arg, link);
+ else
+ TAILQ_INSERT_TAIL(args, arg, link);
+ }
+}
+
+static void
+arglist_clear(struct arglist *args)
+{
+ struct argument *arg;
+
+ while ((arg = TAILQ_FIRST(args)) != NULL) {
+ TAILQ_REMOVE(args, arg, link);
+ free(arg->val);
+ free(arg);
+ }
+}
+
void
arglist_apply_config(struct arglist *args)
{
@@ -194,6 +222,118 @@
}
void
+arglist_from_atfile(struct arglist *args, const char *file)
+{
+ FILE *fp;
+ char *line;
+ size_t len;
+ ssize_t llen;
+
+ TAILQ_INIT(args);
+
+ fp= fopen(file, "r");
+ if (fp == NULL) {
+ /* If the file cannot be read, it has to be treated
+ * literally. */
+ struct argument *arg;
+ arg = argument_new(concat("@", file));
+ TAILQ_INSERT_TAIL(args, arg, link);
+ return;
+ }
+
+ line = NULL;
+ len = 0;
+ while ((llen = getline(&line, &len, fp)) > 0) {
+ char *buf;
+ size_t blen, pos;
+
+ /* Allocate a buffer for an argument. It can be at most llen
+ * bytes long. */
+ buf = xmalloc(llen + 1);
+
+ for (pos = 0; pos < llen; ) {
+ char in_quote;
+
+ /* Find the next possible argument. */
+ blen = 0;
+ pos += strspn(line + pos, " \t\n");
+ in_quote = '\0';
+
+ if (pos >= llen)
+ break;
+
+ while (pos < llen) {
+ if (strchr(" \t\n", line[pos]) != NULL) {
+ if (in_quote != '\0') {
+ buf[blen++] = line[pos++];
+ }
+ else {
+ break;
+ }
+ }
+ else if (line[pos] == '\\') {
+ if (pos+1 < llen) {
+ buf[blen++] = line[pos+1];
+ pos += 2;
+ }
+ else {
+ errx(255, "Incomplete escape sequence: %s", line);
+ }
+ }
+ else if (strchr("\'\"", line[pos]) != NULL) {
+ if (in_quote == line[pos]) {
+ /* We just exited a quoted string. */
+ in_quote = '\0';
+ }
+ else {
+ /* Entering into a quoted string. */
+ in_quote = line[pos];
+ }
+ pos++;
+ }
+ else {
+ buf[blen++] = line[pos++];
+ }
+ }
+
+ buf[blen] = '\0';
+ if (blen > 1 && buf[0] == '@') {
+ /* @file arguments may itself contain @file. Expand it
+ * recursively. */
+ struct arglist file_args;
+ arglist_from_atfile(&file_args, buf + 1);
+ arglist_append_list(args, &file_args);
+ arglist_clear(&file_args);
+ }
+ else {
+ struct argument *arg;
+ arg = argument_copy(buf);
+ TAILQ_INSERT_TAIL(args, arg, link);
+ }
+ }
+ free(buf);
+ }
+ free(line);
+}
+
+void
+arglist_expand_atfile(struct arglist *args)
+{
+ struct argument *arg, *arg2;
+
+ TAILQ_FOREACH_SAFE(arg, args, link, arg2) {
+ if (arg->val[0] == '@') {
+ struct arglist file_args;
+
+ arglist_from_atfile(&file_args, arg->val + 1);
+ arglist_insert_list(args, &file_args, arg2);
+ arglist_clear(&file_args);
+ argument_unlink(args, &arg);
+ }
+ }
+}
+
+void
argument_unlink(struct arglist *args, struct argument **argp)
{
struct argument *arg;
Index: files/bin/common.h
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/cwrappers/files/bin/common.h,v
retrieving revision 1.8
diff -u -r1.8 common.h
--- files/bin/common.h 7 Nov 2017 16:49:22 -0000 1.8
+++ files/bin/common.h 10 Jan 2020 12:17:18 -0000
@@ -69,7 +69,9 @@
char *concat(const char *, const char *);
char *concat2(const char *, const char *, size_t);
void arglist_from_argc(struct arglist *, int, char **);
+void arglist_from_atfile(struct arglist *, const char *);
void arglist_apply_config(struct arglist *);
+void arglist_expand_atfile(struct arglist *);
int command_exec(struct arglist *, int, char **);
size_t wrapper_hash(const char *);
size_t wrapper_hash2(const char *, size_t);
Home |
Main Index |
Thread Index |
Old Index