File: find-cmd-by-dir

package info (click to toggle)
ccontrol 1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, stretch, wheezy
  • size: 656 kB
  • sloc: ansic: 1,533; sh: 337; makefile: 150; python: 141; xml: 64
file content (176 lines) | stat: -rw-r--r-- 5,322 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
Description: Add support for finding commands by directory rather than being named explicitly.
 Add the ability to specify that a command shall be found in a directory and
 let ccontrol choose the actual program to execute depending on its invocation.
 . 
 This means having multiple versions of tools such as the compiler can exist
 under different names, and ccontrol will execute the right one.
 .
 It also updates ccontrol-init to specify enclosing directories by default
 because otherwise no-one will find this functionality.
Author: Ted Percival <ted@midg3t.net>
Bug-Debian: http://bugs.debian.org/447832
Last-Update: 2011-11-14

--- a/ccontrol.1.txt
+++ b/ccontrol.1.txt
@@ -74,37 +74,38 @@
 will end in a "*" to include all subdirectories.
 
 All paths beginning with "~" are relative to the user's home
-directory.
+directory. A path may be specified as a directory, in which case
+ccontrol will append the program name to the directory.
 
 The following settings are available:
 
 cc::
-  Followed by '=' specifies the full path of the compiler to be
+  Followed by '=' specifies the path of the compiler to be
   invoked when ccontrol is invoked as "cc" or "gcc".  ccontrol will
   fail to compile C programs if this is not set.
 
 c++::
-  Followed by '=' specifies the full path of the compiler to be
+  Followed by '=' specifies the path of the compiler to be
   invoked when ccontrol is invoked as "c++" or "g++".  ccontrol will
   fail to compile C++ programs if this is not set.
 
 ld::
-  Followed by '=' specifies the full path of the linker to be invoked
+  Followed by '=' specifies the path of the linker to be invoked
   when ccontrol is invoked as "ld".  ccontrol will fail to link
   programs if this is not set.
 
 make::
-  Followed by '=' specifies the full path of the binary to be invoked
+  Followed by '=' specifies the path of the binary to be invoked
   when ccontrol is invoked as "make".  ccontrol will fail to make if
   this is not set.
 
 ccache::
-  Followed by '=' specifies the full path of "ccache", and indicates
+  Followed by '=' specifies the path of "ccache", and indicates
   that ccache is to be used where appropriate.  If followed by
   'disable', or not set, ccache will not be used.
 
 distcc::
-  Followed by '=' specifies the full path of "distcc", and indicates
+  Followed by '=' specifies the path of "distcc", and indicates
   that distcc is to be used where appropriate.  If followed by
   'disable', or not set, or distcc-hosts is not set, distcc will not
   be used.
--- a/ccontrol.c
+++ b/ccontrol.c
@@ -352,6 +352,14 @@
 
 	/* This handles open failure if fd < 0. */
 	sec = read_config(configname, dirname, fd);
+
+    /* Ensure we exec the right command */
+    {
+        char *cmd = resolve_path(sec.names[type], argv[0]);
+        free(sec.names[type]);
+        sec.names[type] = cmd;
+    }
+
 	fstat(fd, &st);
 
 	/* Run low priority; people like to use apps while compiling. */
--- a/ccontrol-init
+++ b/ccontrol-init
@@ -24,7 +24,7 @@
     else
 	echo Found "$ANS" >&2
     fi
-    echo $ANS
+    echo `dirname $ANS`
 }
 
 test_net()
--- a/ccontrol.h
+++ b/ccontrol.h
@@ -72,6 +72,7 @@
 
 /* ccontrol-parse.c */
 struct section read_config(const char *configname, const char *dir, int fd);
+char *resolve_path(const char *configured_path, const char *cmdname);
 
 /* ccontrol-lock.c */
 typedef void (*undofn_t)(void);
--- a/ccontrol-parse.c
+++ b/ccontrol-parse.c
@@ -5,6 +5,8 @@
 #include <fnmatch.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include "stdrusty.h"
 
 enum token_type {
@@ -228,6 +230,44 @@
 	return num;
 }
 
+/**
+ * Given a path and command name, returns the name of the file that
+ * should be 'exec'ed. If the path is a directory, the command name
+ * is appended. If it is an executable file, that is returned. If
+ * the path is not absolute, it is returned as-is.
+ *
+ * All return values are 'malloc'ed strings.
+ * On error, a copy of the configured_path is returned.
+ */
+char *resolve_path(const char *configured_path, const char *cmdname)
+{
+    struct stat st;
+    const char *basename;
+    char *execcmd;
+
+    if (configured_path[0] != '/'
+            || stat(configured_path, &st) == -1
+            || !S_ISDIR(st.st_mode))
+        return strdup(configured_path);
+
+    basename = strrchr(cmdname, '/');
+    if (basename)
+        ++basename;
+    else
+        basename = cmdname;
+
+    execcmd = malloc(strlen(configured_path) + strlen(basename) + 2);
+    if (!execcmd)
+        fatal("Cannot allocate memory for command", errno);
+
+    /* +1 to include the NUL byte */
+    memcpy(execcmd, configured_path, strlen(configured_path) + 1);
+    strcat(execcmd, "/");
+    strcat(execcmd, basename);
+
+    return execcmd;
+}
+
 /* '=' <path> */
 static char *get_path(struct string *data)
 {
@@ -510,6 +550,20 @@
 		}
 	}
 
+    /* Resolve ccache */
+    if (result->ccache) {
+        char *rawccache = result->ccache;
+        result->ccache = resolve_path(result->ccache, "ccache");
+        free(rawccache);
+    }
+
+    /* Resolve distcc */
+    if (result->distcc) {
+        char *rawdistcc = result->distcc;
+        result->distcc = resolve_path(result->distcc, "distcc");
+        free(rawdistcc);
+    }
+
 	free(data.start_of_file);
 }