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
9 static FILE* logf = NULL;
10
log_open(const char * logfile)11 int 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
log_close(void)21 void log_close(void) {
22 if (logf == NULL) return;
23 if (logf == stdout) return;
24 fclose(logf);
25 logf = NULL;
26 }
27
log_file_header(void)28 int 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
log_env(const char * name,int namelen,const char * value)39 int 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
log_tty_char(wchar ch)45 int log_tty_char(wchar ch) {
46 if (logf == NULL) return 0;
47 fprintf(logf, "+%lx\n", ch);
48 return 1;
49 }
50
log_screen(const byte * img,int len)51 int 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
60 int 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
log_command(char * const * argv,int argc,const char * textfile)72 int 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
log_textfile(const char * textfile)82 int 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
log_test_header(char * const * argv,int argc,const char * textfile)111 int 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
log_test_footer(void)122 int log_test_footer(void) {
123 if (logf == NULL) return 0;
124 fprintf(logf, "Q\n");
125 return 1;
126 }
127