Not only did Indigo not report the error,
IndigioPluginHost wedged, though I was able to kill it with a -9.
Now, in case others are following this topic, I have resolved the problem and have this working. Ideally, all I should have needed to do was
set-user-ID-on-execution bit. But, while
chmod supports that, OS X/darwin does not actually do anything. The solution was to write a short program in C that sets its uid (
setuid)appropriately (I.e. to that of the user running the Indigo server) and then executes a shell script with the embedded IndigioPluginHost call. This works because the C
setuid call is functional in OS X. I generalized the code so the uid, path to the script/program to be executed, args for that executable and and Indigo device ID are set in command line args. The path, args and devId are then passed to the executable defined in the path and run as the uid.
I organized this to meet my needs and it might not work as written for others. For example, if there is no -a argument provided, the program will fail when it tries to create the command to be executed by system. Note also, the compiler complains about an
incompatible implicit declaration of built-in function ‘memset’ . But, it compiles.
I can provide more information. But, it is likely that anyone needing to do what I did is probably a much more accomplished C programmer and should be helping me rather than vis-a-versa.
Here is the code. Any improvements are most welcome.
- Code: Select all
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main ( int argc, char **argv )
{
int uvalue = 0;
char *avalue = NULL;
char *dvalue = NULL;
char *pvalue = NULL;
int vflag = 0;
int index;
int a;
opterr = 0;
while ((a = getopt (argc, argv, "a:u:p:d:vh")) != -1)
switch (a)
{
case 'h':
fprintf (stdout, "-u uid -p path -a args -d devid -v verbose -h help\n");
return 0;
case 'v':
vflag = 1;
break;
case 'd':
dvalue = optarg;
break;
case 'a':
avalue = optarg;
break;
case 'u':
uvalue = atoi(optarg);
break;
case 'p':
pvalue = optarg;
break;
case '?':
if (optopt == 'c')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
abort ();
}
if ( vflag == 1)
printf ("uid = %i, path = %s, action=%s, devid=%s\n", uvalue, pvalue, avalue, dvalue);
setuid( uvalue );
char cmd[512];
memset(cmd, '\0', sizeof(512));
sprintf(cmd, "%s %s %s", pvalue, avalue, dvalue);
system( cmd );
return 0;
}
For reference, the script I am executing, the actual interface to Indigo, is:
- Code: Select all
#!/bin/sh
ACTION=$1
DEVID=$2
cd /Library/Application\ Support/Perceptive\ Automation/Indigo\ 6/IndigoPluginHost.app/Contents/MacOS
./IndigoPluginHost -e "
apcupsdPlugin = indigo.server.getPlugin(\"com.berkinet.apcupsd\")
if apcupsdPlugin.isEnabled():
apcupsdPlugin.executeAction(\"apcupsdServerEvent\", deviceId=${DEVID}, props={\"actionType\":\"${ACTION}\"})
# indigo.server.log(\"Completed Action Call\", type=\"apcupsd\")
"
Note, I did the
cd because getting the
IndigoPluginHost path into a variable, or executing the full path was a royal pain because of the embedded spaces. I hard coded the action to be called since the plugin action handler looks at the actionType property to determine what to do. This helped me avoid creating a bunch of actions and is, therefore, more easily modified.
One more point, to get your UID, in a terminal window use the id command.
$ id
uid=501(rdp) gid=501(rdp) groups=501(rdp),401(com.apple.access_screensharing),12(everyone),33(_appstore),61(localaccounts),80(admin),98(_lpadmin),100(_lpoperator),204(_developer)