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