Commit 20636fed authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Make the C-compiler command a paramter, and generally clean up the

code that invokes it.

If fmtcheck(3) is available, we refuse pedal target practice.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@1882 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent dc459ddd
...@@ -60,6 +60,7 @@ void MCF_ParamSet(struct cli *, const char *param, const char *val); ...@@ -60,6 +60,7 @@ void MCF_ParamSet(struct cli *, const char *param, const char *val);
void mgt_vcc_init(void); void mgt_vcc_init(void);
int mgt_vcc_default(const char *bflag, const char *fflag, int f_fd, int Cflag); int mgt_vcc_default(const char *bflag, const char *fflag, int f_fd, int Cflag);
int mgt_push_vcls_and_start(unsigned *status, char **p); int mgt_push_vcls_and_start(unsigned *status, char **p);
extern char *mgt_cc_cmd;
#include "hash_slinger.h" #include "hash_slinger.h"
......
...@@ -527,6 +527,30 @@ tweak_ping_interval(struct cli *cli, struct parspec *par, const char *arg) ...@@ -527,6 +527,30 @@ tweak_ping_interval(struct cli *cli, struct parspec *par, const char *arg)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void
tweak_cc_command(struct cli *cli, struct parspec *par, const char *arg)
{
(void)par;
if (arg == NULL) {
cli_out(cli, "%s", mgt_cc_cmd);
} else {
#if defined(HAVE_FMTCHECK)
if (arg != fmtcheck(arg, "%s %s")) {
cli_out(cli,
"Parameter has dangerous %%-string expansions.");
cli_result(cli, CLIS_PARAM);
return;
}
#endif
free(mgt_cc_cmd);
mgt_cc_cmd = strdup(arg);
XXXAN(mgt_cc_cmd);
}
}
/*--------------------------------------------------------------------*/
/* /*
* Make sure to end all lines with either a space or newline of the * Make sure to end all lines with either a space or newline of the
* formatting will go haywire. * formatting will go haywire.
...@@ -539,6 +563,10 @@ tweak_ping_interval(struct cli *cli, struct parspec *par, const char *arg) ...@@ -539,6 +563,10 @@ tweak_ping_interval(struct cli *cli, struct parspec *par, const char *arg)
"\nNB: This parameter will not take any effect until the " \ "\nNB: This parameter will not take any effect until the " \
"child process has been restarted.\n" "child process has been restarted.\n"
#define MUST_RELOAD \
"\nNB: This parameter will not take any effect until the " \
"VCL programs have been reloaded.\n"
#define EXPERIMENTAL \ #define EXPERIMENTAL \
"\nNB: We don't know yet if it is a good idea to change " \ "\nNB: We don't know yet if it is a good idea to change " \
"this parameter. Caution advised.\n" "this parameter. Caution advised.\n"
...@@ -700,6 +728,20 @@ static struct parspec parspec[] = { ...@@ -700,6 +728,20 @@ static struct parspec parspec[] = {
"it possible to attach a debugger to the child.\n" "it possible to attach a debugger to the child.\n"
MUST_RESTART, MUST_RESTART,
"3", "seconds" }, "3", "seconds" },
{ "cc_command", tweak_cc_command,
"Command used for compiling the C source code to a "
"dlopen(3) loadable object.\n"
"NB: The string must contain two %%s sequences which "
"will be replaced by the binary and source file names "
"respectively.\n"
MUST_RELOAD,
#ifdef __APPLE__
"exec cc -dynamiclib -Wl,-undefined,dynamic_lookup -o %s -x c"
" - < %s"
#else
"exec cc -nostdinc -fpic -shared -Wl,-x -o %s -x c - < %s"
#endif
, NULL },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h>
#ifndef HAVE_ASPRINTF #ifndef HAVE_ASPRINTF
#include "compat/asprintf.h" #include "compat/asprintf.h"
...@@ -65,6 +66,8 @@ struct vclprog { ...@@ -65,6 +66,8 @@ struct vclprog {
static TAILQ_HEAD(, vclprog) vclhead = TAILQ_HEAD_INITIALIZER(vclhead); static TAILQ_HEAD(, vclprog) vclhead = TAILQ_HEAD_INITIALIZER(vclhead);
char *mgt_cc_cmd;
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
/* keep this in synch with man/vcl.7 */ /* keep this in synch with man/vcl.7 */
...@@ -148,8 +151,9 @@ mgt_CallCc(const char *source, struct vsb *sb) ...@@ -148,8 +151,9 @@ mgt_CallCc(const char *source, struct vsb *sb)
FILE *fo, *fs; FILE *fo, *fs;
char sf[] = "./vcl.XXXXXXXX"; char sf[] = "./vcl.XXXXXXXX";
char *of; char *of;
char buf[BUFSIZ]; struct vsb *cccmd;
int i, j, len, sfd; char buf[128];
int i, j, sfd;
void *p; void *p;
/* Create temporary C source file */ /* Create temporary C source file */
...@@ -161,7 +165,7 @@ mgt_CallCc(const char *source, struct vsb *sb) ...@@ -161,7 +165,7 @@ mgt_CallCc(const char *source, struct vsb *sb)
return (NULL); return (NULL);
} }
fs = fdopen(sfd, "r+"); fs = fdopen(sfd, "r+");
AN(fs); XXXAN(fs);
if (fputs(source, fs) < 0 || fflush(fs)) { if (fputs(source, fs) < 0 || fflush(fs)) {
vsb_printf(sb, vsb_printf(sb,
...@@ -173,55 +177,92 @@ mgt_CallCc(const char *source, struct vsb *sb) ...@@ -173,55 +177,92 @@ mgt_CallCc(const char *source, struct vsb *sb)
} }
rewind(fs); rewind(fs);
/* Name the output shared library */ /* Name the output shared library by brutally overwriting "./vcl." */
of = strdup(sf); of = strdup(sf);
AN(of); XXXAN(of);
memcpy(of, "./bin", 5); memcpy(of, "./bin", 5);
/* Attempt to open a pipe to the system C-compiler */ cccmd = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND);
len = snprintf(buf, sizeof buf, XXXAN(cccmd);
"ln -f %s _.c ;" /* XXX: for debugging */
#ifdef __APPLE__ /*
"exec cc -dynamiclib -Wl,-undefined,dynamic_lookup -o %s -x c - < %s 2>&1", * Attempt to open a pipe to the system C-compiler.
#else * ------------------------------------------------
"env -i cc -nostdinc -fpic -shared -Wl,-x -o %s -x c - < %s 2>&1", *
#endif * The arguments to the C-compiler must be whatever it takes to
sf, of, sf); * create a dlopen(3) compatible object file named $of from a
xxxassert(len < sizeof buf); * source file named $sf.
*
fo = popen(buf, "r"); * The source code is entirely selfcontained, so options should be
* specified to prevent the C-compiler from doing any DWITYW
* processing. For GCC this amounts to at least "-nostdinc".
*
* We wrap the entire command in a 'sh -c "..." 2>&1' to get any
* errors from popen(3)'s shell redirected to our stderr as well.
*
*/
vsb_printf(cccmd, "exec /bin/sh -c \"" );
vsb_printf(cccmd, mgt_cc_cmd, of, sf);
vsb_printf(cccmd, "\" 2>&1");
vsb_finish(cccmd);
/* XXX: check that vsb is happy about cccmd */
fo = popen(vsb_data(cccmd), "r");
if (fo == NULL) { if (fo == NULL) {
vsb_printf(sb, vsb_printf(sb,
"Internal error: Cannot execute cc(1): %s\n", "System error: Cannot execute C-compiler: %s\n"
strerror(errno)); "\tcommand attempted: %s\n",
strerror(errno), vsb_data(cccmd));
free(of); free(of);
unlink(sf); unlink(sf);
fclose(fs); fclose(fs);
vsb_delete(cccmd);
return (NULL); return (NULL);
} }
/* If we get any output, it's bad */ /* Any output is considered fatal */
j = 0; j = 0;
while (1) { while (1) {
if (fgets(buf, sizeof buf, fo) == NULL) i = fread(buf, 1, sizeof buf, fo);
if (i == 0)
break; break;
if (!j) { if (!j) {
vsb_printf(sb, "Internal error: cc(1) complained:\n"); vsb_printf(sb,
"System error:\n"
"C-compiler command complained.\n"
"Command attempted: %s\nMessage:\n",
vsb_data(cccmd));
j++; j++;
} }
vsb_cat(sb, buf); vsb_bcat(sb, buf, i);
} }
i = pclose(fo); i = pclose(fo);
if (j == 0 && i != 0)
unlink(sf);
fclose(fs);
if (j == 0 && i != 0) {
vsb_printf(sb,
"System error:\n"
"C-compiler command failed");
if (WIFEXITED(i))
vsb_printf(sb, ", exit %d", WEXITSTATUS(i));
if (WIFSIGNALED(i))
vsb_printf(sb, ", signal %d", WTERMSIG(i));
if (WCOREDUMP(i))
vsb_printf(sb, ", core dumped");
vsb_printf(sb, vsb_printf(sb,
"Internal error: cc(1) exit status 0x%04x\n", i); "\nCommand attempted: %s\n", vsb_data(cccmd));
}
vsb_delete(cccmd);
/* If the compiler complained, or exited non-zero, fail */ /* If the compiler complained, or exited non-zero, fail */
if (i || j) { if (i || j) {
unlink(of); unlink(of);
free(of); free(of);
of = NULL; return (NULL);
} }
/* Next, try to load the object into the management process */ /* Next, try to load the object into the management process */
...@@ -231,13 +272,10 @@ mgt_CallCc(const char *source, struct vsb *sb) ...@@ -231,13 +272,10 @@ mgt_CallCc(const char *source, struct vsb *sb)
dlerror()); dlerror());
unlink(of); unlink(of);
free(of); free(of);
of = NULL; return (NULL);
} else }
(void)dlclose(p);
/* clean up and return */ (void)dlclose(p);
unlink(sf);
fclose(fs);
return (of); return (of);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment