[jamming] Executing shell command, save results to variable
Diane Holt
holt.diane at gmail.com
Thu Mar 15 11:30:19 PST 2007
On 3/15/07, David Turner <david at freetype.org> wrote:
>
> Hello Dianne,
>
> > If you're still interested, I can send the diff of builtins.c.
>
> I'm currently preparing a minor release of FT-Jam. Just to tell you
> that I'd love to be able to integrate your [ Command ] builtin in it.
>
> Can I ask you to send my your patch. If it's not too big, I'm pretty
> certain that a lot of people on this list would be interested in seeing
> this...
>
> Regards,
>
> - David Turner
>
>
Only if you promise never to put two n's in my name again :)
Here you go... the usual disclaimers regarding not being warranted,
expressed or implied, as to usability, correctness, and all that jazz apply
... IOW, use at your own risk :)
One thing I was reminded of, when I went to look the change back up, is that
I put a hard-coded
#define HAVE_POPEN 1
in jam.h. You may want to consider doing something a bit more legitimate for
determining whether HAVE_POPEN should be defined or not :)
Also, if you have any suggestions for improvements (or find anything buggy),
I hope you'll share them back.
The diff is for builtins.c (see my earlier posting for actually using
Command).
Have fun,
Diane
========================================================================
@@ -55,6 +55,7 @@
LIST *builtin_flags( PARSE *parse, LOL *args, int *jmp );
LIST *builtin_glob( PARSE *parse, LOL *args, int *jmp );
LIST *builtin_match( PARSE *parse, LOL *args, int *jmp );
+LIST *builtin_command( PARSE *parse, LOL *args, int *jmp );
int glob( const char *s, const char *c );
@@ -111,6 +112,10 @@
bindrule( "Temporary" )->procedure =
bindrule( "TEMPORARY" )->procedure =
parse_make( builtin_flags, P0, P0, P0, C0, C0, T_FLAG_TEMP );
+
+ bindrule( "Command" )->procedure =
+ bindrule( "COMMAND" )->procedure =
+ parse_make( builtin_command, P0, P0, P0, C0, C0, 0);
}
/*
@@ -316,3 +321,105 @@
return result;
}
+
+
+#ifdef HAVE_POPEN
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ #define popen _popen
+ #define pclose _pclose
+#endif
+
+typedef struct {
+ int len;
+ char *str;
+} string;
+
+void string_new(string *s) {
+ s->len = 0;
+ s->str = NULL;
+}
+
+void string_append(string *s, char *buf) {
+ /* we don't care too much for efficiency */
+ int l2 = s->len + strlen(buf);
+ char *n = (char*)malloc(l2 + 1);
+ /* or error recovery */
+ if (s->len) strcpy(n, s->str);
+ strcpy(n+s->len, buf);
+ free(s->str);
+ s->str = n;
+ s->len = l2;
+}
+
+void string_free(string *s) {
+ if (s->str != NULL)
+ free(s->str);
+ s->str = NULL;
+ s->len = 0;
+}
+
+LIST *builtin_command( PARSE *parse, LOL *args, int *jmp )
+{
+ LIST* arg = lol_get( args, 0 );
+ LIST* result = L0;
+ string s;
+ int ret;
+ char buffer[1024];
+ FILE *p = NULL;
+
+ string_new( &s );
+
+ fflush(NULL);
+
+ p = popen(arg->string, "r");
+ if ( p == NULL )
+ return L0;
+
+ while ( (ret = fread(buffer, sizeof(char), sizeof(buffer)-1, p)) > 0
)
+ {
+ buffer[ret] = 0;
+ string_append( &s, buffer );
+ }
+
+ pclose(p);
+
+ // Return separate list element for each NL-separated string
+ // in the output of the command. Or, if the ouput has no NL
+ // but has space-separated words, make each word a list element
+ // (ie., echo -n output). Otherwise, if it's just one word (NL or
+ // no), return that.
+
+ if (s.str && s.len > 0)
+ {
+ int i;
+ char token = '\n';
+ const char *sp = s.str;
+
+ if (strchr(s.str, '\n') == NULL)
+ token = ' ';
+ for (i=0 ; i < s.len ; i++)
+ {
+ if ( s.str[i] == token )
+ {
+ s.str[i] = '\0';
+ result = list_new( result, sp, 0 );
+ sp = (const char*)&s.str[i+1];
+ }
+ }
+ if (*sp != '\0')
+ result = list_new( result, sp, 0 );
+ }
+
+ string_free(&s);
+ return result;
+}
+
+#else
+
+LIST *builtin_command( PARSE *parse, LOL *args, int *jmp )
+{
+ return L0;
+}
+
+#endif
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://maillist.perforce.com/pipermail/jamming/attachments/20070315/31bd68be/attachment.html
More information about the jamming
mailing list