How to Programatically Change an Executable Name (Ucmd) of a Unix Process

is it possible to programatically change an executable name (ucmd) of a unix process?

You can do this with the PR_SET_NAME function of prctl():

prctl(PR_SET_NAME, (unsigned long)"xyzzy", 0, 0, 0);

However, /etc/rcX.d/SNNname should be a (symlink to a) script that starts your process, not a link to the process executable itself. This would also solve the problem.

Renaming executable changes behavior

Yes, it is routine (but well done for realizing that it can be done). For example:

$ (cd /usr/bin; ls -li | grep -w vim)
2704450 lrwxr-xr-x 1 root wheel 3 Oct 31 2013 ex -> vim
2704451 lrwxr-xr-x 1 root wheel 3 Oct 31 2013 rview -> vim
2704452 lrwxr-xr-x 1 root wheel 3 Oct 31 2013 rvim -> vim
2378579 lrwxr-xr-x 1 root wheel 3 Oct 31 2013 vi -> vim
2704453 lrwxr-xr-x 1 root wheel 3 Oct 31 2013 view -> vim
2343880 -rwxr-xr-x 1 root wheel 1472736 Oct 31 2013 vim
2704454 lrwxr-xr-x 1 root wheel 3 Oct 31 2013 vimdiff -> vim
$

So, the vim executable can also be invoked as vimdiff or view or vi or ex and it will behave differently depending on how it is invoked. On some systems, these will be hard links instead of symlinks (the data is from Mac OS X 10.9.2 Mavericks), so you'd need to grep for the inode number instead of vim.

Another example:

Bash operates differently when invoked as bash compared with when it is invoked as sh. Classically, shells recognize when they're invoked with a dash - in front of their name (-sh, -bash, etc), and act as login shells when you do that:

$ ps
PID TTY TIME CMD
39301 ttys000 0:01.30 -bash
46766 ttys001 0:00.24 -bash
$

How to reliably obtain, programmatically, the executable path corresponding to a process with a given pid, under linux?

The robustness of the first method (readlink /proc/$PID/exe) can be improved by doing a pair of stats on the link itself and the result of the readlink. If you get a matching st_dev and st_ino, they're the same file. If you don't get a match, or get an ENOENT, then check for " (deleted)" at the end of the string, strip it off and try again. Repeat until you get a match or run out of " (deleted)" instances.

If you don't get a match after all that, the executable file really has been deleted. (And you haven't really specified what you want to do in that case - which you should definitely think about. When you are insisting on robustness, you can't just ignore the fact that deleted files can be in use!)

There's still a race condition between the stats, so you might want to open both files and fstat them instead. Then if you get a device+inode match, you have a file descriptor that can be used with confidence that it actually belongs to the file that was exec'd in the target process, not some other file with a similar name.

The next difficulty is if the process itself goes away during your test, and the PID gets reused. If you care about that, you can read the process start time from /proc/$PID/stat at the beginning and end of the operation, to make sure you were dealing with the same process the whole way through. (Also, there's a way to keep a process from going away: attach to it as a debugger with ptrace.)

Then there's the question fo what you want to do if the process execs a different program while you're looking at it. /proc/$PID/exe will change. If it happens right after your final consistency check, you will return a value that was correct, but isn't anymore. You can't do much about that, except the ptrace, and that's more intrusive than you probably want.

Process name from its pid in linux

There is not any general way to do this unix.
Each OS has different ways to handle it and some are very hard. You mention Linux though. With Linux, the info is in the /proc filesystem.
To get the command line for process id 9999, read the file /proc/9999/cmdline.

Can a C program modify its executable file?

On Windows, when a program is run the entire *.exe file is mapped into memory using the memory-mapped-file functions in Windows. This means that the file isn't necessarily all loaded at once, but instead the pages of the file are loaded on-demand as they are accessed.

When the file is mapped in this way, another application (including itself) can't write to the same file to change it while it's running. (Also, on Windows the running executable can't be renamed either, but it can on Linux and other Unix systems with inode-based filesystems).

It is possible to change the bits mapped into memory, but if you do this the OS does it using "copy-on-write" semantics, which means that the underlying file isn't changed on disk, but a copy of the page(s) in memory is made with your modifications. Before being allowed to do this though, you usually have to fiddle with protection bits on the memory in question (e.g. VirtualProtect).

At one time, it used to be common for low-level assembly programs that were in very constrained memory environments to use self-modifying code. However, nobody does this anymore because we're not running in the same constrained environments, and modern processors have long pipelines that get very upset if you start changing code from underneath them.

How to Search for the unix executable file in OS X programmatically?

Try using either getResourceValue:forKey:error: or resourceValuesForKeys:error: methods of NSURL and requesting NSURLTypeIdentifierKey.

Addendum:

If what @Aravindhanarvi says is correct, on 10.6 there are bugs and the above solution is unreliable. To make things worse @petur solution is also not possible for lack of NSURLIsExecutableKey.

An alternative would be to fall back to the NSFileManager and use methods like isExecutableFileAtPath: and attributesOfItemAtPath:error: (specifically the NSFilePosixPermissions and NSFileType attributes) to implement the same logic suggested by @petur.

How can I redirect all shortcuts to a given executable? Is there any equivalent to a symlink on Windows?

Well, the solution we've decided on is just doing the small little executable that launches our real engine. It took a bit more futzing with Visual Studio to get the project set up than I would have preferred, but it seems to be working out.

#include "stdafx.h"
#include <shellapi.h>

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
HINSTANCE result = ShellExecute(NULL, _T("open"),
_T("engine\\win32\\NewEngine.exe"),
lpCmdLine, NULL, 1);
// ... handle errors ...
return 0;
}

edit: Nope. This seems to work on XP, but not Windows 7 or Vista. Any ideas for why this would fail on Windows 7 or Vista would be much appreciated. If I can't figure this out soon, I may break this out into a separate question.

edit 2: Ah. On XP, forward slashes in the pathname work just fine. On Vista or newer, you need backslashes.



Related Topics



Leave a reply



Submit