summaryrefslogtreecommitdiff
path: root/shells/powershell/files/patch-src_powershell_Program.cs
blob: ec1585be12cae66b51e77ef5402e688b7793f062 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
--- src/powershell/Program.cs.orig	2024-03-30 20:39:17 UTC
+++ src/powershell/Program.cs
@@ -56,6 +56,13 @@ namespace Microsoft.PowerShell
         private const int MACOS_KERN_ARGMAX = 8;
         private const int MACOS_KERN_PROCARGS2 = 49;
         private const int MACOS_PROC_PIDPATHINFO_MAXSIZE = 4096;
+
+        // FreeBSD p/Invoke constants
+        private const int FREEBSD_CTL_KERN = 1;
+        private const int FREEBSD_KERN_PROC = 14;
+        private const int FREEBSD_KERN_PROC_ARGS = 7;
+        private const int FREEBSD_KERN_PROC_PATHNAME = 12;
+        private const int FREEBSD_ENOMEM = 12;
 #endif
 
         /// <summary>
@@ -125,7 +132,62 @@ namespace Microsoft.PowerShell
                 ThrowOnFailure("exec", ExecPwshLogin(args, pwshPath, isMacOS: false));
                 return;
             }
+            else if (OperatingSystem.IsFreeBSD())
+            {
+                Span<int> fmib = stackalloc int[4];
+                int fmibLength = 4;
+                fmib[0] = FREEBSD_CTL_KERN;
+                fmib[1] = FREEBSD_KERN_PROC;
+                fmib[2] = FREEBSD_KERN_PROC_ARGS;
+                fmib[3] = -1;
 
+                int sz = 1;
+                unsafe
+                {
+                    fixed (int *mibptr = fmib)
+                    {
+                        ThrowOnFailure(nameof(procNameFirstByte), SysCtl(mibptr, fmibLength, &procNameFirstByte, &sz, IntPtr.Zero, 0), FREEBSD_ENOMEM);
+                    }
+                }
+
+                if (!IsLogin(procNameFirstByte, args))
+                {
+                    return;
+                }
+
+                fmib[2] = FREEBSD_KERN_PROC_PATHNAME;
+                int pathsz = 0;
+
+                unsafe
+                {
+                    fixed (int *mibptr = fmib)
+                    {
+                        ThrowOnFailure(nameof(pathsz), SysCtl(mibptr, fmibLength, (void *)null, &pathsz, IntPtr.Zero, 0));
+                    }
+                }
+
+                IntPtr execPathPtr = Marshal.AllocHGlobal(pathsz);
+                try
+                {
+                    unsafe
+                    {
+                        fixed (int *mibptr = fmib)
+                        {
+                            ThrowOnFailure(nameof(execPathPtr), SysCtl(mibptr, fmibLength, execPathPtr.ToPointer(), &pathsz, IntPtr.Zero, 0));
+                        }
+                    }
+                    string? execPath = Marshal.PtrToStringAnsi(execPathPtr);
+                    ArgumentNullException.ThrowIfNull(execPath);
+                    ThrowOnFailure("exec", ExecPwshLogin(args, execPath, isMacOS: false));
+                }
+                finally
+                {
+                    Marshal.FreeHGlobal(execPathPtr);
+                }
+
+                return;
+            }
+
             // At this point, we are on macOS
 
             // Set up the mib array and the query for process maximum args size
@@ -417,11 +479,13 @@ namespace Microsoft.PowerShell
         /// </summary>
         /// <param name="call">The native call that was attempted.</param>
         /// <param name="code">The exit code it returned.</param>
-        private static void ThrowOnFailure(string call, int code)
+        /// <param name="ignore">Ignore this error, consider it success.</param>
+        private static void ThrowOnFailure(string call, int code, int ignore = 0)
         {
             if (code < 0)
             {
                 code = Marshal.GetLastWin32Error();
+                if (code == ignore) return;
                 Console.Error.WriteLine($"Call to '{call}' failed with errno {code}");
                 throw new StartupException(call, code);
             }