bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/4] Add a file_exec_file_name RPC


From: Jeremie Koenig
Subject: [PATCH 2/4] Add a file_exec_file_name RPC
Date: Wed, 17 Aug 2011 21:25:21 +0200

From: Emilio Pozuelo Monfort <pochu27@gmail.com>

* hurd/fs.defs (file_exec): Deprecate in favor of...
(file_exec_file_name): ...this new RPC.
Change all implementations and forward old implementations to
the new version.  Change all callers but fallback to old version.
Change comments and documentation.

Signed-off-by: Jeremie Koenig <jk@jk.fr.eu.org>
---
 TODO                              |    2 +-
 doc/hurd.texi                     |   16 ++++----
 exec/hashexec.c                   |   32 ++++++++++----
 hurd/fs.defs                      |   28 +++++++++++--
 hurd/hurd_types.h                 |    9 ++--
 init/init.c                       |   81 ++++++++++++++++++++++++++----------
 libdiskfs/boot-start.c            |    2 +-
 libdiskfs/file-exec.c             |   75 ++++++++++++++++++++++++++++------
 libfshelp/start-translator-long.c |   21 +++++++---
 libnetfs/file-exec.c              |   67 ++++++++++++++++++++++++++----
 libtrivfs/file-exec.c             |   27 ++++++++++++-
 trans/fakeroot.c                  |   59 ++++++++++++++++++++++++---
 utils/login.c                     |   23 +++++++---
 13 files changed, 350 insertions(+), 92 deletions(-)

diff --git a/TODO b/TODO
index b541f38..84c547d 100644
--- a/TODO
+++ b/TODO
@@ -127,25 +127,25 @@ See `tasks', the exported task list.
 *** Use off_t correctly. !!
 *** Add a consistent message printing facility for filesystems to use
     (syslog, but takes special care when the root file system?). !!
 *** Some of diskfs_readonly_changed in ufs/ext2fs should be in generic
     routines. !
 
 ** libfshelp
 *** Put functions here to deal with directory and file change notifications !!!
 *** Translator startup should provide a more useful stdin/stdout than nothing !
 
 ** libtrivfs
 *** Allow for read/write/exec to be passed down.
-*** Implement file_exec when appropriate. !!
+*** Implement file_exec_file_name when appropriate. !!
 *** Provide for the visible owner, etc., to be held in command-line args
     instead of the underlying node, when it's important. !!
 
 ** libps
 *** Add option to print values times with a delay,
     and to print values relative to last printing.
 *** Whizzier columnation (autosizing?)
 *** Make getters more robust.
 
 * Servers
 ** finish default pager in defpager !!
 ** Implement goaway in all the servers that don't already have it. !!
diff --git a/doc/hurd.texi b/doc/hurd.texi
index c0238f9..723e985 100644
--- a/doc/hurd.texi
+++ b/doc/hurd.texi
@@ -2732,61 +2732,61 @@ The @code{file_set_size} RPC is special; not only does 
it change the
 status word specifying the size of the file, but it also changes the
 actual contents of the file.  If the file size is being reduced it
 should release secondary storage associated with the previous contents
 of the file.  If the file is being extended, the new region added to the
 file must be zero-filled.  Unlike the other RPCs in this section,
 @code{file_set_size} should be permitted to any user who is allowed to
 write the file.
 
 
 @node Program Execution
 @subsection Program Execution
 
-@findex file_exec
+@findex file_exec_file_name
 Execution of programs on the Hurd is done through fileservers with the
-@code{file_exec} RPC.  The fileserver is expected to verify that the
-user is allowed to execute the file, make whatever modifications to the
+@code{file_exec_file_name} RPC.  The fileserver is expected to verify that
+the user is allowed to execute the file, make whatever modifications to the
 ports are necessary for setuid execution, and then invoke the standard
 execserver found on @file{/servers/exec}.
 
 This section specifically addresses what fileservers are expected to do,
 with minimal attention to the other parts of the process.  @xref{Running
 Programs}, for more general information.
 
 The file must be opened for execution; if it is not, @code{EBADF} should
 be returned.  In addition, at least one of the execute bits must be on.  A
 failure of this check should result in @code{EACCES}---not
 @code{ENOEXEC}.  It is not proper for the fileserver ever to respond to
-the @code{file_exec} RPC with @code{ENOEXEC}.
+the @code{file_exec_file_name} RPC with @code{ENOEXEC}.
 
 If either the setuid or setgid bits are set, the server needs to
 construct a new authentication handle with the additional new ID's.
-Then all the ports passed to @code{file_exec} need to be reauthenticated
-with the new handle.  If the fileserver is unable to make the new
-authentication handle (for example, because it is not running as root)
+Then all the ports passed to @code{file_exec_file_name} need to be
+reauthenticated with the new handle.  If the fileserver is unable to make the
+new authentication handle (for example, because it is not running as root)
 it is not acceptable to return an error; in such a case the server
 should simply silently fail to implement the setuid/setgid semantics.
 
 If the setuid/setgid transformation adds a new uid or gid to the user's
 authentication handle that was not previously present (as opposed to
 merely reordering them), then the @code{EXEC_SECURE} and
 @code{EXEC_NEWTASK} flags should both be added in the call to
 @code{exec_exec_file_name}.
 
 The server then needs to open a new port onto the executed file which
 will not share any file pointers with the port the user passed in,
 opened with @code{O_READ}.  Finally, all the information (mutated
 appropriately for setuid/setgid) should be sent to the execserver with
 @code{exec_exec_file_name}.  Whatever error code @code{exec_exec_file_name}
-returns should be returned to the caller of @code{file_exec}.
+returns should be returned to the caller of @code{file_exec_file_name}.
 
 @node File Locking
 @subsection File Locking
 
 The @code{flock} call is in flux, as the current Hurd interface (as of
 version @value{VERSION}) is not suitable for implementing the POSIX
 record-locking semantics.
 
 @findex file_lock
 @findex file_lock_stat
 You should ignore the @code{file_lock} and @code{file_lock_stat} calls
 until the new record-locking interface is implemented.
diff --git a/exec/hashexec.c b/exec/hashexec.c
index 929d37b..fbf2e7e 100644
--- a/exec/hashexec.c
+++ b/exec/hashexec.c
@@ -413,33 +413,47 @@ check_hashbang (struct execdata *e,
   rwlock_reader_unlock (&std_lock);
 
   if (user_crdir != MACH_PORT_NULL)
     mach_port_deallocate (mach_task_self (), user_crdir);
   if (user_cwdir != MACH_PORT_NULL)
     mach_port_deallocate (mach_task_self (), user_cwdir);
 
   if (e->error)
     /* We cannot open the interpreter file to execute it.  Lose!  */
     return;
 
   /* Execute the interpreter program.  */
-  e->error = file_exec (interp_file,
-                       oldtask, flags,
-                       new_argv, new_argvlen, envp, envplen,
-                       new_dtable ?: dtable, MACH_MSG_TYPE_COPY_SEND,
-                       new_dtable ? new_dtablesize : dtablesize,
-                       portarray, MACH_MSG_TYPE_COPY_SEND, nports,
-                       intarray, nints,
-                       deallocnames, ndeallocnames,
-                       destroynames, ndestroynames);
+  e->error = file_exec_file_name (interp_file,
+                                 oldtask, flags, interp,
+                                 new_argv, new_argvlen, envp, envplen,
+                                 new_dtable ?: dtable,
+                                 MACH_MSG_TYPE_COPY_SEND,
+                                 new_dtable ? new_dtablesize : dtablesize,
+                                 portarray, MACH_MSG_TYPE_COPY_SEND, nports,
+                                 intarray, nints,
+                                 deallocnames, ndeallocnames,
+                                 destroynames, ndestroynames);
+  /* For backwards compatibility.  Just drop it when we kill file_exec.  */
+  if (e->error == MIG_BAD_ID)
+    e->error = file_exec (interp_file,
+                         oldtask, flags,
+                         new_argv, new_argvlen, envp, envplen,
+                         new_dtable ?: dtable, MACH_MSG_TYPE_COPY_SEND,
+                         new_dtable ? new_dtablesize : dtablesize,
+                         portarray, MACH_MSG_TYPE_COPY_SEND, nports,
+                         intarray, nints,
+                         deallocnames, ndeallocnames,
+                         destroynames, ndestroynames);
+
+
   mach_port_deallocate (mach_task_self (), interp_file);
 
   if (! e->error)
     {
       /* The exec of the interpreter succeeded!  Deallocate the resources
         we passed to that exec.  We don't need to save them in a bootinfo
         structure; the exec of the interpreter takes care of that.  */
       u_int i;
       mach_port_deallocate (mach_task_self (), file);
       task_resume (oldtask);   /* Our caller suspended it.  */
       mach_port_deallocate (mach_task_self (), oldtask);
       if (! argv_copy)
diff --git a/hurd/fs.defs b/hurd/fs.defs
index 52d83bd..1f33e2a 100644
--- a/hurd/fs.defs
+++ b/hurd/fs.defs
@@ -1,14 +1,15 @@
 /* Definitions for the filesystem interface.
-   Copyright (C) 1994,95,96,97,98,99,2002 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2002, 2010
+   Free Software Foundation, Inc.
 
 This file is part of the GNU Hurd.
 
 The GNU Hurd is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 The GNU Hurd is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
@@ -26,25 +27,26 @@ subsystem fs 20000;
 
 #ifdef FILE_IMPORTS
 FILE_IMPORTS
 #endif
 
 /* Operations supported on all files */
 
 INTR_INTERFACE
 
 /* Overlay a task with a file.  Necessary initialization, including
    authentication changes associated with set[ug]id execution must be
    handled by the filesystem.  Filesystems normally implement this by
-   using exec_newtask or exec_loadtask as appropriate.  */
+   using exec_newtask or exec_loadtask as appropriate.
+   Deprecated: use file_exec_file_name instead.  */
 routine file_exec (
        exec_file: file_t;
        RPT
        exec_task: task_t;
        flags: int;
        argv: data_t SCP;
        envp: data_t SCP;
        fdarray: portarray_t SCP;
        portarray: portarray_t SCP;
        intarray: intarray_t SCP;
        deallocnames: mach_port_name_array_t SCP;
        destroynames: mach_port_name_array_t SCP);
@@ -120,26 +122,26 @@ routine file_lock (
    caller has; otherstatus tells what kind of lock anyone has
    (including the caller).  */
 routine file_lock_stat (
        lock_file: file_t;
        RPT
        out mystatus: int;
        out otherstatus: int);
 
 /* Find out what kind of access this file permits the current user
    (regardless of the current open modes for this port).  ALLOWED is a
    bitwise OR of O_READ, O_WRITE, and O_EXEC.  This is not necessarily the
    same as what an open or exec would allow; O_EXEC is set for root even if
-   no executable bits are on (in which case file_exec should fail) and
-   O_WRITE is set a directory can be modified, even though it can't be
+   no executable bits are on (in which case file_exec_file_name should fail)
+   and O_WRITE is set a directory can be modified, even though it can't be
    written directly.  */
 routine file_check_access (
        file: file_t;
        RPT
        out allowed: int);
 
 /* Notice changes to file FILE.  Send notification messages (see
    fs_notify.defs) to PORT as they occur. */
 routine file_notice_changes (
        file: file_t;
        RPT
        port: mach_port_send_t);
@@ -343,12 +345,30 @@ routine file_get_translator_cntl (
 routine file_get_fs_options (
        file: file_t;
        RPT
        out options: data_t, dealloc);
 
 /* Return a new file, NEW_FILE, with the same semantics as FILE, but
    with lookups of `..' (if FILE is a directory) redirected to PARENT.  */
 routine file_reparent (
        file: file_t;
        RPT
        parent: mach_port_t;
        out new_file: mach_port_send_t);
+
+/* Overlay a task with a file.  Necessary initialization, including
+   authentication changes associated with set[ug]id execution must be
+   handled by the filesystem.  Filesystems normally implement this by
+   using exec_newtask or exec_loadtask as appropriate.  */
+routine file_exec_file_name (
+       exec_file: file_t;
+       RPT
+       exec_task: task_t;
+       flags: int;
+       filename: string_t;
+       argv: data_t SCP;
+       envp: data_t SCP;
+       fdarray: portarray_t SCP;
+       portarray: portarray_t SCP;
+       intarray: intarray_t SCP;
+       deallocnames: mach_port_name_array_t SCP;
+       destroynames: mach_port_name_array_t SCP);
diff --git a/hurd/hurd_types.h b/hurd/hurd_types.h
index 86b9bcb..ab8f65a 100644
--- a/hurd/hurd_types.h
+++ b/hurd/hurd_types.h
@@ -1,14 +1,15 @@
 /* C declarations for Hurd server interfaces
-   Copyright (C) 1993,94,95,96,98,99,2001,02 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2002,
+   2010 Free Software Foundation, Inc.
 
 This file is part of the GNU Hurd.
 
 The GNU Hurd is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 The GNU Hurd is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
@@ -67,25 +68,25 @@ typedef struct stat io_statbuf_t;
 typedef struct statfs fsys_statfsbuf_t;
 #else
 typedef struct stat64 io_statbuf_t;
 typedef struct statfs64 fsys_statfsbuf_t;
 #endif
 
 
 /*   Parameters and flags in RPC calls   */
 
 /* Many such parameters and flags are also defined in various libc
    headers. */
 
-/* Bits for flags in fs.defs:file_exec and exec.defs:exec_* calls: */
+/* Bits for flags in fs.defs:file_exec_file_name and exec.defs:exec_* calls: */
 #define EXEC_NEWTASK   0x00000001 /* Create new task; kill old one.  */
 #define EXEC_SECURE    0x00000002 /* Use secure values of portarray, etc. */
 #define EXEC_DEFAULTS  0x00000004 /* Use defaults for unspecified ports.  */
 #define EXEC_SIGTRAP   0x00000008 /* Simulate SIGTRAP on startup.  */
 /* This flag is passed through by the exec server but not examined by it.  */
 #define        EXEC_STACK_ARGS 0x00000010 /* Use arguments from stack, not 
RPC.  */
 
 /* Bits for flags in fs.defs:file_set_translator call: */
 #define FS_TRANS_FORCE     0x00000001 /* Must use translator(no sht circuit) */
 #define FS_TRANS_EXCL      0x00000002 /* Don't do it if already translated.  */
 #define FS_TRANS_SET      0x00000004 /* Set or clear translator */
 #define FS_TRANS_ORPHAN    0x00000008 /* Orphan the active translator.  */
@@ -333,38 +334,38 @@ typedef int *procinfo_t;
 #define FSTYPE_PROC    0x00000010 /* /proc filesystem ala Version 9 */
 #define FSTYPE_IFSOCK  0x00000011 /* PF_LOCAL socket naming point */
 #define FSTYPE_AFS     0x00000012 /* Andrew File System 3.xx */
 #define FSTYPE_DFS     0x00000013 /* Distributed File Sys (OSF) == AFS 4.xx */
 #define FSTYPE_PROC9   0x00000014 /* /proc filesystem ala Plan 9 */
 #define FSTYPE_SOCKET  0x00000015 /* io_t that isn't a file but a socket */
 #define FSTYPE_MISC    0x00000016 /* generic trivfs server */
 #define FSTYPE_EXT2FS  0x00000017 /* Linux filesystem by Remy Card */
 #define FSTYPE_HTTP    0x00000018 /* Transparent HTTP */
 #define FSTYPE_MEMFS   0x00000019 /* In-core filesystem */
 #define FSTYPE_ISO9660 0x0000001a /* ISO9660 */
 
-/* Standard port assignments for file_exec and exec_* */
+/* Standard port assignments for file_exec_file_name and exec_* */
 enum
   {
     INIT_PORT_CWDIR,
     INIT_PORT_CRDIR,
     INIT_PORT_AUTH,
     INIT_PORT_PROC,
     INIT_PORT_CTTYID,
     /* If MACH_PORT_NULL is given for the bootstrap port,
        the bootstrap port of the old task is used.  */
     INIT_PORT_BOOTSTRAP,
     INIT_PORT_MAX
   };
 
-/* Standard ints for file_exec and exec_* */
+/* Standard ints for file_exec_file_name and exec_* */
 enum
   {
     INIT_UMASK,
     INIT_SIGMASK,
     INIT_SIGIGN,
     INIT_SIGPENDING,
     INIT_TRACEMASK,
     INIT_INT_MAX,
   };
 
 #endif
diff --git a/init/init.c b/init/init.c
index d66bee0..9c85078 100644
--- a/init/init.c
+++ b/init/init.c
@@ -1,16 +1,16 @@
 /* Start and maintain hurd core servers and system run state
 
    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-     2005, 2008 Free Software Foundation, Inc.
+     2005, 2008, 2010 Free Software Foundation, Inc.
    This file is part of the GNU Hurd.
 
    The GNU Hurd is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, or (at your option)
    any later version.
 
    The GNU Hurd is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
@@ -366,31 +366,44 @@ run (const char *server, mach_port_t *ports, task_t *task)
       else
        {
          task_create (mach_task_self (),
 #ifdef KERN_INVALID_LEDGER
                       NULL, 0, /* OSF Mach */
 #endif
                       0, task);
          if (bootstrap_args & RB_KDB)
            {
              printf ("Pausing for %s\n", prog);
              getchar ();
            }
-         err = file_exec (file, *task, 0,
-                          (char *)prog, strlen (prog) + 1, /* Args.  */
-                          startup_envz, startup_envz_len,
-                          default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
-                          ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
-                          default_ints, INIT_INT_MAX,
-                          NULL, 0, NULL, 0);
+         err = file_exec_file_name (file, *task, 0, (char *)prog,
+                                    (char *)prog,
+                                    strlen (prog) + 1, /* Args.  */
+                                    startup_envz, startup_envz_len,
+                                    default_dtable,
+                                    MACH_MSG_TYPE_COPY_SEND, 3,
+                                    ports, MACH_MSG_TYPE_COPY_SEND,
+                                    INIT_PORT_MAX,
+                                    default_ints, INIT_INT_MAX,
+                                    NULL, 0, NULL, 0);
+         /* For backwards compatibility.  Just drop it when we kill
+            file_exec.  */
+         if (err == MIG_BAD_ID)
+           err = file_exec (file, *task, 0,
+                            (char *)prog, strlen (prog) + 1, /* Args.  */
+                            startup_envz, startup_envz_len,
+                            default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
+                            ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
+                            default_ints, INIT_INT_MAX,
+                            NULL, 0, NULL, 0);
          if (!err)
            break;
 
          error (0, err, "%s", prog);
        }
 
       printf ("File name for server %s (or nothing to reboot): ", server);
       if (getstring (buf, sizeof (buf)))
        prog = buf;
       else
        crash_system ();
     }
@@ -459,32 +472,43 @@ run_for_real (char *filename, char *args, int arglen, 
mach_port_t ctty,
       proc_make_login_coll (default_ports[INIT_PORT_PROC]);
     }
   if (bootstrap_args & RB_KDB)
     {
       printf ("Pausing for %s\n", filename);
       getchar ();
     }
   progname = strrchr (filename, '/');
   if (progname)
     ++progname;
   else
     progname = filename;
-  err = file_exec (file, task, 0,
-                  args, arglen,
-                  startup_envz, startup_envz_len,
-                  default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
-                  default_ports, MACH_MSG_TYPE_COPY_SEND,
-                  INIT_PORT_MAX,
-                  default_ints, INIT_INT_MAX,
-                  NULL, 0, NULL, 0);
+  err = file_exec_file_name (file, task, 0, filename,
+                            args, arglen,
+                            startup_envz, startup_envz_len,
+                            default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
+                            default_ports, MACH_MSG_TYPE_COPY_SEND,
+                            INIT_PORT_MAX,
+                            default_ints, INIT_INT_MAX,
+                            NULL, 0, NULL, 0);
+  /* For backwards compatibility.  Just drop it when we kill file_exec.  */
+  if (err == MIG_BAD_ID)
+    err = file_exec (file, task, 0,
+                    args, arglen,
+                    startup_envz, startup_envz_len,
+                    default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
+                    default_ports, MACH_MSG_TYPE_COPY_SEND,
+                    INIT_PORT_MAX,
+                    default_ints, INIT_INT_MAX,
+                    NULL, 0, NULL, 0);
+
   mach_port_deallocate (mach_task_self (), default_ports[INIT_PORT_PROC]);
   mach_port_deallocate (mach_task_self (), task);
   if (ctty != MACH_PORT_NULL)
     {
       mach_port_deallocate (mach_task_self (),
                            default_ports[INIT_PORT_CTTYID]);
       default_ports[INIT_PORT_CTTYID] = MACH_PORT_NULL;
     }
   mach_port_deallocate (mach_task_self (), file);
   if (err)
     {
       error (0, err, "Cannot execute %s", filename);
@@ -1050,31 +1074,42 @@ start_child (const char *prog, char **progargs)
 #endif
               0, &child_task);
   proc_child (procserver, child_task);
   proc_task2pid (procserver, child_task, &child_pid);
   proc_task2proc (procserver, child_task, &default_ports[INIT_PORT_PROC]);
 
   if (bootstrap_args & RB_KDB)
     {
       printf ("Pausing for %s\n", args);
       getchar ();
     }
 
-  err = file_exec (file, child_task, 0,
-                  args, arglen,
-                  startup_envz, startup_envz_len,
-                  NULL, MACH_MSG_TYPE_COPY_SEND, 0, /* No fds.  */
-                  default_ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
-                  default_ints, INIT_INT_MAX,
-                  NULL, 0, NULL, 0);
+  err = file_exec_file_name (file, child_task, 0, args,
+                            args, arglen,
+                            startup_envz, startup_envz_len,
+                            NULL, MACH_MSG_TYPE_COPY_SEND, 0, /* No fds.  */
+                            default_ports, MACH_MSG_TYPE_COPY_SEND,
+                            INIT_PORT_MAX,
+                            default_ints, INIT_INT_MAX,
+                            NULL, 0, NULL, 0);
+  /* For backwards compatibility.  Just drop it when we kill file_exec.  */
+  if (err == MIG_BAD_ID)
+    err = file_exec (file, child_task, 0,
+                    args, arglen,
+                    startup_envz, startup_envz_len,
+                    NULL, MACH_MSG_TYPE_COPY_SEND, 0, /* No fds.  */
+                    default_ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
+                    default_ints, INIT_INT_MAX,
+                    NULL, 0, NULL, 0);
+
   mach_port_deallocate (mach_task_self (), default_ports[INIT_PORT_PROC]);
   mach_port_deallocate (mach_task_self (), file);
   free (args);
   if (err)
     {
       error (0, err, "Cannot execute %s", args);
       free (args);
       return -1;
     }
 
   return 0;
 }
diff --git a/libdiskfs/boot-start.c b/libdiskfs/boot-start.c
index e73e4d3..e816b0b 100644
--- a/libdiskfs/boot-start.c
+++ b/libdiskfs/boot-start.c
@@ -185,25 +185,25 @@ diskfs_start_bootstrap ()
          assert (retry == FS_RETRY_NORMAL);
          assert (retry_name[0] == '\0');
          assert (execnode != MACH_PORT_NULL);
          err = file_set_translator (execnode, 0, FS_TRANS_SET, 0, 0, 0,
                                     diskfs_exec_ctl, MACH_MSG_TYPE_COPY_SEND);
          mach_port_deallocate (mach_task_self (), diskfs_exec_ctl);
          mach_port_deallocate (mach_task_self (), execnode);
          assert_perror (err);
        }
       diskfs_exec_ctl = MACH_PORT_NULL;        /* Not used after this.  */
     }
 
-  /* Cache the exec server port for file_exec to use.  */
+  /* Cache the exec server port for file_exec_file_name to use.  */
   _hurd_port_set (&_diskfs_exec_portcell, diskfs_exec);
 
   if (_diskfs_boot_command)
     {
       /* We have a boot command line to run instead of init.  */
       err = argz_create (_diskfs_boot_command, &exec_argv, &exec_argvlen);
       assert_perror (err);
       initname = exec_argv;
       while (*initname == '/')
        initname++;
     }
   else
diff --git a/libdiskfs/file-exec.c b/libdiskfs/file-exec.c
index 452240c..c96aad0 100644
--- a/libdiskfs/file-exec.c
+++ b/libdiskfs/file-exec.c
@@ -1,14 +1,15 @@
-/* File execution (file_exec RPC) for diskfs servers, using exec server.
-   Copyright (C) 1993,94,95,96,97,98,2000,02 Free Software Foundation, Inc.
+/* File execution (file_exec_file_name RPC) for diskfs servers, using exec 
server.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002,
+   2010 Free Software Foundation, Inc.
 
 This file is part of the GNU Hurd.
 
 The GNU Hurd is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 The GNU Hurd is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
@@ -38,24 +39,57 @@ diskfs_S_file_exec (struct protid *cred,
                    size_t envplen,
                    mach_port_t *fds,
                    size_t fdslen,
                    mach_port_t *portarray,
                    size_t portarraylen,
                    int *intarray,
                    size_t intarraylen,
                    mach_port_t *deallocnames,
                    size_t deallocnameslen,
                    mach_port_t *destroynames,
                    size_t destroynameslen)
 {
+  return diskfs_S_file_exec_file_name (cred,
+                                      task,
+                                      flags,
+                                      "",
+                                      argv, argvlen,
+                                      envp, envplen,
+                                      fds, fdslen,
+                                      portarray, portarraylen,
+                                      intarray, intarraylen,
+                                      deallocnames, deallocnameslen,
+                                      destroynames, destroynameslen);
+}
+
+kern_return_t
+diskfs_S_file_exec_file_name (struct protid *cred,
+                             task_t task,
+                             int flags,
+                             char *filename,
+                             char *argv,
+                             size_t argvlen,
+                             char *envp,
+                             size_t envplen,
+                             mach_port_t *fds,
+                             size_t fdslen,
+                             mach_port_t *portarray,
+                             size_t portarraylen,
+                             int *intarray,
+                             size_t intarraylen,
+                             mach_port_t *deallocnames,
+                             size_t deallocnameslen,
+                             mach_port_t *destroynames,
+                             size_t destroynameslen)
+{
   struct node *np;
   uid_t uid;
   gid_t gid;
   mode_t mode;
   int suid, sgid;
   struct protid *newpi;
   struct peropen *newpo;
   error_t err = 0;
   mach_port_t execserver;
   int cached_exec;
   struct hurd_userlink ulink;
   mach_port_t right;
@@ -127,55 +161,70 @@ diskfs_S_file_exec (struct protid *cred,
   /* If the user can't read the file, then we should use a new task,
      which would be inaccessible to the user.  Actually, this doesn't
      work, because the proc server will still give out the task port
      to the user.  Too many things depend on that that it can't be
      changed.  So this vague attempt isn't even worth trying.  */
 #if 0
   if (fshelp_access (&np->dn_stat, S_IREAD, cred->user))
     flags |= EXEC_NEWTASK;
 #endif
 
   if (! err)
     /* Make a new peropen for the exec server to access the file, since any
-       seeking the exec server might want to do should not affect the
-       original peropen on which file_exec was called.  (The new protid for
-       this peropen clones the caller's iouser to preserve the caller's
+       seeking the exec server might want to do should not affect the original
+       peropen on which file_exec_file_name was called.  (The new protid
+       for this peropen clones the caller's iouser to preserve the caller's
        authentication credentials.)  The new peropen's openmodes must have
        O_READ even if the caller had only O_EXEC privilege, so the exec
        server can read the executable file.  We also include O_EXEC so that
        the exec server can turn this peropen into a file descriptor in the
        target process and permit it to exec its /dev/fd/N pseudo-file.  */
     {
       err = diskfs_make_peropen (np, O_READ|O_EXEC, cred->po, &newpo);
       if (! err)
        {
          err = diskfs_create_protid (newpo, cred->user, &newpi);
          if (err)
            diskfs_release_peropen (newpo);
        }
     }
 
   if (! err)
     {
       do
        {
          right = ports_get_send_right (newpi);
-         err = exec_exec (execserver,
-                          right, MACH_MSG_TYPE_COPY_SEND,
-                          task, flags, argv, argvlen, envp, envplen,
-                          fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
-                          portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
-                          intarray, intarraylen,
-                          deallocnames, deallocnameslen,
-                          destroynames, destroynameslen);
+         err = exec_exec_file_name (execserver,
+                                    right, MACH_MSG_TYPE_COPY_SEND,
+                                    task, flags, filename,
+                                    argv, argvlen, envp, envplen,
+                                    fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+                                    portarray, MACH_MSG_TYPE_COPY_SEND,
+                                    portarraylen,
+                                    intarray, intarraylen,
+                                    deallocnames, deallocnameslen,
+                                    destroynames, destroynameslen);
+         /* For backwards compatibility.  Just drop it when we kill
+            exec_exec.  */
+         if (err == MIG_BAD_ID)
+           err = exec_exec (execserver,
+                            right, MACH_MSG_TYPE_COPY_SEND,
+                            task, flags, argv, argvlen, envp, envplen,
+                            fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+                            portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
+                            intarray, intarraylen,
+                            deallocnames, deallocnameslen,
+                            destroynames, destroynameslen);
+
+
          mach_port_deallocate (mach_task_self (), right);
          if (err == MACH_SEND_INVALID_DEST)
            {
              if (cached_exec)
                {
                  /* We were using a previously looked-up exec server port.
                     Try looking up a new one before giving an error.  */
                  cached_exec = 0;
                  _hurd_port_free (&_diskfs_exec_portcell, &ulink, execserver);
 
                  execserver = file_name_lookup (_SERVERS_EXEC, 0, 0);
                  if (execserver == MACH_PORT_NULL)
diff --git a/libfshelp/start-translator-long.c 
b/libfshelp/start-translator-long.c
index 5bf1454..87abba1 100644
--- a/libfshelp/start-translator-long.c
+++ b/libfshelp/start-translator-long.c
@@ -1,14 +1,15 @@
 /*
-   Copyright (C) 1995,96,99,2000,02, 04 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1999, 2000, 2002, 2004, 2010
+   Free Software Foundation, Inc.
    Written by Miles Bader and Michael I. Bushnell.
 
    This file is part of the GNU Hurd.
 
    The GNU Hurd is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2, or (at
    your option) any later version.
 
    The GNU Hurd is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
@@ -256,29 +257,37 @@ fshelp_start_translator_long (fshelp_open_fn_t 
underlying_open_fn,
       mach_port_insert_right (mach_task_self (), bootstrap, bootstrap,
                              MACH_MSG_TYPE_MAKE_SEND);
       break;
 
     default:
       abort ();
     }
 
   saveport = ports[INIT_PORT_BOOTSTRAP];
   ports[INIT_PORT_BOOTSTRAP] = bootstrap;
 
   /* Try and exec the translator in TASK...  */
-  err = file_exec (executable, task, EXEC_DEFAULTS,
-                  argz, argz_len, 0, 0,
-                  fds, fds_type, fds_len,
-                  ports, ports_type, ports_len,
-                  ints, ints_len, 0, 0, 0, 0);
+  err = file_exec_file_name (executable, task, EXEC_DEFAULTS, name,
+                            argz, argz_len, 0, 0,
+                            fds, fds_type, fds_len,
+                            ports, ports_type, ports_len,
+                            ints, ints_len, 0, 0, 0, 0);
+  /* For backwards compatibility.  Just drop it when we kill file_exec.  */
+  if (err == MIG_BAD_ID)
+    err = file_exec (executable, task, EXEC_DEFAULTS,
+                    argz, argz_len, 0, 0,
+                    fds, fds_type, fds_len,
+                    ports, ports_type, ports_len,
+                    ints, ints_len, 0, 0, 0, 0);
+
   ports_moved = 1;
 
   if (ports_type == MACH_MSG_TYPE_COPY_SEND)
     mach_port_deallocate (mach_task_self (), bootstrap);
   ports[INIT_PORT_BOOTSTRAP] = saveport;
 
   if (err)
     {
       task_terminate (task);
       goto lose;
     }
 
diff --git a/libnetfs/file-exec.c b/libnetfs/file-exec.c
index 73c125b..76b2c93 100644
--- a/libnetfs/file-exec.c
+++ b/libnetfs/file-exec.c
@@ -1,14 +1,15 @@
 /*
-   Copyright (C) 1996,97,2000,01,02 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 2000, 2001, 2002, 2010
+   Free Software Foundation, Inc.
    Written by Michael I. Bushnell, p/BSG.
 
    This file is part of the GNU Hurd.
 
    The GNU Hurd is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2, or (at
    your option) any later version.
 
    The GNU Hurd is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
@@ -40,24 +41,57 @@ netfs_S_file_exec (struct protid *cred,
                   size_t envplen,
                   mach_port_t *fds,
                   size_t fdslen,
                   mach_port_t *portarray,
                   size_t portarraylen,
                   int *intarray,
                   size_t intarraylen,
                   mach_port_t *deallocnames,
                   size_t deallocnameslen,
                   mach_port_t *destroynames,
                   size_t destroynameslen)
 {
+  return netfs_S_file_exec_file_name (cred,
+                                     task,
+                                     flags,
+                                     "",
+                                     argv, argvlen,
+                                     envp, envplen,
+                                     fds, fdslen,
+                                     portarray, portarraylen,
+                                     intarray, intarraylen,
+                                     deallocnames, deallocnameslen,
+                                     destroynames, destroynameslen);
+}
+
+kern_return_t
+netfs_S_file_exec_file_name (struct protid *cred,
+                            task_t task,
+                            int flags,
+                            char *filename,
+                            char *argv,
+                            size_t argvlen,
+                            char *envp,
+                            size_t envplen,
+                            mach_port_t *fds,
+                            size_t fdslen,
+                            mach_port_t *portarray,
+                            size_t portarraylen,
+                            int *intarray,
+                            size_t intarraylen,
+                            mach_port_t *deallocnames,
+                            size_t deallocnameslen,
+                            mach_port_t *destroynames,
+                            size_t destroynameslen)
+{
   struct node *np;
   error_t err;
   uid_t uid;
   gid_t gid;
   mode_t mode;
   int suid, sgid;
   mach_port_t right;
 
   if (!cred)
     return EOPNOTSUPP;
 
   if (_netfs_exec == MACH_PORT_NULL)
@@ -124,32 +158,47 @@ netfs_S_file_exec (struct protid *cred,
     {
       struct iouser *user;
       struct protid *newpi;
 
       err = iohelp_dup_iouser (&user, cred->user);
       if (! err)
         {
          newpi = netfs_make_protid (netfs_make_peropen (np, O_READ, cred->po),
                                     user);
          if (newpi)
            {
              right = ports_get_send_right (newpi);
-             err = exec_exec (_netfs_exec,
-                              right, MACH_MSG_TYPE_COPY_SEND,
-                              task, flags, argv, argvlen, envp, envplen,
-                              fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
-                              portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
-                              intarray, intarraylen,
-                              deallocnames, deallocnameslen,
-                              destroynames, destroynameslen);
+             err = exec_exec_file_name (_netfs_exec,
+                                        right, MACH_MSG_TYPE_COPY_SEND,
+                                        task, flags, filename,
+                                        argv, argvlen, envp, envplen,
+                                        fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+                                        portarray, MACH_MSG_TYPE_COPY_SEND,
+                                        portarraylen,
+                                        intarray, intarraylen,
+                                        deallocnames, deallocnameslen,
+                                        destroynames, destroynameslen);
+             /* For backwards compatibility.  Just drop it when we kill
+                exec_exec.  */
+             if (err == MIG_BAD_ID)
+               err = exec_exec (_netfs_exec,
+                                right, MACH_MSG_TYPE_COPY_SEND,
+                                task, flags, argv, argvlen, envp, envplen,
+                                fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+                                portarray, MACH_MSG_TYPE_COPY_SEND,
+                                portarraylen,
+                                intarray, intarraylen,
+                                deallocnames, deallocnameslen,
+                                destroynames, destroynameslen);
+
              mach_port_deallocate (mach_task_self (), right);
              ports_port_deref (newpi);
            }
          else
            {
              err = errno;
              iohelp_free_iouser (user);
            }
        }
     }
 
   if (! err)
diff --git a/libtrivfs/file-exec.c b/libtrivfs/file-exec.c
index a3ab048..f626955 100644
--- a/libtrivfs/file-exec.c
+++ b/libtrivfs/file-exec.c
@@ -1,14 +1,14 @@
 /*
-   Copyright (C) 1994,2002 Free Software Foundation, Inc.
+   Copyright (C) 1994, 2002, 2010 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2, or (at
    your option) any later version.
 
    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
 
    You should have received a copy of the GNU General Public License
@@ -31,12 +31,37 @@ trivfs_S_file_exec (trivfs_protid_t exec_file,
                    mach_msg_type_number_t fdarrayCnt,
                    portarray_t portarray,
                    mach_msg_type_number_t portarrayCnt,
                    intarray_t intarray,
                    mach_msg_type_number_t intarrayCnt,
                    mach_port_array_t deallocnames,
                    mach_msg_type_number_t deallocnamesCnt,
                    mach_port_array_t destroynames,
                    mach_msg_type_number_t destroynamesCnt)
 {
   return EOPNOTSUPP;
 }
+
+kern_return_t
+trivfs_S_file_exec_file_name (trivfs_protid_t exec_file,
+                             mach_port_t reply,
+                             mach_msg_type_name_t replyPoly,
+                             mach_port_t exec_task,
+                             int flags,
+                             string_t filename,
+                             data_t argv,
+                             mach_msg_type_number_t argvCnt,
+                             data_t envp,
+                             mach_msg_type_number_t envpCnt,
+                             portarray_t fdarray,
+                             mach_msg_type_number_t fdarrayCnt,
+                             portarray_t portarray,
+                             mach_msg_type_number_t portarrayCnt,
+                             intarray_t intarray,
+                             mach_msg_type_number_t intarrayCnt,
+                             mach_port_array_t deallocnames,
+                             mach_msg_type_number_t deallocnamesCnt,
+                             mach_port_array_t destroynames,
+                             mach_msg_type_number_t destroynamesCnt)
+{
+  return EOPNOTSUPP;
+}
diff --git a/trans/fakeroot.c b/trans/fakeroot.c
index c110234..101c3fb 100644
--- a/trans/fakeroot.c
+++ b/trans/fakeroot.c
@@ -1,14 +1,14 @@
 /* fakeroot -- a translator for faking actions that aren't really permitted
-   Copyright (C) 2002, 2003, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2008, 2010 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2, or (at
    your option) any later version.
 
    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
 
    You should have received a copy of the GNU General Public License
@@ -696,47 +696,94 @@ netfs_S_file_exec (struct protid *user,
                    size_t envplen,
                    mach_port_t *fds,
                    size_t fdslen,
                    mach_port_t *portarray,
                    size_t portarraylen,
                    int *intarray,
                    size_t intarraylen,
                    mach_port_t *deallocnames,
                    size_t deallocnameslen,
                    mach_port_t *destroynames,
                    size_t destroynameslen)
 {
+  return netfs_S_file_exec_file_name (user,
+                                     task,
+                                     flags,
+                                     "",
+                                     argv, argvlen,
+                                     envp, envplen,
+                                     fds, fdslen,
+                                     portarray, portarraylen,
+                                     intarray, intarraylen,
+                                     deallocnames, deallocnameslen,
+                                     destroynames, destroynameslen);
+}
+
+kern_return_t
+netfs_S_file_exec_file_name (struct protid *user,
+                            task_t task,
+                            int flags,
+                            char *filename,
+                            char *argv,
+                            size_t argvlen,
+                            char *envp,
+                            size_t envplen,
+                            mach_port_t *fds,
+                            size_t fdslen,
+                            mach_port_t *portarray,
+                            size_t portarraylen,
+                            int *intarray,
+                            size_t intarraylen,
+                            mach_port_t *deallocnames,
+                            size_t deallocnameslen,
+                            mach_port_t *destroynames,
+                            size_t destroynameslen)
+{
   error_t err;
   file_t file;
 
   if (!user)
     return EOPNOTSUPP;
 
   mutex_lock (&user->po->np->lock);
   err = check_openmodes (user->po->np->nn, O_EXEC, MACH_PORT_NULL);
   file = user->po->np->nn->file;
   if (!err)
     err = mach_port_mod_refs (mach_task_self (),
                              file, MACH_PORT_RIGHT_SEND, 1);
   mutex_unlock (&user->po->np->lock);
 
   if (!err)
     {
       /* We cannot use MACH_MSG_TYPE_MOVE_SEND because we might need to
         retry an interrupted call that would have consumed the rights.  */
-      err = file_exec (user->po->np->nn->file, task, flags, argv, argvlen,
-                      envp, envplen, fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
-                      portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
-                      intarray, intarraylen, deallocnames, deallocnameslen,
-                      destroynames, destroynameslen);
+      err = file_exec_file_name (user->po->np->nn->file, task, flags,
+                                filename,
+                                argv, argvlen,
+                                envp, envplen,
+                                fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+                                portarray, MACH_MSG_TYPE_COPY_SEND,
+                                portarraylen,
+                                intarray, intarraylen,
+                                deallocnames, deallocnameslen,
+                                destroynames, destroynameslen);
+      /* For backwards compatibility.  Just drop it when we kill
+        file_exec.  */
+      if (err == MIG_BAD_ID)
+       err = file_exec (user->po->np->nn->file, task, flags, argv, argvlen,
+                        envp, envplen, fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+                        portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
+                        intarray, intarraylen, deallocnames, deallocnameslen,
+                        destroynames, destroynameslen);
+
       mach_port_deallocate (mach_task_self (), file);
     }
 
   if (err == 0)
     {
       size_t i;
       mach_port_deallocate (mach_task_self (), task);
       for (i = 0; i < fdslen; ++i)
        mach_port_deallocate (mach_task_self (), fds[i]);
       for (i = 0; i < portarraylen; ++i)
        mach_port_deallocate (mach_task_self (), portarray[i]);
     }
diff --git a/utils/login.c b/utils/login.c
index aefc218..f56e837 100644
--- a/utils/login.c
+++ b/utils/login.c
@@ -1,15 +1,16 @@
 /* Hurdish login
 
-   Copyright (C) 1995,96,97,98,99,2002 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2002, 2010
+   Free Software Foundation, Inc.
 
    Written by Miles Bader <miles@gnu.org>
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2, or (at
    your option) any later version.
 
    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
@@ -873,23 +874,31 @@ main(int argc, char *argv[])
       char *tty = ttyname (0);
       if (tty)
        {
          /* Change the terminal to be owned by the user.  */
          err = chown (tty,
                       ugids.eff_uids.num ? ugids.eff_uids.ids[0] : -1,
                       ugids.eff_gids.num ? ugids.eff_gids.ids[0] : -1);
          if (err)
            error (0, errno, "chown: %s", tty);
        }
     }
 
-  err = file_exec (exec, mach_task_self (), EXEC_DEFAULTS,
-                  sh_args, sh_args_len, env, env_len,
-                  fds, MACH_MSG_TYPE_COPY_SEND, 3,
-                  ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
-                  ints, INIT_INT_MAX,
-                  0, 0, 0, 0);
+  err = file_exec_file_name (exec, mach_task_self (), EXEC_DEFAULTS, shell,
+                            sh_args, sh_args_len, env, env_len,
+                            fds, MACH_MSG_TYPE_COPY_SEND, 3,
+                            ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
+                            ints, INIT_INT_MAX,
+                            0, 0, 0, 0);
+  /* Fallback in case the file server hasn't been restarted.  */
+  if (err == MIG_BAD_ID)
+    err = file_exec (exec, mach_task_self (), EXEC_DEFAULTS,
+                    sh_args, sh_args_len, env, env_len,
+                    fds, MACH_MSG_TYPE_COPY_SEND, 3,
+                    ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
+                    ints, INIT_INT_MAX,
+                    0, 0, 0, 0);
   if (err)
     error(5, err, "%s", shell);
 
   return 0;
 }
-- 
1.7.5.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]