Skip to content

Instantly share code, notes, and snippets.

@NotKyon
Created October 20, 2019 00:50
Show Gist options
  • Save NotKyon/9de31a53321aecd531ea6b21e26c863c to your computer and use it in GitHub Desktop.
Save NotKyon/9de31a53321aecd531ea6b21e26c863c to your computer and use it in GitHub Desktop.
/* read a string from a program's output */
char *mk_com_readprogf(const char *format, ...) {
static char cmd[32768];
static char buf[4096];
static char *out = NULL;
size_t n = 0, m = 0;
FILE *fp = (FILE *)0;
va_list args;
va_start(args, format);
#if MK_SECLIB
vsprintf_s(cmd, sizeof(cmd)/2, format, args);
#else
vsnprintf(cmd, sizeof(cmd)/2, format, args);
cmd[sizeof(cmd)/2 - 1] = 0;
#endif
va_end(args);
if( cmd[0] != '/' ) {
static char path[sizeof(cmd)/2 - 1];
size_t repindex;
char repchar = '\0';
char *pathvar = NULL;
for( repindex = 0; repindex < sizeof(cmd)-1 && cmd[repindex] != '\0'; ++repindex ) {
if( cmd[repindex] == ' ' ) {
if( repindex > 0 && cmd[repindex-1] == '\\' ) {
continue;
}
repchar = cmd[repindex]; // should just be ' ', but we might adjust this
cmd[repindex] = '\0';
break;
}
}
if( ( pathvar = getenv("PATH") ) != NULL ) {
static const char pathenvsep =
#if defined(_WIN32)
';'
#else
':'
#endif
;
const char *s, *e;
size_t pathlen;
s = pathvar;
do {
e = strchr( s, pathenvsep );
if( e != NULL ) {
pathlen = (size_t)(ptrdiff_t)( e - s );
mk_com_strncpy( &path[0], sizeof(path)-1, s, pathlen );
s = e + 1;
} else {
mk_com_strcpy( &path[0], sizeof(path)-1, s );
pathlen = strlen(s);
}
if( pathlen > 0 && path[pathlen-1] != '/' && path[pathlen-1] != '\\' ) {
path[pathlen++] = '/';
path[pathlen] = '\0';
++pathlen;
}
mk_com_strcpy( &path[pathlen], sizeof(path) - pathlen, cmd );
if( mk_fs_isFile( path ) ) {
path[pathlen] = '\0';
if( repchar != '\0' && repindex < sizeof(cmd) ) {
cmd[repindex ] = repchar;
repchar = '\0';
repindex = ~(size_t)0;
}
memmove( &cmd[pathlen], &cmd[0], strlen(cmd) + 1 );
memcpy( &cmd[0], &path[0], pathlen );
break;
}
} while( e != NULL );
}
if( repchar != '\0' && repindex < sizeof(cmd) ) {
cmd[repindex] = repchar;
repchar = '\0';
repindex = ~(size_t)0;
}
}
#ifdef _WIN32
# undef popen
# undef pclose
# define popen _popen
# define pclose _pclose
#endif
fp = popen( cmd, "r" );
if( !fp ) {
return NULL;
}
m = 1024;
out = (char*)malloc( m );
if( !out ) {
abort();
}
*out = '\0';
n = 0;
while( fgets( buf, sizeof(buf) - 1, fp ) != NULL ) {
size_t bufn;
bufn = strlen(buf);
if( n + bufn + 1 > m ) {
char *q;
m += bufn + 1024;
m += m/2;
q = realloc( out, m );
if( !q ) {
abort();
}
out = q;
}
memcpy( &out[n], &buf[0], bufn );
n += bufn;
out[n] = '\0';
}
pclose( fp );
return out;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment