Reputation: 59
I created a program that would help convert my PHP code to a runnable c file, so I can use the PHP functions. The program runs perfectly on my system(Windows 10) but fails to run on my colleagues' systems(Windows 10 also). n my header, I created my own asprintf because the function does not exist on windows.
My asprintf.h
#ifndef ASPRINTF_H
#define ASPRINTF_H
#if defined(__GNUC__) && ! defined(_GNU_SOURCE)
#define _GNU_SOURCE /* needed for (v)asprintf, affects '#include <stdio.h>' */
#endif
#include <stdio.h> /* needed for vsnprintf */
#include <stdlib.h> /* needed for malloc, free */
#include <stdarg.h> /* needed for va_* */
/*
* vscprintf:
* MSVC implements this as _vscprintf, thus we just 'symlink' it here
* GNU-C-compatible compilers do not implement this, thus we implement it here
*/
#ifdef _MSC_VER
#define vscprintf _vscprintf
#endif
#ifdef __GNUC__
int vscprintf(const char *format, va_list ap)
{
va_list ap_copy;
va_copy(ap_copy, ap);
int retval = vsnprintf(NULL, 0, format, ap_copy);
va_end(ap_copy);
return retval;
}
#endif
/*
* asprintf, vasprintf:
* MSVC does not implement these, thus we implement them here
* GNU-C-compatible compilers implement these with the same names, thus we
* don't have to do anything
*/
#ifdef _MSC_VER
int vasprintf(char **strp, const char *format, va_list ap)
{
int len = vscprintf(format, ap);
if (len == -1)
return -1;
char *str = (char*)malloc((size_t) len + 1);
if (!str)
return -1;
int retval = vsnprintf(str, len + 1, format, ap);
if (retval == -1) {
free(str);
return -1;
}
*strp = str;
return retval;
}
int asprintf(char **strp, const char *format, ...)
{
va_list ap;
va_start(ap, format);
int retval = vasprintf(strp, format, ap);
va_end(ap);
return retval;
}
#endif
#endif // ASPRINTF_H
My main.c
#include "asprintf.h"
#include <stdio.h>
#include <stdlib.h>
extern char _binary_script_php_start;
extern char _binary_script_php_end;
int main(int argc, char *argv[]) {
// EXTRACT OUR RESOURCE OBJECT INTO /tmp/test.php
char *p = &_binary_script_php_start;
FILE *fp = fopen("/tmp/test.php","wb");
while ( p != &_binary_script_php_end ) {
fputc(*p++,fp);
}
fclose(fp);
// NOW READ IN OUR STANDARD ARGUMENTS AND LAUNCH OUR COMMAND
int i = 1;
char *cmd = "php /tmp/test.php";
char *s = NULL;
asprintf(&s, "%s",cmd);
for(i = 1; i < argc; i++) {
asprintf(&s, "%s \"%s\"",s,argv[i]);
}
// concatf("%s",cmd);
// for(i = 1; i < argc; i++) {
// concatf("%s \"%s\"",s,argv[i]);
// }
// concatf(&s, "%s",cmd);
// for(i = 1; i < argc; i++) {
// concatf(&s, "%s \"%s\"",s,argv[i]);
// }
system(s);
free(s);
unlink("/tmp/test.php"); // comment me out for debugging if you want
}
I was able to recreate their error by creating a new header file and changing the name of the function. so when they get:
warning: implicit declaration of function 'asprintf' [-Wimplicit-function-declaration] 29 | asprintf(&s, "%s",cmd);
I get:
warning: implicit declaration of function 'concatf' [-Wimplicit-function-declaration] 29 | concatf(&s, "%s",cmd);
Which is not making sense to me, I know for this to work, the function should be declared before the main function and that is already being done. I know I have to define _GNU_SOURCE which is being handled in my header file. Are there rules I am not adhering to? If so why would it work in my environment and not my colleagues'?
To be able to run this create a PHP file called script.php and run the following commands:
php:
ld -r -b binary script.php data.o
exe:
gcc main.c data.o -o runme
if working properply ./runme should run the php file.
Kindly find the source code here: https://github.com/Sammiiie/C_php_http
Upvotes: 0
Views: 1037
Reputation: 4877
These functions, optional by standard, are defined in the document: ISO/IEC TR 24731-2.
They need to be explicitely enabled defining the constant __STDC_WANT_LIB_EXT2__
before including the header stdio.h
.
From ISO/IEC TR 24731-2,5.1.1 Standard headers:
The functions, macros, and types defined in Clause 5 and its subclauses are defined by their respective headers if _STDC_WANT_LIB_EXT2 _ is defined as a macro which expands to the integer constant 1 at the point in the source file where the appropriate header is included.
I.e.
#define __STDC_WANT_LIB_EXT2__ 1
#include <stdio.h>
....
In your case, to enable it only for non MS compilers, you may write:
#ifndef _MSC_VER
#define __STDC_WANT_LIB_EXT2__ 1
#endif
#include <stdio.h>
....
Upvotes: 1