pcw / cw.c

Evan Gates 40154d1 



Evan Gates 481dd85 
Evan Gates 40154d1 
Evan Gates 0bdea5b 



Evan Gates 9675cb5 
Evan Gates 203bee0 




Evan Gates 9675cb5 
Evan Gates 203bee0 














Evan Gates 9675cb5 
Evan Gates 203bee0 



Evan Gates 9675cb5 
Evan Gates 203bee0 


Evan Gates 0bdea5b 


Evan Gates 203bee0 
Evan Gates e08b191 


Evan Gates 0bdea5b 
Evan Gates 203bee0 







Evan Gates 9675cb5 

Evan Gates 203bee0 













Evan Gates 481dd85 
Evan Gates 203bee0 
Evan Gates e08b191 

Evan Gates 0bdea5b 
Evan Gates 203bee0 
Evan Gates e08b191 
Evan Gates 0bdea5b 
Evan Gates e08b191 



Evan Gates 0bdea5b 
Evan Gates e08b191 














Evan Gates 0bdea5b 
Evan Gates e08b191 
Evan Gates 0bdea5b 
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/stat.h>
#include <sys/select.h>
#include <sys/inotify.h>

int quiet = 0;
mode_t type = 0;
mode_t perm = 0600;

void usage(void)
{
	printf("Usage: cw [-c|-f] [-q] [-v] infile outfile\n");
	exit(1);
}

FILE *mopen(char *path, char *mode)
{
	struct stat st;
	FILE *f;

	if (stat(path, &st) < 0 && errno == ENOENT) {
		if (!type)
			err(1, "file %s does not exist", path);
		else if (mknod(path, type | perm, 0) < 0)
			err(1, "file %s could not be created", path);
	}

	if (!quiet) warnx("Opening %s (if it's a fifo, waiting for the other side to be opened)...", path);

	if ((f = fopen(path, mode)) == NULL)
		err(1, "failed to fopen %s", path);

	if (!quiet) warnx("...OK");

	return f;
}

int main(int argc, char **argv)
{
	int evq, in_wd, i;
	FILE *in, *out;
	char buf[4096];
	fd_set rd;

	for (i = 1; i < argc; i++) {
		if (argv[i][0] != '-')
			break;
		if (argv[i][2] != '\0')
			usage();
		switch (argv[i][1]) {
			case 'c' : type = S_IFREG; break; // create regular files
			case 'f' : type = S_IFIFO; break; // create fifos
			case 'q' : quiet = 1; break;
			case 'v' : printf("cw-"VERSION" © Evan Gates\n"); exit(1);
			// is it worth doing character, block, and socket too?
			default  : usage();
		}
	}
	if (i + 1 >= argc)
		usage();

	in = mopen(argv[i], "r");

	while (fgets(buf, sizeof(buf), in))
		fputs(buf, stdout);

	out = mopen(argv[i + 1], "w");

	if (!quiet) fprintf(stderr, "-------------------- new text starts here --------------------\n");

	if ((evq = inotify_init()) < 0)
		err(1, "failed inotify_init()");

	if ((in_wd = inotify_add_watch(evq, argv[i], IN_MODIFY)) < 0)
		err(1, "failed inotify_add_watch()");

	for (;;) {
		FD_ZERO(&rd);
		FD_SET(0, &rd);
		FD_SET(evq, &rd);

		select(evq + 1, &rd, 0, 0, NULL);

		if (FD_ISSET(evq, &rd)) {
			if (read(evq, buf, sizeof(buf)) < 0)
				err(1, "failed read() on evq");

			while (fgets(buf, sizeof(buf), in))
				fputs(buf, stdout);
			fflush(stdout);
		}
		if (FD_ISSET(0, &rd)) {
			fgets(buf, sizeof(buf), stdin);
			fputs(buf, out);
			fflush(out);
		}
	}
	return 0;
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.