pg_logpipe.c

text/plain

Filename: pg_logpipe.c
Type: text/plain
Part: 0
Message: Re: more contrib: log rotator
#include "c.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>

#include "pqsignal.h"

volatile static int hangup_flag = 0;


static void
signalhandler(SIGNAL_ARGS)
{
	hangup_flag = 1;
}


#define BUF_SIZE 8192
#define MAX_ERRORS 200

#define MAX_ERRORS_CHECK() do { errcount++; if (max_errors > 0 && errcount >= max_errors) exit(2); } while(0)

int
main(int argc, char *argv[])
{
	const char *filename;
	int fd = -1;
	static char buf[BUF_SIZE];
	unsigned int errcount = 0;
	unsigned int max_errors = MAX_ERRORS;

	if (argc != 2)
	{
		fprintf(stderr, "%s: missing required argument\n", argv[0]);
		fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
		exit(1);
	}

	if (strcmp(argv[1], "--help")==0)
	{
		printf("this should be a help message...\n");
		exit(0);
	}

	filename = argv[1];

	fd = open(filename, O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND, 0666);
	if (fd < 0)
	{
		fprintf(stderr, "%s: could not open file %s: %s\n",
				argv[0], filename, strerror(errno));
		exit(1);
	}

	pqsignal(SIGUSR1, signalhandler);

	for (;;)
	{
		int read_bytes;
		int written_bytes;
		char * buf_ptr;

		read_bytes = read(0, buf, sizeof(buf));
		if (read_bytes < 0)
		{
			if (errno == EINTR)
				continue;
			else
			{
				fprintf(stderr, "*** %s: read error from %s: %s\n",
						argv[0], filename, strerror(errno));
				MAX_ERRORS_CHECK();
			}
		}
		if (read_bytes == 0)
		{
			/* end of file, postmaster exited? */
			close(fd);
			exit(0);
		}

		if (hangup_flag)
		{
			int fdnew;

			fdnew = open(filename, O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND, 0666);
			if (fdnew < 0)
			{
				fprintf(stderr, "*** %s: could not open new output file %s: %s\n",
					   argv[0], filename, strerror(errno));
				MAX_ERRORS_CHECK();
			}
			else
			{
				close(fd);
				fd = fdnew;
			}
			hangup_flag = 0;
		}

		buf_ptr = buf;
		do
		{
			written_bytes = write(fd, buf_ptr, read_bytes);
			if (written_bytes < 0)
			{
				if (errno == EINTR)
					continue;
				fprintf(stderr, "*** %s: could not write to file %s: %s\n",
						argv[0], filename, strerror(errno));
				MAX_ERRORS_CHECK();

				break;
			}
			if (written_bytes < read_bytes)
			{
				buf_ptr += written_bytes;
				read_bytes -= written_bytes;
				continue;
			}
			break;
		} while(1);
	}

	return 127;
}