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