1 /*
2 * This file is part of uudeview, the simple and friendly multi-part multi-
3 * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may
4 * be contacted at fp@fpx.de
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
17 /*
18 * The TCL Interface of UUDeview
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #if defined(HAVE_TCL) || defined(HAVE_TK)
26
27 #ifdef SYSTEM_WINDLL
28 #include <windows.h>
29 #endif
30 #ifdef SYSTEM_OS2
31 #include <os2.h>
32 #endif
33
34 #ifdef STDC_HEADERS
35 #include <stdlib.h>
36 #include <string.h>
37 #endif
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41 #ifdef HAVE_ERRNO_H
42 #include <errno.h>
43 #endif
44
45 #ifdef HAVE_TK
46 #include <tk.h>
47 #else
48 #include <tcl.h>
49 #endif
50
51 /*
52 * The following variable is a special hack that is needed in order for
53 * Sun shared libraries to be used for Tcl.
54 */
55
56 extern int matherr();
57 int *tclDummyMathPtr = (int *) matherr;
58
59 #include <uudeview.h>
60 #include <uuint.h>
61 #include <fptools.h>
62
63 /*
64 * As Windows DLL, we need a DllEntryPoint
65 */
66
67 #ifdef SYSTEM_WINDLL
68 BOOL _export WINAPI
DllEntryPoint(HINSTANCE hInstance,DWORD seginfo,LPVOID lpCmdLine)69 DllEntryPoint (HINSTANCE hInstance, DWORD seginfo,
70 LPVOID lpCmdLine)
71 {
72 /* Don't do anything, so just return true */
73 return TRUE;
74 }
75 #endif
76
77 /*
78 * Declare external functions as __cdecl for Watcom C
79 */
80
81 #ifdef __WATCOMC__
82 #pragma aux (__cdecl) Tcl_Eval
83 #pragma aux (__cdecl) Tcl_GetVar
84 #pragma aux (__cdecl) Tcl_SetVar
85 #pragma aux (__cdecl) Tcl_AppendResult
86 #pragma aux (__cdecl) Tcl_SetResult
87 #pragma aux (__cdecl) Tcl_CreateCommand
88 #endif
89
90 /*
91 * cvs version
92 */
93 char * uutcl_id = "$Id: uutcl.c,v 1.14 2002/03/06 13:52:45 fp Exp $";
94
95 /*
96 * data for our Callbacks
97 */
98
99 static struct uutclcbdata {
100 Tcl_Interp *interp;
101 char tclproc[256];
102 } theDMcbdata, theBusycbdata;
103
104 /*
105 * Don't let Uu_Init initialize us twice
106 */
107
108 static int uu_AlreadyInitialized = 0;
109
110 /*
111 * mail and news software
112 */
113
114 #ifdef PROG_INEWS
115 char * uue_inewsprog = PROG_INEWS;
116 #else
117 char * uue_inewsprog = NULL;
118 #endif
119 #ifdef PROG_MAILER
120 char * uue_mailprog = PROG_MAILER;
121 #else
122 char * uue_mailprog = NULL;
123 #endif
124 #ifdef MAILER_NEEDS_SUBJECT
125 int uue_mpsubject = 1;
126 #else
127 int uue_mpsubject = 0;
128 #endif
129
130 /*
131 * Mail or Post a file. Remember to keep in sync with uuenview.c
132 */
133
134 static int
SendAFile(Tcl_Interp * interp,FILE * infile,char * infname,int encoding,int linperfile,char * outfname,char * towhom,char * subject,char * from,char * replyto,int isemail)135 SendAFile (Tcl_Interp *interp,
136 FILE *infile, char *infname,
137 int encoding, int linperfile,
138 char *outfname, char *towhom,
139 char *subject, char *from,
140 char *replyto, int isemail)
141 {
142 char *command, *rcptlist, *ptr;
143 FILE *thepipe, *theifile;
144 int len, count, res, part;
145
146 if (towhom==NULL ||
147 (outfname==NULL&&infname==NULL) || (infile&&infname==NULL) ||
148 (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&&
149 encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) {
150 Tcl_SetResult (interp, "oops: Parameter check failed in SendAFile()",
151 TCL_STATIC);
152 return UURET_ILLVAL;
153 }
154
155 #ifndef HAVE_POPEN
156 Tcl_SetResult (interp, "error: Your system does not support sending of files",
157 TCL_STATIC);
158 return UURET_ILLVAL;
159 #else
160 if (isemail && (uue_mailprog == NULL || *uue_mailprog == '\0')) {
161 Tcl_SetResult (interp, "error: Cannot Email file: option not configured",
162 TCL_STATIC);
163 return UURET_ILLVAL;
164 }
165 else if (!isemail && (uue_inewsprog == NULL || *uue_inewsprog == '\0')) {
166 Tcl_SetResult (interp, "error: Cannot Post file: option not configured",
167 TCL_STATIC);
168 return UURET_ILLVAL;
169 }
170
171 len = strlen ((isemail)?uue_mailprog:uue_inewsprog) +
172 ((uue_mpsubject)?strlen(subject):0) +
173 ((isemail)?0:strlen(towhom)) + 32;
174
175 if ((command = (char *) malloc (len)) == NULL) {
176 Tcl_SetResult (interp, "error: Out of memory allocating some bytes",
177 TCL_STATIC);
178 return UURET_NOMEM;
179 }
180
181 if ((rcptlist = (char *) malloc (strlen (towhom) + 16)) == NULL) {
182 Tcl_SetResult (interp, "error: Out of memory allocating some bytes",
183 TCL_STATIC);
184 _FP_free (command);
185 return UURET_NOMEM;
186 }
187
188 if (isemail) {
189 if (uue_mpsubject)
190 sprintf (command, "%s -s \"%s\"", uue_mailprog, subject);
191 else
192 sprintf (command, "%s", uue_mailprog);
193
194 /*
195 * Attach list of recipients to mailer command and compose another list
196 * of recipients
197 */
198
199 count = 0;
200 rcptlist[0] = '\0';
201 ptr = _FP_strtok (towhom, ",; ");
202
203 while (ptr) {
204 strcat (command, " ");
205 strcat (command, ptr);
206
207 if (count++)
208 strcat (rcptlist, ",");
209 strcat (rcptlist, ptr);
210
211 ptr = _FP_strtok (NULL, ",; ");
212 }
213 }
214 else {
215 sprintf (command, "%s", uue_inewsprog);
216
217 count = 0;
218 rcptlist[0] = '\0';
219 ptr = _FP_strtok (towhom, ";, ");
220
221 while (ptr) {
222 if (count++)
223 strcat (rcptlist, ",");
224 strcat (rcptlist, ptr);
225 ptr = _FP_strtok (NULL, ";, ");
226 }
227 }
228
229 if (from && *from == '\0') {
230 from = NULL;
231 }
232
233 if (subject && *subject == '\0') {
234 subject = NULL;
235 }
236
237 if (replyto && *replyto == '\0') {
238 replyto = NULL;
239 }
240
241 /*
242 * Get going ...
243 */
244
245 if (infile == NULL) {
246 if ((theifile = fopen (infname, "rb")) == NULL) {
247 _FP_free (rcptlist);
248 _FP_free (command);
249 return UURET_IOERR;
250 }
251 }
252 else {
253 theifile = infile;
254 }
255
256 for (part=1; !feof (theifile); part++) {
257 if ((thepipe = popen (command, "w")) == NULL) {
258 if (infile==NULL) fclose (theifile);
259 _FP_free (rcptlist);
260 _FP_free (command);
261 return UURET_IOERR;
262 }
263
264 if (UUGetOption(UUOPT_VERBOSE, NULL, NULL, 0)) {
265 #if 0
266 fprintf (stderr, "%s part %03d of %s to %s ... ",
267 (isemail)?"mailing":"posting",
268 part, (infname)?infname:outfname,
269 rcptlist);
270 fflush (stderr);
271 #endif
272 }
273
274 res = UUE_PrepPartialExt (thepipe, theifile, infname, encoding,
275 outfname, 0, part, linperfile, 0,
276 rcptlist, from, subject, replyto,
277 isemail);
278
279 #if 0
280 if (UUGetOption (UUOPT_VERBOSE, NULL, NULL, 0)) {
281 if (res == UURET_OK)
282 fprintf (stderr, "ok.\n");
283 else
284 fprintf (stderr, "%s\n", UUstrerror (res));
285 }
286 #endif
287
288 pclose (thepipe);
289
290 if (res != UURET_OK) {
291 if (infile == NULL) fclose (theifile);
292 _FP_free (rcptlist);
293 _FP_free (command);
294 return res;
295 }
296 }
297
298 if (infile == NULL) fclose (theifile);
299 _FP_free (rcptlist);
300 _FP_free (command);
301 return UURET_OK;
302 #endif
303 }
304
305 /*
306 * Display a Message in a dialog box
307 */
308
309 static void
uutcl_DisplayMessage(void * param,char * message,int level)310 uutcl_DisplayMessage (void *param, char *message, int level)
311 {
312 struct uutclcbdata *data = (struct uutclcbdata *) param;
313 char tmpstring[2048];
314
315 if (data->interp && *data->tclproc) {
316 sprintf (tmpstring, "%s %d {%s}\n", data->tclproc, level, message);
317 Tcl_Eval (data->interp, tmpstring);
318 }
319 }
320
321 /*
322 * Our Busy Callback
323 */
324
325 static int
uutcl_BusyCallback(void * param,uuprogress * progress)326 uutcl_BusyCallback (void *param, uuprogress *progress)
327 {
328 struct uutclcbdata *data = (struct uutclcbdata *) param;
329
330 if (data->interp && *data->tclproc) {
331 Tcl_Eval (data->interp, data->tclproc);
332 }
333 return 0;
334 }
335
336 /*
337 * exchage variables with the interpreter
338 */
339
340 static void
uutcl_UpdateParameter(Tcl_Interp * interp)341 uutcl_UpdateParameter (Tcl_Interp *interp)
342 {
343 char *cval;
344
345 if ((cval = Tcl_GetVar (interp, "OptionFast", TCL_GLOBAL_ONLY))!=NULL)
346 UUSetOption (UUOPT_FAST, atoi (cval), NULL);
347 if ((cval = Tcl_GetVar (interp, "OptionBracket", TCL_GLOBAL_ONLY))!=NULL)
348 UUSetOption (UUOPT_BRACKPOL, atoi (cval), NULL);
349 if ((cval = Tcl_GetVar (interp, "OptionDesperate",TCL_GLOBAL_ONLY))!=NULL)
350 UUSetOption (UUOPT_DESPERATE, atoi (cval), NULL);
351 if ((cval = Tcl_GetVar (interp, "OptionDebug", TCL_GLOBAL_ONLY))!=NULL)
352 UUSetOption (UUOPT_DEBUG, atoi (cval), NULL);
353 if ((cval = Tcl_GetVar (interp, "OptionDumbness", TCL_GLOBAL_ONLY))!=NULL)
354 UUSetOption (UUOPT_DUMBNESS, atoi (cval), NULL);
355 if ((cval = Tcl_GetVar (interp, "OptionUsetext", TCL_GLOBAL_ONLY))!=NULL)
356 UUSetOption (UUOPT_USETEXT, atoi (cval), NULL);
357 if ((cval = Tcl_GetVar (interp, "SaveFilePath", TCL_GLOBAL_ONLY))!=NULL)
358 UUSetOption (UUOPT_SAVEPATH, 0, cval);
359 if ((cval = Tcl_GetVar (interp, "OptionRemove", TCL_GLOBAL_ONLY))!=NULL)
360 UUSetOption (UUOPT_REMOVE, atoi (cval), NULL);
361 if ((cval = Tcl_GetVar (interp, "OptionMoreMime", TCL_GLOBAL_ONLY))!=NULL)
362 UUSetOption (UUOPT_MOREMIME, atoi (cval), NULL);
363 }
364
365 /*
366 * configuration info
367 */
368
369 static int
uutcl_HaveArg(int argc,char * argv[],char * string)370 uutcl_HaveArg (int argc, char *argv[], char *string)
371 {
372 int index;
373
374 for (index=1; index<argc; index++) {
375 if (_FP_stricmp (argv[index], string) == 0)
376 return 1;
377 }
378 return 0;
379 }
380
381 static int UUTCLFUNC
uutcl_Info(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])382 uutcl_Info (ClientData clientData, Tcl_Interp *interp,
383 int argc, char *argv[])
384 {
385 char temp[64], version[64];
386
387 if (argc==1 || uutcl_HaveArg (argc, argv, "version")) {
388 UUGetOption (UUOPT_VERSION, NULL, version, 64);
389 sprintf (temp, " { version %s } ", version);
390 Tcl_AppendResult (interp, temp, NULL);
391 }
392 if (argc==1 || uutcl_HaveArg (argc, argv, "have_tcl"))
393 #ifdef HAVE_TCL
394 Tcl_AppendResult (interp, " { have_tcl 1 } ", NULL);
395 #else
396 Tcl_AppendResult (interp, " { have_tcl 0 } ", NULL);
397 #endif
398 if (argc==1 || uutcl_HaveArg (argc, argv, "have_tk"))
399 #ifdef HAVE_TK
400 Tcl_AppendResult (interp, " { have_tk 1 } ", NULL);
401 #else
402 Tcl_AppendResult (interp, " { have_tk 0 } ", NULL);
403 #endif
404 if (argc==1 || uutcl_HaveArg (argc, argv, "have_mail")) {
405 #ifdef PROG_MAILER
406 if (*PROG_MAILER)
407 Tcl_AppendResult (interp, " { have_mail 1 } ", NULL);
408 else
409 Tcl_AppendResult (interp, " { have_mail 0 } ", NULL);
410 #else
411 Tcl_AppendResult (interp, " { have_mail 0 } ", NULL);
412 #endif
413 }
414 if (argc==1 || uutcl_HaveArg (argc, argv, "prog_mailer")) {
415 #ifdef PROG_MAILER
416 sprintf (temp, " { prog_mailer \"%s\" } ", PROG_MAILER);
417 Tcl_AppendResult (interp, temp, NULL);
418 #else
419 Tcl_AppendResult (interp, " { prog_mailer (none) } ", NULL);
420 #endif
421 }
422 if (argc==1 || uutcl_HaveArg (argc, argv, "have_news")) {
423 #ifdef HAVE_NEWS
424 Tcl_AppendResult (interp, " { have_news 1 } ", NULL);
425 #else
426 Tcl_AppendResult (interp, " { have_news 0 } ", NULL);
427 #endif
428 }
429 if (argc==1 || uutcl_HaveArg (argc, argv, "prog_inews")) {
430 #ifdef PROG_INEWS
431 sprintf (temp, " { prog_inews \"%s\" } ", PROG_INEWS);
432 Tcl_AppendResult (interp, temp, NULL);
433 #else
434 Tcl_AppendResult (interp, " { prog_inews (none) } ", NULL);
435 #endif
436 }
437 if (argc==1 || uutcl_HaveArg (argc, argv, "domainname")) {
438 #ifdef DOMAINNAME
439 sprintf (temp, " { domainname %s } ", DOMAINNAME);
440 Tcl_AppendResult (interp, temp, NULL);
441 #else
442 Tcl_AppendResult (interp, " { domainname (none) } ", NULL);
443 #endif
444 }
445 if (argc==1 || uutcl_HaveArg (argc, argv, "nntpserver")) {
446 #ifdef NNTPSERVER
447 sprintf (temp, " { nntpserver %s } ", NNTPSERVER);
448 Tcl_AppendResult (interp, temp, NULL);
449 #else
450 Tcl_AppendResult (interp, " { nntpserver (none) } ", NULL);
451 #endif
452 }
453 if (argc==1 || uutcl_HaveArg (argc, argv, "need_nntpserver")) {
454 #ifdef NEED_NNTPSERVER
455 Tcl_AppendResult (interp, " { need_nntpserver 1 } ", NULL);
456 #else
457 Tcl_AppendResult (interp, " { need_nntpserver 0 } ", NULL);
458 #endif
459 }
460 return TCL_OK;
461 }
462
463 static int UUTCLFUNC
uutcl_SetMessageProc(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])464 uutcl_SetMessageProc (ClientData clientData, Tcl_Interp *interp,
465 int argc, char *argv[])
466 {
467 char tmpstring[256];
468
469 uutcl_UpdateParameter (interp);
470
471 if (argc != 2) {
472 sprintf (tmpstring,
473 "wrong # args: should be \"%s procedure\"",
474 argv[0]);
475 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
476 return TCL_ERROR;
477 }
478
479 theDMcbdata.interp = interp;
480 strcpy (theDMcbdata.tclproc, argv[1]);
481 return TCL_OK;
482 }
483
484 static int UUTCLFUNC
uutcl_SetBusyProc(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])485 uutcl_SetBusyProc (ClientData clientData, Tcl_Interp *interp,
486 int argc, char *argv[])
487 {
488 char tmpstring[256];
489 long msecs;
490
491 uutcl_UpdateParameter (interp);
492
493 if (argc != 3) {
494 sprintf (tmpstring,
495 "wrong # args: should be \"%s procedure msecs\"",
496 argv[0]);
497 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
498 return TCL_ERROR;
499 }
500
501 if ((msecs = (long) atoi (argv[2])) > 0) {
502 UUSetBusyCallback (&theBusycbdata, uutcl_BusyCallback, msecs);
503 }
504
505 theBusycbdata.interp = interp;
506 strcpy (theBusycbdata.tclproc, argv[1]);
507 return TCL_OK;
508 }
509
510 static int UUTCLFUNC
uutcl_GetProgressInfo(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])511 uutcl_GetProgressInfo (ClientData clientData, Tcl_Interp *interp,
512 int argc, char *argv[])
513 {
514 uuprogress progress;
515 char tmpstring[32];
516
517 if (UUGetOption (UUOPT_PROGRESS, NULL,
518 (char *) &progress, sizeof (uuprogress)) != 0) {
519 Tcl_SetResult (interp, "oops, could not get info?", TCL_STATIC);
520 return TCL_ERROR;
521 }
522 sprintf (tmpstring, "%d", progress.action);
523 Tcl_AppendElement (interp, tmpstring);
524
525 Tcl_AppendElement (interp, progress.curfile);
526
527 sprintf (tmpstring, "%d", progress.partno);
528 Tcl_AppendElement (interp, tmpstring);
529
530 sprintf (tmpstring, "%d", progress.numparts);
531 Tcl_AppendElement (interp, tmpstring);
532
533 sprintf (tmpstring, "%d", progress.percent);
534 Tcl_AppendElement (interp, tmpstring);
535
536 return TCL_OK;
537 }
538
539 static int UUTCLFUNC
uutcl_GetListOfFiles(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])540 uutcl_GetListOfFiles (ClientData clientData, Tcl_Interp *interp,
541 int argc, char *argv[])
542 {
543 char tmpstring[1024], t2[42];
544 int count=0, index=0;
545 uulist *iter;
546
547 uutcl_UpdateParameter (interp);
548
549 while ((iter=UUGetFileListItem(count))) {
550 if (((iter->state & UUFILE_OK) ||
551 UUGetOption (UUOPT_DESPERATE, NULL, NULL, 0)) && iter->filename) {
552 sprintf (tmpstring, " { %d %d {%s} %s %s {",
553 count, iter->state, iter->filename,
554 (iter->mimetype)?iter->mimetype:"{}",
555 (iter->uudet == UU_ENCODED) ? "UUdata " :
556 (iter->uudet == B64ENCODED) ? "Base64 " :
557 (iter->uudet == XX_ENCODED) ? "XXdata " :
558 (iter->uudet == BH_ENCODED) ? "Binhex " :
559 (iter->uudet == YENC_ENCODED) ? "yEnc" : "Text");
560
561 if (iter->haveparts) {
562 sprintf (t2, "%s%s%d ",
563 (iter->begin&&iter->begin==iter->haveparts[0])?"begin ":"",
564 (iter->end &&iter->end == iter->haveparts[0])?"end " :"",
565 iter->haveparts[0]);
566 strcat (tmpstring, t2);
567
568 for (index=1; iter->haveparts[index]; index++) {
569 sprintf (t2, "%s%s%d ",
570 (iter->begin==iter->haveparts[index]) ? "begin " : "",
571 (iter->end == iter->haveparts[index]) ? "end " : "",
572 iter->haveparts[index]);
573 strcat (tmpstring, t2);
574 }
575 }
576
577 if (iter->state & UUFILE_OK)
578 strcat (tmpstring, "OK");
579
580 strcat (tmpstring, "} }");
581
582 Tcl_AppendResult (interp, tmpstring, NULL);
583 }
584 count++;
585 }
586
587 return TCL_OK;
588 }
589
590 /*
591 * Load an encoded file
592 */
593
594 static int UUTCLFUNC
uutcl_LoadFile(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])595 uutcl_LoadFile (ClientData clientData, Tcl_Interp *interp,
596 int argc, char *argv[])
597 {
598 char tmpstring[256];
599 int res;
600
601 uutcl_UpdateParameter (interp);
602
603 if (argc != 2) {
604 sprintf (tmpstring,
605 "wrong # args: should be \"%s filename\"",
606 argv[0]);
607 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
608 return TCL_ERROR;
609 }
610
611 if ((res = UULoadFile (argv[1], NULL, 0)) != UURET_OK) {
612 sprintf (tmpstring, "couldn't read %s: %s (%s)",
613 argv[1], UUstrerror (res),
614 (res==UURET_IOERR)?
615 strerror(UUGetOption(UUOPT_ERRNO,NULL,NULL,0)):"");
616 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
617 return TCL_ERROR;
618 }
619
620 return TCL_OK;
621 }
622
623 /*
624 * Decode A File. This function overwrites files without asking, because
625 * this was already done by the script
626 */
627
628 static int UUTCLFUNC
uutcl_DecodeFile(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])629 uutcl_DecodeFile (ClientData clientData, Tcl_Interp *interp,
630 int argc, char *argv[])
631 {
632 char tmpstring[256];
633 uulist *iter;
634 int res;
635
636 uutcl_UpdateParameter (interp);
637
638 if (argc < 2 || argc > 3) {
639 sprintf (tmpstring,
640 "wrong # args: should be \"%s number ?targetname?\"",
641 argv[0]);
642 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
643 return TCL_ERROR;
644 }
645
646 if ((iter = UUGetFileListItem (atoi (argv[1]))) == NULL) {
647 Tcl_SetResult (interp, "invalid file number", TCL_STATIC);
648 return TCL_ERROR;
649 }
650
651 if ((res = UUDecodeFile (iter, (argc==3)?argv[2]:NULL)) != UURET_OK) {
652 sprintf (tmpstring, "Error while decoding %s (%s): %s (%s)",
653 (iter->filename) ? iter->filename : "",
654 (iter->subfname) ? iter->subfname : "",
655 UUstrerror (res),
656 (res==UURET_IOERR)?
657 strerror(UUGetOption(UUOPT_ERRNO,NULL,NULL,0)):"");
658 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
659 return TCL_ERROR;
660 }
661
662 return TCL_OK;
663 }
664
665 static int UUTCLFUNC
uutcl_GetTempFile(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])666 uutcl_GetTempFile (ClientData clientData, Tcl_Interp *interp,
667 int argc, char *argv[])
668 {
669 char tmpstring[256];
670 uulist *iter;
671 int res;
672
673 uutcl_UpdateParameter (interp);
674
675 if (argc != 2) {
676 sprintf (tmpstring,
677 "wrong # args: should be \"%s number\"",
678 argv[0]);
679 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
680 return TCL_ERROR;
681 }
682
683 if ((iter = UUGetFileListItem (atoi (argv[1]))) == NULL) {
684 Tcl_SetResult (interp, "invalid file number", TCL_STATIC);
685 return TCL_ERROR;
686 }
687
688 if ((res = UUDecodeToTemp (iter)) != UURET_OK) {
689 sprintf (tmpstring, "Error while decoding %s (%s): %s (%s)",
690 (iter->filename) ? iter->filename : "",
691 (iter->subfname) ? iter->subfname : "",
692 UUstrerror (res),
693 (res==UURET_IOERR)?
694 strerror(UUGetOption(UUOPT_ERRNO,NULL,NULL,0)):"");
695 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
696 return TCL_ERROR;
697 }
698
699 if (iter->binfile == NULL) {
700 Tcl_SetResult (interp, "unknown error while decoding", TCL_STATIC);
701 return TCL_ERROR;
702 }
703
704 Tcl_SetResult (interp, iter->binfile, TCL_VOLATILE);
705 return TCL_OK;
706 }
707
708 /*
709 * InfoFile takes two parameters: the number of the file to get info for,
710 * and the name of the text widget to send the text to
711 */
712
713 struct uuInfoCBData {
714 Tcl_Interp *interp;
715 char * widget;
716 };
717
718 static int
uutcl_InfoCallback(void * param,char * string)719 uutcl_InfoCallback (void *param, char *string)
720 {
721 struct uuInfoCBData *data = (struct uuInfoCBData *) param;
722 char tmpstring[1024], *p;
723
724 sprintf (tmpstring, "%s insert end \"", data->widget);
725
726 p = tmpstring + strlen (tmpstring);
727
728 while (*string) {
729 switch (*string) {
730 case '"':
731 case '\\':
732 case '[':
733 case ']':
734 case '$':
735 *p++ = '\\';
736 /* fallthrough */
737 default:
738 *p++ = *string;
739 }
740 string++;
741 }
742 *p++ = '"';
743 *p++ = '\0';
744
745 if (Tcl_Eval (data->interp, tmpstring) != TCL_OK)
746 return 1;
747
748 return 0;
749 }
750
751 static int UUTCLFUNC
uutcl_InfoFile(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])752 uutcl_InfoFile (ClientData clientData, Tcl_Interp *interp,
753 int argc, char *argv[])
754 {
755 struct uuInfoCBData data;
756 char tmpstring[256];
757 uulist *iter;
758 int res;
759
760 uutcl_UpdateParameter (interp);
761
762 if (argc != 3) {
763 sprintf (tmpstring,
764 "wrong # args: should be \"%s number textwidget\"",
765 argv[0]);
766 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
767 return TCL_ERROR;
768 }
769
770 if ((iter = UUGetFileListItem (atoi (argv[1]))) == NULL) {
771 Tcl_SetResult (interp, "invalid file number", TCL_STATIC);
772 return TCL_ERROR;
773 }
774
775 sprintf (tmpstring, "%s delete 1.0 end", argv[2]);
776 if (Tcl_Eval (interp, tmpstring) != TCL_OK)
777 return TCL_ERROR;
778
779 data.interp = interp;
780 data.widget = argv[2];
781
782 if ((res = UUInfoFile (iter, &data, uutcl_InfoCallback)) != UURET_OK) {
783 sprintf (tmpstring, "Error while getting info for %s (%s): %s (%s)",
784 (iter->filename) ? iter->filename : "",
785 (iter->subfname) ? iter->subfname : "",
786 UUstrerror (res),
787 (res==UURET_IOERR)?
788 strerror(UUGetOption(UUOPT_ERRNO,NULL,NULL,0)):"");
789 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
790 return TCL_ERROR;
791 }
792
793 return TCL_OK;
794 }
795
796 /*
797 * ShowFile takes two parameters: the number of the file to get info for,
798 * and the name of the text widget to send the text to. We might have to
799 * decode the file before we can show it.
800 * Hey, the above callback worked so well, let's use it again!
801 */
802
803 static int UUTCLFUNC
uutcl_ListFile(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])804 uutcl_ListFile (ClientData clientData, Tcl_Interp *interp,
805 int argc, char *argv[])
806 {
807 uulist *iter;
808 struct uuInfoCBData data;
809 char tmpstring[1024];
810 FILE *inpfile;
811 int res;
812
813 uutcl_UpdateParameter (interp);
814
815 if (argc != 3) {
816 sprintf (tmpstring,
817 "wrong # args: should be \"%s number textwidget\"",
818 argv[0]);
819 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
820 return TCL_ERROR;
821 }
822
823 if ((iter = UUGetFileListItem (atoi (argv[1]))) == NULL) {
824 Tcl_SetResult (interp, "invalid file number", TCL_STATIC);
825 return TCL_ERROR;
826 }
827
828 if ((res = UUDecodeToTemp (iter)) != UURET_OK) {
829 sprintf (tmpstring, "Error while decoding %s (%s): %s (%s)",
830 (iter->filename) ? iter->filename : "",
831 (iter->subfname) ? iter->subfname : "",
832 UUstrerror(res),
833 (res==UURET_IOERR)?
834 strerror(UUGetOption(UUOPT_ERRNO,NULL,NULL,0)):"");
835 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
836 return TCL_ERROR;
837 }
838
839 sprintf (tmpstring, "%s delete 1.0 end", argv[2]);
840 if (Tcl_Eval (interp, tmpstring) != TCL_OK)
841 return TCL_ERROR;
842
843 if (iter->binfile==NULL || (inpfile=fopen (iter->binfile, "r"))==NULL) {
844 Tcl_SetResult (interp, "couldn't read file", TCL_STATIC);
845 return TCL_ERROR;
846 }
847 if ((inpfile = fopen (iter->binfile, "r")) == NULL) {
848 sprintf (tmpstring, "Could not open temp file %s of %s (%s): %s",
849 iter->binfile,
850 (iter->filename) ? iter->filename : "",
851 (iter->subfname) ? iter->subfname : "",
852 strerror (errno));
853 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
854 return TCL_ERROR;
855 }
856
857 data.interp = interp;
858 data.widget = argv[2];
859
860 while (!feof (inpfile)) {
861 if (_FP_fgets (tmpstring, 512, inpfile) == NULL)
862 break;
863
864 if (ferror (inpfile))
865 break;
866
867 if (uutcl_InfoCallback (&data, tmpstring))
868 break;
869 }
870
871 if (ferror (inpfile)) {
872 sprintf (tmpstring, "Error while reading from temp file %s of %s (%s): %s",
873 iter->binfile,
874 (iter->filename) ? iter->filename : "",
875 (iter->subfname) ? iter->subfname : "",
876 strerror (errno));
877 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
878 fclose (inpfile);
879 return TCL_ERROR;
880 }
881
882 fclose (inpfile);
883 return TCL_OK;
884 }
885
886 static int UUTCLFUNC
uutcl_Rename(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])887 uutcl_Rename (ClientData clientData, Tcl_Interp *interp,
888 int argc, char *argv[])
889 {
890 char tmpstring[256];
891 uulist *iter;
892 int res;
893
894 uutcl_UpdateParameter (interp);
895
896 if (argc != 3) {
897 sprintf (tmpstring,
898 "wrong # args: should be \"%s number newname\"",
899 argv[0]);
900 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
901 return TCL_ERROR;
902 }
903
904 if (*argv[2] == '\0') {
905 Tcl_SetResult (interp, "illegal file name", TCL_STATIC);
906 return TCL_ERROR;
907 }
908
909 if ((iter = UUGetFileListItem (atoi (argv[1]))) == NULL) {
910 Tcl_SetResult (interp, "invalid file number", TCL_STATIC);
911 return TCL_ERROR;
912 }
913
914 if ((res = UURenameFile (iter, argv[2])) != UURET_OK) {
915 sprintf (tmpstring,
916 "could not rename %s to %s: %s (%s)",
917 (iter->filename) ? iter->filename : "",
918 argv[2], UUstrerror (res),
919 (res==UURET_IOERR)?
920 strerror(UUGetOption(UUOPT_ERRNO,NULL,NULL,0)):"");
921 Tcl_SetResult (interp, tmpstring, TCL_VOLATILE);
922 return TCL_ERROR;
923 }
924
925 return TCL_OK;
926 }
927
928 /*
929 * clean up memory and temp files
930 */
931
932 static int UUTCLFUNC
uutcl_CleanUp(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])933 uutcl_CleanUp (ClientData clientData, Tcl_Interp *interp,
934 int argc, char *argv[])
935 {
936 uutcl_UpdateParameter (interp);
937
938 UUCleanUp ();
939
940 return TCL_OK;
941 }
942
943 /*
944 * Generic function to extract the encoding and linperfile parameters
945 * from the command's command line
946 */
947
948 static int
uutcl_GetEncodeParams(Tcl_Interp * interp,int argc,char * argv[],int argv1,int * encoding,int argv2,int * linperfile)949 uutcl_GetEncodeParams (Tcl_Interp *interp,
950 int argc, char *argv[],
951 int argv1, int *encoding,
952 int argv2, int *linperfile)
953 {
954 if (argv2 && argv2 < argc) {
955 *linperfile = atoi (argv[argv2]);
956
957 if (*linperfile != 0 && *linperfile < 200) {
958 Tcl_SetResult (interp, "illegal number of lines per file", TCL_STATIC);
959 return TCL_ERROR;
960 }
961 }
962 if (argv1 && argv1 < argc) {
963 switch (*argv[argv1]) {
964 case '0':
965 case 'u':
966 case 'U':
967 *encoding = UU_ENCODED;
968 break;
969 case '1':
970 case 'x':
971 case 'X':
972 *encoding = XX_ENCODED;
973 break;
974 case '2':
975 case 'b':
976 case 'B':
977 *encoding = B64ENCODED;
978 break;
979 case '3':
980 case 't':
981 case 'T':
982 *encoding = PT_ENCODED;
983 break;
984 case '4':
985 case 'q':
986 case 'Q':
987 *encoding = QP_ENCODED;
988 break;
989 case '5':
990 case 'y':
991 case 'Y':
992 *encoding = YENC_ENCODED;
993 break;
994 default:
995 Tcl_SetResult (interp, "invalid encoding method", TCL_STATIC);
996 return TCL_ERROR;
997 }
998 }
999 return TCL_OK;
1000 }
1001
1002 /*
1003 * Encode and store in a file.
1004 * Syntax:
1005 * uu_EncodeToFile source path \
1006 * [ dest subject intro lines encoding from replyto]
1007 *
1008 * Most arguments are just for compatibilty with the other encoding procs.
1009 */
1010
1011 static int UUTCLFUNC
uutcl_EncodeToFile(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])1012 uutcl_EncodeToFile (ClientData clientData, Tcl_Interp *interp,
1013 int argc, char *argv[])
1014 {
1015 int encoding=UU_ENCODED, linperfile=0, res;
1016 char errstring[256], olddir[256];
1017
1018 if (argc < 3 || argc > 10) {
1019 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
1020 return TCL_ERROR;
1021 }
1022
1023 uutcl_UpdateParameter (interp);
1024
1025 if (uutcl_GetEncodeParams (interp, argc, argv,
1026 7, &encoding,
1027 6, &linperfile) != TCL_OK)
1028 return TCL_ERROR;
1029
1030 UUGetOption (UUOPT_SAVEPATH, NULL, olddir, 256);
1031 UUSetOption (UUOPT_SAVEPATH, 0, argv[2]);
1032
1033 if ((res = UUEncodeToFile (NULL, argv[1], encoding,
1034 (argc>3) ? argv[3] : NULL,
1035 (argc>2) ? argv[2] : NULL,
1036 linperfile)) != UURET_OK) {
1037 UUSetOption (UUOPT_SAVEPATH, 0, olddir);
1038 sprintf (errstring, "error while encoding %s to file: %s (%s)", argv[1],
1039 UUstrerror(res),
1040 (res==UURET_IOERR)?
1041 strerror(UUGetOption(UUOPT_ERRNO,NULL,NULL,0)):"");
1042 Tcl_SetResult (interp, errstring, TCL_VOLATILE);
1043 return TCL_ERROR;
1044 }
1045 UUSetOption (UUOPT_SAVEPATH, 0, olddir);
1046 return TCL_OK;
1047 }
1048
1049 /*
1050 * Encode and send by email
1051 * Syntax:
1052 * uu_EncodeToMail source addr \
1053 * [ dest subject intro lines encoding from replyto ]
1054 *
1055 * addr can be a single address or a list of addresses
1056 */
1057
1058 static int UUTCLFUNC
uutcl_EncodeToMail(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])1059 uutcl_EncodeToMail (ClientData clientData, Tcl_Interp *interp,
1060 int argc, char *argv[])
1061 {
1062 int encoding=UU_ENCODED, linperfile=0, res;
1063 char errstring[256];
1064
1065 if (argc < 3 || argc > 10) {
1066 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
1067 return TCL_ERROR;
1068 }
1069 uutcl_UpdateParameter (interp);
1070
1071 if (uutcl_GetEncodeParams (interp, argc, argv,
1072 7, &encoding,
1073 6, &linperfile) != TCL_OK)
1074 return TCL_ERROR;
1075
1076 if ((res = SendAFile (interp, NULL, argv[1], encoding, linperfile,
1077 /* outfname */ (argc>3) ? argv[3] : NULL,
1078 /* towhom */ argv[2],
1079 /* subject */ (argc>4) ? argv[4] : NULL,
1080 /* from */ (argc>8) ? argv[8] : NULL,
1081 /* replyto */ (argc>9) ? argv[9] : NULL,
1082 1)) != UURET_OK) {
1083 /*
1084 * If res==UURET_ILLVAL, SendAMail has already filled in the result
1085 */
1086 if (res != UURET_ILLVAL) {
1087 sprintf (errstring, "error while emailing %s: %s (%s)", argv[1],
1088 UUstrerror(res),
1089 (res==UURET_IOERR)?
1090 strerror(UUGetOption(UUOPT_ERRNO,NULL,NULL,0)):"");
1091 Tcl_SetResult (interp, errstring, TCL_VOLATILE);
1092 }
1093 return TCL_ERROR;
1094 }
1095 return TCL_OK;
1096 }
1097
1098 /*
1099 * Encode and post to the news
1100 * Syntax:
1101 * uu_EncodeToNews source addr \
1102 * [ dest subject intro lines encoding from replyto ]
1103 *
1104 * addr can be a single newsgroup or a list of newsgroups
1105 */
1106
1107 static int UUTCLFUNC
uutcl_EncodeToNews(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])1108 uutcl_EncodeToNews (ClientData clientData, Tcl_Interp *interp,
1109 int argc, char *argv[])
1110 {
1111 int encoding=UU_ENCODED, linperfile=0, res;
1112 char errstring[256];
1113
1114 if (argc < 3 || argc > 10) {
1115 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
1116 return TCL_ERROR;
1117 }
1118 uutcl_UpdateParameter (interp);
1119
1120 if (uutcl_GetEncodeParams (interp, argc, argv,
1121 7, &encoding,
1122 6, &linperfile) != TCL_OK)
1123 return TCL_ERROR;
1124
1125 if ((res = SendAFile (interp, NULL, argv[1], encoding, linperfile,
1126 /* outfname */ (argc>3) ? argv[3] : NULL,
1127 /* towhom */ argv[2],
1128 /* subject */ (argc>4) ? argv[4] : NULL,
1129 /* from */ (argc>8) ? argv[8] : NULL,
1130 /* replyto */ (argc>9) ? argv[9] : NULL,
1131 0)) != UURET_OK) {
1132 /*
1133 * If res==UURET_ILLVAL, SendAMail has already filled in the result
1134 */
1135 if (res != UURET_ILLVAL) {
1136 sprintf (errstring, "error while posting %s: %s (%s)", argv[1],
1137 UUstrerror(res),
1138 (res==UURET_IOERR)?
1139 strerror(UUGetOption(UUOPT_ERRNO,NULL,NULL,0)):"");
1140 Tcl_SetResult (interp, errstring, TCL_VOLATILE);
1141 }
1142 return TCL_ERROR;
1143 }
1144 return TCL_OK;
1145 }
1146
1147 /*
1148 * Initialize the TCL package. The only function that is exported from
1149 * this module.
1150 */
1151
1152 int UUTCLEXPORT UUTCLFUNC
Uu_Init(Tcl_Interp * interp)1153 Uu_Init (Tcl_Interp *interp)
1154 {
1155 char tmp[32];
1156
1157 /*
1158 * Check whether we are already initialized
1159 */
1160
1161 if (uu_AlreadyInitialized++)
1162 return TCL_OK;
1163
1164 /*
1165 * Initialize decoding engine
1166 */
1167
1168 if (UUInitialize () != UURET_OK) {
1169 Tcl_SetResult (interp, "Error initializing decoding engine", TCL_STATIC);
1170 return TCL_ERROR;
1171 }
1172
1173 /*
1174 * register commands
1175 */
1176
1177 Tcl_CreateCommand (interp, "uu_Info", uutcl_Info, NULL, NULL);
1178 Tcl_CreateCommand (interp, "uu_SetMessageProc",uutcl_SetMessageProc,
1179 NULL, NULL);
1180 Tcl_CreateCommand (interp, "uu_SetBusyProc", uutcl_SetBusyProc,NULL,NULL);
1181 Tcl_CreateCommand (interp, "uu_GetProgressInfo",uutcl_GetProgressInfo,
1182 NULL, NULL);
1183 Tcl_CreateCommand (interp, "uu_GetListOfFiles",uutcl_GetListOfFiles,
1184 NULL, NULL);
1185 Tcl_CreateCommand (interp, "uu_LoadFile", uutcl_LoadFile, NULL, NULL);
1186 Tcl_CreateCommand (interp, "uu_DecodeFile", uutcl_DecodeFile, NULL, NULL);
1187 Tcl_CreateCommand (interp, "uu_GetTempFile", uutcl_GetTempFile,NULL,NULL);
1188 Tcl_CreateCommand (interp, "uu_InfoFile", uutcl_InfoFile, NULL, NULL);
1189 Tcl_CreateCommand (interp, "uu_ListFile", uutcl_ListFile, NULL, NULL);
1190 Tcl_CreateCommand (interp, "uu_Rename", uutcl_Rename, NULL, NULL);
1191 Tcl_CreateCommand (interp, "uu_CleanUp", uutcl_CleanUp, NULL, NULL);
1192 Tcl_CreateCommand (interp, "uu_EncodeToFile", uutcl_EncodeToFile,NULL,NULL);
1193 Tcl_CreateCommand (interp, "uu_EncodeToMail", uutcl_EncodeToMail,NULL,NULL);
1194 Tcl_CreateCommand (interp, "uu_EncodeToNews", uutcl_EncodeToNews,NULL,NULL);
1195
1196 /*
1197 * our message-handling function and busy callback
1198 */
1199
1200 theDMcbdata.interp = NULL;
1201 theDMcbdata.tclproc[0] = '\0';
1202 UUSetMsgCallback (&theDMcbdata, uutcl_DisplayMessage);
1203
1204 theBusycbdata.interp = NULL;
1205 theBusycbdata.tclproc[0] = '\0';
1206 UUSetBusyCallback (&theBusycbdata, uutcl_BusyCallback, 1000);
1207
1208 /*
1209 * only set variables if they aren't set already
1210 */
1211
1212 sprintf (tmp, "%d", UUGetOption (UUOPT_FAST, NULL, NULL, 0));
1213 if (Tcl_GetVar (interp, "OptionFast", TCL_GLOBAL_ONLY) == NULL)
1214 Tcl_SetVar (interp, "OptionFast", tmp, TCL_GLOBAL_ONLY);
1215
1216 sprintf (tmp, "%d", UUGetOption (UUOPT_BRACKPOL, NULL, NULL, 0));
1217 if (Tcl_GetVar (interp, "OptionBracket", TCL_GLOBAL_ONLY) == NULL)
1218 Tcl_SetVar (interp, "OptionBracket", tmp, TCL_GLOBAL_ONLY);
1219
1220 sprintf (tmp, "%d", UUGetOption (UUOPT_DESPERATE, NULL, NULL, 0));
1221 if (Tcl_GetVar (interp, "OptionDesperate", TCL_GLOBAL_ONLY) == NULL)
1222 Tcl_SetVar (interp, "OptionDesperate", tmp, TCL_GLOBAL_ONLY);
1223
1224 sprintf (tmp, "%d", UUGetOption (UUOPT_DEBUG, NULL, NULL, 0));
1225 if (Tcl_GetVar (interp, "OptionDebug", TCL_GLOBAL_ONLY) == NULL)
1226 Tcl_SetVar (interp, "OptionDebug", tmp, TCL_GLOBAL_ONLY);
1227
1228 sprintf (tmp, "%d", UUGetOption (UUOPT_USETEXT, NULL, NULL, 0));
1229 if (Tcl_GetVar (interp, "OptionUsetext", TCL_GLOBAL_ONLY) == NULL)
1230 Tcl_SetVar (interp, "OptionUsetext", tmp, TCL_GLOBAL_ONLY);
1231
1232 return TCL_OK;
1233 }
1234
1235 #endif
1236