Full Code of nickodell/pact for AI

master 9bb7d2e981d1 cached
6 files
4.6 KB
1.6k tokens
3 symbols
1 requests
Download .txt
Repository: nickodell/pact
Branch: master
Commit: 9bb7d2e981d1
Files: 6
Total size: 4.6 KB

Directory structure:
gitextract_7arvnqt5/

├── .gitignore
├── COPYING-WTFPL
├── Makefile
├── README.md
├── pact.c
└── test.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
pact


================================================
FILE: COPYING-WTFPL
================================================
            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
                    Version 2, December 2004

 Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>

 Everyone is permitted to copy and distribute verbatim or modified
 copies of this license document, and changing it is allowed as long
 as the name is changed.

            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. You just DO WHAT THE FUCK YOU WANT TO.


================================================
FILE: Makefile
================================================
CFLAGS = -O2 -Wall -Werror -std=c99
ifeq ($(debug),1)
	CFLAGS += -DPRINT_DEBUG=1
endif

pact: pact.c
	gcc pact.c ${CFLAGS} -o pact

install: pact
	cp pact /bin/pact

clean:
	rm -f pact


================================================
FILE: README.md
================================================
# pact

Give pact several process IDs. When one process ID dies, pact will kill all
provided PIDs.

Example usage:

    #!/bin/bash
    
    cmd1 &
    PID1=$!
    cmd2 --some-arg &
    PID2=$!
    
    ./pact $PID1 $PID2

##Advanced usage

pact also accepts a one character modifier before the process ID.
It can be either M or K. M monitors the process without killing it, and 
K will not monitor the process, but it will kill the process if another
monitored process dies.

Example:

    #!/bin/bash
    
    (sleep 5)&
    PID1=$!
    (sleep 24h)&
    PID2=$!

    # If the shell dies, kill the other processes. If one of the
    # processes die, don't kill the shell.
    ./pact $PID1 $PID2 M$$
    
    # Pause, because otherwise the shell will immediately die and pact
    # will kill the subprocesses.
    pause


================================================
FILE: pact.c
================================================
#define _POSIX_SOURCE
#define _POSIX_C_SOURCE 199309L

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>


#ifdef PRINT_DEBUG
#define DEBUG(...) fprintf(stdout, __VA_ARGS__)
#else
#define DEBUG(...)
#endif
#define ERROR(...) fprintf(stderr, __VA_ARGS__)

struct child_proc {
	pid_t pid;
	bool monitorProc;
	bool killProc;
	bool procChanged;
};

bool killAll = false;

void on_SIGTERM(int signal) {
	killAll = true;
}


int main(int argc, char *argv[]) {
	// Trap SIGTERM
	struct sigaction action;
	memset(&action, 0, sizeof(struct sigaction));
	action.sa_handler = on_SIGTERM;
	sigaction(SIGTERM, &action, NULL);

	int numProcs = argc - 1;
	// Check the arguments are sane and that every argument corresponds
	// to a process
	if(argc < 2) {
		ERROR("You must give pact some PID's!\n");
		ERROR("Usage: %s [K/M]PID ...\n", argv[0]);
		return 42;
	}
	struct child_proc procs[numProcs];
	memset(&procs, 0, sizeof(procs));
	for(int i = 0; i < numProcs; i++) {
		char* currentArg = argv[i + 1];
		int pid;
		char modifier;
		int ret;
		bool hasModifier = !isdigit(currentArg[0]);
		if(hasModifier) {
			DEBUG("Arg has modifier\n");
			modifier = currentArg[0];
			currentArg++;
			ret = sscanf(currentArg, "%d", &pid);
			switch (modifier) {
			case 'K':
				procs[i].monitorProc = false;
				procs[i].killProc = true;
				break;
			case 'M':
				procs[i].monitorProc = true;
				procs[i].killProc = false;
				break;
			default:
				ERROR("Unrecognized modifier %c\n", modifier);
				break;
			}
		} else {
			DEBUG("Arg has no modifier\n");
			ret = sscanf(currentArg, "%d", &pid);
			procs[i].monitorProc = true;
			procs[i].killProc = true;
		}
		if(ret != 1) {
			ERROR("Error - \"%s\" is not a valid argument.\n", currentArg);
			killAll = true;
		} else {
			procs[i].pid = pid;

		}
	}
	// Fork and let the child handle the work
	int ret = fork();
	if(ret > 0) {
		exit(0);
	} else if(ret < 0) {
		ERROR("Cannot fork()\n");
	} else if(ret == 0) {
		// We're the child, continue with the program
	}
	// Wait for one of those processes to die
	while(!killAll) {
		for(int i = 0; i < numProcs; i++) {
			pid_t pid = procs[i].pid;
			if(kill(pid, 0) == -1) {
				// Process no longer exists, don't kill it
				// later
				procs[i].procChanged = true;
				// Don't start killing processes if we got
				// the K modifier for this process
				if(procs[i].monitorProc) {
					killAll = true;
					break;
				}
			}
		}
		if(!killAll) {
			DEBUG("Sleeping\n");
			struct timespec ts;
			ts.tv_sec = 1;
			ts.tv_nsec = 0;
			nanosleep(&ts, NULL);
		}
	}
	// Kill all other processes
	for(int i = 0; i < numProcs; i++) {
		pid_t pid = procs[i].pid;
		if(!procs[i].killProc || procs[i].procChanged || pid == 0) {
			continue;
		}
		DEBUG("Killing %d\n", pid);
		kill(pid, SIGTERM);
	}
	return 0;
}


================================================
FILE: test.sh
================================================
#!/bin/bash

echo "shell at $$"

(sleep 24h)&
PID1=$!
echo "sleep1 at $PID1"
(sleep 1)&
PID2=$!
echo "sleep2 at $PID2"

./pact $PID1 $PID2


ps -A | grep $PID1
ps -A | grep $PID2

#read

#ps -A | grep $PID1
#ps -A | grep $PID2
Download .txt
gitextract_7arvnqt5/

├── .gitignore
├── COPYING-WTFPL
├── Makefile
├── README.md
├── pact.c
└── test.sh
Download .txt
SYMBOL INDEX (3 symbols across 1 files)

FILE: pact.c
  type child_proc (line 24) | struct child_proc {
  function on_SIGTERM (line 33) | void on_SIGTERM(int signal) {
  function main (line 38) | int main(int argc, char *argv[]) {
Condensed preview — 6 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5K chars).
[
  {
    "path": ".gitignore",
    "chars": 5,
    "preview": "pact\n"
  },
  {
    "path": "COPYING-WTFPL",
    "chars": 483,
    "preview": "            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE\n                    Version 2, December 2004\n\n Copyright (C) 200"
  },
  {
    "path": "Makefile",
    "chars": 185,
    "preview": "CFLAGS = -O2 -Wall -Werror -std=c99\nifeq ($(debug),1)\n\tCFLAGS += -DPRINT_DEBUG=1\nendif\n\npact: pact.c\n\tgcc pact.c ${CFLAG"
  },
  {
    "path": "README.md",
    "chars": 820,
    "preview": "# pact\n\nGive pact several process IDs. When one process ID dies, pact will kill all\nprovided PIDs.\n\nExample usage:\n\n    "
  },
  {
    "path": "pact.c",
    "chars": 2968,
    "preview": "#define _POSIX_SOURCE\n#define _POSIX_C_SOURCE 199309L\n\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#incl"
  },
  {
    "path": "test.sh",
    "chars": 227,
    "preview": "#!/bin/bash\n\necho \"shell at $$\"\n\n(sleep 24h)&\nPID1=$!\necho \"sleep1 at $PID1\"\n(sleep 1)&\nPID2=$!\necho \"sleep2 at $PID2\"\n\n"
  }
]

About this extraction

This page contains the full source code of the nickodell/pact GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 6 files (4.6 KB), approximately 1.6k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!