For Windows users only

At the command line, that is.

Problem: When you run a .rb file from the
command line, you have to type a (potentially
lengthy) command.

First idea: Wrap it in a batch file.

However: Did you know that Windows is too dumb
to associate the stdout of a program with the
stdout of the batch file? I.e., if you have a
foo.bat file and you say “foo >outfile” it will
NOT work (at least not in older Windows versions…
I can’t speak of NT, 2K, XP).

Well, you can use “start” on Win98. Still kind of
a pain.

My solution:

Write a C program that will detect its own name and
directory; locate a corresponding Ruby program in
that same directory; read the #! line from the
beginning (usu. ignored in Win); and run the Ruby
program. It passes in the parameters, too.

Note that you only have to compile once, since the
program knows its own name. You can just
copy fakeruby.exe myprog.exe
assuming there is a myprog.rb in that directory.

I know, it’s kind of an exercise in futility. But
if you want the code, here it is. It compiles fine
with djgpp.

Feel free to criticize it or improve it. It’s far
from perfect. For some reason, execvp() didn’t work
for me.

Cheers,
Hal

···

==============================================
#include <assert.h>
#include <stdio.h>

#define LONG 512

main(int argc, char *argv[])
{
char file[LONG], *line, *rubyopts;
char *ext, *line1;
int name_len, i;
FILE *input;
char sysstr[LONG];

line = (char *) malloc(LONG);
rubyopts = (char *) malloc(LONG);

strcpy(file, argv[0]);
name_len = strlen(file);
ext = file + name_len - 3;
for (i=0; i<3; i++)
(ext+i) = toupper((ext+i));
assert(strcmp(ext,“EXE”)==0);
strcpy(ext-1,".rb");

input = fopen(file,“r”);
line1 = fgets(line,LONG,input);
/*!!! check error */
fclose(input);

strcpy(sysstr, "ruby ");
strcpy(args[0],file);
strcpy(argv[0],file);
for(i=1; i<argc; i++)
args[i]=argv[i];
args[argc] = NULL;

if (strncmp(line,"#!",2)==0) /* Found a #! line /
{
rubyopts = strstr(line,"ruby "); /
may be null /
/
space is needed because ‘ruby’ may be earlier in
* the path… a tab found here will make it fail!!
*/

if (!rubyopts) 
{
  fprintf(stderr,"Warning: #! line does not contain 'ruby'\n");
  strcpy(rubyopts,"");
}
else
{
  rubyopts += 4; /* skip 'ruby' */
  rubyopts[strlen(rubyopts)-1]='\0'; /* chomp! */
}
strcat(sysstr,rubyopts);

}

for (i=0; i<argc; i++)
{
strcat(sysstr," ");
strcat(sysstr,argv[i]);
}

/* Using system()… execvp() didn’t work on

  • my machine, even with the proper terminating
  • NULL pointer.
    */

system(sysstr);

/* Bad style – not freeing memory. */
}

My solution:

Write a C program that will detect its own name and
directory; locate a corresponding Ruby program in
that same directory; read the #! line from the
beginning (usu. ignored in Win); and run the Ruby
program. It passes in the parameters, too.

My solution: Use Cygwin!!!

–Gavin

On Win2k and XP Home I just type the name of the ruby file, plus any
paramters. Like on Unix.

James

···

-----Original Message-----
From: Hal E. Fulton [mailto:hal9000@hypermetrics.com]
Sent: Thursday, August 15, 2002 11:19 PM
To: ruby-talk ML
Subject: For Windows users only…

At the command line, that is.

Problem: When you run a .rb file from the
command line, you have to type a (potentially
lengthy) command.

Having bluntly stated my solution, let me elaborate by example. Below is
a complete Cygwin transcript demonstrating: (a) running Ruby programs; (b)
redirecting standard output; © redirecting standard error; (d) fortune.

Before I get into it, can I ask a question? Am I missing out on anything
by not using the “native” windows installation?

Transacript follows after signoff.

Cheers,
Gavin

The steady state of disks is full.
– Ken Thompson

···

Next three birthdays:
John Brondum 2002-09-18 (in 33 days)
David Wells 2002-09-21 (in 36 days)
Ian Morris 2002-09-30 (in 45 days)

Gavin Sinclair@NOSEDOG ~
$ cd /tmp

Gavin Sinclair@NOSEDOG /tmp
$ cat > demo.rb
#!/usr/local/bin/ruby

puts <<EOF
I’m a little vegemite
As bright as bright can be
We all enjoy our vegemite
For breakfast, lunch and tea
EOF

Gavin Sinclair@NOSEDOG /tmp
A $ ./demo.rb
I’m a little vegemite
As bright as bright can be
We all enjoy our vegemite
For breakfast, lunch and tea

Gavin Sinclair@NOSEDOG /tmp
B $ ./demo.rb > output

Gavin Sinclair@NOSEDOG /tmp
$ cat output
I’m a little vegemite
As bright as bright can be
We all enjoy our vegemite
For breakfast, lunch and tea

Gavin Sinclair@NOSEDOG /tmp
$ cat > err.rb
#!/usr/local/bin/ruby

STDERR.puts "I’m nasty"
STDOUT.puts “I’m nice”

Gavin Sinclair@NOSEDOG /tmp
$ ./err.rb
I’m nasty
I’m nice

Gavin Sinclair@NOSEDOG /tmp
B $ ./err.rb > /dev/null
I’m nasty

Gavin Sinclair@NOSEDOG /tmp
C $ ./err.rb 2> /dev/null
I’m nice

D Gavin Sinclair@NOSEDOG /tmp
$ fortune -o
The problem with being best man at a wedding is
that you never get a chance to prove it.

Gavin Sinclair@NOSEDOG /tmp
$

At the command line, that is.

Problem: When you run a .rb file from the
command line, you have to type a (potentially
lengthy) command.

First idea: Wrap it in a batch file.

However: Did you know that Windows is too dumb
to associate the stdout of a program with the
stdout of the batch file? I.e., if you have a
foo.bat file and you say “foo >outfile” it will
NOT work (at least not in older Windows versions…
I can’t speak of NT, 2K, XP).

Well, you can use “start” on Win98. Still kind of
a pain.

My solution:

Write a C program that will detect its own name and
directory; locate a corresponding Ruby program in
that same directory; read the #! line from the
beginning (usu. ignored in Win); and run the Ruby
program. It passes in the parameters, too.

Note that you only have to compile once, since the
program knows its own name. You can just
copy fakeruby.exe myprog.exe
assuming there is a myprog.rb in that directory.

I know, it’s kind of an exercise in futility. But
if you want the code, here it is. It compiles fine
with djgpp.

Feel free to criticize it or improve it. It’s far
from perfect. For some reason, execvp() didn’t work
for me.

Cheers,
Hal

[lovely-looking C code snipped]

My solution:

Write a C program that will detect its own name and
directory; […]

Note that you only have to compile once, since the
program knows its own name. You can just
copy fakeruby.exe myprog.exe
assuming there is a myprog.rb in that directory.

I have used almost exactly the same solution for Perl on Windows for
several years. It has worked quite well.

The only tricky thing I know of for this to work, is that you may
have to “compensate” for the way arguments are passed between
processes on Windows (this is only a problem for arguments with
spaces, or other “funny” characters (I could write long article just
about these differences between Windows and UNIX :wink: ))

This solution is the best I’ve found so far.
It works in all situations (as far as I know).
Much better than BAT-file-wrappers, or extension-associations if you
want things to work:

- in different "shells", and not just in CMD.EXE
  but also for example tcsh, bash and ksh

- from other applications like Visual Studio (eg. the Tool menu)

- on different flavors of Windows (Windows9x, NT4,
  Windows2000, XP ...)

Feel free to criticize it or improve it. It’s far
from perfect. For some reason, execvp() didn’t work
for me.

[…]

system(sysstr);

I used “CreateProcess” instead of “system” (or “execvp”).

Since we are trying to make things work correctly on Windows, I felt
that it was better to use the native API, to get better control of
what is done.

/Johan Holmberg

···

On Fri, 16 Aug 2002, Hal E. Fulton wrote:

Hal E. Fulton wrote:

At the command line, that is.

Problem: When you run a .rb file from the
command line, you have to type a (potentially
lengthy) command.

Run msconfig from Start Menu->Run. Under the “Environment” tab of the
program that opens, there is a variable called PATH. The value of path
is a semicolon delimited list of directories. Add C:\RUBY\BIN (or
whatever directory holds ruby.exe on your computer) to the PATH variable
and apply the changes. You might have to restart, but you won’t have to
type the full path to ruby ever again!

-Brian D. Baker

Gavin Sinclair wrote:

Having bluntly stated my solution, let me elaborate by example. Below is
a complete Cygwin transcript demonstrating: (a) running Ruby programs; (b)
redirecting standard output; © redirecting standard error; (d) fortune.

Before I get into it, can I ask a question? Am I missing out on anything
by not using the “native” windows installation?

Transacript follows after signoff.

Cheers,
Gavin

The steady state of disks is full.
– Ken Thompson

Next three birthdays:
John Brondum 2002-09-18 (in 33 days)
David Wells 2002-09-21 (in 36 days)
Ian Morris 2002-09-30 (in 45 days)

Gavin Sinclair@NOSEDOG ~
$ cd /tmp

Gavin Sinclair@NOSEDOG /tmp
$ cat > demo.rb
#!/usr/local/bin/ruby

puts <<EOF
I’m a little vegemite
As bright as bright can be
We all enjoy our vegemite
For breakfast, lunch and tea
EOF

Gavin Sinclair@NOSEDOG /tmp
A $ ./demo.rb
I’m a little vegemite
As bright as bright can be
We all enjoy our vegemite
For breakfast, lunch and tea

Gavin Sinclair@NOSEDOG /tmp
B $ ./demo.rb > output

Gavin Sinclair@NOSEDOG /tmp
$ cat output
I’m a little vegemite
As bright as bright can be
We all enjoy our vegemite
For breakfast, lunch and tea

Gavin Sinclair@NOSEDOG /tmp
$ cat > err.rb
#!/usr/local/bin/ruby

STDERR.puts "I’m nasty"
STDOUT.puts “I’m nice”

Gavin Sinclair@NOSEDOG /tmp
$ ./err.rb
I’m nasty
I’m nice

Gavin Sinclair@NOSEDOG /tmp
B $ ./err.rb > /dev/null
I’m nasty

Gavin Sinclair@NOSEDOG /tmp
C $ ./err.rb 2> /dev/null
I’m nice

D Gavin Sinclair@NOSEDOG /tmp
$ fortune -o
The problem with being best man at a wedding is
that you never get a chance to prove it.

Gavin Sinclair@NOSEDOG /tmp
$

At the command line, that is.

Problem: When you run a .rb file from the
command line, you have to type a (potentially
lengthy) command.

First idea: Wrap it in a batch file.

However: Did you know that Windows is too dumb
to associate the stdout of a program with the
stdout of the batch file? I.e., if you have a
foo.bat file and you say “foo >outfile” it will
NOT work (at least not in older Windows versions…
I can’t speak of NT, 2K, XP).

Well, you can use “start” on Win98. Still kind of
a pain.

My solution:

Write a C program that will detect its own name and
directory; locate a corresponding Ruby program in
that same directory; read the #! line from the
beginning (usu. ignored in Win); and run the Ruby
program. It passes in the parameters, too.

Note that you only have to compile once, since the
program knows its own name. You can just
copy fakeruby.exe myprog.exe
assuming there is a myprog.rb in that directory.

I know, it’s kind of an exercise in futility. But
if you want the code, here it is. It compiles fine
with djgpp.

Feel free to criticize it or improve it. It’s far
from perfect. For some reason, execvp() didn’t work
for me.

Cheers,
Hal

[lovely-looking C code snipped]

Do a search and you will see the “thought” behind why the native build
was decided upon.

Bob

Hal E. Fulton wrote:

At the command line, that is.

Problem: When you run a .rb file from the
command line, you have to type a (potentially
lengthy) command.

Run msconfig from Start Menu->Run. Under the “Environment” tab of the
program that opens, there is a variable called PATH. The value of path
is a semicolon delimited list of directories. Add C:\RUBY\BIN (or
whatever directory holds ruby.exe on your computer) to the PATH variable
and apply the changes. You might have to restart, but you won’t have to
type the full path to ruby ever again!

Thanks. I’m well familiar with PATH. But I don’t
like typing this sort of thing:

ruby -Ithis -Ithat -Ithe_other myprog.rb

But I don’t want to put everything in RUBYLIB,
either.

Basically I was trying to

  1. Just type “myprog”
  2. Get Windows to honor the #! line
  3. Avoid the problems with batch files

I know: I should just run Linux all the time…

Cheers,
Hal

···

----- Original Message -----
From: “Brian D. Baker” baker.921@osu.edu
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, August 16, 2002 4:17 PM
Subject: Re: For Windows users only…