Source

pcw / cw.c

Full commit
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;
}