1#include <stdio.h>
2#include <string.h>
3#include <unistd.h>
4#include <stdarg.h>
5#include <time.h>
6#include <sys/stat.h>
7#include "lesstest.h"
8
9static FILE* logf = NULL;
10
11int log_open(const char* logfile) {
12	if (logf != NULL) fclose(logf);
13	logf = (strcmp(logfile, "-") == 0) ? stdout : fopen(logfile, "w");
14	if (logf == NULL) {
15		fprintf(stderr, "cannot create %s\n", logfile);
16		return 0;
17	}
18	return 1;
19}
20
21void log_close(void) {
22	if (logf == NULL) return;
23	if (logf == stdout) return;
24	fclose(logf);
25	logf = NULL;
26}
27
28int log_file_header(void) {
29	if (logf == NULL) return 0;
30	time_t now = time(NULL);
31	struct tm* tm = gmtime(&now);
32	fprintf(logf, "!lesstest!\n!version %d\n!created %d-%02d-%02d %02d:%02d:%02d\n",
33		LESSTEST_VERSION,
34		tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
35		tm->tm_hour, tm->tm_min, tm->tm_sec);
36	return 1;
37}
38
39int log_env(const char* name, int namelen, const char* value) {
40	if (logf == NULL) return 0;
41	fprintf(logf, "E \"%.*s\" \"%s\"\n", namelen, name, value);
42	return 1;
43}
44
45int log_tty_char(wchar ch) {
46	if (logf == NULL) return 0;
47	fprintf(logf, "+%lx\n", ch);
48	return 1;
49}
50
51int log_screen(const byte* img, int len) {
52	if (logf == NULL) return 0;
53	fwrite("=", 1, 1, logf);
54	fwrite(img, 1, len, logf);
55	fwrite("\n", 1, 1, logf);
56	return 1;
57}
58
59#if 0
60int log_debug(char const* fmt, ...) {
61	va_list ap;
62	va_start(ap, fmt);
63	fprintf(logf, "D ");
64	vfprintf(logf, fmt, ap);
65	fprintf(logf, "\n");
66	va_end(ap);
67	fflush(logf);
68	return 1;
69}
70#endif
71
72int log_command(char* const* argv, int argc, const char* textfile) {
73	if (logf == NULL) return 0;
74	fprintf(logf, "A");
75	int a;
76	for (a = 1; a < argc; ++a)
77		fprintf(logf, " \"%s\"", (a < argc-1) ? argv[a] : textfile);
78	fprintf(logf, "\n");
79	return 1;
80}
81
82int log_textfile(const char* textfile) {
83	if (logf == NULL) return 0;
84	struct stat st;
85	if (stat(textfile, &st) < 0) {
86		fprintf(stderr, "cannot stat %s\n", textfile);
87		return 0;
88	}
89	FILE* fd = fopen(textfile, "r");
90	if (fd == NULL) {
91		fprintf(stderr, "cannot open %s\n", textfile);
92		return 0;
93	}
94	fprintf(logf, "F \"%s\" %ld\n", textfile, (long) st.st_size);
95	off_t nread = 0;
96	while (nread < st.st_size) {
97		char buf[4096];
98		size_t n = fread(buf, 1, sizeof(buf), fd);
99		if (n <= 0) {
100			fprintf(stderr, "read only %ld/%ld from %s\n", (long) nread, (long) st.st_size, textfile);
101			fclose(fd);
102			return 0;
103		}
104		nread += n;
105		fwrite(buf, 1, n, logf);
106	}
107	fclose(fd);
108	return 1;
109}
110
111int log_test_header(char* const* argv, int argc, const char* textfile) {
112	if (logf == NULL) return 0;
113	fprintf(logf, "T \"%s\"\n", textfile);
114	if (!log_command(argv, argc, textfile))
115		return 0;
116	if (!log_textfile(textfile))
117		return 0;
118	fprintf(logf, "R\n");
119	return 1;
120}
121
122int log_test_footer(void) {
123	if (logf == NULL) return 0;
124	fprintf(logf, "Q\n");
125	return 1;
126}
127