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
|
||||
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, $^)
|
||||
|
||||
$(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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
@ -51,3 +50,7 @@ void ct_resetterm(struct ct_term *const 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