[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