1 /*
2 ATP QWK MAIL READER FOR READING AND REPLYING TO QWK MAIL PACKETS.
3 Copyright (C) 1992, 1993, 1997 Thomas McWilliams
4 Copyright (C) 1990 Rene Cougnenc
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, or (at your option)
9 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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22 makemail.c
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <fcntl.h>
29
30 #include "reader.h"
31 #include "readlib.h"
32 #include "makemail.h"
33 #include "qlib.h"
34 #include "ansi.h"
35
36
37 static FILE *RepMsg;
38
39 /*
40 * Creation du bloc d'entete du fichier message correspondant au serveur
41 * FirstHeader, creates the opening header block for reply packet file.
42 */
43 static void
FirstHeader(void)44 FirstHeader(void)
45 {
46 char Block[BLKSIZE], tbuf[QWK_FIELD_LEN + 1];
47 (void) memcpy(tbuf, CurBoard, field_len); /* Preserve lowercase name for */
48 tbuf[field_len] = NUL_CHAR;
49 (void) strupr(tbuf); /* later use .... */
50 (void) memset(Block, (int) SPC_CHAR, block_SIZE); /* Fill with spaces */
51 str2mem(Block, tbuf); /* Insert BBS name for header */
52 if (fwrite(Block, block_SIZE, one_record, RepMsg) != one_record) {
53 printf("FirstHeader() %s\n", txt[73]);
54 (void) sleep(3);
55 } else
56 fflush(RepMsg); /* Write this block to the file */
57 }
58
59
60 /*
61 * DoRepExport, called by DoRep() to actually write out the reply.
62 */
63 static atp_BOOL_T
DoRepExport(const char * filemsg,const unsigned long MaxChars,const size_t NbBlocs)64 DoRepExport(const char *filemsg, const unsigned long MaxChars, const size_t NbBlocs)
65 {
66 /* only export messages not marked as "killed" */
67 atp_BOOL_T mrep = TRUE;
68 unsigned long lndx;
69 byte *ptr = (byte *) (rbuf + block_SIZE);
70 /* Translate to QWK style "pi" line feed */
71 for (lndx = 0L; lndx < MaxChars; lndx++, ptr++) { /*@-strictops */
72 if (*ptr == (byte)'\n')
73 *ptr = QWK_LINE_FEED;
74 else if (*ptr == DOS_SPACE) /*@=strictops */
75 *ptr = SPC_CHAR;
76 }
77 if (fwrite(rbuf, block_SIZE, NbBlocs + 1, RepMsg) != NbBlocs + 1) {
78 /* "error writing file " */
79 printf("%s %s\n", txt[73], filemsg);
80 mrep = FALSE;
81 }
82 return mrep;
83 }
84
85 static FILE *MsgFile, *IdxFile;
86 static char MessageFile[MAXPATHS];
87
88 /*
89 * DoRepFill, load message into rbuf buffer and process.
90 *
91 * Note: Either a message will be skipped or packed in one atomic operation.
92 * The only time count will be -1 is if there is some failure
93 * in exporting a message that is marked for export.
94 */
95 ATP_INLINE int
DoRepFill(const char * filemsg,const char * msg_total_blocks,const char * export_status)96 DoRepFill(const char *filemsg, const char *msg_total_blocks, const char *export_status)
97 {
98 int count = -1;
99 const size_t text_blocks = (size_t) (atoi(msg_total_blocks) - 1);
100 const unsigned long TextChars = text_blocks * block_SIZE;
101 const unsigned long current_max = (unsigned long) get_RbufSize();
102
103 if (current_max <= TextChars && !reup((size_t) TextChars + block_SIZE)) {
104 /* message too big */
105 printf("%s\n%s %lu\n", txt[1], txt[72], TextChars);
106 } else if (TextChars && fread(rbuf + header_SIZE, block_SIZE, text_blocks, MsgFile) != text_blocks) {
107 /* error reading file */
108 printf("max char %lu\n%s %s\n", TextChars, txt[58], MessageFile);
109 /*@-strictops */
110 } else if ((byte) (*export_status) > HIGH_ASCII) {
111 count = 0; /* message skipped */
112 } else if (DoRepExport(filemsg, TextChars, text_blocks))
113 count = 1; /* message exported */
114
115 assert(-1 <= count && count <= 1);
116 return count;
117 }
118
119
120 /*
121 * DoRep, reads from reply conference then writes to messages.rep.
122 *
123 * Note: There are two ways to exit from the do loop. The first is if a
124 * call to DoRepFill fails (result code of -1). The second is if fread()
125 * fails (which is presumed to indicate that we are at the end of the
126 * replies file). This function should return TRUE if export count is at
127 * least 1, and result is not an error (-1);
128 */
129
130 static atp_BOOL_T
DoRep(const char * filemsg)131 DoRep(const char *filemsg)
132 {
133 int count = 0, result = -1;
134 atp_BOOL_T mrep = FALSE;
135 char Qmail[HDRSIZE];
136
137 do {
138
139 if ((fread(Qmail, header_SIZE, one_record, MsgFile)) == one_record) {
140 (void) memcpy(rbuf, Qmail, block_SIZE);
141 result = DoRepFill(filemsg, Qmail + HSizeMsg, Qmail + HStatus);
142 count += result;
143 } else
144 break;
145
146 } while (0 <= result);
147
148 if (count != 0 && result != -1)
149 mrep = TRUE; /* no errors and at least one reply exported */
150 return mrep;
151 }
152
153
154 /*
155 * Cnf2Msg - convert reply ".cnf" file into ".msg" file for export.
156 *
157 */
158 atp_BOOL_T
Cnf2Msg(const char * filemsg)159 Cnf2Msg(const char *filemsg)
160 {
161 atp_BOOL_T mrep = FALSE;
162
163 /* Open MsgFile and IdxFile */
164 if (OpenRepFile(pack_them)) {
165 if ((RepMsg = fopen(filemsg, "wb")) == NULL) {
166 /* "unable to open file" */
167 fprintf(stderr, "%s %s\n", txt[51], filemsg);
168 perror("Does 'workpath' specified in atprc exist? ");
169 } else {
170 FirstHeader();
171 /* copy .cnf to messpath */
172 rewind(MsgFile);
173 mrep = DoRep(filemsg);
174 fclose(RepMsg);
175 if (!mrep)
176 do_unlink(filemsg);
177 }
178 /* close message path */
179 fclose(MsgFile);
180 fclose(IdxFile);
181 }
182 return mrep;
183 }
184
185
186 /*
187 * display_ORF_result, prints result message for OpenRepFile.
188 */
189 ATP_INLINE void
display_ORF_result(atp_BOOL_T ret_code,pakrep_t mode,atp_BOOL_T FileExist)190 display_ORF_result(atp_BOOL_T ret_code, pakrep_t mode, atp_BOOL_T FileExist)
191 {
192 if (!ret_code) {
193 /* "unable to open file" */
194 printf("%s %s\n", txt[51], MessageFile); /*@-strictops */
195 } else if (mode == add_reply) { /*@=strictops */
196 if (FileExist)
197 /* "Adding message to file" */
198 printf("%s %s \n", txt[76], MessageFile);
199 else
200 /* "creating file" */
201 printf("%s %s \n", txt[77], MessageFile);
202 }
203 }
204
205 static char IndexFile[MAXPATHS];
206
207 /*
208 * Ouverture ou creation du fichier messages.
209 * OpenRepFile - open or create the message file for replies.
210 */
211 atp_BOOL_T
OpenRepFile(const pakrep_t mode)212 OpenRepFile(const pakrep_t mode)
213 {
214 atp_BOOL_T FileExist = FALSE, ret_code = TRUE;
215
216 /* valid modes are "pack_them" and "add_reply" */ /*@-strictops */
217 assert(mode == pack_them || mode == add_reply); /*@=strictops */
218 make_c_i_paths(MessageFile, IndexFile, REPL_CONF);
219
220 if (access(MessageFile, F_OK) == SUCCESS)
221 FileExist = TRUE;
222
223 /* see if rep file exists and it is open */
224 if (FileExist && get_saved_conf() == RCONF_IDX) {
225 MsgFile = fmsg;
226 IdxFile = fidx; /*@-strictops */
227 assert(MsgFile != NULL && IdxFile != NULL);
228 } else if (OpenCon(&MsgFile, NULL, MessageFile) == ATP_ERROR
229 || OpenCon(&IdxFile, &MsgFile, IndexFile) == ATP_ERROR) { /*@=strictops */
230 ret_code = FALSE;
231 }
232 display_ORF_result(ret_code, mode, FileExist);
233 return ret_code;
234 }
235
236
237 /***** begin KodeMessage routines *****/
238
239 /*
240 * KodeSubj, handle PCBoard style long subjects lines in replies.
241 * Note that sprintf() returns a char pointer under SunOS but
242 * an integer under POSIX. Therefore for portability, char_cnt
243 * must be calculated in a separate operation.
244 */
245 static size_t
KodeSubj(char CONSPTR tampbuf)246 KodeSubj(char CONSPTR tampbuf)
247 {
248 size_t text_start_offset = 0;
249 char *long_subj = NULL ;
250
251 /* if a long subject line was entered, format it PCBoard style */
252 if (PCBLONG && (long_subj = get_reply_lsubj()) != NULL) {
253 byte CONSPTR net_flag = (byte *) tampbuf;
254 char *buf_ptr = tampbuf;
255 size_t char_cnt;
256
257 /* write head string and subject to reply buffer */
258 sprintf(tampbuf, "%s%s", LSUBJ_HEAD, long_subj);
259 free_string(long_subj);
260
261 /* guarantee temination before taking length */
262 tampbuf[LSUBJ_HEAD_LEN + LSUBJ_BODY_LEN] = NUL_CHAR;
263 char_cnt = strlen(tampbuf);
264 buf_ptr += char_cnt;
265
266 /* adjust for FIDO network if needed */
267 *net_flag = (byte) (fido ? SPC_CHAR : DOS_SPACE);
268
269 /* pad message with space characters */
270 while (char_cnt < (size_t)(LSUBJ_HEAD_LEN + LSUBJ_LEN)) {
271 *buf_ptr++ = SPC_CHAR;
272 char_cnt++;
273 }
274 #ifdef ATPDBG
275 assert((STRING_LEN(LSUBJ_HEAD) + STRING_LEN(LSUBJ_TAIL) + LSUBJ_LEN) == LSUBJ_BUF_LEN);
276 assert(STRING_LEN(LSUBJ_HEAD) == 10);
277 assert(STRING_LEN(LSUBJ_TAIL) == 8);
278 assert(buf_ptr == (tampbuf + 64));
279 #endif
280 strcpy(buf_ptr, LSUBJ_TAIL);
281 strcat(buf_ptr, "\n");
282 text_start_offset = strlen(tampbuf);
283 assert( text_start_offset == (LSUBJ_BUF_LEN + STRING_LEN("\n")));
284 }
285 return text_start_offset;
286 }
287
288 static size_t CountBlocks;
289 static size_t CountTotalChars;
290 static size_t CountRecordChars;
291 static char *tampon, *tamp;
292
293 /*
294 * KodeMsgTag, add the tagline to the reply message.
295 */
296 static void
KodeMsgTag(void)297 KodeMsgTag(void)
298 {
299 /*@only@*/ byte CONSPTR base_ptr = get_CurTag();
300
301 if (base_ptr != NULL) {
302 const byte *ptr = base_ptr;
303 const atp_CODE_T chrset = get_charset();
304
305 /*@-strictops */
306 while (*ptr != (byte) NUL_CHAR) {
307 if (chrset == ISOLAT1) /*@=strictops */
308 /* translate ISO Latin1 to DOS chars */
309 *tamp = codepc[(unsigned) *ptr];
310 else
311 *tamp = *ptr;
312 tamp++;
313 ptr++;
314 CountRecordChars++;
315 CountTotalChars++;
316 if (CountRecordChars > block_SIZE) {
317 CountBlocks++;
318 CountRecordChars = 1;
319 }
320 }
321 free_string((char *) base_ptr);
322 }
323 }
324
325 /*
326 * KodeMsgFin, finish up by adding tagine and padding out last block
327 */
328 static void
KodeMsgFin(char * Qmail)329 KodeMsgFin(char *Qmail)
330 {
331
332 /* Add the the tagline. Rajout de la signature du programme */
333 if (get_tag_flag())
334 KodeMsgTag();
335
336 /* Ajuste la taille du dernier bloc � 128 octets */
337 /* Adjust the size of the last block to 128 bytes */
338 while (CountRecordChars < block_SIZE) {
339 *tamp = SPC_CHAR;
340 tamp++;
341 CountRecordChars++;
342 CountTotalChars++;
343 }
344
345 /* Inscrit dans le Header le nombre blocs de 128 octets */
346 /* Inscribe in the header the number of 128 byte blocks */
347 {
348 char tmp[20];
349 sprintf(tmp, "%lu", (unsigned long) CountBlocks);
350 str2mem(Qmail + HSizeMsg, tmp);
351 }
352 }
353
354 /*
355 * KodeXlat, translate the message from host to MSDOS character set.
356 */
357 static void
KodeXlat(FILE * TmpaFile)358 KodeXlat(FILE * TmpaFile)
359 {
360 byte ch;
361 unsigned LinCt = 0; /* counts line length */
362 const atp_CODE_T chrset = get_charset();
363 rewind(TmpaFile);
364 while (fread(&ch, (size_t)1, one_record, TmpaFile) == one_record) {
365 if (LinCt >= REPLY_LINE_LEN)
366 ch = '\n';
367 /*@-strictops */ /*@-usedef */
368 LinCt = (ch == (byte)'\n') ? 0 : LinCt + 1; /*@=usedef */
369
370 if (chrset == ISOLAT1 && ch >= HIGH_ASCII)
371 ch = codepc[(unsigned)ch]; /* translate back to DOS set */
372 ch = (byte)((ch == DOS_SPACE || ch == (byte)CNTRL_Z) ? SPC_CHAR : ch);
373
374 /* skip ^M carriage returns */
375 if (ch != (byte)CR) { /*@=strictops */
376 *tamp = ch;
377 tamp++;
378 CountRecordChars++;
379 CountTotalChars++;
380 if (CountRecordChars > block_SIZE) {
381 CountBlocks++;
382 CountRecordChars = 1;
383 }
384 }
385 }
386 }
387
388
389 /* Ecrit les fichiers conf et index.
390 * KodeWrite, write out newly encoded message and update .cnf and idx files.
391 */
392 static void
KodeWrite(char * Qmail,long klast)393 KodeWrite(char *Qmail, long klast)
394 {
395 /* Ecrit l'entete du message, suivi du message */
396 /* Write the reply header followed by the reply itself */
397
398 printf("%s...\n", txt[75]); /* "sauvegarde du message" */
399 rewind(MsgFile);
400 fseek(MsgFile, 0L, SEEK_END);
401 if (fwrite(Qmail, header_SIZE, one_record, MsgFile) != one_record ||
402 fwrite(tampon, CountTotalChars, one_record, MsgFile) != one_record) {
403 printf("KodeWrite() %s\n", txt[73]);
404 (void) sleep(3);
405 } else {
406 fflush(MsgFile);
407
408 /* Update the index */
409
410 fseek(IdxFile, 0L, SEEK_END); /*@-strictops */
411 if (WriteIndex(IdxFile, (long) (ftell(IdxFile) / IDXSIZE), (block_SIZE * (CountBlocks - 1)), klast) == ATP_OK) /*@=strictops */
412 fflush(IdxFile);
413 }
414 }
415
416
417 /*
418 * KodeXlatFin, clean up the tail end of the message.
419 */
420 static void
KodeXlatFin(void)421 KodeXlatFin(void)
422 {
423 /* point to last character */
424 if (tamp > tampon)
425 tamp--;
426
427 /* guarantee a non-empty message */
428 if (CountTotalChars == (size_t) 0 || (CountTotalChars == (size_t) 1 && /*@i@*/ *tampon == '\n')) {
429 assert(tamp == tampon);
430 *tamp = SPC_CHAR;
431 CountTotalChars = CountRecordChars = (size_t) 1;
432 }
433 /*@-strictops */
434 if (*tamp != '\n') { /*@=strictops */
435 tamp++;
436 CountRecordChars++;
437 CountTotalChars++;
438 }
439 /* mark end of text proper */
440 *tamp = DOS_SPACE;
441 tamp++;
442 if (CountRecordChars > block_SIZE) {
443 CountBlocks++;
444 CountRecordChars = 1;
445 }
446 }
447
448
449 /*
450 * KodeDoFin, finish up and close files for KodeDo().
451 */
452 static void
KodeDoFin(long ksave_cnf,long ksave_idx)453 KodeDoFin(long ksave_cnf, long ksave_idx)
454 {
455 if (get_saved_conf() == RCONF_IDX) {
456 fseek(fmsg, ksave_cnf, SEEK_SET);
457 fseek(fidx, ksave_idx, SEEK_SET);
458 } else {
459 fclose(MsgFile);
460 fclose(IdxFile);
461 }
462 /* update list of active conferences */
463 ActvConf();
464 }
465
466
467 /* Codage du message dans le tampon.
468 * KodeDo, encode the reply with QWK standard characters.
469 */
470 static void
KodeDo(FILE * TmpaFile,char * Qmail)471 KodeDo(FILE * TmpaFile, char *Qmail)
472 {
473 long int klast, ksavec = 0L, ksavei = 0L;
474 CountBlocks = 2;
475
476 /* if we are already in the Reply Conference, save position */
477 if ( get_saved_conf() == RCONF_IDX) {
478 ksavec = ftell(fmsg);
479 ksavei = ftell(fidx);
480 }
481 /* determine size of MsgFile */
482 fseek(MsgFile, 0L, SEEK_END);
483 klast = ftell(MsgFile);
484
485 /* handle PCBoard long subjects */
486 CountTotalChars = CountRecordChars = KodeSubj(tampon);
487 tamp = tampon + CountRecordChars;
488
489 /* translate the message from host to MSDOS character set */
490 KodeXlat(TmpaFile);
491
492 /* clean-up the tail end of the message */
493 KodeXlatFin();
494
495 /* apend tagline and finish up */
496 KodeMsgFin(Qmail);
497
498 /* write out and update cnf and idx files */
499 KodeWrite(Qmail, klast);
500
501 /* Close and erase the work file */
502 KodeDoFin(ksavec,ksavei);
503 }
504
505 /*
506 * Ecriture du message proprement dit, cod� selon le format PcBoard, c.a.d les cr/lf remplac�s par '\343'
507 *
508 * KodeMessage - encodes reply in PcBoard/QWK format.
509 * note: CR/LF are replaced with '\343', the DOS "pi" character.
510 */
511 atp_ERROR_T
KodeMessage(const char * fname,char * Qmail)512 KodeMessage(const char *fname, char *Qmail)
513 {
514 atp_ERROR_T ret_code = ATP_ERROR;
515 FILE *TmpaFile;
516
517 /* Ouvre le fichier cr�� par l'�diteur */
518 /* Open the reply file created by the editor */
519
520 if ((TmpaFile = fopen(fname, "r")) == NULL) {
521 printf("%s %s\n", txt[51], fname); /* "unable to open file" */
522 } else {
523 long int repsize;
524 fseek(TmpaFile, 0L, SEEK_END);
525 if ((repsize = ftell(TmpaFile)) >= 0L) {
526 const size_t tampon_size = (size_t)(repsize+1024L); /* !! why the 1024L? */
527 if (repsize > (long) (MAXSEND - 256)) {
528 printf("\nERROR: Reply file exceeds %lu bytes%c\n", (unsigned long) MAXSEND, BELL);
529 fclose(MsgFile);
530 } else if ((tampon = (char *) malloc(tampon_size)) == NULL) {
531 printf("%s\n", txt[1]); /* memory allocation error */
532 fclose(MsgFile);
533 } else {
534 KodeDo(TmpaFile, Qmail);
535 ret_code = ATP_OK;
536 free_buffer(tampon, tampon_size);
537 tampon = NULL;
538 }
539 }
540 fclose(TmpaFile);
541 }
542 return ret_code;
543 }
544 /***** end of KodeMessage routines *****/
545
546 /*
547 * codepc - table converts a LINUX screen code to an MS-DOS screen code.
548 */
549 const unsigned char codepc[] =
550 {
551
552 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
553 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
554 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
555 0x18, 0x19, 0x20, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
556 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
557 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
558 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
559 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
560 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
561 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
562 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
563 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
564 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
565 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
566 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
567 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
568
569 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 87 */
570 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 8f */
571 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 97 */
572 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 9f */
573 0x20, 0xad, 0x9b, 0x9c, 0xfe, 0x9d, 0x7c, 0xfe, /* a7 */
574 0xfe, 0xfe, 0xa6, 0xae, 0xaa, 0x2d, 0xfe, 0xfe, /* af */
575 0xf8, 0xf1, 0xfd, 0xfe, 0xfe, 0xe6, 0xfe, 0xf9, /* b7 */
576 0xfe, 0xfe, 0x97, 0xaf, 0xac, 0xab, 0xfe, 0xa8, /* bf */
577 0xfe, 0xfe, 0xfe, 0xfe, 0x8e, 0x8f, 0x92, 0x80, /* c7 */
578 0xfe, 0x90, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* cf */
579 0xfe, 0xa5, 0xfe, 0xfe, 0xfe, 0xfe, 0x99, 0xfe, /* d7 */
580 0xfe, 0xfe, 0xfe, 0xfe, 0x9a, 0xfe, 0xfe, 0xe1, /* df */
581 0x85, 0xa0, 0x83, 0xfe, 0x84, 0x86, 0x91, 0x87, /* e7 */
582 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b, /* ef */
583 0xfe, 0xa4, 0x95, 0xa2, 0x93, 0xfe, 0x94, 0xf6, /* f7 */
584 0xfe, 0x97, 0xa3, 0x96, 0x81, 0xfe, 0xfe, 0x98};
585
586
587 /*
588 * codelu - table converts an MS_DOS screen code to a LINUX screen code.
589 */
590 const unsigned char codelu[] =
591 {
592
593 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
594 0x20, 0x09, 0x0a, 0x20, 0x20, 0x0d, 0x20, 0x20,
595 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
596 0x20, 0x20, 0x20, 0x1b, 0x20, 0x20, 0x20, 0x20,
597 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
598 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
599 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
600 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
601 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
602 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
603 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
604 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
605 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
606 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
607 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
608 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7e,
609
610 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7, /* 87 */
611 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5, /* 8f */
612 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9, /* 97 */
613 0xff, 0xd6, 0xdc, 0xa2, 0xa3, 0xa5, 0x50, 0x66, /* 9f */
614 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba, /* a7 */
615 0xbf, 0xad, 0xac, 0xbd, 0xbc, 0xa1, 0xab, 0xbb, /* af */
616 0xfe, 0xfe, 0xfe, 0xa6, 0xa6, 0xa6, 0xa6, 0xfe, /* b7 */
617 0xfe, 0xa6, 0xa6, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* bf */
618 0xfe, 0xad, 0xad, 0xa6, 0xad, 0x2b, 0xa6, 0xa6, /* c7 */
619 0xfe, 0xfe, 0xad, 0xad, 0xa6, 0xad, 0x2b, 0xad, /* cf */
620 0xad, 0xad, 0xad, 0xfe, 0xfe, 0xfe, 0xfe, 0x2b, /* d7 */
621 0x2b, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* df */
622 0xa3, 0xdf, 0xfe, 0xfe, 0x53, 0x73, 0xb5, 0x74, /* e7 */
623 0xa7, 0x4f, 0x4f, 0x64, 0xad, 0x6f, 0xc6, 0xfe, /* ef */
624 0xad, 0xb1, 0xfe, 0xfe, 0xa6, 0xa6, 0xf7, 0x7e, /* f7 */
625 0xb0, 0xb7, 0xb7, 0x76, 0x6e, 0xb2, 0xfe, 0x20};
626
627
628 /*
629 * codevt - table generates MS_DOS line characters with VT102 codes.
630 */
631 const unsigned char codevt[] =
632 {
633 /* dummy 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
634 /* dummy 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
635 /* dummy 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
636 /* dummy 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
637 /* dummy 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
638 /* dummy 5 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
639 /* dummy 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
640 /* dummy 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
641 /* dummy 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
642 /* dummy 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
643 /* dummy a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
644 /* 0xb0 */ 'a', 'a', 'a', 'x', 'u', 'u', 'u', 'k',
645 /* 0xb8 */ 'k', 'u', 'x', 'k', 'j', 'j', 'j', 'k',
646 /* 0xc0 */ 'm', 'v', 'w', 't', 'q', 'n', 't', 't',
647 /* 0xc8 */ 'm', 'l', 'v', 'w', 't', 'q', 'n', 'v',
648 /* 0xd0 */ 'v', 'w', 'w', 'm', 'm', 'l', 'l', 'n',
649 /* 0xd8 */ 'n', 'j', 'l', 'a', 'a', 'a', 'a', 'a'};
650
651
652 /*
653 * code7bit - table maps 8 bit MS_DOS codes to a 7bit approximation.
654 */
655 const unsigned char code7bit[] =
656 {
657
658 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
659 0x20, 0x09, 0x0a, 0x20, 0x20, 0x0d, 0x20, 0x20,
660 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
661 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
662 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
663 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
664 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
665 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
666 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
667 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
668 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
669 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
670 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
671 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
672 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
673 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
674
675 /* 80 */ 'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c',
676 /* 88 */ 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A',
677 /* 90 */ 'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u',
678 /* 98 */ 'y', 'O', 'U', 'c', 'L', 'v', 'P', 'f',
679 /* a0 */ 'a', 'i', 'o', 'u', 'n', 'N', 'a', 'o',
680 /* a8 */ '?', '~', '~', '-', '-', '!', '<', '>',
681 /* b0 */ '#', '#', '#', '|', '+', '+', '+', '+',
682 /* b8 */ '+', '+', '|', '+', '+', '+', '+', '+',
683 /* c0 */ '+', '+', '+', '+', '-', '+', '+', '+',
684 /* c8 */ '+', '+', '+', '+', '+', '-', '+', '+',
685 /* d0 */ '+', '+', '+', '+', '+', '+', '+', '+',
686 /* d8 */ '+', '+', '+', '#', '#', '#', '#', '#',
687 /* e0 */ '8', 'B', 'G', 'p', 'S', 's', 'm', 't',
688 /* e8 */ 'o', 'O', 'O', 'd', '8', 'o', 'E', '-',
689 /* f0 */ '=', '#', '<', '>', '|', '|', '/', '=',
690 /* f8 */ 'o', 'o', '.', 'v', 'n', '2', '*', ' '};
691
692 /* end of makemail.c */
693