implement pgetppid
pgetppid will aid in detecting which terminal emulator a process is running under
This commit is contained in:
parent
edeec36ffa
commit
25f1180429
4 changed files with 105 additions and 2 deletions
2
Makefile
2
Makefile
|
|
@ -27,7 +27,7 @@ all: tests
|
||||||
.PHONY: tests
|
.PHONY: tests
|
||||||
tests: $(BIN) $(BIN)/ct_test
|
tests: $(BIN) $(BIN)/ct_test
|
||||||
|
|
||||||
$(BIN)/ct_test: $(BUILD) $(addprefix $(BUILD)/, ct_test.o term.o termio.o)
|
$(BIN)/ct_test: $(BUILD) $(addprefix $(BUILD)/, ct_test.o term.o termio.o pgetppid.o)
|
||||||
$(LD) $(LDFLAGS) -o $@ $(filter %.o, $^)
|
$(LD) $(LDFLAGS) -o $@ $(filter %.o, $^)
|
||||||
|
|
||||||
$(BUILD)/%.o: $(SRC)/%.c
|
$(BUILD)/%.o: $(SRC)/%.c
|
||||||
|
|
|
||||||
85
src/pgetppid.c
Normal file
85
src/pgetppid.c
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* XXX: WARNING: TODO
|
||||||
|
* This file's implementation is Linux dependent!
|
||||||
|
* XXX: WARNING: TODO
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "pgetppid.h"
|
||||||
|
#include "ct_shared.h"
|
||||||
|
|
||||||
|
int pgetppid(const pid_t pid, pid_t *const ppid, char *const name) {
|
||||||
|
/* I'm making the assumption that each line in /proc/pid/status
|
||||||
|
* has a hard length limit of PAGE_SIZE.
|
||||||
|
*/
|
||||||
|
static int CT_K_PAGE_SIZE;
|
||||||
|
CT_K_PAGE_SIZE = getpagesize();
|
||||||
|
|
||||||
|
FILE *stream;
|
||||||
|
char line[CT_K_PAGE_SIZE];
|
||||||
|
|
||||||
|
/* The maximum PID value on a 64-Bit Linux kernel is defined 4194304,
|
||||||
|
* not INT_MAX even through pid_t is typedef'd to signed int.
|
||||||
|
* Hence "/proc/4194304/status\0" is the maximum path (length 21).
|
||||||
|
*/
|
||||||
|
#define PROCPATH_MAX (21)
|
||||||
|
char procname[PROCPATH_MAX]; // Holds /proc/4294967296/status\0
|
||||||
|
// XXX: NOTE: should this be %d not %u since pid_t is typedef'd to signed int?
|
||||||
|
snprintf(procname, PROCPATH_MAX, "/proc/%u/status", pid);
|
||||||
|
#undef PROCPATH_MAX
|
||||||
|
stream = fopen(procname, "r");
|
||||||
|
if (stream == NULL) {
|
||||||
|
return NERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* /proc/pid/status format: ($ cat /proc/$$/status)
|
||||||
|
Name: bash
|
||||||
|
Umask: 0022
|
||||||
|
State: S (sleeping)
|
||||||
|
Tgid: 17248
|
||||||
|
Ngid: 0
|
||||||
|
Pid: 17248
|
||||||
|
PPid: 17200
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Name Line Format: "Name:___$NAME\n\0" where _ are spaces (5+3+len(NAME)+2 =
|
||||||
|
* 10+len(NAME)) `man proc_pid_status` claims $NAME will be truncated to
|
||||||
|
* TASK_COMM_LEN (including \0 terminating byte) aka 15+1 bytes long. However,
|
||||||
|
* They fail to account for work-queue-threads and kernel-threads which
|
||||||
|
* seem to not have this restriction.
|
||||||
|
* ie `rcu_exp_par_gp_kthread_worker/0` clearly exceeds this.
|
||||||
|
* We define NAMELINE_MAX to 9 + TASK_COMM_LEN (yes 9) because TASK_COMMON =
|
||||||
|
* len(NAME)+1 (for \0).
|
||||||
|
* NOTE: TASK_COMM_LEN isn't accessible in userspace so we define CT_PROC_NAME_MAX
|
||||||
|
*/
|
||||||
|
#define NAMELINE_MAX (9 + CT_PROC_NAME_MAX)
|
||||||
|
if (fgets(line, NAMELINE_MAX, stream) == NULL)
|
||||||
|
goto fail;
|
||||||
|
/* Fail if over max length, ie this is kernel related
|
||||||
|
* thread and we've recursed too deep. */
|
||||||
|
// if (line[NAMELINE_MAX - 2] != '\n')
|
||||||
|
// goto fail;
|
||||||
|
else if (sscanf(line, "Name: %s\n", name) == 0)
|
||||||
|
return 0;
|
||||||
|
#undef NAMELINE_MAX
|
||||||
|
|
||||||
|
/* Skip over the Umask, State, Tgid, Ngid, Pid lines
|
||||||
|
* The compiler can unroll this loop for us. */
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
if (fgets(line, CT_K_PAGE_SIZE, stream) == NULL)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fgets(line, CT_K_PAGE_SIZE, stream) == NULL)
|
||||||
|
goto fail;
|
||||||
|
else if (sscanf(line, "PPid: %d\n", ppid) == 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
fclose(stream);
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
fclose(stream);
|
||||||
|
return NERR;
|
||||||
|
}
|
||||||
|
|
||||||
15
src/pgetppid.h
Normal file
15
src/pgetppid.h
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef CURSETREE_PGETPPID_H
|
||||||
|
#define CURSETREE_PGETPPID_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/* XXX: WARNING: TODO: Linux kernel specific
|
||||||
|
* TASK_COMM_LEN isn't accessible in userspace so we define CT_PROC_NAME_MAX
|
||||||
|
* instead, representing the maximum (in most instances) truncated length of
|
||||||
|
* a process' Name field in /proc/pid/status.
|
||||||
|
*/
|
||||||
|
#define CT_PROC_NAME_MAX 16
|
||||||
|
|
||||||
|
int pgetppid(const pid_t pid, pid_t *const ppid, char *const name);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
@ -51,3 +50,7 @@ void ct_resetterm(struct ct_term *const term) {
|
||||||
free(term);
|
free(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: use pgetppid() and write a terminfo parser, otherwise default to TERM */
|
||||||
|
// static inline int ct_detectterm() {
|
||||||
|
// secure_getenv("TERM");
|
||||||
|
// }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue