Just this:
PHP Code:
void gsc_utils_execute() { // Returns complete command output as a string
char *cmd;
if ( ! stackGetParams("s", &cmd)) {
printf("scriptengine> ERROR: please specify the command as string to gsc_execute_command()\n");
stackPushUndefined();
return;
}
setenv("LD_PRELOAD", "", 1); // dont inherit lib of parent
char *result = exec(cmd);
stackPushString( result );
free(result); // <------
}
Because:
http://man7.org/linux/man-pages/man3/getline.3.html
Code:
getline() reads an entire line from stream, storing the address of
the buffer containing the text into *lineptr. The buffer is null-
terminated and includes the newline character, if one was found.
If *lineptr is set to NULL and *n is set 0 before the call, then
getline() will allocate a buffer for storing the line. This buffer
should be freed by the user program even if getline() failed.
And init the char *result in exec(char *) to NULL, since setting a pointer to NULL automatically is "luck" (depending on compiler if they init it).
Full test:
PHP Code:
#include <stdio.h>
#include <stdlib.h>
char *exec(const char* command) {
FILE *fp;
char *result = NULL; // plz init, otherwise it COULD be non-NULL (depending on compiler)
size_t len = 0;
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return NULL;
}
while(getline(&result, &len, fp) != -1) {
fputs(result, stdout); // nice for debugging, but in actual release server kinda spammy to print every result
}
pclose(fp);
return result;
}
int main() {
char *result = exec("ls -l");
printf("ret: \"%s\"", result);
free(result);
return 0;
}
Just compile it:
gcc exec.c -o exec.exe
And run it with valgrind: valgrind --tool=memcheck ./exec.exe
Everything will be ok then, but when you forget free(result);, valgrind will print the error:
Code:
k_tracker@euve78301:~$ valgrind --tool=memcheck ./exec.exe
==17356== Memcheck, a memory error detector
==17356== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==17356== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==17356== Command: ./exec.exe
==17356==
total 625772
-rwxr-xr-x 1 k_tracker k_tracker 1300 Dez 12 2014 autobahn2.js
-rwxr-xr-x 1 k_tracker k_tracker 913 Dez 10 2014 autobahn.js
drwxr-xr-x 3 k_tracker k_tracker 4096 Okt 15 2013 bin
drwxrwxr-x 2 k_tracker k_tracker 4096 Nov 30 05:21 boost
-rwxr-xr-x 1 k_tracker k_tracker 22803 Jan 21 2015 calculator.js
-rwxr-xr-x 1 k_tracker k_tracker 3737 Dez 10 2014 chat.js
drwxr-xr-x 2 k_tracker k_tracker 4096 Okt 15 2013 classes
-rwxr-xr-x 1 k_tracker k_tracker 3475 Nov 19 2012 debug.php
-rwxr-xr-x 1 k_tracker k_tracker 330 Dez 15 2014 dns.js
-rw-rw-r-- 1 k_tracker k_tracker 516 Jan 3 03:15 exec.c
-rwxrwxr-x 1 k_tracker k_tracker 8832 Jan 3 03:15 exec.exe
drwxrwxr-x 2 k_tracker k_tracker 4096 Okt 1 03:06 filefront
-rw-rw-r-- 1 k_tracker k_tracker 452 Okt 1 03:00 kt.txt
drwxr-xr-x 4 k_tracker k_tracker 4096 Okt 15 2013 lib
-rwxr-xr-x 1 k_tracker k_tracker 3380 Nov 19 2012 main.php
drwxr-xr-x 14 k_tracker k_tracker 4096 Dez 1 20:16 mariadb
-rwxr-xr-x 1 k_tracker k_tracker 309533236 Jun 17 2015 mariadb.1
-rw-rw-r-- 1 k_tracker k_tracker 331091501 Okt 15 23:14 mariadb.tar.gz
-rwxr-xr-x 1 k_tracker k_tracker 3858 Jul 1 2015 my.cnf
drwxr-xr-x 7 k_tracker k_tracker 4096 Dez 10 2014 nodejs
drwxr-xr-x 28 k_tracker k_tracker 4096 Sep 24 16:07 node_modules
drwxr-xr-x 2 k_tracker k_tracker 4096 Jul 2 2015 ntop
-rwxr-xr-x 1 k_tracker k_tracker 6681 Nov 19 2012 query_master.js
-rwxr-xr-x 1 k_tracker k_tracker 335 Dez 10 2014 rpc.js
-rwxr-xr-x 1 k_tracker k_tracker 46 Okt 15 2013 server.sh
drwxr-xr-x 2 k_tracker k_tracker 4096 Sep 24 16:07 tmp
drwxr-xr-x 4 k_tracker k_tracker 4096 Jun 30 2015 tracker
drwxr-xr-x 4 k_tracker k_tracker 4096 Jun 30 2015 tracker_floater
drwxr-xr-x 5 k_tracker k_tracker 4096 Nov 15 00:13 tracker_iznogod
-rwxr-xr-x 1 k_tracker k_tracker 327 Jul 10 2014 unity2.js
-rwxr-xr-x 1 k_tracker k_tracker 1082 Jul 10 2014 unity.js
-rwxr-xr-x 1 k_tracker k_tracker 709 Dez 11 2014 wamp_client.js
-rwxr-xr-x 1 k_tracker k_tracker 238 Dez 11 2014 wamp.js
ret: "-rwxr-xr-x 1 k_tracker k_tracker 238 Dez 11 2014 wamp.js
"==17356==
==17356== HEAP SUMMARY:
==17356== in use at exit: 120 bytes in 1 blocks
==17356== total heap usage: 2 allocs, 1 frees, 376 bytes allocated
==17356==
==17356== LEAK SUMMARY:
==17356== definitely lost: 120 bytes in 1 blocks
==17356== indirectly lost: 0 bytes in 0 blocks
==17356== possibly lost: 0 bytes in 0 blocks
==17356== still reachable: 0 bytes in 0 blocks
==17356== suppressed: 0 bytes in 0 blocks
==17356== Rerun with --leak-check=full to see details of leaked memory
==17356==
==17356== For counts of detected and suppressed errors, rerun with: -v
==17356== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
k_tracker@euve78301:~$
About the pointer syntax, the asterix belongs to the variable name. You can simply understand this, when you want e.g. 2 pointers. What do you write?
This?
Or this?
Well, as said already, the 2nd way is the correct way, since the asterix belongs to the variable name.
Also why just return the last line? Just return an array with every line :^)
Simple example from scandir():
PHP Code:
void gsc_utils_scandir() {
char *dirname;
if ( ! stackGetParams("s", &dirname)) {
stackPushUndefined();
return;
}
DIR *dir;
struct dirent *dir_ent;
dir = opendir(dirname);
if ( ! dir) {
stackPushUndefined();
return;
}
stackPushArray();
while (dir_ent = readdir(dir)) {
stackPushString(dir_ent->d_name);
stackPushArrayLast();
}
closedir(dir);
}