Skip to content

Instantly share code, notes, and snippets.

@jborean93
Created December 2, 2022 07:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jborean93/f6af9751de9fb31d407bd22a3dacd0d4 to your computer and use it in GitHub Desktop.
Save jborean93/f6af9751de9fb31d407bd22a3dacd0d4 to your computer and use it in GitHub Desktop.
Get the Command Line of a process on macOS
Add-Type -CompilerOptions '/unsafe' -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace macOS
{
public static class Native
{
[DllImport("libc", SetLastError = true)]
private unsafe static extern int sysctl(int *name, int namelen, void *oldp, ref nint oldlenp, void *newp,
nint newlen);
private static int Sysctl<T>(Span<int> name, Span<T> oldValue, Span<T> newValue)
where T : unmanaged
{
unsafe
{
fixed (int* namePtr = name)
fixed (T* oldPtr = oldValue)
fixed (T* newPtr = newValue)
{
nint oldSize = (nint)(oldValue.Length * Marshal.SizeOf<T>());
nint newSize = (nint)(newValue.Length * Marshal.SizeOf<T>());
int res = sysctl(
namePtr,
name.Length,
oldPtr,
ref oldSize,
newPtr,
newSize);
if (res != 0)
{
throw new System.ComponentModel.Win32Exception();
}
return (int)(oldSize / Marshal.SizeOf<T>());
}
}
}
public static int GetMaxArgumentSize()
{
Span<int> mibs = stackalloc int[2]
{
1, // CTL_KERN
8, // KERN_ARGMAX
};
Span<int> value = stackalloc int[1];
Sysctl(mibs, value, null);
return value[0];
}
public static string[] GetCommandLine(int pid)
{
int maxArgLength = GetMaxArgumentSize();
byte[] argBuffer = new byte[maxArgLength];
Span<int> mibs = stackalloc int[3]
{
1, // CTL_KERN
49, // KERN_PROCARGS2
pid,
};
Span<byte> buffer = argBuffer.AsSpan();
int length = Sysctl(mibs, buffer, null);
buffer = buffer[..length];
// First 4 bytes are the arg count
int argCount = BitConverter.ToInt32(buffer[..4]);
buffer = buffer[4..];
string[] arguments = new string[argCount];
// Next is the executable
int exeLength = buffer.IndexOf((byte)0);
buffer = buffer[(exeLength + 1)..];
// It is aligned to the next byte boundary
while (true)
{
int nextIdx = buffer.IndexOf((byte)0);
if (nextIdx != 0)
{
break;
}
buffer = buffer[1..];
}
// Finally are the arguments
for (int i = 0; i < argCount; i++)
{
int nextIdx = buffer.IndexOf((byte)0);
string argument = Encoding.UTF8.GetString(buffer.Slice(0, nextIdx));
buffer = buffer[(nextIdx + 1)..];
arguments[i] = argument;
}
return arguments;
}
}
}
'@
[macOS.Native]::GetCommandLine($pid)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment