Merge branch 'dbmjz'
[exim.git] / test / src / mtpscript.c
CommitLineData
c55a77db
PH
1/* A little hacked up program that allows a script to play the part of a remote
2SMTP/LMTP server on stdin/stdout for testing purposes. Hacked from the more
3complicated version that does it over a socket. */
4
5
6/* ANSI C standard includes */
7
8#include <ctype.h>
9#include <signal.h>
10#include <stdarg.h>
11#include <stddef.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <time.h>
16
17/* Unix includes */
18
19#include <errno.h>
20#include <unistd.h>
21
22
23static FILE *log;
24
25
26/*************************************************
27* SIGALRM handler - crash out *
28*************************************************/
29
30static void
31sigalrm_handler(int sig)
32{
33sig = sig; /* Keep picky compilers happy */
34fprintf(log, "Server timed out\n");
35exit(99);
36}
37
38
39
40/*************************************************
41* Main Program *
42*************************************************/
43
44int main(int argc, char **argv)
45{
46char *logfile;
47char *logmode = "w";
48FILE *script;
49unsigned char sbuffer[1024];
50unsigned char ibuffer[1024];
51
52if (argc < 3)
53 {
54 fprintf(stdout, "500 Script and log file required\n");
55 exit(1);
56 }
57
58/* Get the script and log open */
59
60script = fopen(argv[1], "r");
61if (script == NULL)
62 {
63 fprintf(stdout, "500 Failed to open script %s: %s\r\n", argv[1],
64 strerror(errno));
65 exit(1);
66 }
67
68logfile = argv[2];
69if (logfile[0] == '+')
70 {
71 logfile++;
72 logmode = "a";
73 }
74
75log = fopen(logfile, logmode);
76if (log == NULL)
77 {
78 fprintf(stdout, "500 Failed to open log %s: %s\r\n", logfile,
79 strerror(errno));
80 exit(1);
81 }
82
83/* SIGALRM handler crashes out */
84
85signal(SIGALRM, sigalrm_handler);
86
87/* Read the script, and do what it says. */
88
89while (fgets(sbuffer, sizeof(sbuffer), script) != NULL)
90 {
91 int n = (int)strlen(sbuffer);
92 while (n > 0 && isspace(sbuffer[n-1])) n--;
93 sbuffer[n] = 0;
94
95 /* If the script line starts with a digit, it is a response line which
96 we are to send. */
97
98 if (isdigit(sbuffer[0]))
99 {
100 fprintf(log, "%s\n", sbuffer);
101 fflush(log);
102 fprintf(stdout, "%s\r\n", sbuffer);
103 fflush(stdout);
104 }
105
106 /* If the script line starts with "*sleep" we just sleep for a while
107 before continuing. Do not write this to the log, as it may not get
108 written at the right place in a log that's being shared. */
109
110 else if (strncmp(sbuffer, "*sleep ", 7) == 0)
111 {
112 sleep(atoi(sbuffer+7));
113 }
114
115 /* Otherwise the script line is the start of an input line we are expecting
116 from the client, or "*eof" indicating we expect the client to close the
117 connection. Read command line or data lines; the latter are indicated
118 by the expected line being just ".". */
119
120 else
121 {
122 int data = strcmp(sbuffer, ".") == 0;
123
124 fprintf(log, "%s\n", sbuffer);
125 fflush(log);
126
127 /* Loop for multiple data lines */
128
129 for (;;)
130 {
131 int n;
132 alarm(5);
133 if (fgets(ibuffer, sizeof(ibuffer), stdin) == NULL)
134 {
135 fprintf(log, "%sxpected EOF read from client\n",
136 (strncmp(sbuffer, "*eof", 4) == 0)? "E" : "Une");
137 goto END_OFF;
138 }
139 alarm(0);
140 n = (int)strlen(ibuffer);
141 while (n > 0 && isspace(ibuffer[n-1])) n--;
142 ibuffer[n] = 0;
143 fprintf(log, "<<< %s\n", ibuffer);
144 if (!data || strcmp(ibuffer, ".") == 0) break;
145 }
146
147 /* Check received what was expected */
148
149 if (strncmp(sbuffer, ibuffer, (int)strlen(sbuffer)) != 0)
150 {
151 fprintf(log, "Comparison failed - bailing out\n");
152 goto END_OFF;
153 }
154 }
155 }
156
157/* This could appear in the wrong place in a shared log, so forgo it. */
158/* fprintf(log, "End of script\n"); */
159
160END_OFF:
161fclose(script);
162fclose(log);
163
164exit(0);
165}
166
167/* End of mtpscript.c */