1 /* Copyright (C) 1991-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <unistd.h>
19 #include <getcwd.h>
20 #include <hurd.h>
21 #include <hurd/fd.h>
22 #include <fcntl.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 
26 /* Replace the current process, executing FILE_NAME with arguments ARGV and
27    environment ENVP.  ARGV and ENVP are terminated by NULL pointers.  */
28 int
__execveat(int dirfd,const char * file_name,char * const argv[],char * const envp[],int flags)29 __execveat (int dirfd, const char *file_name, char *const argv[],
30             char *const envp[], int flags)
31 {
32   error_t err;
33   char *concat_name = NULL;
34   const char *abs_path;
35 
36   file_t file = __file_name_lookup_at (dirfd, flags, file_name, O_EXEC, 0);
37   if (file == MACH_PORT_NULL)
38     return -1;
39 
40   if (file_name[0] == '/')
41     {
42       /* Already an absolute path */
43       abs_path = file_name;
44     }
45   else
46     {
47       /* Relative path */
48       char *cwd;
49       if (dirfd == AT_FDCWD)
50 	{
51 	  cwd = __getcwd (NULL, 0);
52 	  if (cwd == NULL)
53 	    {
54 	      __mach_port_deallocate (__mach_task_self (), file);
55 	      return -1;
56 	    }
57 	}
58       else
59 	{
60 	  err = HURD_DPORT_USE (dirfd,
61 	    (cwd = __hurd_canonicalize_directory_name_internal (port, NULL, 0),
62 	     cwd == NULL ? errno : 0));
63 	  if (err)
64 	    {
65 	      __mach_port_deallocate (__mach_task_self (), file);
66 	      return __hurd_fail (err);
67 	    }
68 	}
69 
70       int res = __asprintf (&concat_name, "%s/%s", cwd, file_name);
71       free (cwd);
72       if (res == -1)
73 	{
74 	  __mach_port_deallocate (__mach_task_self (), file);
75 	  return -1;
76 	}
77 
78       abs_path = concat_name;
79     }
80 
81   /* Hopefully this will not return.  */
82   err = _hurd_exec_paths (__mach_task_self (), file,
83 			  file_name, abs_path, argv, envp);
84 
85   /* Oh well.  Might as well be tidy.  */
86   __mach_port_deallocate (__mach_task_self (), file);
87   free (concat_name);
88 
89   return __hurd_fail (err);
90 }
91 
92 weak_alias (__execveat, execveat)
93