-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCONVERS.C
3175 lines (2898 loc) · 89.8 KB
/
CONVERS.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* convers server - based on conversd written by DK5SG
* ported to WNOS by DB3FL - 9109xx/9110xx
* ported to NOS by PE1NMB - 920120
* Mods by PA0GRI
* Cleanup, and additional mods by WG7J
* Additions by N2RJT & WA2ZKD
* More mods by N5KNX 1/96.
*/
#undef riskcmdoutlossage 1 /* defined => don't flush on NLs in /cmd output
* (risking loss if noblocking is also defined)
*/
#define noblocking 1 /* defined => drop data from TX queue if > LOCSFLOW,
* so as to conserve mem devoted to o/p queues
* (to avoid breaking XCONVERS, blocking is forced on for that code only)
*/
#undef oldlocks 1 /* defined => use global 'locked' flag, which is
* modified asynchronously by multiple convers
* processes, hence can't work reliably.
*/
#undef Oldcode 1 /* defined => use larger work buffers for msg display
* consuming more stack space
*/
#undef no_dupes 1 /* defined => /name, USER cmds are checked to
* eliminate duplicate user names. No other
* converse server does this, so why bother?
*/
#include <time.h>
#include <ctype.h>
#ifdef UNIX
#include <sys/types.h>
#include <sys/stat.h>
#endif
#ifdef MSDOS
#include <alloc.h>
#include <io.h>
#endif
#include <errno.h>
#include "global.h"
#ifdef CONVERS
#include "mailbox.h"
#include "netuser.h"
#include "pktdrvr.h"
#include "timer.h"
#include "cmdparse.h"
#include "usock.h"
#include "socket.h"
#include "session.h"
#include "files.h"
#include "mailutil.h"
#include "commands.h"
/*
* Explanations of compile-time options:
*
* #define XCONVERS 1 "LZW Compressed convers server and links"
* Socket 3601 implies use of LZW-compressed links.
* LZW compression tends to use MORE link bandwidth
* since most msgs are short, and are dominated by
* the size of the data dictionary which must accompany
* the msgs. XCONVERS is thus deprecated.
* Start by: start convers 3601
* #define CNV_VERBOSE 1 "Verbose msgs"
* Converse msgs can be longer instead of terser, at
* the expense of more RAM and bandwidth used.
* #define CNV_CHAN_NAMES 1 "Convers named channels"
* Channels can have names, if the sysop puts them in
* channel.dat file. The format is simple: each line
* contains a number followed by a space and a channel
* name. All linked convers nodes should use the same
* names!
* #define CNV_CALLCHECK 1 "Convers only allows callsigns"
* Some people like this, others don't. It forces the
* name used in convers to be a Ham callsign.
* #define CNV_LOCAL_CHANS 1 "Convers local channels and msg-only channels"
* Local channels only allow chatting on local node, ie,
* the data are not sent to linked convers servers.
* Msg-only channels only allow /msg traffic.
* Nice for when you step out for a few minutes.
* #define CNV_ENHANCED_VIA 1 "If convers user is local, 'via' gives more info"
* For the /who output, if the user is local, use the
* otherwise blank "via" field to show how the user is
* connected. If ax25, show the port name. If netrom,
* show the node name. If telnet, just say telnet,
* since his domain name won't fit.
* #define CNV_CHG_PERSONAL 1 "Allow users to change personal data permanently"
* Enables the CONVERS SETINFO command, which allows
* changes made with the /personal command to be stored
* permanently in dbase.dat. Nice for lazy sysops!
* #define CNV_LINKCHG_MSG 1 "Send link-change messages in convers"
* Sends a message on all channels alerting local users
* whenever a link to another convers node is added or
* dropped. When a link is dropped, all of the lost
* users are listed on one line (or more..) instead
* of showing "XXXXX signed off" for each individual.
* #define LINK 1 "permit this convers node to be linked with others"
* This is normally defined, since it's much more fun!
* #define CNV_TOPICS 1 "Include channel topic gathering"
* Only if LINK and CNV_CHAN_NAMES are also #defined.
* #define CNV_VERBOSE_CHGS "Default to /VERBOSE yes"
* Show signon/signoff notifications; generates lots
* of msgs and hence local traffic.
* #define CNV_STRICT_ASCII 1 "Disallow 8-bit char codes in messages"
* Define if you wish to limit msg text to the 7-bit ASCII
* set. Actually only the first char of the msg is tested!
* #define CNV_TIMESTAMP_MSG 1 "Add hh:mm prefix to msgs sent to local users"
*/
#ifndef LINK
#undef CNV_LINKCHG_MSG
#undef CNV_TOPICS
#endif
#ifndef CNV_CHAN_NAMES
#undef CNV_TOPICS
#endif
char Chostname[CNAMELEN+1];
int ConvUsers;
int ConvHosts;
#ifdef CNV_VERBOSE
static char cnumber[] = "*** Channel numbers must be in the range 0..%d.\n";
#ifdef CNV_LOCAL_CHANS
static char clocal[] = "*** This is a local channel - no chatting with other nodes\n";
static char cmessage[]= "*** This is a message channel - only /msg allowed or received\n";
#endif
#else
static char cnumber[] = "* range 0..%d.\n";
#ifdef CNV_LOCAL_CHANS
static char clocal[] = "* LOCAL CHANNEL\n";
static char cmessage[]= "* MESSAGE CHANNEL\n";
#endif
#endif
#define MAXCHANNEL 32767
#define LINELEN 256
/* The convers daemon stack needs to be AT LEAST 4 times the LINELEN !
* since quiet a few of the commands have local vars of size 2 or 3 * LINELEN.
*/
#ifdef Oldcode
#define CDAEMONSTACK 2048
#else
#define CDAEMONSTACK 1280
#endif
#define CLINKSTACK 1024
#define MAX_WAITTIME (60*60*3)
#define NAMELEN 10 /* Adjust all sscanf %10s lengths to match! */
#define CONNECT_TIMEOUT (300*1000L)
#define myfeatures "up" /* see tpp-1.14 SPECS: ping-pong + USER/UDAT */
struct convection {
int type; /* Connection type */
#define CT_UNKNOWN 0
#define CT_USER 1
#define CT_HOST 2
#define CT_CLOSED 3
char name[NAMELEN+1]; /* Name of user or host */
char host[NAMELEN+1]; /* Name of host where user is logged on */
struct convection *via; /* Pointer to neighbor host */
char *data; /* room for some personal data */
int channel; /* Channel number */
int32 time; /* Connect time */
int maxq; /* Maximum outstanding data before link reset */
#ifdef oldlocks
int locked; /* Set if mesg already sent */
#endif
int fd; /* Socket descriptor */
int flags; /* User flags */
#define CLOSE_SOCK 1
#define USE_SOUND 2
#define USE_LZW 4
#define VERBOSE 8
/* This buffer is only needed for local users; a lot of space is wasted
* for users from other hosts (256 bytes per user!). Fixed 930728 - WG7J
* char ibuf[LINELEN];
*/
char *ibuf; /* Input buffer */
unsigned long received; /* Number of bytes received */
unsigned long xmitted; /* Number of bytes transmitted */
struct convection *next; /* Linked list pointer */
};
#define CM_UNKNOWN (1 << CT_UNKNOWN)
#define CM_USER (1 << CT_USER)
#define CM_HOST (1 << CT_HOST)
#define CM_CLOSED (1 << CT_CLOSED)
#define NULLCONNECTION ((struct convection *) 0)
static struct convection *convections;
#ifdef __GNUC__
struct linklist; /* forward definition to keep GCC happy */
#endif
/* N2RJT - added channel names */
#ifdef CNV_CHAN_NAMES
struct channelname {
int channel; /* channel number */
char *name; /* channel name */
#ifdef CNV_TOPICS
char *topic;
unsigned long timestamp;
#endif
struct channelname *next; /* linked list pointer */
};
#define NULLCHANNELNAME ((struct channelname *) 0)
static struct channelname *channelnames = NULLCHANNELNAME;
#ifdef CNV_LOCAL_CHANS
/* following 2 defs could dereference a NULL ptr, fatal under Linux */
/* #define ISLOCAL(chan) (!strncmpi(channame_of(chan,NULL),"loc",3))*/
/* #define ISMESSAGE(chan) (!strncmpi(channame_of(chan,NULL),"msg",3))*/
#define ISLOCAL(chan,x) ((x=channame_of(chan,NULL))!=NULLCHAR?!strncmpi(x,"loc",3):0)
#define ISMESSAGE(chan,x) ((x=channame_of(chan,NULL))!=NULLCHAR?!strncmpi(x,"msg",3):0)
#endif
#define PERSONAL_LEN 24
#else /* !CNV_CHAN_NAMES */
#define PERSONAL_LEN 31
#ifdef CNV_LOCAL_CHANS
#define ISLOCAL(chan,x) (chan>=30000 && chan < 32000)
#define ISMESSAGE(chan,x) (chan >= 32000)
#endif
#endif /* CNV_CHAN_NAMES */
#ifndef CNV_LOCAL_CHANS
#define ISLOCAL(chan,x) (0)
#define ISMESSAGE(chan,x) (0)
#endif
struct permlink {
char name[NAMELEN+1]; /* Name of link */
char softrev[NAMELEN+1]; /* Software and version (optional) */
struct socket dest; /* address and tcp port to link with */
#ifdef XCONVERS
int use_lzw;
#endif
struct convection *convection; /* Pointer to associated connection */
int32 statetime; /* Time of last (dis)connect */
int tries; /* Number of connect tries */
int32 waittime; /* Time between connect tries */
int32 retrytime; /* Time of next connect try */
int fd; /* socket descriptor */
struct permlink *next; /* Linked list pointer */
};
#define NULLPERMLINK ((struct permlink *) 0)
struct filter_link {
struct filter_link *next;
int32 addr;
};
#define NULLFL ((struct filter_link *) 0)
#ifdef LINK
struct proc *Linker;
static void connect_permlinks __ARGS((int a,void *b,void *c));
static void update_permlinks __ARGS((char *name,struct convection *cp));
#endif
int conv0 __ARGS((int argc,char *argv[],void *p));
int conv1 __ARGS((int argc,char *argv[],void *p));
void conv_incom __ARGS((int s,void *t,void *p));
void xconv_incom __ARGS((int s,void *t,void *p));
static void conv_incom2 __ARGS((int s,void *t,void *p,struct convection *cp));
static void free_connection __ARGS((register struct convection *cp));
static char *formatline __ARGS((char *prefix,char *text));
static char *timestring __ARGS((long gmt));
#ifdef oldlocks
static void clear_locks __ARGS((void));
#endif
static void send_msg_to_user __ARGS((char *fromname,char *toname,char *text,struct convection *cp));
static void send_user_change_msg __ARGS((char *name,char *host,int oldchannel,int newchannel,struct convection *cp));
static void send_link_change_msg __ARGS((struct convection *cp,char *name,char *change));
static void send_invite_msg __ARGS((char *fromname,char *toname,int channel,struct convection *cp));
static void personal_command __ARGS((struct convection *cp));
static void bye_command __ARGS((struct convection *cp));
static void name_command __ARGS((struct convection *cp));
static void who_command __ARGS((struct convection *cp));
static void send_msg_to_channel __ARGS((char *fromname,int channel,char *text,struct convection *cp));
static void free_closed_connections __ARGS((void));
static struct convection *alloc_connection __ARGS((int fd));
static void process_commands __ARGS((struct convection *cp,struct mbx *m));
static void set_personal __ARGS((struct convection *cp));
static void personal_data __ARGS((struct convection *cp));
static void store_personal __ARGS((struct convection *cp));
static void version_command __ARGS((struct convection *cp));
static void help_command __ARGS((struct convection *cp));
static void flags_command __ARGS((struct convection *cp));
static void h_host_command __ARGS((struct convection *cp));
static void h_invi_command __ARGS((struct convection *cp));
static void invite_command __ARGS((struct convection *cp));
static void h_loop_command __ARGS((struct convection *cp));
static void h_udat_command __ARGS((struct convection *cp));
static void h_umsg_command __ARGS((struct convection *cp));
static void h_user_command __ARGS((struct convection *cp));
static void h_ping_command __ARGS((struct convection *cp));
static void h_unknown_command __ARGS((struct convection *cp));
#ifdef LINK
int ShowConfLinks __ARGS((int s, int full));
static void links_command __ARGS((struct convection *cp));
static void h_cmsg_command __ARGS((struct convection *cp));
#endif
static void msg_command __ARGS((struct convection *cp));
static int channum_of __ARGS((char *name));
static char *channame_of __ARGS((int num, char **topicptr));
static void read_channels __ARGS((void));
static void show_channels __ARGS((struct convection *cp));
static void free_channels __ARGS((void));
static void channel_command __ARGS((struct convection *cp));
static char *pvia __ARGS((void *p));
static char *skipfields __ARGS((int fnum, char *p));
static char *trimfield __ARGS((char *str, int maxlen));
static int link_done __ARGS((struct linklist *head, struct convection *p));
void check_buffer_overload __ARGS((void));
#ifdef CNV_TOPICS
static void h_topi_command __ARGS((struct convection *cp));
#endif
#ifdef AX25
static int doconfcall __ARGS((int argc,char *argv[],void *p));
static int doct4 __ARGS((int argc,char *argv[],void *p));
#endif
static struct filter_link *Filterlinks;
static int FilterMode;
static struct permlink *permlinks;
extern char Ccall[AXALEN];
extern char shortversion[];
static int allow_info_updates;
static int docinfo __ARGS((int argc,char *argv[], void *p));
static int docfilter __ARGS((int argc,char *argv[],void *p));
static int dochostname __ARGS((int argc,char *argv[],void *p));
static int dociface __ARGS((int argc,char *argv[],void *p));
static int doclink __ARGS((int argc,char *argv[],void *p));
static int docxlink __ARGS((int argc,char *argv[],void *p));
static int doclinks __ARGS((int argc,char *argv[],void *p,int lzw));
static int docunlink __ARGS((int argc,char *argv[],void *p));
static int docmaxwait __ARGS((int argc,char *argv[],void *p));
static int dohmaxq __ARGS((int argc,char *argv[],void *p));
static int doumaxq __ARGS((int argc,char *argv[],void *p));
static int doconfstat __ARGS((int argc,char *argv[],void *p));
static int dotdisc __ARGS((int argc,char *argv[],void *p));
static int docdefaultchannel __ARGS((int argc,char *argv[],void *p));
static char USERcmd[] = "/\377\200USER %s %s %lu %d %d\n";
static char UMSGcmd[] = "/\377\200UMSG %s %s %s\n";
static char CMSGcmd[] = "/\377\200CMSG %s %d %s\n";
static char INVIcmd[] = "/\377\200INVI %s %s %d\n";
static char UDATcmd[] = "/\377\200UDAT %s %s %s\n";
static char HOSTcmd[] = "/\377\200HOST %s %s %s\n";
static char LOOPcmd[] = "/\377\200LOOP %s %s %s\n";
#ifdef CNV_TOPICS
static char TOPIcmd[] = "/\377\200TOPI %s %s %lu %d %s\n";
#endif
static struct cmds DFAR Ccmds[] = {
"channel", docdefaultchannel, 0, 0, NULLCHAR,
#ifdef LINK
"drop", docunlink, 0, 0, NULLCHAR,
"filter", docfilter, 0, 0, NULLCHAR,
"hmaxq", dohmaxq, 0, 0, NULLCHAR,
#endif
"hostname", dochostname,0, 0, NULLCHAR,
"interface",dociface, 0, 0, NULLCHAR,
#ifdef LINK
"link", doclink, 0, 0, NULLCHAR,
"maxwait", docmaxwait, 0, 0, NULLCHAR,
#endif
#ifdef AX25
"mycall", doconfcall, 0, 0, NULLCHAR,
#endif
"online", doconfstat, 0, 0, NULLCHAR,
#ifdef CNV_CHG_PERSONAL
"setinfo", docinfo, 0, 0, NULLCHAR,
#endif
#ifdef AX25
"t4", doct4, 0, 0, NULLCHAR,
#endif
"tdisc", dotdisc, 0, 0, NULLCHAR,
"umaxq", doumaxq, 0, 0, NULLCHAR,
#if defined(XCONVERS) && defined(LINK)
"xlink", docxlink, 0, 0, NULLCHAR,
#endif
NULLCHAR,
};
/* N2RJT - usputs doesn't return length. */
static int
usputscnt(int s, char *x)
{
if (usputs(s,x)!=EOF)
return strlen(x);
else
return -1;
}
#ifdef CNV_CHAN_NAMES
static int
channum_of(char *name)
{
struct channelname *tick;
tick = channelnames;
while (tick != NULLCHANNELNAME) {
if (tick->name != NULLCHAR)
if (!stricmp(name,tick->name))
return tick->channel;
tick = tick->next;
}
return -1;
}
static char *
channame_of(int num, char **topicptr)
{
struct channelname *tick;
tick = channelnames;
while (tick != NULLCHANNELNAME) {
if (num==tick->channel) {
#ifdef CNV_TOPICS
if (topicptr != NULL) *topicptr = tick->topic;
#endif
return tick->name;
}
tick = tick->next;
}
return NULLCHAR;
}
static void
read_channels()
{
FILE *f;
char line[256], *s2;
struct channelname *temp, *list;
if (channelnames != NULLCHANNELNAME)
return;
list = NULLCHANNELNAME;
if ((f=fopen(Channelfile,READ_TEXT))==NULLFILE)
return;
while (fgets(line,sizeof(line),f)!=NULL) {
rip(line);
temp = (struct channelname *) mallocw(sizeof(struct channelname));
temp->channel = atoi(line);
#ifdef CNV_TOPICS
temp->topic =
#endif
temp->name = NULLCHAR;
if ((s2 = strchr(line,' '))!=0) {
s2++;
temp->name = strdup(s2);
}
temp->next = NULLCHANNELNAME;
if (list)
list->next = temp;
else
channelnames = temp;
list = temp;
}
fclose(f);
}
static void
show_channels(struct convection *cp)
{
struct channelname *temp;
char *chtype;
if (channelnames != NULLCHANNELNAME) {
cp->xmitted += usputscnt(cp->fd, "Channel names:\n");
}
temp = channelnames;
while (temp != NULLCHANNELNAME) {
#ifdef CNV_LOCAL_CHANS
if (ISLOCAL(temp->channel,chtype)) chtype="(local)";
else if (ISMESSAGE(temp->channel,chtype)) chtype="(message)";
else
#endif
#ifdef CNV_TOPICS
if(temp->topic) chtype=temp->topic;
else
#endif
chtype="";
cp->xmitted += usprintf(cp->fd, "%5d %-8s %s\n",
temp->channel, temp->name, chtype);
temp = temp->next;
}
cp->xmitted += usputscnt(cp->fd, "***\n");
}
/* Called by conv0 to free allocations for channel names */
static void
free_channels(void)
{
struct channelname *temp,*nxt;
for(temp = channelnames; temp; temp = nxt) {
free(temp->name);
#ifdef CNV_TOPICS
free(temp->topic);
#endif
nxt = temp->next;
free(temp);
}
channelnames=NULLCHANNELNAME;
}
#endif /* CNV_CHAN_NAMES */
/* Multiplexer for top-level convers command */
int
doconvers(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return subcmd(Ccmds,argc,argv,p);
}
#ifdef AX25
/* Display or change our AX.25 conference call */
static int
doconfcall(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char tmp[AXBUF];
if(argc < 2){
tprintf("%s\n",pax25(tmp,Ccall));
return 0;
}
if(setcall(Ccall,argv[1]) == -1)
return -1;
return 0;
}
int32 CT4init = 7200; /* 2 hours default */
/* Set link redundancy timer */
static int
doct4(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&CT4init,"Conf. redundancy timer (sec)",argc,argv);
}
#endif /* AX25 */
#ifdef LINK
static int32 CMaxwait = MAX_WAITTIME;
/* Set maxwait time for timed out links */
static int
docmaxwait(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&CMaxwait,"Re-link max wait (sec)",argc,argv);
}
static int HMaxQ = 5*1024;
/* Set max qlimit for host links */
static int
dohmaxq(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setint(&HMaxQ,"Max. Host Queue (bytes)",argc,argv);
}
#endif /* LINK */
static int UMaxQ = 2048; /* Big enough to accommodate convers.hlp */
/* Set max qlimit for user links */
static int
doumaxq(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setint(&UMaxQ,"Max. User Queue (bytes)",argc,argv);
}
int CDefaultChannel;
/* Set the initial channel */
static int
docdefaultchannel(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setint(&CDefaultChannel,"Default channel",argc,argv);
}
static int32 Ctdiscinit = 0;
/* Set convers redundancy timer */
static int
dotdisc(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&Ctdiscinit,"redundancy timer (sec)",argc,argv);
}
static int
dochostname(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if(argc == 1)
tprintf("%s\n",Chostname);
else {
strncpy(Chostname,argv[1],CNAMELEN);
Chostname[CNAMELEN] = '\0';
}
return 0;
}
#ifdef CNV_CHG_PERSONAL
static int
docinfo(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setbool(&allow_info_updates,"Allow users to change info file",argc,argv);
}
#endif
#ifdef LINK
static int
docfilter(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int32 addr;
struct filter_link *fl;
if(argc == 1) {
if(Filterlinks) {
tprintf("Mode is: %s\n", FilterMode ? "Accept" : "Refuse");
for(fl=Filterlinks;fl;fl=fl->next)
tprintf("%s\n",inet_ntoa(fl->addr));
}
return 0;
}
if(!stricmp(argv[1],"mode")) {
if(argc == 2)
tprintf("Mode is: %s\n", FilterMode ? "Accept" : "Refuse");
else {
if(*argv[2] == 'a' || *argv[2] == 'A')
FilterMode = 1;
else
FilterMode = 0;
}
return 0;
}
if((addr = resolve(argv[1])) == 0) {
tprintf(Badhost,argv[1]);
return 1;
}
/* check to see if we already have this in the list */
for(fl=Filterlinks;fl;fl=fl->next)
if(fl->addr == addr)
return 0; /* already have this one ! */
/* Seems like a new one */
fl = (struct filter_link *)callocw(1,sizeof(struct filter_link));
fl->addr = addr;
fl->next = Filterlinks;
Filterlinks = fl;
return 0;
}
#ifdef XCONVERS
static int
doclinks(argc,argv,p, use_lzw)
#else
static int
doclink(argc,argv,p)
#endif /* XCONVERS */
int argc;
char *argv[];
void *p;
#ifdef XCONVERS
int use_lzw;
#endif
{
int32 addr;
int i;
struct permlink *pl;
if(argc == 1) {
for(pl=permlinks;pl;pl=pl->next)
#ifdef XCONVERS
tprintf("%10s: %s %s\n",pl->name,pinet(&pl->dest),
pl->use_lzw ? "XCONVERS" : "CONVERS");
#else
tprintf("%10s: %s\n",pl->name,pinet(&pl->dest));
#endif /* XCONVERS */
(void)ShowConfLinks(Curproc->output, 1); /* even more info */
return 0;
}
if((addr = resolve(argv[1])) == 0) {
tprintf(Badhost,argv[1]);
return 1;
}
/* check to see if we already have a link to such animal,
* this happens when we stop and restart the server - WG7J
*/
for(pl=permlinks;pl;pl=pl->next)
if(pl->dest.address == addr)
return 1; /* already have this one ! */
/* Seems like a new link ! Go add it */
pl = (struct permlink *)callocw(1,sizeof(struct permlink ));
pl->dest.address = addr;
#ifdef XCONVERS
pl->use_lzw = use_lzw;
pl->dest.port = (use_lzw ? IPPORT_XCONVERS : IPPORT_CONVERS);
#else
pl->dest.port = IPPORT_CONVERS;
#endif
pl->next = permlinks;
permlinks = pl;
if (argc > 2 && (i=atoi(argv[2]))!=0) { /* could be a port number */
pl->dest.port = i;
argc--; argv++;
}
if(argc > 2) {
strncpy(pl->name,argv[2],NAMELEN); /* callocw() put terminal NUL for us */
update_permlinks(pl->name,NULLCONNECTION);
pl->retrytime -= 45; /* initial connect should happen sooner */
} else
strcpy(pl->name,"Unknown"); /* can't call update_permlinks() without unique name! */
if(!Linker)
Linker = newproc("Clinker",CLINKSTACK,connect_permlinks,0,0,NULL,0);
return 0;
}
#ifdef XCONVERS
static int
doclink(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doclinks(argc,argv,p,0);
}
static int
docxlink(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doclinks(argc,argv,p,1);
}
#endif /* XCONVERS */
static int
docunlink(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int32 addr;
struct permlink *pl;
if(argc > 1 && (addr = resolve(argv[1])) == 0) {
tprintf(Badhost,argv[1]);
return 1;
}
for(pl=permlinks;pl;pl=pl->next) {
if(!pl->dest.address) continue; /* skip previously-dropped links */
if(argc == 1 || pl->dest.address == addr) {
tprintf("Unlinking %s\n",inet_ntoa(pl->dest.address));
#ifdef CNV_LINKCHG_MSG
send_link_change_msg(pl->convection,pl->name,"unlinked by sysop");
#endif
shutdown(pl->fd,2);
#ifdef notdef
close_s(pl->fd);
if(pl->convection)
pl->convection->flags &= ~CLOSE_SOCK; /* do not close socket again */
#endif
pl->dest.address = 0; /* flag to connect_permlinks() to free entry */
if (argc > 1) return 0;
}
}
if(argc > 1)
tprintf("Not linked to %s\n",argv[1]);
return 0;
}
#endif /* LINK */
static int
dociface(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setflag(argc,argv[1],IS_CONV_IFACE,argv[2]);
}
static int
doconfstat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int quick;
char *cp = NULLCHAR;
if (argc==1) quick=1; /* no opt means quick format */
else {
quick=0;
cp=argv[1];
if(!strnicmp(cp,"long",strlen(cp)))
cp = NULLCHAR;
}
(void)ShowConfUsers(Curproc->output,quick,cp);
return 0;
}
/* Remember how many we've started .. maybe second for LZW link */
static int convers_servers = 0;
/* Stop convers server */
int
conv0(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int16 port;
if(argc < 2)
port = IPPORT_CONVERS;
else
port = atoi(argv[1]);
if (convers_servers > 0)
convers_servers--;
#ifdef CNV_CHAN_NAMES
if (!convers_servers)
free_channels();
#endif
#ifdef LINK
if(!convers_servers && Linker) {
killproc(Linker);
Linker = NULLPROC;
}
#endif /* LINK */
return stop_tcp(port);
}
/* Start up convers server */
int
conv1(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int16 port;
#ifdef CNV_CHAN_NAMES
if (!convers_servers)
read_channels();
#endif /* CNV_CHAN_NAMES */
convers_servers++;
if(argc < 2)
port = IPPORT_CONVERS;
else
port = atoi(argv[1]);
#ifdef XCONVERS
if (port == IPPORT_XCONVERS)
return start_tcp(port,"XCONVERS Server",xconv_incom,CDAEMONSTACK);
else
#endif
return start_tcp(port,"CONVERS Server",conv_incom,CDAEMONSTACK);
}
/* Free a connection structure ... won't remove from chain (be careful) */
static void
free_connection(cp)
register struct convection *cp;
{
register struct permlink *p;
for(p = permlinks; p; p = p->next)
if(p->convection == cp)
p->convection = NULLCONNECTION;
/* if(cp->data) free() checks for NULL; smaller code :-) */
free(cp->data);
free(cp->ibuf);
if(cp->flags & CLOSE_SOCK)
close_s(cp->fd);
cp->next = NULLCONNECTION; /* defensive */
free((char *) cp);
}
static void
free_closed_connections()
{
register struct convection *cp,*p;
time_t currtime;
currtime = time(&currtime);
for(p = NULLCONNECTION,cp = convections; cp; )
if(cp->type == CT_CLOSED ||
(cp->type == CT_UNKNOWN && cp->time + 300 < currtime)) {
if(p) {
p->next = cp->next;
free_connection(cp);
cp = p->next;
} else {
convections = cp->next;
free_connection(cp);
cp = convections;
}
} else {
p = cp;
cp = cp->next;
}
}
static struct convection *
alloc_connection(fd)
int fd;
{
register struct convection *cp;
time_t currtime;
currtime = time(NULL);
cp = (struct convection *)callocw(1,sizeof(struct convection ));
cp->ibuf = (char *)callocw(1,LINELEN);
cp->fd = fd;
cp->maxq = UMaxQ; /* Maximum qlimit for user */
#ifdef CNV_VERBOSE_CHGS
cp->flags = CLOSE_SOCK+USE_SOUND+VERBOSE; /* establish default behaviour */
#else
cp->flags = CLOSE_SOCK+USE_SOUND; /* establish default behaviour */
#endif
cp->time = currtime;
cp->next = convections;
convections = cp;
return cp;
}
/* check the host links for backlogged data.
* If larger than set threshold, kill the link.
* WG7J, 930208
*/
void check_buffer_overload(void) {
struct convection *p;
/* check the size of the outstanding data buffers */
for(p = convections; p; p = p->next)
if((p->maxq != 0) && (socklen(p->fd,1) > p->maxq)) {
/* notify everyone of this special :-) occasion */
bye_command(p);
/* Blow this one out of the water */
shutdown(p->fd,2);
close_s(p->fd);
}
}
#ifdef LINK
static void
update_permlinks(name,cp)
char *name;
struct convection *cp;
{
register struct permlink *p;
time_t currtime;