1 /*
2 etterfilter -- the actual compiler
3
4 Copyright (C) ALoR & NaGA
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22 #include <ef.h>
23 #include <ef_functions.h>
24 #include <ec_filter.h>
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29
30
31 /* protos */
32
33 static void print_progress_bar(struct filter_op *fop);
34 static size_t create_data_segment(u_char **data, struct filter_header *fh, struct filter_op *fop, size_t n);
35 static size_t add_data_segment(u_char **data, size_t base, u_char **string, size_t slen);
36
37 /*******************************************/
38
write_output(void)39 int write_output(void)
40 {
41 int fd;
42 struct filter_op *fop;
43 struct filter_header fh;
44 size_t ninst, i, data_len;
45 u_char pad = 0, *data = NULL;
46
47 /* conver the tree to an array of filter_op */
48 ninst = compile_tree(&fop);
49
50 if (fop == NULL)
51 return -E_NOTHANDLED;
52
53 if (ninst == 0)
54 return -E_INVALID;
55
56 /* create the file */
57 fd = open(EF_GBL_OPTIONS->output_file, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0644);
58 ON_ERROR(fd, -1, "Can't create file %s", EF_GBL_OPTIONS->output_file);
59
60 /* display the message */
61 USER_MSG(" Writing output to \'%s\' ", EF_GBL_OPTIONS->output_file);
62
63 /* compute the header */
64 fh.magic = htons(EC_FILTER_MAGIC);
65 strncpy(fh.version, EC_VERSION, sizeof(fh.version));
66 fh.data = sizeof(fh);
67
68 data_len = create_data_segment(&data, &fh, fop, ninst);
69
70 /* write the header */
71 write(fd, &fh, sizeof(struct filter_header));
72
73 /* write the data segment */
74 write(fd, data, data_len);
75
76 /* write padding to next 8-byte boundary */
77 for (i = 0; i < fh.code - (fh.data + data_len); i++)
78 write(fd, &pad, 1);
79
80 /* write the instructions */
81 for (i = 0; i < ninst; i++) {
82 print_progress_bar(&fop[i]);
83 write(fd, &fop[i], sizeof(struct filter_op));
84 }
85
86 close(fd);
87
88 USER_MSG(" done.\n\n");
89
90 USER_MSG(" -> Script encoded into %d instructions.\n\n", (int)(i - 1));
91
92 return E_SUCCESS;
93 }
94
95 /*
96 * creates the data segment into an byte array supplied as argument data
97 * and update the file header instruction pointer 8-byte aligned
98 *
99 * returns length of the data segment
100 */
create_data_segment(u_char ** data,struct filter_header * fh,struct filter_op * fop,size_t n)101 static size_t create_data_segment(u_char** data, struct filter_header *fh, struct filter_op *fop, size_t n)
102 {
103 size_t i, len = 0;
104
105 for (i = 0; i < n; i++) {
106
107 switch(fop[i].opcode) {
108 case FOP_FUNC:
109 if (fop[i].op.func.slen) {
110 ef_debug(1, "@");
111 len += add_data_segment(data, len, &fop[i].op.func.string, fop[i].op.func.slen);
112 }
113 if (fop[i].op.func.rlen) {
114 ef_debug(1, "@");
115 len += add_data_segment(data, len, &fop[i].op.func.replace, fop[i].op.func.rlen);
116 }
117 break;
118
119 case FOP_TEST:
120 if (fop[i].op.test.slen) {
121 ef_debug(1, "@");
122 len += add_data_segment(data, len, &fop[i].op.test.string, fop[i].op.test.slen);
123 }
124 break;
125
126 case FOP_ASSIGN:
127 if (fop[i].op.assign.slen) {
128 ef_debug(1, "@");
129 len += add_data_segment(data, len, &fop[i].op.test.string, fop[i].op.test.slen);
130 }
131 break;
132 }
133
134 }
135
136 /* where starts the code ? */
137 fh->code = fh->data + len;
138 /* 8-byte aligned please */
139 if (fh->code % 8)
140 fh->code += 8 - fh->code % 8;
141
142
143 return len;
144 }
145
146
147 /*
148 * add a string to the buffer
149 */
add_data_segment(u_char ** data,size_t base,u_char ** string,size_t slen)150 static size_t add_data_segment(u_char **data, size_t base, u_char **string, size_t slen)
151 {
152 /* make room for the new string */
153 SAFE_REALLOC(*data, base + slen + 1);
154
155 /* copy the string, NULL separated */
156 memcpy(*data + base, *string, slen + 1);
157
158 /*
159 * change the pointer to the new string location
160 * it is an offset from the base of the data segment
161 */
162 *string = (u_char *)base;
163
164 /* retur the len of the added string */
165 return slen + 1;
166 }
167
168 /*
169 * prints a differnt sign for every different instruction
170 */
print_progress_bar(struct filter_op * fop)171 static void print_progress_bar(struct filter_op *fop)
172 {
173 switch(fop->opcode) {
174 case FOP_EXIT:
175 ef_debug(1, "!");
176 break;
177 case FOP_TEST:
178 ef_debug(1, "?");
179 break;
180 case FOP_ASSIGN:
181 ef_debug(1, "=");
182 break;
183 case FOP_FUNC:
184 ef_debug(1, ".");
185 break;
186 case FOP_JMP:
187 ef_debug(1, ":");
188 break;
189 case FOP_JTRUE:
190 case FOP_JFALSE:
191 ef_debug(1, ";");
192 break;
193 }
194 }
195
196 /* EOF */
197
198 // vim:ts=3:expandtab
199
200