/[pkg-mixmaster]/trunk/Mix/Src/mix.c
ViewVC logotype

Contents of /trunk/Mix/Src/mix.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations) (download)
Wed Oct 31 08:19:51 2001 UTC (11 years, 6 months ago) by rabbi
File MIME type: text/plain
File size: 16902 byte(s)
Initial revision
1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 Mixmaster initialization, configuration
9 $Id: mix.c,v 1.1 2001/10/31 08:19:53 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdarg.h>
17 #include <ctype.h>
18 #include <time.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #ifdef POSIX
22 #include <unistd.h>
23 #include <pwd.h>
24 #include <sys/utsname.h>
25 #else
26 #include <io.h>
27 #include <direct.h>
28 #endif
29 #ifdef WIN32
30 #include <windows.h>
31 #endif
32 #include <assert.h>
33 #include "menu.h"
34
35 int buf_vappendf(BUFFER *b, char *fmt, va_list args);
36
37 /** config ***************************************************************/
38
39 char MIXDIR[PATHMAX];
40 char POOLDIR[PATHMAX];
41
42 /* programs */
43 char SENDMAIL[LINELEN] = "/usr/lib/sendmail -t";
44 char SENDANONMAIL[LINELEN];
45 char NEWS[LINELEN];
46 char TYPE1[LINELEN];
47
48 /* addresses */
49 char MAILtoNEWS[LINELEN] = "mail2news@anon.lcs.mit.edu";
50 char REMAILERNAME[LINELEN] = "Anonymous Remailer";
51 char ANONNAME[LINELEN] = "Anonymous";
52 char REMAILERADDR[LINELEN];
53 char ANONADDR[LINELEN];
54 char COMPLAINTS[LINELEN];
55 int AUTOREPLY;
56 char SMTPRELAY[LINELEN];
57
58 #ifdef USE_SOCK
59 char HELONAME[LINELEN];
60 char ENVFROM[LINELEN];
61 int POP3DEL = 0;
62 int POP3SIZELIMIT = 0;
63 long POP3TIME = 60 * 60;
64
65 #endif
66
67 char SHORTNAME[LINELEN];
68
69 /* remailer configuration */
70 int REMAIL = 1;
71 int MIX = 1;
72 int PGP = 1;
73 int UNENCRYPTED = 0;
74 int REMIX = 1;
75
76 int POOLSIZE = 0;
77 int RATE = 100;
78 int MIDDLEMAN = 0;
79 int AUTOBLOCK = 1;
80 char FORWARDTO[LINELEN] = "*";
81 int SIZELIMIT = 0; /* maximal size of remailed messages */
82 int INFLATEMAX = 50; /* maximal size of Inflate: padding */
83 int MAXRANDHOPS = 20;
84 int BINFILTER = 0; /* filter binary attachments? */
85 long PACKETEXP = 7 * SECONDSPERDAY; /* Expiration time for old packets */
86 long IDEXP = 7 * SECONDSPERDAY; /* 0 = no ID log !! */
87 long SENDPOOLTIME = 60 * 60; /* frequency for sending pool messages */
88
89 char ERRLOG[LINELEN];
90 char ADDRESS[LINELEN];
91 char NAME[LINELEN];
92
93 char ORGANIZATION[LINELEN] = "Anonymous Posting Service";
94 char MID[LINELEN] = "y";
95
96 /* client config */
97 int NUMCOPIES = 1;
98 char CHAIN[LINELEN] = "*,*,*,*";
99 int VERBOSE = 2;
100 int DISTANCE = 2;
101 int MINREL = 98;
102 int RELFINAL = 99;
103 long MAXLAT = 36 * 60 * 60;
104 char PGPPUBRING[PATHMAX];
105 char PGPSECRING[PATHMAX];
106 char MAILBOX[PATHMAX] = "mbox";
107 char MAILABUSE[PATHMAX];
108 char MAILBLOCK[PATHMAX];
109 #ifdef WIN32
110 char MAILUSAGE[PATHMAX] = "nul:";
111 char MAILANON[PATHMAX] = "nul:";
112 char MAILERROR[PATHMAX] = "nul:";
113 #else
114 char MAILUSAGE[PATHMAX] = "/dev/null";
115 char MAILANON[PATHMAX] = "/dev/null";
116 char MAILERROR[PATHMAX] = "/dev/null";
117 #endif
118 char MAILBOUNCE[PATHMAX];
119
120 #if defined(S_IFDIR) && !defined(S_ISDIR)
121 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
122 #endif
123
124 static int mixdir(char *d, int create)
125 {
126 int err;
127 struct stat buf;
128
129 if (d != MIXDIR)
130 strncpy(MIXDIR, d, PATHMAX);
131 if (MIXDIR[strlen(MIXDIR) - 1] == '/')
132 MIXDIR[strlen(MIXDIR) - 1] = '\0';
133 err = stat(MIXDIR, &buf);
134 if (err == -1) {
135 if (create) {
136 #ifndef POSIX
137 err = mkdir(MIXDIR);
138 #else
139 err = mkdir(MIXDIR, S_IRWXU);
140 #endif
141 if (err == 0)
142 errlog(NOTICE, "Creating directory %s.\n", MIXDIR);
143 } else
144 err = 1;
145 } else if (!S_ISDIR(buf.st_mode))
146 err = -1;
147 if (err == 0)
148 strcatn(MIXDIR, "/", PATHMAX);
149 return (err);
150 }
151
152 void whoami(char *addr, char *defaultname)
153 {
154 char *p = NULL;
155
156 #if defined(HAVE_GETDOMAINNAME) || defined(HAVE_GETHOSTNAME)
157 char line[LINELEN];
158
159 #endif
160 #ifdef HAVE_UNAME
161 struct utsname uts;
162
163 #endif
164 #ifdef POSIX
165 p = getlogin();
166 #endif
167 if (p == NULL)
168 strcpy(addr, defaultname);
169 else
170 strncpy(addr, p, LINELEN);
171
172 strcatn(addr, "@", LINELEN);
173 #ifdef HAVE_UNAME
174 if (uname(&uts) != -1)
175 strcatn(addr, uts.nodename, LINELEN);
176 #elif defined(HAVE_GETHOSTNAME)
177 if (gethostname(line, LINELEN) == 0)
178 strcatn(addr, line, LINELEN);
179 #endif
180 if (addr[strlen(addr) - 1] == '@')
181 strcatn(addr, SHORTNAME, LINELEN);
182
183 if (strchr(strchr(addr, '@'), '.') == NULL) {
184 #ifdef HAVE_GETDOMAINNAME
185 if (getdomainname(line, LINELEN) == 0 && !streq(line, "(none)")) {
186 strcatn(addr, ".", LINELEN);
187 strcatn(addr, line, LINELEN);
188 }
189 #endif
190 }
191 }
192
193 #define read_conf(t) readconfline(line, #t, sizeof(#t)-1, t)
194
195 static int readconfline(char *line, char *name, int namelen, char *var)
196 {
197 if (strncmp(line, name, namelen) == 0 &&
198 (isspace(line[namelen]) || line[namelen] == '=')) {
199 line += namelen;
200 if (*line == '=')
201 line++;
202 while (isspace(*line))
203 line++;
204 if (line[0] == '\n' || line[0] == '\0') /* leave default */
205 return (1);
206 strncpy(var, line, LINELEN);
207 if (var[strlen(var) - 1] == '\n')
208 var[strlen(var) - 1] = '\0';
209 return (1);
210 } else
211 return (0);
212 }
213
214 #define read_conf_i(t) readiconfline(line, #t, sizeof(#t)-1, &t)
215
216 static int readiconfline(char *line, char *name, int namelen, int *var)
217 {
218 if (strncmp(line, name, namelen) == 0 &&
219 (isspace(line[namelen]) || line[namelen] == '=')) {
220 line += namelen;
221 if (*line == '=')
222 line++;
223 while (isspace(*line))
224 line++;
225 if (line[0] == '\n' || line[0] == '\0') /* leave default */
226 return (1);
227 switch (tolower(line[0])) {
228 case 'n':
229 *var = 0;
230 break;
231 case 'y':
232 *var = 1;
233 break;
234 case 'x':
235 *var = 2;
236 break;
237 default:
238 sscanf(line, "%d", var);
239 }
240 return (1);
241 } else
242 return (0);
243 }
244
245 #define read_conf_t(t) readtconfline(line, #t, sizeof(#t)-1, &t)
246
247 static int readtconfline(char *line, char *name, int namelen, long *var)
248 {
249 char *linenext;
250 int mod = 0;
251 long l = 0;
252 long n;
253
254 if (strncmp(line, name, namelen) == 0 &&
255 (isspace(line[namelen]) || line[namelen] == '=')) {
256 line += namelen;
257 if (*line == '=')
258 line++;
259 for (;; line++) {
260 n = strtol(line, &linenext, 10);
261 if (linenext == line)
262 break;
263 line = linenext;
264 mod = 1;
265 assert(line != NULL);
266 while (isspace(*line))
267 line++;
268 switch (tolower(*line)) {
269 case 'd':
270 l += 24 * 60 * 60 * n;
271 break;
272 case 'm':
273 l += 60 * n;
274 break;
275 case 'h':
276 default:
277 l += 60 * 60 * n;
278 break;
279 }
280 }
281 if (mod)
282 *var = l;
283 return (1);
284 } else
285 return (0);
286 }
287
288 int mix_configline(char *line)
289 {
290 return (read_conf(ADDRESS) || read_conf(NAME) ||
291 read_conf(SHORTNAME) || read_conf(REMAILERADDR) ||
292 read_conf(ANONADDR) || read_conf(REMAILERNAME) ||
293 read_conf(ANONNAME) || read_conf(COMPLAINTS) ||
294 read_conf_i(AUTOREPLY) || read_conf(SMTPRELAY) ||
295 #ifdef USE_SOCK
296 read_conf(HELONAME) || read_conf(ENVFROM) ||
297 #endif
298 read_conf(SENDMAIL) || read_conf(SENDANONMAIL) ||
299 read_conf_i(REMAIL) || read_conf_i(MIX) ||
300 read_conf_i(PGP) || read_conf_i(UNENCRYPTED) ||
301 read_conf_i(REMIX) || read_conf(NEWS) ||
302 read_conf(MAILtoNEWS) || read_conf(ERRLOG) ||
303 read_conf(ORGANIZATION) || read_conf(MID) ||
304 read_conf(TYPE1) || read_conf_i(POOLSIZE) ||
305 read_conf_i(RATE) || read_conf_i(MIDDLEMAN) ||
306 read_conf_i(AUTOBLOCK) || read_conf(FORWARDTO) ||
307 read_conf_i(SIZELIMIT) || read_conf_i(INFLATEMAX) ||
308 read_conf_i(MAXRANDHOPS) || read_conf_i(BINFILTER) ||
309 read_conf_t(PACKETEXP) || read_conf_t(IDEXP) ||
310 read_conf_t(SENDPOOLTIME) || read_conf_i(NUMCOPIES) ||
311 read_conf(CHAIN) || read_conf_i(VERBOSE) ||
312 read_conf_i(DISTANCE) || read_conf_i(MINREL) ||
313 read_conf_i(RELFINAL) || read_conf_t(MAXLAT) ||
314 read_conf(PGPPUBRING) || read_conf(PGPSECRING) ||
315 #ifdef USE_SOCK
316 read_conf_i(POP3DEL) || read_conf_i(POP3SIZELIMIT) ||
317 read_conf_t(POP3TIME) ||
318 #endif
319 read_conf(MAILBOX) || read_conf(MAILABUSE) ||
320 read_conf(MAILBLOCK) || read_conf(MAILUSAGE) ||
321 read_conf(MAILANON) || read_conf(MAILERROR) ||
322 read_conf(MAILBOUNCE));
323 }
324
325 static int mix_config(void)
326 {
327 char *d;
328 FILE *f;
329 char line[PATHMAX];
330 int err = -1;
331 #ifdef POSIX
332 struct passwd *pw;
333 #endif
334 struct stat buf;
335 #ifdef HAVE_UNAME
336 struct utsname uts;
337 #endif
338 #ifdef WIN32
339 HKEY regsw, reg, regpgp;
340 DWORD type, len;
341 int rkey = 0;
342 #endif
343
344 #ifdef POSIX
345 pw = getpwuid(getuid());
346 #endif
347
348 if (MIXDIR[0]) /* if set by main() */
349 err = mixdir(MIXDIR, 1);
350
351 #ifdef WIN32
352 RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &regsw);
353 len=sizeof(line);
354 if (err == -1 &&
355 RegOpenKeyEx(regsw, "Mixmaster", 0, KEY_QUERY_VALUE, &reg) == 0) {
356 if (RegQueryValueEx(reg, "MixDir", 0, &type, line, &len) == 0)
357 err = mixdir(line, 1);
358 RegCloseKey(reg);
359 }
360 #endif
361
362 if (err == -1 && (d = getenv("MIXPATH")) != NULL)
363 err = mixdir(d, 1);
364
365 #ifdef SPOOL
366 if (err == -1 && strlen(SPOOL) > 0)
367 err = mixdir(SPOOL, 0);
368 #endif
369
370 #ifdef POSIX
371 if (err == -1 && pw != NULL) {
372 strcatn(line, pw->pw_dir, PATHMAX);
373 if (line[strlen(line) - 1] != '/')
374 strcatn(line, "/", PATHMAX);
375 strcatn(line, "Mix", PATHMAX);
376 err = mixdir(line, 1);
377 }
378 #endif
379
380 if (err == -1) {
381 getcwd(MIXDIR, PATHMAX);
382 mixdir(MIXDIR, 0);
383 }
384
385 strncpy(POOLDIR, MIXDIR, PATHMAX - 32);
386 strcatn(POOLDIR, POOL, PATHMAX);
387 if (POOLDIR[strlen(POOLDIR) - 1] == '/')
388 POOLDIR[strlen(POOLDIR) - 1] = '\0';
389 if (stat(POOLDIR, &buf) != 0)
390 if
391 #ifndef POSIX
392 (mkdir(POOLDIR) != 0)
393 #else
394 (mkdir(POOLDIR, S_IRWXU) == -1)
395 #endif
396 strncpy(POOLDIR, MIXDIR, PATHMAX);
397
398 f = mix_openfile(MIXCONF, "r");
399 if (f != NULL) {
400 while (fgets(line, LINELEN, f) != NULL)
401 if (line[0] > ' ' && line[0] != '#')
402 mix_configline(line);
403 fclose(f);
404 }
405 if (IDEXP > 0 && IDEXP < 5 * SECONDSPERDAY)
406 IDEXP = 5 * SECONDSPERDAY;
407 if (MAXRANDHOPS > 20)
408 MAXRANDHOPS = 20;
409
410 if (strchr(SHORTNAME, '.'))
411 *strchr(SHORTNAME, '.') = '\0';
412 if (strchr(SHORTNAME, ' '))
413 *strchr(SHORTNAME, ' ') = '\0';
414 #ifdef HAVE_UNAME
415 if (SHORTNAME[0] == '\0' && uname(&uts) != -1)
416 strncpy(SHORTNAME, uts.nodename, LINELEN);
417 #elif defined(HAVE_GETHOSTNAME)
418 if (SHORTNAME[0] == '\0')
419 gethostname(SHORTNAME, LINELEN);
420 #endif
421 if (SHORTNAME[0] == '\0')
422 strcpy(SHORTNAME, "unknown");
423
424 if (ADDRESS[0] == '\0')
425 whoami(ADDRESS, "user");
426
427 #ifdef HAVE_GECOS
428 if (NAME[0] == '\0' && pw != NULL)
429 strcatn(NAME, pw->pw_gecos, sizeof(NAME));
430 #endif
431
432 if (REMAILERADDR[0] == '\0')
433 strncpy(REMAILERADDR, ADDRESS, LINELEN);
434
435 if (COMPLAINTS[0] == '\0')
436 strncpy(COMPLAINTS, REMAILERADDR, LINELEN);
437
438 if (strchr(REMAILERNAME, '@') == NULL) {
439 strcatn(REMAILERNAME, " <", LINELEN);
440 strcatn(REMAILERNAME, REMAILERADDR, LINELEN);
441 strcatn(REMAILERNAME, ">", LINELEN);
442 }
443 if (strchr(ANONNAME, '@') == NULL && ANONADDR[0] != '\0') {
444 strcatn(ANONNAME, " <", LINELEN);
445 strcatn(ANONNAME, ANONADDR, LINELEN);
446 strcatn(ANONNAME, ">", LINELEN);
447 }
448 if (strchr(ANONNAME, '@') == NULL) {
449 strcatn(ANONNAME, " <", LINELEN);
450 strcatn(ANONNAME, REMAILERADDR, LINELEN);
451 strcatn(ANONNAME, ">", LINELEN);
452 }
453 #ifndef USE_PGP
454 if (TYPE1[0] == '\0')
455 PGP = 0;
456 #endif
457 #ifndef USE_RSA
458 MIX = 0;
459 #endif
460
461 #ifdef WIN32
462 if (RegOpenKeyEx(regsw, "PGP", 0, KEY_ALL_ACCESS, &regpgp) == 0)
463 rkey++;
464 if (rkey && RegOpenKeyEx(regpgp, "PGPlib", 0, KEY_QUERY_VALUE, &reg) == 0)
465 rkey++;
466 if (PGPPUBRING[0] == '\0' && rkey == 2) {
467 len = PATHMAX;
468 RegQueryValueEx(reg, "PubRing", 0, &type, PGPPUBRING, &len);
469 }
470 if (PGPSECRING[0] == '\0' && rkey == 2) {
471 len = PATHMAX;
472 RegQueryValueEx(reg, "SecRing", 0, &type, PGPSECRING, &len);
473 }
474 if (rkey == 2)
475 RegCloseKey(reg);
476 if (rkey)
477 RegCloseKey(regpgp);
478 RegCloseKey(regsw);
479 #endif
480
481 if (PGPPUBRING[0] == '\0') {
482 char *d;
483
484 if ((d = getenv("HOME")) != NULL) {
485 strcpy(PGPPUBRING, d);
486 strcatn(PGPPUBRING, "/.pgp/", PATHMAX);
487 }
488 strcatn(PGPPUBRING, "pubring.pkr", PATHMAX);
489 if (stat(PGPPUBRING, &buf) == -1)
490 strcpy(strrchr(PGPPUBRING, '.'), ".pgp");
491 }
492 if (PGPSECRING[0] == '\0') {
493 char *d;
494
495 if ((d = getenv("HOME")) != NULL) {
496 strcpy(PGPSECRING, d);
497 strcatn(PGPSECRING, "/.pgp/", PATHMAX);
498 }
499 strcatn(PGPSECRING, "secring.skr", PATHMAX);
500 if (stat(PGPSECRING, &buf) == -1)
501 strcpy(strrchr(PGPSECRING, '.'), ".pgp");
502 }
503 if (streq(NEWS, "mail-to-news"))
504 strncpy(NEWS, MAILtoNEWS, sizeof(NEWS));
505
506 if (f == NULL) {
507 f = mix_openfile(MIXCONF, "w");
508 if (f == NULL)
509 errlog(WARNING, "Can't open %s%s!\n", MIXDIR, MIXCONF);
510 else {
511 fprintf(f, "# mix.cfg - mixmaster configuration file\n");
512 fprintf(f, "NAME %s\n", NAME);
513 fprintf(f, "ADDRESS %s\n", ADDRESS);
514 fprintf(f, "\n# edit to set up a remailer:\n");
515 fprintf(f, "REMAIL n\n");
516 fprintf(f, "SHORTNAME %s\n", SHORTNAME);
517 fprintf(f, "REMAILERADDR %s\n", REMAILERADDR);
518 fprintf(f, "COMPLAINTS %s\n", COMPLAINTS);
519 fclose(f);
520 }
521 REMAIL = 0;
522 }
523
524 return (0);
525 }
526
527 /** Library initialization: ******************************************/
528
529 static int initialized = 0;
530
531 int mix_init(char *mixdir)
532 {
533 if (!initialized) {
534 if (mixdir)
535 strncpy(MIXDIR, mixdir, LINELEN);
536 mix_config();
537 #if defined(USE_SOCK) && defined(WIN32)
538 sock_init();
539 #endif
540 /* atexit (mix_exit); */
541 initialized = 1;
542 }
543
544 if (rnd_init() == -1)
545 rnd_seed();
546 return(0);
547 }
548
549 void mix_exit(void)
550 {
551 if (!initialized)
552 return;
553 rnd_final();
554 #if defined(USE_SOCK) && defined(WIN32)
555 sock_exit();
556 #endif
557 initialized=0;
558 }
559
560 int mix_regular(int force)
561 {
562 FILE *f;
563 long now, tpool = 0, tpop3 = 0, tdaily = 0;
564 int ret = 0;
565
566 mix_init(NULL);
567 now = time(NULL);
568
569 f = mix_openfile(REGULAR, "r+");
570 if (f != NULL) {
571 lock(f);
572 fscanf(f, "%ld %ld %ld", &tpool, &tpop3, &tdaily);
573 if (now - tpool > SENDPOOLTIME)
574 force |= FORCE_POOL;
575 #ifdef USE_SOCK
576 if (now - tpop3 > POP3TIME)
577 force |= FORCE_POP3;
578 #endif
579 if (now - tdaily > SECONDSPERDAY)
580 force |= FORCE_DAILY;
581 if (force & FORCE_POOL)
582 tpool = now;
583 if (force & FORCE_POP3)
584 tpop3 = now;
585 if (force & FORCE_DAILY)
586 tdaily = now;
587 rewind(f);
588 fprintf(f, "%ld %ld %ld\n", tpool, tpop3, tdaily);
589 unlock(f);
590 fclose(f);
591 } else {
592 force = FORCE_POOL | FORCE_POP3 | FORCE_DAILY;
593 f = mix_openfile(REGULAR, "w+");
594 if (f != NULL) {
595 lock(f);
596 fprintf(f, "%ld %ld %ld\n", now, now, now);
597 unlock(f);
598 fclose(f);
599 } else
600 errlog(ERRORMSG, "Can't create %s!\n", REGULAR);
601 }
602
603 if (force & FORCE_DAILY)
604 mix_daily(), ret = 1;
605 #ifdef USE_SOCK
606 if (force & FORCE_POP3)
607 pop3get();
608 #endif
609 if (force & FORCE_POOL)
610 ret = pool_send();
611
612 return (ret);
613 }
614
615 int mix_daily(void)
616 {
617 idexp();
618 pool_packetexp();
619 stats(NULL);
620 keymgt(0);
621 return (0);
622 }
623
624 int mix_daemon(void)
625 {
626 long t;
627 t = SENDPOOLTIME;
628 #ifdef USE_SOCK
629 if (POP3TIME < t)
630 t = POP3TIME;
631 #endif
632
633 for(;;) {
634 mix_regular(0);
635 #ifdef WIN32
636 Sleep(t * 1000);
637 #else
638 sleep(t);
639 #endif
640 }
641 }
642
643 /** error ***************************************************************/
644
645 void errlog(int type, char *fmt,...)
646 {
647 va_list args;
648 BUFFER *msg;
649 FILE *e = NULL;
650 time_t t;
651 struct tm *tc;
652 char line[LINELEN];
653 int p;
654 char err[6][8] =
655 {"", "Error", "Warning", "Notice", "Info", "Info"};
656
657 if ((VERBOSE == 0 && type != ERRORMSG) || (type == LOG && VERBOSE < 2)
658 || (type == DEBUGINFO && VERBOSE < 3))
659 return;
660
661 t = time(NULL);
662 tc = localtime(&t);
663 strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S] ", tc);
664
665 msg = buf_new();
666 buf_appends(msg, line);
667 p = msg->length;
668 buf_appendf(msg, "%s: ", err[type]);
669 va_start(args, fmt);
670 buf_vappendf(msg, fmt, args);
671 va_end(args);
672
673 if (streq(ERRLOG, "stdout"))
674 e = stdout;
675 else if (streq(ERRLOG, "stderr"))
676 e = stderr;
677
678 if (e == NULL && (ERRLOG[0] == '\0' ||
679 (e = mix_openfile(ERRLOG, "a")) == NULL))
680 mix_status("%s", msg->data + p);
681 else {
682 buf_write(msg, e);
683 if (e != stderr && e != stdout) {
684 fclose(e);
685 /* duplicate the error message on screen */
686 mix_status("%s", msg->data + p);
687 }
688 }
689 buf_free(msg);
690 }
691
692 static char statusline[BUFSIZE] = "";
693
694 void mix_status(char *fmt,...)
695 {
696 va_list args;
697
698 if (fmt != NULL) {
699 va_start(args, fmt);
700 #ifdef _MSC
701 _vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
702 #else
703 vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
704 #endif
705 va_end(args);
706 }
707 #ifdef USE_NCURSES
708 if (menu_initialized) {
709 cl(LINES - 2, 10);
710 printw("%s", statusline);
711 refresh();
712 } else
713 #endif
714 {
715 fprintf(stderr, "%s", statusline);
716 }
717 }
718
719 void mix_genericerror(void)
720 {
721 if (streq(statusline, "") || strfind(statusline, "...") ||
722 strifind(statusline, "generating"))
723 mix_status("Failed!");
724 else
725 mix_status(NULL);
726 }

  ViewVC Help
Powered by ViewVC 1.1.5