argv[0] handling

John Tytgat John.Tytgat at aaug.net
Tue Jun 14 15:49:46 PDT 2005


In message <b153da7a4d.peter at chocky.org>
          Peter Naulls <peter at chocky.org> wrote:

> We've briefly mumbled about this in the past, but it's time for a
> revisit.
> 
> Presently, argv[0] is just the literal value passed from RISC OS.  It
> may contain a RISC OS path name, or RISC OS path variables, etc.   This
> means that programs that use argv[0] as the basis of their display can
> often do odd things.  It's possible to see "<Obey$Dir>.progname" as a
> program's title.  Or a full RISC OS path name as a bash prompt as
> programs attempt to trim to a Unix leafname.
> 
> This is clearly easily fixed with OS_FSControl 37 and unixfy, which I've
> just put into my build.

Not really "easily" IMHO.  The RISC OS oddity (again IMHO) of temporary FS
selection makes that OS_FSControl 37 doesn't return FS specification
in its result in those cases.  Fixing this is not really easy (I've
considered to add code in SUL for this (because a potentional solution
needs to hook on vectors) but it isn't that trivial when you want to have
it working in all cases. This better get enhanced in RISC OS itself (which
would probably a much bigger challenge to convince both RISC OS teams).

Anyway for your reference, I've added to this mail a patch in
source/unix/unix.c which I did many moons ago so you might want to
compare both implementations.

> Without wanting to add nth degree
> configurability, does anyone thing that this might not always be
> appropriate?   In particular, this will result in programs which are
> just called with a leaf name always ending up with the full path.

That shouldn't be a problem because I guess if you start programs
using their explicit paths in the Unix world you get those paths
and programname in argv[0] as well.

> And of course, pathnames in argv[0] will always be in Unix form.

That doesn't need to be.  When you use __unixify_std(), see my patch, it
will use the weak symbol __riscosify_control which can say not to do any
mapping at all.

> Heuristics may be sensible here.

Mmh, unless we have some real cases advocating this, I would just stick to
use __risosify_control, either directly, either indirectly.

> Bear in mind that any handling like this will have to be either a system
> variable or a weak symbol, since this occurs before main() is called,
> and therefore beyond the control of the runtime riscosify flags.

There is a weak initial riscosify_control value which can (and should
IMHO) be used.

John.
-- 
John Tytgat, in his comfy chair at home                                 BASS
John.Tytgat at aaug.net                             ARM powered, RISC OS driven
-------------- next part --------------
Index: gccsdk/unixlib/source/unix/unix.c
===================================================================
RCS file: /usr/local/cvsroot/gccsdk/unixlib/source/unix/unix.c,v
retrieving revision 1.39
diff -u -r1.39 unix.c
--- gccsdk/unixlib/source/unix/unix.c   21 Mar 2005 12:14:57 -0000      1.39
+++ gccsdk/unixlib/source/unix/unix.c   14 Jun 2005 22:31:35 -0000
@@ -1036,6 +1036,64 @@
 
   free (temp);
 
+#if 0
+  /* Convert the process filename, either to a RISC OS full path, either
+     to an Unix full path.  Note that there is a fundamental problem when
+     you start a process via a temporary FS selection and that the current
+     FS get taken instead.  Use "/ADFS::MyDisc.$.my_risc_os_process" or
+     "run ADFS::MyDisc.$.my_risc_os_process" instead of
+     "ADFS::MyDisc.$.my_risc_os_process" to avoid this problem.  */
+    {
+      int regs[10];
+      char *new_argv0, *new_uargv0;
+      _kernel_oserror *err;
+      int filetype;
+
+      regs[0] = 37;
+      regs[1] = (int)argv[0];
+      regs[5] = regs[4] = regs[3] = regs[2] = 0;
+      if ((err = __os_swi(OS_FSControl, regs)) != NULL)
+       {
+         __seterr (err);
+         __unixlib_fatal ("cannot convert process filename");
+       }
+      if (regs[5] > 0)
+       __unixlib_fatal ("cannot convert process filename");
+
+      if ((new_argv0 = malloc(1 - regs[5])) == NULL)
+       __unixlib_fatal ("cannot allocate memory to convert process filename");
+
+      regs[0] = 37;
+      regs[1] = (int)argv[0];
+      regs[2] = (int)new_argv0;
+      regs[4] = regs[3] = 0;
+      regs[5] = 1 - regs[5];
+      if ((err = __os_swi(OS_FSControl, regs)) != NULL)
+       {
+         __seterr (err);
+         __unixlib_fatal ("cannot convert process filename");
+       }
+
+      if (__os_file (OSFILE_READCATINFO, new_argv0, regs) != NULL
+         || regs[0] != 1)
+       {
+         __os_print ("WARNING: cannot stat() process filename\r\nDid you use a temporary FS used to startup ? If so, better use '*run' instead.\r\n");
+         __os_nl ();
+         filetype = __RISCOSIFY_FILETYPE_NOTFOUND;
+       }
+      else
+       filetype = ((regs[2] & 0xfff00000U) == 0xfff00000U) ? (regs[2] >> 8) & 0xfff : __RISCOSIFY_FILETYPE_NOTFOUND;
+
+      /* Convert to Unix full path, if needed.  */
+      if ((new_uargv0 = __unixify_std (new_argv0, NULL, 0, filetype)) == NULL)
+       __unixlib_fatal ("cannot allocate memory to convert process filename");
+
+      free(new_argv0);
+      free(argv[0]);
+      argv[0] = new_uargv0;
+    }
+#endif
+
   process->argc = argc;
   process->argv = argv;
 


More information about the gcc mailing list