|
|
1.1 root 1: /* scfgxtrn.c */
2:
3: /* $Id: scfgxtrn.c,v 1.38 2006/05/25 07:35:26 rswindell Exp $ */
4:
5: /****************************************************************************
6: * @format.tab-size 4 (Plain Text/Source Code File Header) *
7: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
8: * *
9: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html *
10: * *
11: * This program is free software; you can redistribute it and/or *
12: * modify it under the terms of the GNU General Public License *
13: * as published by the Free Software Foundation; either version 2 *
14: * of the License, or (at your option) any later version. *
15: * See the GNU General Public License for more details: gpl.txt or *
16: * http://www.fsf.org/copyleft/gpl.html *
17: * *
18: * Anonymous FTP access to the most recent released source is available at *
19: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
20: * *
21: * Anonymous CVS access to the development source and modification history *
22: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
23: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
24: * (just hit return, no password is necessary) *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
26: * *
27: * For Synchronet coding style and modification guidelines, see *
28: * http://www.synchro.net/source.html *
29: * *
30: * You are encouraged to submit any modifications (preferably in Unix diff *
31: * format) via e-mail to [email protected] *
32: * *
33: * Note: If this box doesn't appear square, then you need to fix your tabs. *
34: ****************************************************************************/
35: /****************************************************************************/
36: /* Synchronet configuration utility */
37: /****************************************************************************/
38:
39: #include "scfg.h"
40:
41: char *daystr(char days);
42: static void hotkey_cfg(void);
43:
44: static char* mdaystr(long mdays)
45: {
46: int i;
47: char tmp[16];
48: static char str[256];
49:
50: if(mdays==0 || mdays==1)
51: return("Any");
52:
53: str[0]=0;
54: for(i=1;i<32;i++) {
55: if((mdays&(1<<i))==0)
56: continue;
57: if(str[0])
58: strcat(str," ");
59: sprintf(tmp,"%u",i);
60: strcat(str,tmp);
61: }
62:
63: return(str);
64: }
65:
66: static char* dropfile(int type, ulong misc)
67: {
68: static char str[128];
69: char fname[64]="";
70:
71: switch(type) {
72: case XTRN_SBBS:
73: strcpy(fname,"XTRN.DAT");
74: break;
75: case XTRN_WWIV:
76: strcpy(fname,"CHAIN.TXT");
77: break;
78: case XTRN_GAP:
79: strcpy(fname,"DOOR.SYS");
80: break;
81: case XTRN_RBBS:
82: strcpy(fname,"DORINFO#.DEF");
83: break;
84: case XTRN_RBBS1:
85: strcpy(fname,"DORINFO1.DEF");
86: break;
87: case XTRN_WILDCAT:
88: strcpy(fname,"CALLINFO.BBS");
89: break;
90: case XTRN_PCBOARD:
91: strcpy(fname,"PCBOARD.SYS");
92: break;
93: case XTRN_SPITFIRE:
94: strcpy(fname,"SFDOORS.DAT");
95: break;
96: case XTRN_UTI:
97: strcpy(fname,"UTIDOOR.TXT");
98: break;
99: case XTRN_SR:
100: strcpy(fname,"DOORFILE.SR");
101: break;
102: case XTRN_TRIBBS:
103: strcpy(fname,"TRIBBS.SYS");
104: break;
105: case XTRN_DOOR32:
106: strcpy(fname,"DOOR32.SYS");
107: break;
108: }
109:
110: if(misc&XTRN_LWRCASE)
111: strlwr(fname);
112:
113: switch(type) {
114: case XTRN_SBBS:
115: sprintf(str,"%-15s %s","Synchronet",fname);
116: break;
117: case XTRN_WWIV:
118: sprintf(str,"%-15s %s","WWIV",fname);
119: break;
120: case XTRN_GAP:
121: sprintf(str,"%-15s %s","GAP",fname);
122: break;
123: case XTRN_RBBS:
124: sprintf(str,"%-15s %s","RBBS/QuickBBS",fname);
125: break;
126: case XTRN_RBBS1:
127: sprintf(str,"%-15s %s","RBBS/QuickBBS",fname);
128: break;
129: case XTRN_WILDCAT:
130: sprintf(str,"%-15s %s","Wildcat",fname);
131: break;
132: case XTRN_PCBOARD:
133: sprintf(str,"%-15s %s","PCBoard",fname);
134: break;
135: case XTRN_SPITFIRE:
136: sprintf(str,"%-15s %s","SpitFire",fname);
137: break;
138: case XTRN_UTI:
139: sprintf(str,"%-15s %s","MegaMail",fname);
140: break;
141: case XTRN_SR:
142: sprintf(str,"%-15s %s","Solar Realms",fname);
143: break;
144: case XTRN_TRIBBS:
145: sprintf(str,"%-15s %s","TriBBS",fname);
146: break;
147: case XTRN_DOOR32:
148: sprintf(str,"%-15s %s","Mystic",fname);
149: break;
150: default:
151: strcpy(str,"None");
152: break;
153: }
154: return(str);
155: }
156:
157: void xprogs_cfg()
158: {
159: static int xprogs_dflt;
160: int i;
161:
162: while(1) {
163: i=0;
164: strcpy(opt[i++],"Fixed Events");
165: strcpy(opt[i++],"Timed Events");
166: strcpy(opt[i++],"Native Program List");
167: strcpy(opt[i++],"External Editors");
168: strcpy(opt[i++],"Global Hot Key Events");
169: strcpy(opt[i++],"Online Programs (Doors)");
170: opt[i][0]=0;
171: SETHELP(WHERE);
172: /*
173: &Online External Programs:&
174:
175: From this menu, you can configure external events, external editors, or
176: online external programs (doors).
177: */
178: switch(uifc.list(WIN_ORG|WIN_CHE|WIN_ACT,0,0,0,&xprogs_dflt,0
179: ,"External Programs",opt)) {
180: case -1:
181: i=save_changes(WIN_MID);
182: if(i==-1)
183: break;
184: if(!i) {
185: cfg.new_install=new_install;
186: write_xtrn_cfg(&cfg,backup_level);
187: write_main_cfg(&cfg,backup_level);
188: refresh_cfg(&cfg);
189: }
190: return;
191: case 0:
192: fevents_cfg();
193: break;
194: case 1:
195: tevents_cfg();
196: break;
197: case 2:
198: natvpgm_cfg();
199: break;
200: case 3:
201: xedit_cfg();
202: break;
203: case 4:
204: hotkey_cfg();
205: break;
206: case 5:
207: xtrnsec_cfg();
208: break; } }
209: }
210:
211: void fevents_cfg()
212: {
213: static int event_dflt;
214: int i;
215:
216: while(1) {
217: i=0;
218: sprintf(opt[i++],"%-32.32s%.40s","Logon Event",cfg.sys_logon);
219: sprintf(opt[i++],"%-32.32s%.40s","Logout Event",cfg.sys_logout);
220: sprintf(opt[i++],"%-32.32s%.40s","Daily Event",cfg.sys_daily);
221: opt[i][0]=0;
222: SETHELP(WHERE);
223: /*
224: &External Events:&
225:
226: From this menu, you can configure the logon and logout events, and the
227: system daily event.
228: */
229: switch(uifc.list(WIN_ACT|WIN_SAV|WIN_CHE|WIN_BOT|WIN_RHT,0,0,60,&event_dflt,0
230: ,"Fixed Events",opt)) {
231: case -1:
232: return;
233: case 0:
234: SETHELP(WHERE);
235: /*
236: &Logon Event:&
237:
238: This is the command line for a program that will execute during the
239: logon sequence of every user. The program cannot have user interaction.
240: The program will be executed after the LOGON message is displayed and
241: before the logon user list is displayed. If you wish to place a program
242: in the logon sequence of users that includes interaction or requires
243: account information, you probably want to use an online external
244: program configured to run as a logon event.
245: */
246: uifc.input(WIN_MID|WIN_SAV,0,0,"Logon Event"
247: ,cfg.sys_logon,sizeof(cfg.sys_logon)-1,K_EDIT);
248: break;
249: case 1:
250: SETHELP(WHERE);
251: /*
252: &Logout Event:&
253:
254: This is the command line for a program that will execute during the
255: logout sequence of every user. This program cannot have user
256: interaction because it is executed after carrier is dropped. If you
257: wish to have a program execute before carrier is dropped, you probably
258: want to use an &Online External Program& configured to run as a logoff
259: event.
260: */
261: uifc.input(WIN_MID|WIN_SAV,0,0,"Logout Event"
262: ,cfg.sys_logout,sizeof(cfg.sys_logout)-1,K_EDIT);
263: break;
264: case 2:
265: SETHELP(WHERE);
266: /*
267: &Daily Event:&
268:
269: This is the command line for a program that will run after the first
270: user that logs on after midnight, logs off (regardless of what node).
271: */
272: uifc.input(WIN_MID|WIN_SAV,0,0,"Daily Event"
273: ,cfg.sys_daily,sizeof(cfg.sys_daily)-1,K_EDIT);
274:
275: break; } }
276: }
277:
278: void tevents_cfg()
279: {
280: static int dflt,dfltopt,bar;
281: char str[81],done=0,*p;
282: int j,k;
283: uint i;
284: static event_t savevent;
285:
286: while(1) {
287: for(i=0;i<cfg.total_events && i<MAX_OPTS;i++)
288: sprintf(opt[i],"%-8.8s %.50s",cfg.event[i]->code,cfg.event[i]->cmd);
289: opt[i][0]=0;
290: j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_RHT;
291: if(cfg.total_events)
292: j|=WIN_DEL|WIN_GET;
293: if(cfg.total_events<MAX_OPTS)
294: j|=WIN_INS|WIN_INSACT|WIN_XTR;
295: if(savevent.code[0])
296: j|=WIN_PUT;
297: SETHELP(WHERE);
298: /*
299: &Timed Events:&
300:
301: This is a list of the configured timed external events.
302:
303: To add an event hit INS .
304:
305: To delete an event, select it and hit DEL .
306:
307: To configure an event, select it and hit ENTER .
308: */
309: i=uifc.list(j,0,0,45,&dflt,&bar,"Timed Events",opt);
310: if((signed)i==-1)
311: return;
312: if((i&MSK_ON)==MSK_INS) {
313: i=cfg.total_events;
314: SETHELP(WHERE);
315: /*
316: &Timed Event Internal Code:&
317:
318: This is the internal code for the timed event.
319: */
320: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Event Internal Code",str,LEN_CODE
321: ,K_UPPER)<1)
322: continue;
323: if((cfg.event=(event_t **)realloc(cfg.event
324: ,sizeof(event_t *)*(cfg.total_events+1)))==NULL) {
325: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_events+1);
326: cfg.total_events=0;
327: bail(1);
328: continue; }
329: if((cfg.event[i]=(event_t *)malloc(sizeof(event_t)))==NULL) {
330: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(event_t));
331: continue; }
332: memset((event_t *)cfg.event[i],0,sizeof(event_t));
333: strcpy(cfg.event[i]->code,str);
334: cfg.event[i]->node=1;
335: cfg.event[i]->days=0xff;
336: cfg.total_events++;
337: uifc.changes=1;
338: continue; }
339: if((i&MSK_ON)==MSK_DEL) {
340: i&=MSK_OFF;
341: free(cfg.event[i]);
342: cfg.total_events--;
343: for(j=i;j<cfg.total_events;j++)
344: cfg.event[j]=cfg.event[j+1];
345: uifc.changes=1;
346: continue; }
347: if((i&MSK_ON)==MSK_GET) {
348: i&=MSK_OFF;
349: savevent=*cfg.event[i];
350: continue; }
351: if((i&MSK_ON)==MSK_PUT) {
352: i&=MSK_OFF;
353: *cfg.event[i]=savevent;
354: uifc.changes=1;
355: continue; }
356: done=0;
357: while(!done) {
358: k=0;
359: sprintf(opt[k++],"%-32.32s%s","Internal Code",cfg.event[i]->code);
360: sprintf(opt[k++],"%-32.32s%.40s","Start-up Directory",cfg.event[i]->dir);
361: sprintf(opt[k++],"%-32.32s%.40s","Command Line",cfg.event[i]->cmd);
362: sprintf(opt[k++],"%-32.32s%s","Enabled"
363: ,cfg.event[i]->misc&EVENT_DISABLED ? "No":"Yes");
364: sprintf(opt[k++],"%-32.32s%u","Execution Node",cfg.event[i]->node);
365: sprintf(opt[k++],"%-32.32s%s","Execution Days of Month"
366: ,mdaystr(cfg.event[i]->mdays));
367: sprintf(opt[k++],"%-32.32s%s","Execution Days of Week",daystr(cfg.event[i]->days));
368: if(cfg.event[i]->freq) {
369: sprintf(str,"%u times a day",1440/cfg.event[i]->freq);
370: sprintf(opt[k++],"%-32.32s%s","Execution Frequency",str);
371: } else {
372: sprintf(str,"%2.2u:%2.2u"
373: ,cfg.event[i]->time/60,cfg.event[i]->time%60);
374: sprintf(opt[k++],"%-32.32s%s","Execution Time",str);
375: }
376: sprintf(opt[k++],"%-32.32s%s","Requires Exclusive Execution"
377: ,cfg.event[i]->misc&EVENT_EXCL ? "Yes":"No");
378: sprintf(opt[k++],"%-32.32s%s","Force Users Off-line For Event"
379: ,cfg.event[i]->misc&EVENT_FORCE ? "Yes":"No");
380: sprintf(opt[k++],"%-32.32s%s","Native (32-bit) Executable"
381: ,cfg.event[i]->misc&EX_NATIVE ? "Yes" : "No");
382: sprintf(opt[k++],"%-32.32s%s","Use Shell to Execute"
383: ,cfg.event[i]->misc&XTRN_SH ? "Yes" : "No");
384: sprintf(opt[k++],"%-32.32s%s","Background Execution"
385: ,cfg.event[i]->misc&EX_BG ? "Yes" : "No");
386: sprintf(opt[k++],"%-32.32s%s","Always Run After Init/Re-init"
387: ,cfg.event[i]->misc&EVENT_INIT ? "Yes":"No");
388:
389: opt[k][0]=0;
390: SETHELP(WHERE);
391: /*
392: &Timed Event:&
393:
394: This is the configuration menu for a timed event. An event is an
395: external program that performs some type of automated function on the
396: system. Use this menu to configure how and when this event will be
397: executed.
398:
399: If you need the BBS to swap out of memory for this event (to make more
400: available memory), add the program name (first word of the command line)
401: to &Global Swap List& from the &External Programs& menu.
402: */
403: sprintf(str,"%s Timed Event",cfg.event[i]->code);
404: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_L2R|WIN_BOT,0,0,70,&dfltopt,0
405: ,str,opt)) {
406: case -1:
407: done=1;
408: break;
409: case 0:
410: strcpy(str,cfg.event[i]->code);
411: SETHELP(WHERE);
412: /*
413: &Timed Event Internal Code:&
414:
415: Every timed event must have its own unique internal code for Synchronet
416: to reference it by. It is helpful if this code is an abreviation of the
417: command line.
418: */
419: uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
420: ,str,LEN_CODE,K_EDIT|K_UPPER);
421: if(code_ok(str))
422: strcpy(cfg.event[i]->code,str);
423: else {
424: uifc.helpbuf=invalid_code;
425: uifc.msg("Invalid Code");
426: uifc.helpbuf=0; }
427: break;
428: case 1:
429: SETHELP(WHERE);
430: /*
431: &Timed Event Start-up Directory:&
432:
433: This is the DOS drive/directory where the event program is located.
434: If a path is specified here, it will be made the current directory
435: before the event's command line is executed. This eliminates the need
436: for batch files that just change the current drive and directory before
437: executing the event.
438:
439: If this option is not used, the current NODE's directory will be the
440: current DOS drive/directory before the command line is executed.
441: */
442: uifc.input(WIN_MID|WIN_SAV,0,10,"Directory"
443: ,cfg.event[i]->dir,sizeof(cfg.event[i]->dir)-1,K_EDIT);
444: break;
445: case 2:
446: SETHELP(WHERE);
447: /*
448: &Timed Event Command Line:&
449:
450: This is the command line to execute upon this timed event.
451: */
452: uifc.input(WIN_MID|WIN_SAV,0,10,"Command"
453: ,cfg.event[i]->cmd,sizeof(cfg.event[i]->cmd)-1,K_EDIT);
454: break;
455:
456: case 3:
457: k=cfg.event[i]->misc&EVENT_DISABLED ? 1:0;
458: strcpy(opt[0],"Yes");
459: strcpy(opt[1],"No");
460: opt[2][0]=0;
461: SETHELP(WHERE);
462: /*
463: `Event Enabled:`
464:
465: If you want disable this event from executing, set this option to ~No~.
466: */
467: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
468: ,"Enabled",opt);
469: if((k==0 && cfg.event[i]->misc&EVENT_DISABLED)
470: || (k==1 && !(cfg.event[i]->misc&EVENT_DISABLED))) {
471: cfg.event[i]->misc^=EVENT_DISABLED;
472: uifc.changes=1;
473: }
474: break;
475:
476: case 4:
477: SETHELP(WHERE);
478: /*
479: &Timed Event Node:&
480:
481: This is the node number to execute the timed event.
482: */
483: sprintf(str,"%u",cfg.event[i]->node);
484: uifc.input(WIN_MID|WIN_SAV,0,0,"Node Number"
485: ,str,3,K_EDIT|K_NUMBER);
486: cfg.event[i]->node=atoi(str);
487: break;
488: case 5:
489: SETHELP(WHERE);
490: /*
491: `Days of Month to Execute Event:`
492:
493: Specifies the days of the month (`1-31`, separated by spaces) on which
494: to execute this event, or `Any` to execute event on any and all days of
495: the month.
496: */
497: SAFECOPY(str,mdaystr(cfg.event[i]->mdays));
498: uifc.input(WIN_MID|WIN_SAV,0,0,"Days of Month to Execute Event (or Any)"
499: ,str,16,K_EDIT);
500: cfg.event[i]->mdays=0;
501: for(p=str;*p;p++) {
502: if(!isdigit(*p))
503: continue;
504: cfg.event[i]->mdays|=(1<<atoi(p));
505: while(*p && isdigit(*p))
506: p++;
507: }
508: break;
509: case 6:
510: j=0;
511: while(1) {
512: for(k=0;k<7;k++)
513: sprintf(opt[k],"%-30s %3s"
514: ,wday[k],(cfg.event[i]->days&(1<<k)) ? "Yes":"No");
515: strcpy(opt[k++],"All");
516: strcpy(opt[k++],"None");
517: opt[k][0]=0;
518: SETHELP(WHERE);
519: /*
520: &Days of Week to Execute Event:&
521:
522: These are the days of the week that this event will be executed.
523: */
524: k=uifc.list(WIN_MID|WIN_SAV|WIN_ACT,0,0,0,&j,0
525: ,"Days of Week to Execute Event",opt);
526: if(k==-1)
527: break;
528: if(k==7)
529: cfg.event[i]->days=0xff;
530: else if(k==8)
531: cfg.event[i]->days=0;
532: else
533: cfg.event[i]->days^=(1<<k);
534: uifc.changes=1;
535: }
536: break;
537: case 7:
538: if(cfg.event[i]->freq==0)
539: k=0;
540: else
541: k=1;
542: strcpy(opt[0],"Yes");
543: strcpy(opt[1],"No");
544: opt[2][0]=0;
545: SETHELP(WHERE);
546: /*
547: &Execute Event at a Specific Time:&
548:
549: If you want the system execute this event at a specific time, set
550: this option to &Yes&. If you want the system to execute this event more
551: than once a day at predetermined intervals, set this option to &No&.
552: */
553: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
554: ,"Execute Event at a Specific Time",opt);
555: if(k==0) {
556: sprintf(str,"%2.2u:%2.2u",cfg.event[i]->time/60
557: ,cfg.event[i]->time%60);
558: SETHELP(WHERE);
559: /*
560: &Time to Execute Event:&
561:
562: This is the time (in 24 hour HH:MM format) to execute the event.
563: */
564: if(uifc.input(WIN_MID|WIN_SAV,0,0
565: ,"Time to Execute Event (HH:MM)"
566: ,str,5,K_UPPER|K_EDIT)>0) {
567: cfg.event[i]->freq=0;
568: cfg.event[i]->time=atoi(str)*60;
569: if((p=strchr(str,':'))!=NULL)
570: cfg.event[i]->time+=atoi(p+1); } }
571: else if(k==1) {
572: sprintf(str,"%u"
573: ,cfg.event[i]->freq && cfg.event[i]->freq<=1440
574: ? 1440/cfg.event[i]->freq : 0);
575: SETHELP(WHERE);
576: /*
577: &Number of Executions Per Day:&
578:
579: This is the maximum number of times the system will execute this event
580: per day.
581: */
582: if(uifc.input(WIN_MID|WIN_SAV,0,0
583: ,"Number of Executions Per Day"
584: ,str,4,K_NUMBER|K_EDIT)>0) {
585: cfg.event[i]->time=0;
586: k=atoi(str);
587: if(k && k<=1440)
588: cfg.event[i]->freq=1440/k;
589: else
590: cfg.event[i]->freq=0;
591: }
592: }
593: break;
594: case 8:
595: k=cfg.event[i]->misc&EVENT_EXCL ? 0:1;
596: strcpy(opt[0],"Yes");
597: strcpy(opt[1],"No");
598: opt[2][0]=0;
599: SETHELP(WHERE);
600: /*
601: &Exclusive Event Execution:&
602:
603: If this event must be run exclusively (all nodes inactive), set this
604: option to &Yes&.
605: */
606: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Exclusive Execution"
607: ,opt);
608: if(!k && !(cfg.event[i]->misc&EVENT_EXCL)) {
609: cfg.event[i]->misc|=EVENT_EXCL;
610: uifc.changes=1; }
611: else if(k==1 && cfg.event[i]->misc&EVENT_EXCL) {
612: cfg.event[i]->misc&=~EVENT_EXCL;
613: uifc.changes=1; }
614: break;
615: case 9:
616: k=cfg.event[i]->misc&EVENT_FORCE ? 0:1;
617: strcpy(opt[0],"Yes");
618: strcpy(opt[1],"No");
619: opt[2][0]=0;
620: SETHELP(WHERE);
621: /*
622: &Force Users Off-line for Event:&
623:
624: If you want to have your users' on-line time reduced so the event can
625: execute precisely on time, set this option to &Yes&.
626: */
627: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
628: ,"Force Users Off-line for Event",opt);
629: if(!k && !(cfg.event[i]->misc&EVENT_FORCE)) {
630: cfg.event[i]->misc|=EVENT_FORCE;
631: uifc.changes=1; }
632: else if(k==1 && cfg.event[i]->misc&EVENT_FORCE) {
633: cfg.event[i]->misc&=~EVENT_FORCE;
634: uifc.changes=1; }
635: break;
636:
637: case 10:
638: k=cfg.event[i]->misc&EX_NATIVE ? 0:1;
639: strcpy(opt[0],"Yes");
640: strcpy(opt[1],"No");
641: opt[2][0]=0;
642: SETHELP(WHERE);
643: /*
644: &Native (32-bit) Executable:&
645:
646: If this event program is a native 32-bit executable,
647: set this option to &Yes&.
648: */
649: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
650: ,"Native (32-bit)",opt);
651: if(!k && !(cfg.event[i]->misc&EX_NATIVE)) {
652: cfg.event[i]->misc|=EX_NATIVE;
653: uifc.changes=TRUE;
654: }
655: else if(k==1 && cfg.event[i]->misc&EX_NATIVE) {
656: cfg.event[i]->misc&=~EX_NATIVE;
657: uifc.changes=TRUE;
658: }
659: break;
660:
661: case 11:
662: k=cfg.event[i]->misc&XTRN_SH ? 0:1;
663: strcpy(opt[0],"Yes");
664: strcpy(opt[1],"No");
665: opt[2][0]=0;
666: SETHELP(WHERE);
667: /*
668: `Use Shell to Execute Command:`
669:
670: If this command-line requires the system command shell to execute, (Unix
671: shell script or DOS batch file), set this option to ~Yes~.
672: */
673: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
674: ,"Use Shell",opt);
675: if(!k && !(cfg.event[i]->misc&XTRN_SH)) {
676: cfg.event[i]->misc|=XTRN_SH;
677: uifc.changes=TRUE;
678: }
679: else if(k==1 && cfg.event[i]->misc&XTRN_SH) {
680: cfg.event[i]->misc&=~XTRN_SH;
681: uifc.changes=TRUE;
682: }
683: break;
684:
685: case 12:
686: k=cfg.event[i]->misc&EX_BG ? 0:1;
687: strcpy(opt[0],"Yes");
688: strcpy(opt[1],"No");
689: opt[2][0]=0;
690: SETHELP(WHERE);
691: /*
692: &Execute Event in Background (Asynchronously):&
693:
694: If you would like this event to run simultaneously with other events,
695: set this option to &Yes&. Exclusive events will not run in the background.
696: */
697: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
698: ,"Background (Asynchronous) Execution",opt);
699: if(!k && !(cfg.event[i]->misc&EX_BG)) {
700: cfg.event[i]->misc|=EX_BG;
701: uifc.changes=TRUE;
702: }
703: else if(k==1 && cfg.event[i]->misc&EX_BG) {
704: cfg.event[i]->misc&=~EX_BG;
705: uifc.changes=TRUE;
706: }
707: break;
708:
709: case 13:
710: k=cfg.event[i]->misc&EVENT_INIT ? 0:1;
711: strcpy(opt[0],"Yes");
712: strcpy(opt[1],"No");
713: opt[2][0]=0;
714: SETHELP(WHERE);
715: /*
716: `Always Run After Initialization or Re-initialization:`
717:
718: If you want this event to always run after the BBS is initialized or
719: re-initialized, set this option to ~Yes~.
720: */
721: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
722: ,"Always Run After Initialization or Re-initialization",opt);
723: if(!k && !(cfg.event[i]->misc&EVENT_INIT)) {
724: cfg.event[i]->misc|=EVENT_INIT;
725: uifc.changes=1;
726: }
727: else if(k==1 && cfg.event[i]->misc&EVENT_INIT) {
728: cfg.event[i]->misc&=~EVENT_INIT;
729: uifc.changes=1;
730: }
731: break;
732: }
733: }
734: }
735: }
736:
737:
738: void xtrn_cfg(uint section)
739: {
740: static int ext_dflt,ext_bar,opt_dflt,time_dflt;
741: char str[128],code[9],done=0,*p;
742: int j,k;
743: uint i,n,xtrnnum[MAX_OPTS+1];
744: static xtrn_t savxtrn;
745:
746: while(1) {
747: for(i=0,j=0;i<cfg.total_xtrns && j<MAX_OPTS;i++)
748: if(cfg.xtrn[i]->sec==section) {
749: sprintf(opt[j],"%-25s",cfg.xtrn[i]->name);
750: xtrnnum[j++]=i; }
751: xtrnnum[j]=cfg.total_xtrns;
752: opt[j][0]=0;
753: i=WIN_ACT|WIN_CHE|WIN_SAV|WIN_RHT;
754: if(j)
755: i|=WIN_DEL|WIN_GET;
756: if(cfg.total_xtrns<MAX_OPTS)
757: i|=WIN_INS|WIN_INSACT|WIN_XTR;
758: if(savxtrn.name[0])
759: i|=WIN_PUT;
760: SETHELP(WHERE);
761: /*
762: &Online External Programs:&
763:
764: This is a list of the configured online external programs (doors).
765:
766: To add a program, select the desired location with the arrow keys and
767: hit INS .
768:
769: To delete a program, select it with the arrow keys and hit DEL .
770:
771: To configure a program, select it with the arrow keys and hit ENTER .
772: */
773: sprintf(str,"%s Online Programs",cfg.xtrnsec[section]->name);
774: i=uifc.list(i,0,0,45,&ext_dflt,&ext_bar,str,opt);
775: if((signed)i==-1)
776: return;
777: if((i&MSK_ON)==MSK_INS) {
778: i&=MSK_OFF;
779: SETHELP(WHERE);
780: /*
781: &Online Program Name:&
782:
783: This is the name or description of the online program (door).
784: */
785: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Online Program Name",str,25
786: ,0)<1)
787: continue;
788: sprintf(code,"%.8s",str);
789: p=strchr(code,' ');
790: if(p) *p=0;
791: strupr(code);
792: SETHELP(WHERE);
793: /*
794: &Online Program Internal Code:&
795:
796: Every online program must have its own unique code for Synchronet to
797: refer to it internally. This code is usually an abreviation of the
798: online program name.
799: */
800: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Internal Code"
801: ,code,LEN_CODE,K_EDIT|K_UPPER)<1)
802: continue;
803: if(!code_ok(code)) {
804: uifc.helpbuf=invalid_code;
805: uifc.msg("Invalid Code");
806: uifc.helpbuf=0;
807: continue; }
808: if((cfg.xtrn=(xtrn_t **)realloc(cfg.xtrn,sizeof(xtrn_t *)*(cfg.total_xtrns+1)))
809: ==NULL) {
810: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_xtrns+1);
811: cfg.total_xtrns=0;
812: bail(1);
813: continue; }
814: if(j)
815: for(n=cfg.total_xtrns;n>xtrnnum[i];n--)
816: cfg.xtrn[n]=cfg.xtrn[n-1];
817: if((cfg.xtrn[xtrnnum[i]]=(xtrn_t *)malloc(sizeof(xtrn_t)))==NULL) {
818: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(xtrn_t));
819: continue; }
820: memset((xtrn_t *)cfg.xtrn[xtrnnum[i]],0,sizeof(xtrn_t));
821: strcpy(cfg.xtrn[xtrnnum[i]]->name,str);
822: strcpy(cfg.xtrn[xtrnnum[i]]->code,code);
823: cfg.xtrn[xtrnnum[i]]->sec=section;
824: cfg.total_xtrns++;
825: uifc.changes=TRUE;
826: continue; }
827: if((i&MSK_ON)==MSK_DEL) {
828: i&=MSK_OFF;
829: free(cfg.xtrn[xtrnnum[i]]);
830: cfg.total_xtrns--;
831: for(j=xtrnnum[i];j<cfg.total_xtrns;j++)
832: cfg.xtrn[j]=cfg.xtrn[j+1];
833: uifc.changes=TRUE;
834: continue; }
835: if((i&MSK_ON)==MSK_GET) {
836: i&=MSK_OFF;
837: savxtrn=*cfg.xtrn[xtrnnum[i]];
838: continue; }
839: if((i&MSK_ON)==MSK_PUT) {
840: i&=MSK_OFF;
841: *cfg.xtrn[xtrnnum[i]]=savxtrn;
842: cfg.xtrn[xtrnnum[i]]->sec=section;
843: uifc.changes=TRUE;
844: continue; }
845: done=0;
846: i=xtrnnum[i];
847: while(!done) {
848: k=0;
849: sprintf(opt[k++],"%-27.27s%s","Name",cfg.xtrn[i]->name);
850: sprintf(opt[k++],"%-27.27s%s","Internal Code",cfg.xtrn[i]->code);
851: sprintf(opt[k++],"%-27.27s%.40s","Start-up Directory",cfg.xtrn[i]->path);
852: sprintf(opt[k++],"%-27.27s%.40s","Command Line",cfg.xtrn[i]->cmd);
853: sprintf(opt[k++],"%-27.27s%.40s","Clean-up Command Line",cfg.xtrn[i]->clean);
854: if(cfg.xtrn[i]->cost)
855: sprintf(str,"%lu credits",cfg.xtrn[i]->cost);
856: else
857: strcpy(str,"None");
858: sprintf(opt[k++],"%-27.27s%s","Execution Cost",str);
859: sprintf(opt[k++],"%-27.27s%.40s","Access Requirements",cfg.xtrn[i]->arstr);
860: sprintf(opt[k++],"%-27.27s%.40s","Execution Requirements"
861: ,cfg.xtrn[i]->run_arstr);
862: sprintf(opt[k++],"%-27.27s%s","Multiple Concurrent Users"
863: ,cfg.xtrn[i]->misc&MULTIUSER ? "Yes" : "No");
864: sprintf(opt[k++],"%-27.27s%s%s%s","Intercept Standard I/O"
865: ,cfg.xtrn[i]->misc&IO_INTS ? "Yes" : "No"
866: ,(cfg.xtrn[i]->misc&(IO_INTS|WWIVCOLOR))
867: ==(IO_INTS|WWIVCOLOR) ? ", WWIV Color" : nulstr
868: ,(cfg.xtrn[i]->misc&(IO_INTS|XTRN_NOECHO))
869: ==(IO_INTS|XTRN_NOECHO) ? ", No Echo" : nulstr);
870: sprintf(opt[k++],"%-27.27s%s","Native (32-bit) Executable"
871: ,cfg.xtrn[i]->misc&XTRN_NATIVE ? "Yes" : "No");
872: sprintf(opt[k++],"%-27.27s%s","Use Shell to Execute"
873: ,cfg.xtrn[i]->misc&XTRN_SH ? "Yes" : "No");
874: sprintf(opt[k++],"%-27.27s%s","Modify User Data"
875: ,cfg.xtrn[i]->misc&MODUSERDAT ? "Yes" : "No");
876: switch(cfg.xtrn[i]->event) {
877: case EVENT_LOGON:
878: strcpy(str,"Logon");
879: break;
880: case EVENT_LOGOFF:
881: strcpy(str,"Logoff");
882: break;
883: case EVENT_NEWUSER:
884: strcpy(str,"New User");
885: break;
886: case EVENT_BIRTHDAY:
887: strcpy(str,"Birthday");
888: break;
889: case EVENT_POST:
890: strcpy(str,"Message Posted");
891: break;
892: case EVENT_UPLOAD:
893: strcpy(str,"File Uploaded");
894: break;
895: case EVENT_DOWNLOAD:
896: strcpy(str,"File Downloaded");
897: break;
898: default:
899: strcpy(str,"No");
900: break;
901: }
902: if(cfg.xtrn[i]->misc&EVENTONLY && cfg.xtrn[i]->event)
903: strcat(str,", Only");
904: sprintf(opt[k++],"%-27.27s%s","Execute on Event",str);
905: sprintf(opt[k++],"%-27.27s%s","Pause After Execution"
906: ,cfg.xtrn[i]->misc&XTRN_PAUSE ? "Yes" : "No");
907: sprintf(opt[k++],"%-23.23s%-4s%s","BBS Drop File Type"
908: ,cfg.xtrn[i]->misc&REALNAME ? "(R)":nulstr
909: ,dropfile(cfg.xtrn[i]->type,cfg.xtrn[i]->misc));
910: sprintf(opt[k++],"%-27.27s%s","Place Drop File In"
911: ,cfg.xtrn[i]->misc&STARTUPDIR ? "Start-Up Directory":"Node Directory");
912: sprintf(opt[k++],"Time Options...");
913: opt[k][0]=0;
914: SETHELP(WHERE);
915: /*
916: &Online Program Configuration:&
917:
918: This menu is for configuring the selected online program.
919: */
920: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_MID,0,0,60,&opt_dflt,0,cfg.xtrn[i]->name
921: ,opt)) {
922: case -1:
923: done=1;
924: break;
925: case 0:
926: SETHELP(WHERE);
927: /*
928: &Online Program Name:&
929:
930: This is the name or description of the online program (door).
931: */
932: strcpy(str,cfg.xtrn[i]->name);
933: if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Online Program Name"
934: ,cfg.xtrn[i]->name,sizeof(cfg.xtrn[i]->name)-1,K_EDIT))
935: strcpy(cfg.xtrn[i]->name,str);
936: break;
937: case 1:
938: SETHELP(WHERE);
939: /*
940: &Online Program Internal Code:&
941:
942: Every online program must have its own unique code for Synchronet to
943: refer to it internally. This code is usually an abreviation of the
944: online program name.
945: */
946: strcpy(str,cfg.xtrn[i]->code);
947: uifc.input(WIN_MID|WIN_SAV,0,10,"Internal Code"
948: ,str,LEN_CODE,K_UPPER|K_EDIT);
949: if(code_ok(str))
950: strcpy(cfg.xtrn[i]->code,str);
951: else {
952: uifc.helpbuf=invalid_code;
953: uifc.msg("Invalid Code");
954: uifc.helpbuf=0;
955: }
956: break;
957: case 2:
958: SETHELP(WHERE);
959: /*
960: &Online Program Start-up Directory:&
961:
962: This is the DOS drive/directory where the online program is located.
963: If a path is specified here, it will be made the current directory
964: before the program's command line is executed. This eliminates the need
965: for batch files that just change the current drive and directory before
966: executing the program.
967:
968: If this option is not used, the current NODE's directory will be the
969: current DOS drive/directory before the command line is executed.
970: */
971: uifc.input(WIN_MID|WIN_SAV,0,10,""
972: ,cfg.xtrn[i]->path,sizeof(cfg.xtrn[i]->path)-1,K_EDIT);
973: break;
974: case 3:
975: SETHELP(WHERE);
976: /*
977: &Online Program Command Line:&
978:
979: This is the command line to execute to run the online program.
980: */
981: uifc.input(WIN_MID|WIN_SAV,0,10,"Command"
982: ,cfg.xtrn[i]->cmd,sizeof(cfg.xtrn[i]->cmd)-1,K_EDIT);
983: break;
984: case 4:
985: SETHELP(WHERE);
986: /*
987: &Online Program Clean-up Command:&
988:
989: This is the command line to execute after the main command line. This
990: option is usually only used for multiuser online programs.
991: */
992: uifc.input(WIN_MID|WIN_SAV,0,10,"Clean-up"
993: ,cfg.xtrn[i]->clean,sizeof(cfg.xtrn[i]->clean)-1,K_EDIT);
994: break;
995: case 5:
996: ultoa(cfg.xtrn[i]->cost,str,10);
997: SETHELP(WHERE);
998: /*
999: &Online Program Cost to Run:&
1000:
1001: If you want users to be charged credits to run this online program,
1002: set this value to the number of credits to charge. If you want this
1003: online program to be free, set this value to &0&.
1004: */
1005: uifc.input(WIN_MID|WIN_SAV,0,0,"Cost to Run (in Credits)"
1006: ,str,10,K_EDIT|K_NUMBER);
1007: cfg.xtrn[i]->cost=atol(str);
1008: break;
1009: case 6:
1010: sprintf(str,"%s Access",cfg.xtrn[i]->name);
1011: getar(str,cfg.xtrn[i]->arstr);
1012: break;
1013: case 7:
1014: sprintf(str,"%s Execution",cfg.xtrn[i]->name);
1015: getar(str,cfg.xtrn[i]->run_arstr);
1016: break;
1017: case 8:
1018: k=cfg.xtrn[i]->misc&MULTIUSER ? 0:1;
1019: strcpy(opt[0],"Yes");
1020: strcpy(opt[1],"No");
1021: opt[2][0]=0;
1022: SETHELP(WHERE);
1023: /*
1024: &Supports Multiple Users:&
1025:
1026: If this online program supports multiple simultaneous users (nodes),
1027: set this option to &Yes&.
1028: */
1029: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Supports Multiple Users"
1030: ,opt);
1031: if(!k && !(cfg.xtrn[i]->misc&MULTIUSER)) {
1032: cfg.xtrn[i]->misc|=MULTIUSER;
1033: uifc.changes=TRUE; }
1034: else if(k==1 && cfg.xtrn[i]->misc&MULTIUSER) {
1035: cfg.xtrn[i]->misc&=~MULTIUSER;
1036: uifc.changes=TRUE; }
1037: break;
1038: case 9:
1039: k=cfg.xtrn[i]->misc&IO_INTS ? 0:1;
1040: strcpy(opt[0],"Yes");
1041: strcpy(opt[1],"No");
1042: opt[2][0]=0;
1043: SETHELP(WHERE);
1044: /*
1045: &Intercept Standard I/O:&
1046:
1047: If this online program uses a FOSSIL driver or SOCKET communications,
1048: set this option to &No&.
1049: */
1050: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Intercept Standard I/O"
1051: ,opt);
1052: if(!k && !(cfg.xtrn[i]->misc&IO_INTS)) {
1053: cfg.xtrn[i]->misc|=IO_INTS;
1054: uifc.changes=TRUE; }
1055: else if(k==1 && cfg.xtrn[i]->misc&IO_INTS) {
1056: cfg.xtrn[i]->misc&=~(IO_INTS|WWIVCOLOR);
1057: uifc.changes=TRUE; }
1058: else if(k==-1)
1059: break;
1060: if(!(cfg.xtrn[i]->misc&IO_INTS))
1061: break;
1062: k=cfg.xtrn[i]->misc&WWIVCOLOR ? 0:1;
1063: SETHELP(WHERE);
1064: /*
1065: &Program Uses WWIV Color Codes:&
1066:
1067: If this program was written for use exclusively under WWIV, set this
1068: option to &Yes&.
1069: */
1070: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1071: ,"Program Uses WWIV Color Codes"
1072: ,opt);
1073: if(!k && !(cfg.xtrn[i]->misc&WWIVCOLOR)) {
1074: cfg.xtrn[i]->misc|=WWIVCOLOR;
1075: uifc.changes=TRUE; }
1076: else if(k==1 && cfg.xtrn[i]->misc&WWIVCOLOR) {
1077: cfg.xtrn[i]->misc&=~WWIVCOLOR;
1078: uifc.changes=TRUE; }
1079: k=cfg.xtrn[i]->misc&XTRN_NOECHO ? 1:0;
1080: SETHELP(WHERE);
1081: /*
1082: `Echo Input:`
1083:
1084: If you want the BBS to copy ("echo") all keyboard input to the screen
1085: output, set this option to ~Yes~ (for native Win32 programs only).
1086: */
1087: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1088: ,"Echo Keyboard Input"
1089: ,opt);
1090: if(!k && cfg.xtrn[i]->misc&XTRN_NOECHO) {
1091: cfg.xtrn[i]->misc&=~XTRN_NOECHO;
1092: uifc.changes=TRUE;
1093: } else if(k==1 && !(cfg.xtrn[i]->misc&XTRN_NOECHO)) {
1094: cfg.xtrn[i]->misc|=XTRN_NOECHO;
1095: uifc.changes=TRUE;
1096: }
1097: break;
1098: case 10:
1099: k=cfg.xtrn[i]->misc&XTRN_NATIVE ? 0:1;
1100: strcpy(opt[0],"Yes");
1101: strcpy(opt[1],"No");
1102: opt[2][0]=0;
1103: SETHELP(WHERE);
1104: /*
1105: &Native (32-bit) Executable:&
1106:
1107: If this online program is a native 32-bit executable,
1108: set this option to &Yes&.
1109: */
1110: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1111: ,"Native (32-bit)",opt);
1112: if(!k && !(cfg.xtrn[i]->misc&XTRN_NATIVE)) {
1113: cfg.xtrn[i]->misc|=XTRN_NATIVE;
1114: uifc.changes=TRUE; }
1115: else if(k==1 && cfg.xtrn[i]->misc&XTRN_NATIVE) {
1116: cfg.xtrn[i]->misc&=~XTRN_NATIVE;
1117: uifc.changes=TRUE; }
1118: break;
1119: case 11:
1120: k=cfg.xtrn[i]->misc&XTRN_SH ? 0:1;
1121: strcpy(opt[0],"Yes");
1122: strcpy(opt[1],"No");
1123: opt[2][0]=0;
1124: SETHELP(WHERE);
1125: /*
1126: `Use Shell to Execute Command:`
1127:
1128: If this command-line requires the system command shell to execute, (Unix
1129: shell script or DOS batch file), set this option to ~Yes~.
1130: */
1131: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1132: ,"Use Shell",opt);
1133: if(!k && !(cfg.xtrn[i]->misc&XTRN_SH)) {
1134: cfg.xtrn[i]->misc|=XTRN_SH;
1135: uifc.changes=TRUE;
1136: }
1137: else if(k==1 && cfg.xtrn[i]->misc&XTRN_SH) {
1138: cfg.xtrn[i]->misc&=~XTRN_SH;
1139: uifc.changes=TRUE;
1140: }
1141: break;
1142: case 12:
1143: k=cfg.xtrn[i]->misc&MODUSERDAT ? 0:1;
1144: strcpy(opt[0],"Yes");
1145: strcpy(opt[1],"No");
1146: opt[2][0]=0;
1147: SETHELP(WHERE);
1148: /*
1149: &Program Can Modify User Data:&
1150:
1151: If this online programs recognizes the Synchronet MODUSER.DAT format
1152: or the RBBS/QuickBBS EXITINFO.BBS format and you want it to be able to
1153: modify the data of users who run the program, set this option to &Yes&.
1154: */
1155: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1156: ,"Program Can Modify User Data",opt);
1157: if(!k && !(cfg.xtrn[i]->misc&MODUSERDAT)) {
1158: cfg.xtrn[i]->misc|=MODUSERDAT;
1159: uifc.changes=TRUE; }
1160: else if(k==1 && cfg.xtrn[i]->misc&MODUSERDAT) {
1161: cfg.xtrn[i]->misc&=~MODUSERDAT;
1162: uifc.changes=TRUE; }
1163: break;
1164: case 13:
1165: k=0;
1166: strcpy(opt[k++],"No");
1167: strcpy(opt[k++],"Logon");
1168: strcpy(opt[k++],"Logoff");
1169: strcpy(opt[k++],"New User");
1170: strcpy(opt[k++],"Birthday");
1171: strcpy(opt[k++],"Message Posted");
1172: strcpy(opt[k++],"File Uploaded");
1173: strcpy(opt[k++],"File Downloaded");
1174: opt[k][0]=0;
1175: k=cfg.xtrn[i]->event;
1176: SETHELP(WHERE);
1177: /*
1178: &Execute Online Program on Event:&
1179:
1180: If you would like this online program to automatically execute on a
1181: specific user event, select the event. Otherwise, select &No&.
1182: */
1183: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1184: ,"Execute on Event",opt);
1185: if(k==-1)
1186: break;
1187: if(cfg.xtrn[i]->event!=k) {
1188: cfg.xtrn[i]->event=k;
1189: uifc.changes=TRUE; }
1190: if(!cfg.xtrn[i]->event) {
1191: if(cfg.xtrn[i]->misc&EVENTONLY) {
1192: cfg.xtrn[i]->misc&=~EVENTONLY;
1193: uifc.changes=TRUE;
1194: }
1195: break;
1196: }
1197: k=cfg.xtrn[i]->misc&EVENTONLY ? 0:1;
1198: strcpy(opt[0],"Yes");
1199: strcpy(opt[1],"No");
1200: opt[2][0]=0;
1201: SETHELP(WHERE);
1202: /*
1203: &Execute Online Program as Event Only:&
1204:
1205: If you would like this online program to execute as an event only
1206: (not available to users on the online program menu), set this option
1207: to &Yes&.
1208: */
1209: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k
1210: ,0,"Execute as Event Only"
1211: ,opt);
1212: if(!k && !(cfg.xtrn[i]->misc&EVENTONLY)) {
1213: cfg.xtrn[i]->misc|=EVENTONLY;
1214: uifc.changes=TRUE; }
1215: else if(k==1 && cfg.xtrn[i]->misc&EVENTONLY) {
1216: cfg.xtrn[i]->misc&=~EVENTONLY;
1217: uifc.changes=TRUE; }
1218: break;
1219: case 14:
1220: k=cfg.xtrn[i]->misc&XTRN_PAUSE ? 0:1;
1221: strcpy(opt[0],"Yes");
1222: strcpy(opt[1],"No");
1223: opt[2][0]=0;
1224: SETHELP(WHERE);
1225: /*
1226: `Pause Screen After Execution:`
1227:
1228: Set this option to ~Yes~ if you would like an automatic screen pause
1229: (`[Hit a key]` prompt) to appear after the program executes.
1230:
1231: This can be useful if the program displays information just before exiting
1232: or you want to debug a program with a program not running correctly.
1233: */
1234: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1235: ,"Pause After Execution",opt);
1236: if((!k && !(cfg.xtrn[i]->misc&XTRN_PAUSE))
1237: || (k && cfg.xtrn[i]->misc&XTRN_PAUSE)) {
1238: cfg.xtrn[i]->misc^=XTRN_PAUSE;
1239: uifc.changes=TRUE;
1240: }
1241: break;
1242: case 15:
1243: k=0;
1244: strcpy(opt[k++],"None");
1245: sprintf(opt[k++],"%-15s %s","Synchronet","XTRN.DAT");
1246: sprintf(opt[k++],"%-15s %s","WWIV","CHAIN.TXT");
1247: sprintf(opt[k++],"%-15s %s","GAP","DOOR.SYS");
1248: sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO#.DEF");
1249: sprintf(opt[k++],"%-15s %s","Wildcat","CALLINFO.BBS");
1250: sprintf(opt[k++],"%-15s %s","PCBoard","PCBOARD.SYS");
1251: sprintf(opt[k++],"%-15s %s","SpitFire","SFDOORS.DAT");
1252: sprintf(opt[k++],"%-15s %s","MegaMail","UTIDOOR.TXT");
1253: sprintf(opt[k++],"%-15s %s","Solar Realms","DOORFILE.SR");
1254: sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO1.DEF");
1255: sprintf(opt[k++],"%-15s %s","TriBBS","TRIBBS.SYS");
1256: sprintf(opt[k++],"%-15s %s","Mystic","DOOR32.SYS");
1257: opt[k][0]=0;
1258: k=cfg.xtrn[i]->type;
1259: SETHELP(WHERE);
1260: /*
1261: &Online Program BBS Drop File Type:&
1262:
1263: If this online program requires a specific BBS data (drop) file
1264: format, select the file format from the list.
1265: */
1266: k=uifc.list(WIN_MID|WIN_ACT,0,0,0,&k,0
1267: ,"BBS Drop File Type",opt);
1268: if(k==-1)
1269: break;
1270: if(cfg.xtrn[i]->type!=k) {
1271: cfg.xtrn[i]->type=k;
1272: if(cfg.xtrn[i]->type==XTRN_DOOR32)
1273: cfg.xtrn[i]->misc|=XTRN_NATIVE;
1274: uifc.changes=TRUE; }
1275: if(cfg.xtrn[i]->type && cfg.uq&UQ_ALIASES) {
1276: strcpy(opt[0],"Yes");
1277: strcpy(opt[1],"No");
1278: opt[2][0]=0;
1279: k=cfg.xtrn[i]->misc&REALNAME ? 0:1;
1280: k=uifc.list(WIN_MID,0,0,0,&k,0,"Use Real Names",opt);
1281: if(k==0 && !(cfg.xtrn[i]->misc&REALNAME)) {
1282: cfg.xtrn[i]->misc|=REALNAME;
1283: uifc.changes=TRUE; }
1284: else if(k==1 && cfg.xtrn[i]->misc&REALNAME) {
1285: cfg.xtrn[i]->misc&=~REALNAME;
1286: uifc.changes=TRUE;
1287: }
1288: }
1289: if(cfg.xtrn[i]->type) {
1290: strcpy(opt[0],"Yes");
1291: strcpy(opt[1],"No");
1292: opt[2][0]=0;
1293: k=cfg.xtrn[i]->misc&XTRN_LWRCASE ? 0:1;
1294: k=uifc.list(WIN_MID,0,0,0,&k,0,"Lowercase Filename",opt);
1295: if(k==0 && !(cfg.xtrn[i]->misc&XTRN_LWRCASE)) {
1296: cfg.xtrn[i]->misc|=XTRN_LWRCASE;
1297: uifc.changes=TRUE;
1298: }
1299: else if(k==1 && cfg.xtrn[i]->misc&XTRN_LWRCASE) {
1300: cfg.xtrn[i]->misc&=~XTRN_LWRCASE;
1301: uifc.changes=TRUE;
1302: }
1303: }
1304: break;
1305: case 16:
1306: k=0;
1307: strcpy(opt[0],"Node Directory");
1308: strcpy(opt[1],"Start-up Directory");
1309: opt[2][0]=0;
1310: SETHELP(WHERE);
1311: /*
1312: &Directory for Drop File:&
1313:
1314: You can have the data file created in the current &Node Directory& or the
1315: &Start-up Directory& (if one is specified).
1316: */
1317: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Create Drop File In"
1318: ,opt);
1319: if(!k && cfg.xtrn[i]->misc&STARTUPDIR) {
1320: cfg.xtrn[i]->misc&=~STARTUPDIR;
1321: uifc.changes=TRUE; }
1322: else if(k==1 && !(cfg.xtrn[i]->misc&STARTUPDIR)) {
1323: cfg.xtrn[i]->misc|=STARTUPDIR;
1324: uifc.changes=TRUE; }
1325: break;
1326: case 17:
1327: while(1) {
1328: k=0;
1329: if(cfg.xtrn[i]->textra)
1330: sprintf(str,"%u minutes",cfg.xtrn[i]->textra);
1331: else
1332: strcpy(str,"None");
1333: sprintf(opt[k++],"%-25.25s%s","Extra Time",str);
1334: if(cfg.xtrn[i]->maxtime)
1335: sprintf(str,"%u minutes",cfg.xtrn[i]->maxtime);
1336: else
1337: strcpy(str,"None");
1338: sprintf(opt[k++],"%-25.25s%s","Maximum Time",str);
1339: sprintf(opt[k++],"%-25.25s%s","Suspended (Free) Time"
1340: ,cfg.xtrn[i]->misc&FREETIME ? "Yes" : "No");
1341: sprintf(opt[k++],"%-25.25s%s","Monitor Time Left"
1342: ,cfg.xtrn[i]->misc&XTRN_CHKTIME ? "Yes" : "No");
1343: opt[k][0]=0;
1344: SETHELP(WHERE);
1345: /*
1346: &Online Program Time Options:&
1347:
1348: This sub-menu allows you to define specific preferences regarding the
1349: time users spend running this program.
1350: */
1351: k=uifc.list(WIN_SAV|WIN_ACT|WIN_RHT|WIN_BOT,0,0,40
1352: ,&time_dflt,0
1353: ,"Online Program Time Options",opt);
1354: if(k==-1)
1355: break;
1356: switch(k) {
1357: case 0:
1358: ultoa(cfg.xtrn[i]->textra,str,10);
1359: SETHELP(WHERE);
1360: /*
1361: &Extra Time to Give User in Program:&
1362:
1363: If you want to give users extra time while in this online program,
1364: set this value to the number of minutes to add to their current time
1365: left online.
1366: */
1367: uifc.input(WIN_MID|WIN_SAV,0,0
1368: ,"Extra Time to Give User (in minutes)"
1369: ,str,2,K_EDIT|K_NUMBER);
1370: cfg.xtrn[i]->textra=atoi(str);
1371: break;
1372: case 1:
1373: ultoa(cfg.xtrn[i]->maxtime,str,10);
1374: SETHELP(WHERE);
1375: /*
1376: &Maximum Time Allowed in Program:&
1377:
1378: If this program supports a drop file that contains the number of minutes
1379: left online for the current user, this option allows the sysop to set
1380: the maximum number of minutes that will be allowed in the drop file.
1381:
1382: Setting this option to &0&, disables this feature.
1383: */
1384: uifc.input(WIN_MID|WIN_SAV,0,0
1385: ,"Maximum Time (in minutes, 0=disabled)"
1386: ,str,2,K_EDIT|K_NUMBER);
1387: cfg.xtrn[i]->maxtime=atoi(str);
1388: break;
1389: case 2:
1390: k=cfg.xtrn[i]->misc&FREETIME ? 0:1;
1391: strcpy(opt[0],"Yes");
1392: strcpy(opt[1],"No");
1393: opt[2][0]=0;
1394: SETHELP(WHERE);
1395: /*
1396: &Suspended (Free) Time:&
1397:
1398: If you want the user's time online to be suspended while running this
1399: online program (e.g. Free Time), set this option to &Yes&.
1400: */
1401: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1402: ,"Suspended (Free) Time",opt);
1403: if(!k && !(cfg.xtrn[i]->misc&FREETIME)) {
1404: cfg.xtrn[i]->misc|=FREETIME;
1405: uifc.changes=TRUE; }
1406: else if(k==1 && cfg.xtrn[i]->misc&FREETIME) {
1407: cfg.xtrn[i]->misc&=~FREETIME;
1408: uifc.changes=TRUE; }
1409: break;
1410: case 3:
1411: k=cfg.xtrn[i]->misc&XTRN_CHKTIME ? 0:1;
1412: strcpy(opt[0],"Yes");
1413: strcpy(opt[1],"No");
1414: opt[2][0]=0;
1415: SETHELP(WHERE);
1416: /*
1417: &Monitor Time Left:&
1418:
1419: If you want Synchronet to monitor the user's time left onlnie while this
1420: program runs (and disconnect the user if their time runs out), set this
1421: option to &Yes&.
1422: */
1423: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1424: ,"Monitor Time Left",opt);
1425: if(!k && !(cfg.xtrn[i]->misc&XTRN_CHKTIME)) {
1426: cfg.xtrn[i]->misc|=XTRN_CHKTIME;
1427: uifc.changes=TRUE; }
1428: else if(k==1 && cfg.xtrn[i]->misc&XTRN_CHKTIME) {
1429: cfg.xtrn[i]->misc&=~XTRN_CHKTIME;
1430: uifc.changes=TRUE; }
1431: break;
1432: }
1433: }
1434: break;
1435:
1436: } } }
1437: }
1438:
1439: void xedit_cfg()
1440: {
1441: static int dflt,dfltopt,bar;
1442: char str[81],code[81],done=0,*p;
1443: int j,k;
1444: uint i;
1445: static xedit_t savxedit;
1446:
1447: while(1) {
1448: for(i=0;i<cfg.total_xedits && i<MAX_OPTS;i++)
1449: sprintf(opt[i],"%-8.8s %.40s",cfg.xedit[i]->code,cfg.xedit[i]->rcmd);
1450: opt[i][0]=0;
1451: j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_RHT;
1452: if(cfg.total_xedits)
1453: j|=WIN_DEL|WIN_GET;
1454: if(cfg.total_xedits<MAX_OPTS)
1455: j|=WIN_INS|WIN_INSACT|WIN_XTR;
1456: if(savxedit.name[0])
1457: j|=WIN_PUT;
1458: SETHELP(WHERE);
1459: /*
1460: &External Editors:&
1461:
1462: This is a list of the configured external editors.
1463:
1464: To add an editor, select the desired location and hit INS .
1465:
1466: To delete an editor, select it and hit DEL .
1467:
1468: To configure an editor, select it and hit ENTER .
1469: */
1470: i=uifc.list(j,0,0,45,&dflt,&bar,"External Editors",opt);
1471: if((signed)i==-1)
1472: return;
1473: if((i&MSK_ON)==MSK_INS) {
1474: i&=MSK_OFF;
1475: SETHELP(WHERE);
1476: /*
1477: &External Editor Name:&
1478:
1479: This is the name or description of the external editor.
1480: */
1481: if(uifc.input(WIN_MID|WIN_SAV,0,0,"External Editor Name",str,40
1482: ,0)<1)
1483: continue;
1484: sprintf(code,"%.8s",str);
1485: p=strchr(code,' ');
1486: if(p) *p=0;
1487: strupr(code);
1488: SETHELP(WHERE);
1489: /*
1490: &External Editor Internal Code:&
1491:
1492: This is the internal code for the external editor.
1493: */
1494: if(uifc.input(WIN_MID|WIN_SAV,0,0,"External Editor Internal Code",code,8
1495: ,K_UPPER|K_EDIT)<1)
1496: continue;
1497: if(!code_ok(code)) {
1498: uifc.helpbuf=invalid_code;
1499: uifc.msg("Invalid Code");
1500: uifc.helpbuf=0;
1501: continue; }
1502:
1503: if((cfg.xedit=(xedit_t **)realloc(cfg.xedit
1504: ,sizeof(xedit_t *)*(cfg.total_xedits+1)))==NULL) {
1505: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_xedits+1);
1506: cfg.total_xedits=0;
1507: bail(1);
1508: continue; }
1509: if(cfg.total_xedits)
1510: for(j=cfg.total_xedits;j>i;j--)
1511: cfg.xedit[j]=cfg.xedit[j-1];
1512: if((cfg.xedit[i]=(xedit_t *)malloc(sizeof(xedit_t)))==NULL) {
1513: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(xedit_t));
1514: continue; }
1515: memset((xedit_t *)cfg.xedit[i],0,sizeof(xedit_t));
1516: strcpy(cfg.xedit[i]->name,str);
1517: strcpy(cfg.xedit[i]->code,code);
1518: cfg.total_xedits++;
1519: uifc.changes=TRUE;
1520: continue; }
1521: if((i&MSK_ON)==MSK_DEL) {
1522: i&=MSK_OFF;
1523: free(cfg.xedit[i]);
1524: cfg.total_xedits--;
1525: for(j=i;j<cfg.total_xedits;j++)
1526: cfg.xedit[j]=cfg.xedit[j+1];
1527: uifc.changes=TRUE;
1528: continue; }
1529: if((i&MSK_ON)==MSK_GET) {
1530: i&=MSK_OFF;
1531: savxedit=*cfg.xedit[i];
1532: continue; }
1533: if((i&MSK_ON)==MSK_PUT) {
1534: i&=MSK_OFF;
1535: *cfg.xedit[i]=savxedit;
1536: uifc.changes=TRUE;
1537: continue; }
1538: done=0;
1539: while(!done) {
1540: k=0;
1541: sprintf(opt[k++],"%-32.32s%s","Name",cfg.xedit[i]->name);
1542: sprintf(opt[k++],"%-32.32s%s","Internal Code",cfg.xedit[i]->code);
1543: sprintf(opt[k++],"%-32.32s%.40s","Remote Command Line",cfg.xedit[i]->rcmd);
1544: sprintf(opt[k++],"%-32.32s%.40s","Access Requirements",cfg.xedit[i]->arstr);
1545: sprintf(opt[k++],"%-32.32s%s%s","Intercept Standard I/O"
1546: ,cfg.xedit[i]->misc&IO_INTS ? "Yes":"No"
1547: ,cfg.xedit[i]->misc&WWIVCOLOR ? ", WWIV" : nulstr);
1548: sprintf(opt[k++],"%-32.32s%s","Native (32-bit) Executable"
1549: ,cfg.xedit[i]->misc&XTRN_NATIVE ? "Yes" : "No");
1550: sprintf(opt[k++],"%-32.32s%s","Use Shell to Execute"
1551: ,cfg.xedit[i]->misc&XTRN_SH ? "Yes" : "No");
1552: sprintf(opt[k++],"%-32.32s%s","Quoted Text"
1553: ,cfg.xedit[i]->misc"EALL ? "All":cfg.xedit[i]->misc"ENONE
1554: ? "None" : "Prompt User");
1555: sprintf(opt[k++],"%-32.32s%s","QuickBBS Style (MSGTMP)"
1556: ,cfg.xedit[i]->misc&QUICKBBS ? "Yes":"No");
1557: sprintf(opt[k++],"%-32.32s%s","Expand Line Feeds to CRLF"
1558: ,cfg.xedit[i]->misc&EXPANDLF ? "Yes":"No");
1559: sprintf(opt[k++],"%-32.32s%s","Strip FidoNet Kludge Lines"
1560: ,cfg.xedit[i]->misc&STRIPKLUDGE ? "Yes":"No");
1561: sprintf(opt[k++],"%-32.32s%s","BBS Drop File Type"
1562: ,dropfile(cfg.xedit[i]->type,cfg.xedit[i]->misc));
1563: opt[k][0]=0;
1564: SETHELP(WHERE);
1565: /*
1566: &External Editor Configuration:&
1567:
1568: This menu allows you to change the settings for the selected external
1569: message editor. External message editors are very common on BBSs. Some
1570: popular editors include &SyncEdit&, &WWIVedit&, &FEdit&, &GEdit&, &IceEdit&,
1571: and many others.
1572: */
1573:
1574: sprintf(str,"%s Editor",cfg.xedit[i]->name);
1575: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_L2R|WIN_BOT,0,0,70,&dfltopt,0
1576: ,str,opt)) {
1577: case -1:
1578: done=1;
1579: break;
1580: case 0:
1581: SETHELP(WHERE);
1582: /*
1583: &External Editor Name:&
1584:
1585: This is the name or description of the external editor.
1586: */
1587: strcpy(str,cfg.xedit[i]->name);
1588: if(!uifc.input(WIN_MID|WIN_SAV,0,10,"External Editor Name"
1589: ,cfg.xedit[i]->name,sizeof(cfg.xedit[i]->name)-1,K_EDIT))
1590: strcpy(cfg.xedit[i]->name,str);
1591: break;
1592: case 1:
1593: strcpy(str,cfg.xedit[i]->code);
1594: SETHELP(WHERE);
1595: /*
1596: &External Editor Internal Code:&
1597:
1598: Every external editor must have its own unique internal code for
1599: Synchronet to reference it by. It is helpful if this code is an
1600: abreviation of the name.
1601: */
1602: uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
1603: ,str,LEN_CODE,K_EDIT|K_UPPER);
1604: if(code_ok(str))
1605: strcpy(cfg.xedit[i]->code,str);
1606: else {
1607: uifc.helpbuf=invalid_code;
1608: uifc.msg("Invalid Code");
1609: uifc.helpbuf=0; }
1610: break;
1611: case 2:
1612: SETHELP(WHERE);
1613: /*
1614: &External Editor Remote Command Line:&
1615:
1616: This is the command line to execute when using this editor remotely.
1617: */
1618: uifc.input(WIN_MID|WIN_SAV,0,10,"Remote"
1619: ,cfg.xedit[i]->rcmd,sizeof(cfg.xedit[i]->rcmd)-1,K_EDIT);
1620: break;
1621: case 3:
1622: sprintf(str,"%s External Editor",cfg.xedit[i]->name);
1623: getar(str,cfg.xedit[i]->arstr);
1624: break;
1625: case 4:
1626: k=cfg.xedit[i]->misc&IO_INTS ? 0:1;
1627: strcpy(opt[0],"Yes");
1628: strcpy(opt[1],"No");
1629: opt[2][0]=0;
1630: SETHELP(WHERE);
1631: /*
1632: &Intercept Standard I/O:&
1633:
1634: If this external editor uses a FOSSIL driver or SOCKET communications,
1635: set this option to &No&.
1636: */
1637: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Intercept Standard I/O"
1638: ,opt);
1639: if(!k && !(cfg.xedit[i]->misc&IO_INTS)) {
1640: cfg.xedit[i]->misc|=IO_INTS;
1641: uifc.changes=TRUE; }
1642: else if(k==1 && cfg.xedit[i]->misc&IO_INTS) {
1643: cfg.xedit[i]->misc&=~(IO_INTS|WWIVCOLOR);
1644: uifc.changes=TRUE; }
1645: if(!(cfg.xedit[i]->misc&IO_INTS))
1646: break;
1647: k=cfg.xedit[i]->misc&WWIVCOLOR ? 0:1;
1648: strcpy(opt[0],"Yes");
1649: strcpy(opt[1],"No");
1650: opt[2][0]=0;
1651: SETHELP(WHERE);
1652: /*
1653: &Editor Uses WWIV Color Codes:&
1654:
1655: If this editor was written for use exclusively under WWIV, set this
1656: option to &Yes&.
1657: */
1658: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1659: ,"Editor Uses WWIV Color Codes",opt);
1660: if(!k && !(cfg.xedit[i]->misc&WWIVCOLOR)) {
1661: cfg.xedit[i]->misc|=WWIVCOLOR;
1662: uifc.changes=TRUE; }
1663: else if(k==1 && cfg.xedit[i]->misc&WWIVCOLOR) {
1664: cfg.xedit[i]->misc&=~WWIVCOLOR;
1665: uifc.changes=TRUE; }
1666: break;
1667: case 5:
1668: k=cfg.xedit[i]->misc&XTRN_NATIVE ? 0:1;
1669: strcpy(opt[0],"Yes");
1670: strcpy(opt[1],"No");
1671: opt[2][0]=0;
1672: SETHELP(WHERE);
1673: /*
1674: &Native (32-bit) Executable:&
1675:
1676: If this editor is a native 32-bit executable, set this option to &Yes&.
1677: */
1678: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1679: ,"Native (32-bit)",opt);
1680: if(!k && !(cfg.xedit[i]->misc&XTRN_NATIVE)) {
1681: cfg.xedit[i]->misc|=XTRN_NATIVE;
1682: uifc.changes=TRUE; }
1683: else if(k==1 && cfg.xedit[i]->misc&XTRN_NATIVE) {
1684: cfg.xedit[i]->misc&=~XTRN_NATIVE;
1685: uifc.changes=TRUE; }
1686: break;
1687: case 6:
1688: k=cfg.xedit[i]->misc&XTRN_SH ? 0:1;
1689: strcpy(opt[0],"Yes");
1690: strcpy(opt[1],"No");
1691: opt[2][0]=0;
1692: SETHELP(WHERE);
1693: /*
1694: `Use Shell to Execute Command:`
1695:
1696: If this command-line requires the system command shell to execute, (Unix
1697: shell script or DOS batch file), set this option to ~Yes~.
1698: */
1699: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1700: ,"Use Shell",opt);
1701: if(!k && !(cfg.xedit[i]->misc&XTRN_SH)) {
1702: cfg.xedit[i]->misc|=XTRN_SH;
1703: uifc.changes=TRUE;
1704: } else if(k==1 && cfg.xedit[i]->misc&XTRN_SH) {
1705: cfg.xedit[i]->misc&=~XTRN_SH;
1706: uifc.changes=TRUE;
1707: }
1708: break;
1709: case 7:
1710: k=3;
1711: strcpy(opt[0],"All");
1712: strcpy(opt[1],"None");
1713: strcpy(opt[2],"Prompt User");
1714: opt[3][0]=0;
1715: SETHELP(WHERE);
1716: /*
1717: &Quoted Text:&
1718:
1719: If you want all the message text to be automatically entered into the
1720: message edit/quote file (&INPUT.MSG& or &MSGTMP&), select &All&.
1721:
1722: If you want the user to be prompted for which lines to quote before
1723: running the editor, select &Prompt User&.
1724:
1725: If you want none of the lines to be automatically quoted, select &None&.
1726: This option is mainly for use with editors that support the "ES.TXT&
1727: drop file (like &SyncEdit v2.x&).
1728: */
1729: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Quoted Text"
1730: ,opt);
1731: if(!k && !(cfg.xedit[i]->misc"EALL)) {
1732: cfg.xedit[i]->misc|=QUOTEALL;
1733: cfg.xedit[i]->misc&=~QUOTENONE;
1734: uifc.changes=TRUE; }
1735: else if(k==1 && !(cfg.xedit[i]->misc"ENONE)) {
1736: cfg.xedit[i]->misc|=QUOTENONE;
1737: cfg.xedit[i]->misc&=~QUOTEALL;
1738: uifc.changes=TRUE; }
1739: else if(k==2 && cfg.xedit[i]->misc&(QUOTENONE|QUOTEALL)) {
1740: cfg.xedit[i]->misc&=~(QUOTENONE|QUOTEALL);
1741: uifc.changes=TRUE; }
1742: break;
1743: case 8:
1744: k=cfg.xedit[i]->misc&QUICKBBS ? 0:1;
1745: strcpy(opt[0],"Yes");
1746: strcpy(opt[1],"No");
1747: opt[2][0]=0;
1748: SETHELP(WHERE);
1749: /*
1750: &QuickBBS Style (MSGTMP):&
1751:
1752: If this external editor uses the QuickBBS style MSGTMP interface, set
1753: this option to &Yes&.
1754: */
1755: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"QuickBBS Style (MSGTMP)"
1756: ,opt);
1757: if(!k && !(cfg.xedit[i]->misc&QUICKBBS)) {
1758: cfg.xedit[i]->misc|=QUICKBBS;
1759: uifc.changes=TRUE; }
1760: else if(k==1 && cfg.xedit[i]->misc&QUICKBBS) {
1761: cfg.xedit[i]->misc&=~QUICKBBS;
1762: uifc.changes=TRUE; }
1763: break;
1764: case 9:
1765: k=cfg.xedit[i]->misc&EXPANDLF ? 0:1;
1766: strcpy(opt[0],"Yes");
1767: strcpy(opt[1],"No");
1768: opt[2][0]=0;
1769: SETHELP(WHERE);
1770: /*
1771: &Expand Line Feeds to Carriage Return/Line Feed Pairs:&
1772:
1773: If this external editor saves new lines as a single line feed character
1774: instead of a carriage return/line feed pair, set this option to &Yes&.
1775: */
1776: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Expand LF to CRLF"
1777: ,opt);
1778: if(!k && !(cfg.xedit[i]->misc&EXPANDLF)) {
1779: cfg.xedit[i]->misc|=EXPANDLF;
1780: uifc.changes=TRUE; }
1781: else if(k==1 && cfg.xedit[i]->misc&EXPANDLF) {
1782: cfg.xedit[i]->misc&=~EXPANDLF;
1783: uifc.changes=TRUE; }
1784: break;
1785: case 10:
1786: k=cfg.xedit[i]->misc&STRIPKLUDGE ? 0:1;
1787: strcpy(opt[0],"Yes");
1788: strcpy(opt[1],"No");
1789: opt[2][0]=0;
1790: SETHELP(WHERE);
1791: /*
1792: &Strip FidoNet Kludge Lines From Messages:&
1793:
1794: If this external editor adds FidoNet Kludge lines to the message text,
1795: set this option to &Yes& to strip those lines from the message.
1796: */
1797: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1798: ,"Strip FidoNet Kludge Lines"
1799: ,opt);
1800: if(!k && !(cfg.xedit[i]->misc&STRIPKLUDGE)) {
1801: cfg.xedit[i]->misc|=STRIPKLUDGE;
1802: uifc.changes=TRUE; }
1803: else if(k==1 && cfg.xedit[i]->misc&STRIPKLUDGE) {
1804: cfg.xedit[i]->misc&=~STRIPKLUDGE;
1805: uifc.changes=TRUE; }
1806: break;
1807: case 11:
1808: k=0;
1809: strcpy(opt[k++],"None");
1810: sprintf(opt[k++],"%-15s %s","Synchronet","XTRN.DAT");
1811: sprintf(opt[k++],"%-15s %s","WWIV","CHAIN.TXT");
1812: sprintf(opt[k++],"%-15s %s","GAP","DOOR.SYS");
1813: sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO#.DEF");
1814: sprintf(opt[k++],"%-15s %s","Wildcat","CALLINFO.BBS");
1815: sprintf(opt[k++],"%-15s %s","PCBoard","PCBOARD.SYS");
1816: sprintf(opt[k++],"%-15s %s","SpitFire","SFDOORS.DAT");
1817: sprintf(opt[k++],"%-15s %s","MegaMail","UTIDOOR.TXT");
1818: sprintf(opt[k++],"%-15s %s","Solar Realms","DOORFILE.SR");
1819: sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO1.DEF");
1820: sprintf(opt[k++],"%-15s %s","TriBBS","TRIBBS.SYS");
1821: sprintf(opt[k++],"%-15s %s","Mystic","DOOR32.SYS");
1822: opt[k][0]=0;
1823: k=cfg.xedit[i]->type;
1824: SETHELP(WHERE);
1825: /*
1826: &External Program BBS Drop File Type:&
1827:
1828: If this external editor requires a specific BBS data (drop) file
1829: format, select the file format from the list.
1830: */
1831: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
1832: ,"BBS Drop File Type",opt);
1833: if(k==-1)
1834: break;
1835: if(cfg.xedit[i]->type!=k) {
1836: cfg.xedit[i]->type=k;
1837: if(cfg.xedit[i]->type==XTRN_DOOR32)
1838: cfg.xedit[i]->misc|=XTRN_NATIVE;
1839: uifc.changes=TRUE;
1840: }
1841: if(cfg.xedit[i]->type) {
1842: strcpy(opt[0],"Yes");
1843: strcpy(opt[1],"No");
1844: opt[2][0]=0;
1845: k=cfg.xedit[i]->misc&XTRN_LWRCASE ? 0:1;
1846: k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Lowercase Filename",opt);
1847: if(k==0 && !(cfg.xedit[i]->misc&XTRN_LWRCASE)) {
1848: cfg.xedit[i]->misc|=XTRN_LWRCASE;
1849: uifc.changes=TRUE;
1850: }
1851: else if(k==1 && cfg.xedit[i]->misc&XTRN_LWRCASE) {
1852: cfg.xedit[i]->misc&=~XTRN_LWRCASE;
1853: uifc.changes=TRUE;
1854: }
1855: }
1856: break;
1857:
1858: } } }
1859: }
1860:
1861: int natvpgm_cfg()
1862: {
1863: static int dflt,bar;
1864: char str[81];
1865: int j;
1866: uint i;
1867:
1868: while(1) {
1869: for(i=0;i<MAX_OPTS && i<cfg.total_natvpgms;i++)
1870: sprintf(opt[i],"%-12s",cfg.natvpgm[i]->name);
1871: opt[i][0]=0;
1872: j=WIN_ACT|WIN_CHE|WIN_L2R|WIN_SAV;
1873: if(cfg.total_natvpgms)
1874: j|=WIN_DEL;
1875: if(cfg.total_natvpgms<MAX_OPTS)
1876: j|=WIN_INS|WIN_INSACT|WIN_XTR;
1877: SETHELP(WHERE);
1878: /*
1879: &Native (32-bit) Program List:&
1880:
1881: This is a list of all native (32-bit) external program (executable file)
1882: names that you may execute under &Synchronet&. This list is not
1883: used in Synchronet for DOS. Any programs not listed here will be assumed
1884: to be DOS programs and executed accordingly.
1885:
1886: Use INS and DELETE to add and remove native program names.
1887:
1888: To change the filename of a program, hit ENTER .
1889: */
1890: i=uifc.list(j,0,0,30,&dflt,&bar,"Native (32-bit) Program List",opt);
1891: if((signed)i==-1)
1892: break;
1893: if((i&MSK_ON)==MSK_INS) {
1894: i&=MSK_OFF;
1895: SETHELP(WHERE);
1896: /*
1897: &Native (32-bit) Program Name:&
1898:
1899: This is the executable filename of the native external program.
1900: */
1901: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Native Program Name",str,12
1902: ,0)<1)
1903: continue;
1904: if((cfg.natvpgm=(natvpgm_t **)realloc(cfg.natvpgm
1905: ,sizeof(natvpgm_t *)*(cfg.total_natvpgms+1)))==NULL) {
1906: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_natvpgms+1);
1907: cfg.total_natvpgms=0;
1908: bail(1);
1909: continue; }
1910: if(cfg.total_natvpgms)
1911: for(j=cfg.total_natvpgms;j>i;j--)
1912: cfg.natvpgm[j]=cfg.natvpgm[j-1];
1913: if((cfg.natvpgm[i]=(natvpgm_t *)malloc(sizeof(natvpgm_t)))==NULL) {
1914: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(natvpgm_t));
1915: continue; }
1916: memset((natvpgm_t *)cfg.natvpgm[i],0,sizeof(natvpgm_t));
1917: strcpy(cfg.natvpgm[i]->name,str);
1918: cfg.total_natvpgms++;
1919: uifc.changes=TRUE;
1920: continue; }
1921: if((i&MSK_ON)==MSK_DEL) {
1922: i&=MSK_OFF;
1923: free(cfg.natvpgm[i]);
1924: cfg.total_natvpgms--;
1925: for(j=i;j<cfg.total_natvpgms;j++)
1926: cfg.natvpgm[j]=cfg.natvpgm[j+1];
1927: uifc.changes=TRUE;
1928: continue; }
1929: SETHELP(WHERE);
1930: /*
1931: &Native Program Name:&
1932:
1933: This is the executable filename of the Native external program.
1934: */
1935: strcpy(str,cfg.natvpgm[i]->name);
1936: if(uifc.input(WIN_MID|WIN_SAV,0,5,"Native (32-bit) Program Name",str,12
1937: ,K_EDIT)>0)
1938: strcpy(cfg.natvpgm[i]->name,str);
1939: }
1940: return(0);
1941: }
1942:
1943:
1944: void xtrnsec_cfg()
1945: {
1946: static int xtrnsec_dflt,xtrnsec_opt;
1947: char str[81],code[9],done=0,*p;
1948: int j,k;
1949: uint i;
1950: static xtrnsec_t savxtrnsec;
1951:
1952: while(1) {
1953: for(i=0;i<cfg.total_xtrnsecs && i<MAX_OPTS;i++)
1954: sprintf(opt[i],"%-25s",cfg.xtrnsec[i]->name);
1955: opt[i][0]=0;
1956: j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_BOT;
1957: if(cfg.total_xtrnsecs)
1958: j|=WIN_DEL|WIN_GET;
1959: if(cfg.total_xtrnsecs<MAX_OPTS)
1960: j|=WIN_INS|WIN_INSACT|WIN_XTR;
1961: if(savxtrnsec.name[0])
1962: j|=WIN_PUT;
1963: SETHELP(WHERE);
1964: /*
1965: &Online Program Sections:&
1966:
1967: This is a list of &Online Program Sections& configured for your system.
1968:
1969: To add an online program section, select the desired location with the
1970: arrow keys and hit INS .
1971:
1972: To delete an online program section, select it and hit DEL .
1973:
1974: To configure an online program section, select it and hit ENTER .
1975: */
1976: i=uifc.list(j,0,0,45,&xtrnsec_dflt,0,"Online Program Sections",opt);
1977: if((signed)i==-1)
1978: return;
1979: if((i&MSK_ON)==MSK_INS) {
1980: i&=MSK_OFF;
1981: SETHELP(WHERE);
1982: /*
1983: &Online Program Section Name:&
1984:
1985: This is the name of this section.
1986: */
1987: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Online Program Section Name",str,40
1988: ,0)<1)
1989: continue;
1990: sprintf(code,"%.8s",str);
1991: p=strchr(code,' ');
1992: if(p) *p=0;
1993: strupr(code);
1994: SETHELP(WHERE);
1995: /*
1996: &Online Program Section Internal Code:&
1997:
1998: Every online program section must have its own unique internal code
1999: for Synchronet to reference it by. It is helpful if this code is an
2000: abreviation of the name.
2001: */
2002: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Online Program Section Internal Code"
2003: ,code,LEN_CODE,K_EDIT|K_UPPER)<1)
2004: continue;
2005: if(!code_ok(code)) {
2006: uifc.helpbuf=invalid_code;
2007: uifc.msg("Invalid Code");
2008: uifc.helpbuf=0;
2009: continue; }
2010: if((cfg.xtrnsec=(xtrnsec_t **)realloc(cfg.xtrnsec
2011: ,sizeof(xtrnsec_t *)*(cfg.total_xtrnsecs+1)))==NULL) {
2012: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_xtrnsecs+1);
2013: cfg.total_xtrnsecs=0;
2014: bail(1);
2015: continue; }
2016: if(cfg.total_xtrnsecs) {
2017: for(j=cfg.total_xtrnsecs;j>i;j--)
2018: cfg.xtrnsec[j]=cfg.xtrnsec[j-1];
2019: for(j=0;j<cfg.total_xtrns;j++)
2020: if(cfg.xtrn[j]->sec>=i)
2021: cfg.xtrn[j]->sec++; }
2022:
2023:
2024: if((cfg.xtrnsec[i]=(xtrnsec_t *)malloc(sizeof(xtrnsec_t)))==NULL) {
2025: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(xtrnsec_t));
2026: continue; }
2027: memset((xtrnsec_t *)cfg.xtrnsec[i],0,sizeof(xtrnsec_t));
2028: strcpy(cfg.xtrnsec[i]->name,str);
2029: strcpy(cfg.xtrnsec[i]->code,code);
2030: cfg.total_xtrnsecs++;
2031: uifc.changes=TRUE;
2032: continue; }
2033: if((i&MSK_ON)==MSK_DEL) {
2034: i&=MSK_OFF;
2035: free(cfg.xtrnsec[i]);
2036: for(j=0;j<cfg.total_xtrns;) {
2037: if(cfg.xtrn[j]->sec==i) { /* delete xtrns of this group */
2038: free(cfg.xtrn[j]);
2039: cfg.total_xtrns--;
2040: k=j;
2041: while(k<cfg.total_xtrns) { /* move all xtrns down */
2042: cfg.xtrn[k]=cfg.xtrn[k+1];
2043: k++; } }
2044: else j++; }
2045: for(j=0;j<cfg.total_xtrns;j++) /* move xtrn group numbers down */
2046: if(cfg.xtrn[j]->sec>i)
2047: cfg.xtrn[j]->sec--;
2048: cfg.total_xtrnsecs--;
2049: while(i<cfg.total_xtrnsecs) {
2050: cfg.xtrnsec[i]=cfg.xtrnsec[i+1];
2051: i++; }
2052: uifc.changes=TRUE;
2053: continue; }
2054: if((i&MSK_ON)==MSK_GET) {
2055: i&=MSK_OFF;
2056: savxtrnsec=*cfg.xtrnsec[i];
2057: continue; }
2058: if((i&MSK_ON)==MSK_PUT) {
2059: i&=MSK_OFF;
2060: *cfg.xtrnsec[i]=savxtrnsec;
2061: uifc.changes=TRUE;
2062: continue; }
2063: done=0;
2064: while(!done) {
2065: k=0;
2066: sprintf(opt[k++],"%-27.27s%s","Name",cfg.xtrnsec[i]->name);
2067: sprintf(opt[k++],"%-27.27s%s","Internal Code",cfg.xtrnsec[i]->code);
2068: sprintf(opt[k++],"%-27.27s%.40s","Access Requirements"
2069: ,cfg.xtrnsec[i]->arstr);
2070: sprintf(opt[k++],"%s","Available Online Programs...");
2071: opt[k][0]=0;
2072: sprintf(str,"%s Program Section",cfg.xtrnsec[i]->name);
2073: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_MID,0,0,60,&xtrnsec_opt,0,str
2074: ,opt)) {
2075: case -1:
2076: done=1;
2077: break;
2078: case 0:
2079: SETHELP(WHERE);
2080: /*
2081: &Online Program Section Name:&
2082:
2083: This is the name of this section.
2084: */
2085: strcpy(str,cfg.xtrnsec[i]->name); /* save */
2086: if(!uifc.input(WIN_MID|WIN_SAV,0,10
2087: ,"Program Section Name"
2088: ,cfg.xtrnsec[i]->name,sizeof(cfg.xtrnsec[i]->name)-1,K_EDIT))
2089: strcpy(cfg.xtrnsec[i]->name,str);
2090: break;
2091: case 1:
2092: strcpy(str,cfg.xtrnsec[i]->code);
2093: SETHELP(WHERE);
2094: /*
2095: &Online Program Section Internal Code:&
2096:
2097: Every online program section must have its own unique internal code
2098: for Synchronet to reference it by. It is helpful if this code is an
2099: abreviation of the name.
2100: */
2101: uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
2102: ,str,LEN_CODE,K_EDIT|K_UPPER);
2103: if(code_ok(str))
2104: strcpy(cfg.xtrnsec[i]->code,str);
2105: else {
2106: uifc.helpbuf=invalid_code;
2107: uifc.msg("Invalid Code");
2108: uifc.helpbuf=0;
2109: }
2110: break;
2111: case 2:
2112: getar(cfg.xtrnsec[i]->name,cfg.xtrnsec[i]->arstr);
2113: break;
2114: case 3:
2115: xtrn_cfg(i);
2116: break;
2117: }
2118: }
2119: }
2120: }
2121:
2122: void hotkey_cfg(void)
2123: {
2124: static int dflt,dfltopt,bar;
2125: char str[81],done=0;
2126: int j,k;
2127: uint i;
2128: static hotkey_t savhotkey;
2129:
2130: while(1) {
2131: for(i=0;i<cfg.total_hotkeys && i<MAX_OPTS;i++)
2132: sprintf(opt[i],"Ctrl-%c %.40s"
2133: ,cfg.hotkey[i]->key+'@'
2134: ,cfg.hotkey[i]->cmd);
2135: opt[i][0]=0;
2136: j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_RHT;
2137: if(cfg.total_hotkeys)
2138: j|=WIN_DEL|WIN_GET;
2139: if(cfg.total_hotkeys<MAX_OPTS)
2140: j|=WIN_INS|WIN_INSACT|WIN_XTR;
2141: if(savhotkey.cmd[0])
2142: j|=WIN_PUT;
2143: SETHELP(WHERE);
2144: /*
2145: &Global Hot Key Events:&
2146:
2147: This is a list of programs or loadable modules that can be executed by
2148: anyone on the BBS at any time (while the BBS has control of user input).
2149:
2150: To add a hot key event, select the desired location and hit INS .
2151:
2152: To delete a hot key event, select it and hit DEL .
2153:
2154: To configure a hot key event, select it and hit ENTER .
2155: */
2156: i=uifc.list(j,0,0,45,&dflt,&bar,"Global Hot Key Events",opt);
2157: if((signed)i==-1)
2158: return;
2159: if((i&MSK_ON)==MSK_INS) {
2160: i&=MSK_OFF;
2161: SETHELP(WHERE);
2162: /*
2163: &Global Hot Key:&
2164:
2165: This is the control key used to trigger the hot key event. Example, A
2166: indicates a Ctrl-A hot key event.
2167: */
2168: if(uifc.input(WIN_MID|WIN_SAV,0,0,"Control Key",str,1
2169: ,K_UPPER)<1)
2170: continue;
2171:
2172: if((cfg.hotkey=(hotkey_t **)realloc(cfg.hotkey
2173: ,sizeof(hotkey_t *)*(cfg.total_hotkeys+1)))==NULL) {
2174: errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_hotkeys+1);
2175: cfg.total_hotkeys=0;
2176: bail(1);
2177: continue; }
2178: if(cfg.total_hotkeys)
2179: for(j=cfg.total_hotkeys;j>i;j--)
2180: cfg.hotkey[j]=cfg.hotkey[j-1];
2181: if((cfg.hotkey[i]=(hotkey_t *)malloc(sizeof(hotkey_t)))==NULL) {
2182: errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(hotkey_t));
2183: continue; }
2184: memset((hotkey_t *)cfg.hotkey[i],0,sizeof(hotkey_t));
2185: cfg.hotkey[i]->key=str[0]-'@';
2186: cfg.total_hotkeys++;
2187: uifc.changes=TRUE;
2188: continue; }
2189: if((i&MSK_ON)==MSK_DEL) {
2190: i&=MSK_OFF;
2191: free(cfg.hotkey[i]);
2192: cfg.total_hotkeys--;
2193: for(j=i;j<cfg.total_hotkeys;j++)
2194: cfg.hotkey[j]=cfg.hotkey[j+1];
2195: uifc.changes=TRUE;
2196: continue; }
2197: if((i&MSK_ON)==MSK_GET) {
2198: i&=MSK_OFF;
2199: savhotkey=*cfg.hotkey[i];
2200: continue; }
2201: if((i&MSK_ON)==MSK_PUT) {
2202: i&=MSK_OFF;
2203: *cfg.hotkey[i]=savhotkey;
2204: uifc.changes=TRUE;
2205: continue; }
2206: done=0;
2207: while(!done) {
2208: k=0;
2209: sprintf(opt[k++],"%-27.27sCtrl-%c","Global Hot Key"
2210: ,cfg.hotkey[i]->key+'@');
2211: sprintf(opt[k++],"%-27.27s%.40s","Command Line",cfg.hotkey[i]->cmd);
2212: opt[k][0]=0;
2213: SETHELP(WHERE);
2214: /*
2215: &Global Hot Key Event:&
2216:
2217: This menu allows you to change the settings for the selected global
2218: hot key event. Hot key events are control characters that are used to
2219: execute an external program or module anywhere in the BBS.
2220: */
2221: sprintf(str,"Ctrl-%c Hot Key Event",cfg.hotkey[i]->key+'@');
2222: switch(uifc.list(WIN_SAV|WIN_ACT|WIN_L2R|WIN_BOT,0,0,60,&dfltopt,0
2223: ,str,opt)) {
2224: case -1:
2225: done=1;
2226: break;
2227: case 0:
2228: SETHELP(WHERE);
2229: /*
2230: &Global Hot-Ctrl Key:&
2231:
2232: This is the global control key used to execute this event.
2233: */
2234: sprintf(str,"%c",cfg.hotkey[i]->key+'@');
2235: if(uifc.input(WIN_MID|WIN_SAV,0,10,"Global Hot Ctrl-Key"
2236: ,str,1,K_EDIT|K_UPPER)>0)
2237: cfg.hotkey[i]->key=str[0]-'@';
2238: break;
2239: case 1:
2240: SETHELP(WHERE);
2241: /*
2242: &Hot Key Event Command Line:&
2243:
2244: This is the command line to execute when this hot key is pressed.
2245: */
2246: uifc.input(WIN_MID|WIN_SAV,0,10,"Command Line"
2247: ,cfg.hotkey[i]->cmd,sizeof(cfg.hotkey[i]->cmd)-1,K_EDIT);
2248: break;
2249: } } }
2250:
2251: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.