Change process name on MacOS of arbitrary binaries - macos

I want to be able to set the process name (as it appears in the Activity Monitor) of arbitrary binaries in MacOS. Preferably, this wouldn't require any manual reverse engineering.
To clarify, I'm not asking to change it at runtime. Rather, to set up a script which will change the code of another executable.
(similar to how you can change argv[0] in C code)

You may achieve it for some apps, but with relevant consiquences.
First of all, let's think of what is going to be the name in Activity monitor. It is a name of a executable file for shell scripts, and it is a Bundle or displayed Bundle name for bundles.
So, to change the name you will basically need to change the name of file or the record inside Info.plist.
Both is not doable for Apple provided apps, until you disable SIP (if this could be the way for you - all is doable).
Speaking about non-Apple apps, you could change their names or Info.plist records, but it would result in non-valid code signature for them. You will need to manually allow such apps to run on your mac and get over all Apple popups about that.
There is no API you can use to achieve this goal. You are either going to use hacky ways, or need to change what you want to have.

Related

OS X sandboxing questions

I have a Mac application in the App Store and am looking to adopt sandboxing before it becomes a mandatory requirement. I've run into two issues and was hoping to post here for some insight into best practice in the following situations:
Within my application I use an NSOpenPanel to prompt the user to load a proprietary file format. After loading the file my application parses it and gathers a list of NSURLs to local files. These local files are then passed to NSImage's initWithContentsOfURL: method. Unfortunately, the act of loading the image files causes the sandbox to cancel the action. I understand that this happens because the user has given my application explicit permission to open the file selected by the NSOpenPanel, but not for the files referenced within my proprietary format. How can I handle this (supposedly fairly common) situation?
I have a unix executable file contained within my applications bundle that I would like to execute using an NSTask. Is this legal under sandboxing, given that the script is contained within my bundle?
If anyone could clarify the above points, that would be appreciated.
1) From my understanding the NSURL object contains the permissions necessary to re-access the files later, so if you are using hardcoded paths, you could replace them with archived NSURL objects. This is also assuming the user selected those filies within an NSOpenPanel at an earlier point.
2) You can run a NSTask but it inherits the permissions of your main app.
Hopefully others can chime in with more information. I've found the Mac Developer Boards, specifically the "Application Sandboxing" forums to be helpful, as Apple employees often drop in. So far, I've found sandboxing to be an unusable mess.
Easy one first: you can run your helper with NSTask and it will inherit the sandbox of your app.
Those URLs: not easily/reliably/at all. There is a way to save NSURLs to files you have access to in such a way that a subsequent run of your application and re-load them and regain access, however it is deemed fragile and not to be recommended. Read the Apple developer forums and this is an Apple acknowledged problem they are "working on"; given this using the fragile solution is probably not worth the effort - search the developer forums for the fragile solution if you really want to hack something that sort of works now.

Programatic file associations in OS X

Is it possible to use an Apple Script or a Unix executable to associate a file type with an app?
My problem is I'm using File Vault and it forgets previous associations (it's a well known bug so it seems). For instance, I like to use Flying Meat's Acorn for my graphics files rather than Preview. I can Cmd-I, change all, and while it sticks for one file the next time I reboot it's forgotten the association for everything else.
This has been driving me nuts for literally years. Any ideas?
I use Magic Launch and would highly recommend it. Not only can you associate programs with certain file types, but you can establish complex rules for when to use what app.
Or, to better answer your original question, you could try this:
defaults write com.apple.LaunchServices LSHandlers -array-add \
"<dict><key>LSHandlerContentType</key><string>public.png</string><key>LSHandlerRoleAll</key><string>com.flyingmeat.acorn</string></dict>"

Is a launchd daemon the best route to go for reading/writing to privileged files in Cocoa?

I have an application which needs to be able to write to Any User/Current host preference files (which requires admin privileges per Preferences Utilities Reference) and also to enable/disable a launchd agent via its plist (writable only by root).
I'm using SFAuthorizationView to require users to authenticate as an admin before altering these values.
I'm trying to decide on the best way to do the actual altering of these values.
The cheap hackish option seems to be to use AuthorizationExecuteWithPrivileges() and mv or defaults, either via BLAuthentication or creating something similar myself. The downside to this is not getting the return value of whatever command line app I'm executing, plus some odd esoteric bugs I've encountered (such as getting a -60008 error in certain situations). This is strongly recommended against by Apple, obviously, but people do seem to do it and have some success with it.
The second most hackish option would seem to be the whole create a helper app with the suid bit set and the --self-repair option as discussed in various places. This seems possible, but like it's probably not much less trouble than the third option.
The third option is to create a fully fledged launchd daemon which will run as root and communicate with my application via a socket. This seems like a bit of overkill to read and write some plist files, but it's also possible I may find other uses for it down the road, and it wont be the only daemon for my application, so it doesn't seem unreasonable to just add another.
I'm thinking about modifying this sample code for my purposes.
My two questions are:
Does the launchd daemon option seem like the best route to go for this, or is there a much easier route I'm missing?
Has anybody else successfully used that code as a basis for something similar, and does anybody see any glaring issues with it I'm missing? I've used it successfully in a test app, but I'd be curious to hear you guys' opinion on it.
launchd is definitely the best and safest way to go: you’ll need an installer package to get your helper into place. Do be sure that your helper does and can do absolutely nothing except edit the files you wish to target.
No experience w/the code, but it’s based off of BetterAuthorizationSample, so that’s a nice start.
There's also the openauth API, which allows you to open files that require root privileges.

File-level filesystem change notification in Mac OS X

I want my code to be notified when any file under (either directly or indirectly) a given directory is modified. By "modified", I mean I want my code to be notified whenever a file's contents are altered, it's renamed, or it's deleted; or if a new file is added. For my application, there can be thousands of files.
I looked as FSEvents, but its Technology Overview says, in part:
The important point to take away is that the granularity of notifications is at a directory level. It tells you only that something in the directory has changed, but does not tell you what changed.
It also says:
The file system events API is also not designed for finding out when a particular file changes. For such purposes, the kqueues mechanism is more appropriate.
However, in order to use kqueue on a given file, one has to open the file to obtain a file descriptor. It's impractical to manage thousands of file descriptors (and would probably exceed the maximum allowable number of open file descriptors anyway).
Curiously, under Windows, I can use the ReadDirectoryChangesW() function and it does precisely what I want.
So how can one do what I want under Mac OS X? Or, asked another way: how would one go about writing the equivalent of ReadDirectoryChangesW() for Mac OS X in user-space (and do so very efficiently)?
EDIT: Not verified, but Konstantin indicates below that this code sample is obsolete as of 2012.
I don't believe there's a specific API for what you're looking for. Apple provides sample code for a similar problem called Watcher. It is not what you are looking for, but it is about the best you can do at this point. You have to take snapshots of the directory, and rescan it when you find out something changed. Modification time is the best thing to check of course, if you can trust modification time.
You are probably correct that trying to register for an unbounded number of kqueues would likely be unworkable.
I haven't tried this myself, but it seems like FSEvents is able to provide file-level notifications as of 10.7 (Lion). From the description of FSEventStreamCreateFlags:
kFSEventStreamCreateFlagFileEvents
Request file-level notifications. Your stream will receive events about individual files in the hierarchy you're watching instead of only receiving directory level notifications. Use this flag with care as it will generate significantly more events than without it.
Available in OS X v10.7 and later.
The closest utility (that I know of) that matches your needs on Mac OS X is fslogger.
See the link for a description, dmg and source code:
OSXBook - fslogger
You might want to check out man fs_usage, though it's not specific to a directory and requires root privileges.

How do you control printer tray selection for printer in Windows

We need to be able to change the default selected print tray of a given printer. Does anyone have VC++/win32 code for doing this?
In case it matters, I believe we have to change the default setting for the printer. Our print jobs are executed by an application other than ours, so we can't make these kinds of changes in the context of a print operation originating from inside our application. Unless there is some way to modify the default print settings in a different application, I think we are stuck changing the user's defaults for the printer, initiating our print job, then setting the defaults back to the original values.
We'd really prefer to have the defaults change for the current user only, and not require any special UAC elevation, etc...
I suspect that it will use something similar to what is shown in this MSDN article, and involve setting fields in the DEVMODE structure (either dmDefaultSource or dmFormName or both).
Any takers? Or does anyone have any gotchas they'd like to share?
EDIT: Here is a link for DEVMODE documentation DEVMODE documentation
EDIT: I should also point out that we are looking for a general solution - not something specific to a particular printer (we deploy in many, many environments)
FYI - the solution we wound up using was to capture the DEVMODE structure. We have a small win32 app that presents the printer settings dialog (via DocumentProperties with fMode set to DM_IN_PROMPT). The resultant DEVMODE is then saved to disk. When we do our printing, we capture the current DEVMODE, set the stored DEVMODE, initiate the print, then restore the original DEVMODE.
This actually works quite well. Occasionally, the print drivers will update and cause the stored DEVMODE to break, but that doesn't happen very often and it's easy enough for users to fix.
As an extra bonus, this approach allows us to capture ALL of the printer settings (not just the output tray) - so we were able to support advanced settings like stapling, collating, etc...
Tip: If you try this, be sure to write to disk as a binary output stream. In my initial evaluation of this approach, I accidentally set the output stream up as a text output stream. Things would work fine for many cases, then suddenly break for some printers (that used high order bytes in their DEVMODE private data). A dumb, but easy, mistake to make - and one that took a very nice solution off the table for awhile.
Setting features like this can be tricky, especially if the driver doesn't follow Microsoft's print guidelines. That being said, we've had some success with System.Drawing.Printing.PrinterSettings. You can set PaperSource but I'm not sure you can set the defaults.
If you haven't seen this example you may want to look further at it. It describes a method to store and reload printer settings. One of my guys pointed it to me:
PrinterSettings - Changing, Storing and Loading Printer Settings
Another method, that could work but might not work for you, is to determine your the handful of setups you need. Install a printer with each of these (ie: Tray 1, Tray 2) setups. Then simply switch the default printer on print. Not what you are looking for but it may help.
What we typically do in these situations is have the 3rd party app write the data to a folder that we are monitoring, we then pick up the file and parse the Postscript or PCL ourselves and change the paper tray and then send onto the destination device. A lot simpler then it may sound.
dmDefaultSource controls the tray. Unfortunately the values you'll want to set this to differs depending on your driver as this is a bin number and not necessarily the same number as the tray# printed on your printer.
The following link provides some VB6 code for gathering information about your printers tray/bin assignments. You can use that information to programatically assign dmDefaultSource to the appropriate bin # for a tray. You basically need to use DeviceCapabilities to return information about your printers and then search for a string (like "Tray 1") to get the associated bin number.
http://support.microsoft.com/kb/194789
I had to do something very similar recently on a specific printer driver and it required a vendor specific SDK. The tray doesn't seem to appear in DEVMODE or any of the other PRINTINFO_* structures so I guess I'd drop an email to the printer vendor.
As a last resort, I can think of two possible hacks. One is to automate the driver at GUI level using a scripted tool such as AutoIT. Second is to dump the registry to file, change the driver setting, dump the registry again, and compare the differences (may or may not work).
As far as I know, printers are controlled by the printer driver by sending them SNMP or PJL commands. But not all printers implement completely these sets of commands.
For HP printers I found at: http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?lang=en&cc=us&objectID=bpl07282&jumpid=reg_R1002_USEN some PJL commands (there are some related to the tray too).
I'm not sure this help, but take it as a hint for future searches...

Resources