I am trying to open terminal on session of some process, but it is too hard. I am wrote some simple code, but it do not work when process is inside terminal emulator. Also, it should work for graphical session (and in this case start GUI program). I known to start a GUI program, I probably could use systemd run --user via DBUS (it is also hard, because I must known, where is socket for DBUS daemon and what is cookie).
This is my code:
static int get_terminal(char *data, int *major_r, int *minor_r)
{
int number, major, minor;
char *end;
while (' ' == *data) ++data;
puts(data);
end = data;
while (' ' != *end && '\0' != *end) ++ end;
*end = '\0';
puts(data);
number = atoi(data);
major = (number >> 8) & 0xFF;
minor = ((number >> 13) & ~0b1111111) | (number & 0b11111111);
*major_r = major;
*minor_r = minor;
//printf ("Major: %d\nMinor: %d\nFrom:%d\n\n", major, minor,number);
}
#if 0
static void spawn_message_on_tty(int major, int minor, const char *app, const char *file, dbus_int32_t rights)
{
int fd =
}
#endif
static void skip_value(char **next_val_)
{
bool complex_field = false;
char *next_val = *next_val_;
while (' ' == *next_val) ++next_val;
if ('(' == *next_val) {
while (')' != *next_val && '\0' != *next_val) ++next_val;
}
else {
while (' ' != *next_val && '\0' != *next_val) ++next_val;
}
puts(next_val);
*next_val_ = next_val;
}
static DBusHandlerResult handle_dbus_message(DBusConnection *connection, DBusMessage *message, void *user_data)
{
DBusError error;
const char *method = dbus_message_get_member(message);
const char *interface = dbus_message_get_interface(message);
if (0==strcmp("pl.art.lach.slawek.apps.SecureHome.SessionHelper", interface)) {
if (0==strcmp("askForPermission", method)) {
int fd;
int pos;
char path[PATH_MAX+1];
char buffer[819200];
dbus_int32_t rights;
pid_t prog_pid;
pid_t current_prog_pid;
char *curr = buffer;
int major, minor;
const char *file;
const char *app;
dbus_error_init(&error);
dbus_message_get_args(message, &error, DBUS_TYPE_STRING,&file, DBUS_TYPE_STRING,&app, DBUS_TYPE_INT32, &prog_pid,DBUS_TYPE_INT32, &rights,DBUS_TYPE_INVALID);
if (dbus_error_is_set(&error)) {
return DBUS_HANDLER_RESULT_HANDLED;
}
#if 0
/proc/[pid]/status:
(7) tty_nr %d
The controlling terminal of the process. (The minor
device number is contained in the combination of
bits 31 to 20 and 7 to 0; the major device number is
in bits 15 to 8.)
Separated by space probably
#endif
current_prog_pid = prog_pid;
do {
snprintf(path, sizeof(path), "/proc/%d/stat", current_prog_pid);
fd = open(path, O_RDONLY);
if (-1 == fd) {
return DBUS_HANDLER_RESULT_HANDLED;
}
if (1 > (pos = read(fd, buffer, sizeof(buffer)))) {
close(fd);
return DBUS_HANDLER_RESULT_HANDLED;
}
close(fd);
buffer[pos] = '\0';
skip_value(&curr);
skip_value(&curr);
skip_value(&curr);
skip_value(&curr);
skip_value(&curr);
skip_value(&curr);
skip_value(&curr);
get_terminal(curr, &major, &minor);
printf ("Major: %d\nMinor: %d\n\n", major, minor);
if (5 != major) {
pid_t new_prog_id;
char *substr;
snprintf(path, sizeof(path), "/proc/%d/status", current_prog_pid);
fd = open(path, O_RDONLY);
if (1 > (pos = read(fd, buffer, sizeof(buffer)))) {
close(fd);
return DBUS_HANDLER_RESULT_HANDLED;
}
close(fd);
buffer[pos] = '\0';
substr = strstr(buffer, "\nPPid:");
if (NULL == substr) {
return DBUS_HANDLER_RESULT_HANDLED;
}
substr += sizeof("\nPPID:") - 1;
while (isspace(*substr)) ++ substr;
new_prog_id = atoi(substr);
if (new_prog_id == current_prog_pid) {
return DBUS_HANDLER_RESULT_HANDLED;
}
current_prog_pid = new_prog_id;
continue;
}
break;
} while (true);
printf ("Major: %d\nMinor: %d\n\n", major, minor);
}
}
return DBUS_HANDLER_RESULT_HANDLED;
}
So I read from state the controlling terminal and try to go up (to parent process) until we found 5 major number (tty) as controlling terminal. But I went to 1 and got 0 in next step as pid.