-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
484 lines (420 loc) · 14.2 KB
/
main.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
/* MAIN.C V-2.8-mea
| Copyright (c) 1988,1989,1990,1991 by
| The Hebrew University of Jerusalem, Computation Center.
|
| This software is distributed under a license from the Hebrew University
| of Jerusalem. It may be copied only under the terms listed in the license
| agreement. This copyright message should never be changed or removed.
| This software is gievn without any warranty, and the Hebrew University
| of Jerusalem assumes no responsibility for any damage that might be caused
| by use oR misuse of this software.
|
| The main module for the RSCS. Initialyze the things, queues the read
| requests and sleeps...
| The initial state of a line is ACTIVE. When the receive QIO is queued for
| an active line, its status is changed to DRAIN to show the real state.
| The IoLines database is defined here. All the other modules point to it
| (defined as external).
|
| This program can be run in debug mode. For doing so, first compile it when
| the DEBUG compilation variable is defined. Then, define it as foreign DCL
| symbol, and run it with one parameter (1 - 4) which the logging level.
| The default logging level is 1.
|
| NOTE: The buffer size defined in CONSTS.H must be larger in 20 characters
| than the maximum buffer size used for a line. This is because there
| is an overhead of less than 20 characters for each block.
|
| Currently, the program supports only single stream, and doesn't support
| splitted records nor SYSIN files.
|
| The value of the variable MustShutDown defines whether we have to shut down
| or not. Zero = keep running. 1 = Shutdown immediately. -1 = shutdown when
| all lines are signed-off.
|
| Sections: MAIN - The main section.
| INIT-LINE-DB - Read the permanent database into memory.
| LOGGER - The logging routines.
| INIT - Initialyze some commonly used variables.
*/
#include <stdio.h>
FILE *AddressFd; /* Temporary - for DMF routine address */
#define MAIN /* So the global variables will be defined here */
#include "consts.h" /* Our RSCS constants */
#include "headers.h"
#include "prototypes.h"
#include <sysexits.h> /* BSD UNIXoid thing */
static void init_lines_data_base __(( void ));
static void init_variables __(( void ));
static void handle_sigsegv();
#ifdef SIGBUS /* Not everybody has strict alignments -- RISC processors
usually do, and raise a SIGBUS at such conditions. */
static void handle_sigbus();
#endif
INTERNAL int LogLevel; /* Referenced in READ_CONFIG.C also */
INTERNAL int MustShutDown; /* For UNIX - When we have to exit
the main loop */
FILE *LogFd = NULL;
/* For the routine that initialize static variables: */
EXTERNAL struct JOB_HEADER NetworkJobHeader;
EXTERNAL struct DATASET_HEADER NetworkDatasetHeader;
/*====================== MAIN =====================================*/
/*
| The main engine. Initialize all things, fire read requests, and then hiber.
| All the work will be done in AST level.
*/
int
main(cc, vv)
char *vv[];
int cc;
{
char line[512]; /* Long buffer for OPCOM messages */
long LOAD_DMF(); /* The loading routine of DMF framing
routine */
/* Init the command mailbox, the timer process.
*/
LogFd = NULL; MustShutDown = 0; /* =0 - Run. NonZero = Shut down */
InformUsersCount = 0;
LogLevel = 1;
if (cc > 1) { /* Read the log level as the first parameter */
switch (**++vv) {
case '2': LogLevel = 2; break;
case '3': LogLevel = 3; break;
case '4': LogLevel = 4; break;
case '5': LogLevel = 5; break;
case '6': LogLevel = 6; break;
default: break;
}
}
#ifdef UNIX
if (getuid() != 0) { /* NOT started as ROOT ! */
fprintf(stderr,"FUNET-NJE MUST BE STARTED WITH ROOT PRIVILEDGES! Aborting!\n");
exit(EX_USAGE);
}
# ifdef PID_FILE
{
FILE *PidFil = fopen(PID_FILE,"r");
int pid = 0;
if (PidFil != NULL) {
fscanf(PidFil,"%d",&pid);
fclose(PidFil);
}
if (pid > 2 && kill(pid,0) == 0) {
/* There exists a process! */
fprintf(stderr,"*** THERE ALREADY EXISTS A (FUNET-NJE) PROCESS WITH REGISTERED PID!\n*** WON'T START UNTIL PID %d AS REGISTERED IN %s IS ELIMINATED\n",
pid,PID_FILE);
exit(EX_SOFTWARE);
}
}
# endif
/* Read our configuration from the configuration file */
init_lines_data_base(); /* Clear it.
Next routine will fill it */
if (read_configuration() == 0)
exit(EX_DATAERR);
read_ebcasc_table(EBCDICTBL);
rscsacct_open(RSCSACCT_LOG);
/* We got all configuration, so we can now
spit error messages into our logfile.
This is the time to detach... */
if (cc < 3) /* Detach only if not other parameter after loglevel */
detach();
# ifdef PID_FILE
{
FILE *PidFil = fopen(PID_FILE,"w");
if( PidFil != NULL ) {
chmod(PID_FILE,0644);
fprintf(PidFil,"%d\n",(int)getpid());
fclose(PidFil);
}
}
# endif
#endif
if (open_route_file() == 0) { /* Open the routing table */
send_opcom("FUNET-NJE aborting. Problems opening the route table!");
exit(1);
}
#ifdef VMS
init_crc_table(); /* For DECnet links */
#endif
init_headers(); /* Init byte-swapped values in NJE
headers */
init_variables(); /* Init some commonly used variables */
init_command_mailbox(); /* To get operator's command and file
queueing */
init_timer(); /* Our own timer mechanism.
Will tick each second */
#ifdef VMS
if(*ClusterNode != '\0') /* We run in cluster mode */
init_cluster_listener();
#endif
/* Initialize the lines */
#ifdef VMS
/* This must be the last one, since it allocates non-paged pool.
Check whether we have a DMF at all. */
for (i = 0; i < MAX_LINES; i++) {
if ((IoLines[i].state == ACTIVE) &&
(IoLines[i].type == DMF)) {
/* DMF_routine_address = LOAD_DMF(); */
/*************************** Temp *******************************/
if ((AddressFd = fopen(ADDRESS_FILE, "r")) == NULL) {
logger(1, "Can't open DMF address file.\n");
exit(1);
}
if ((fscanf(AddressFd, "%x", &DMF_routine_address)) != 1) {
logger(1, "Can't Fscanf address.\n"); exit(1);
}
fclose(AddressFd);
logger(1, "DMF routine address: %x\n", DMF_routine_address);
/****************************************************************/
break; /* Loaded only once */
}
}
#endif
/* If we got up to here, almost all initialization was ok;
we must call it before initializing the lines, as from
there we start a mess, and this SEND_OPCOM seems to collide
with AST routines when calling Logger(). */
sprintf(line,
"HUyNJE, Version-%s(%s)/%s started on node %s, logfile=%s\r\n",
VERSION, SERIAL_NUMBER, version_time, LOCAL_NAME, LOG_FILE);
strcat(line, " Copyright (1988,1989,1990) - The Hebrew University of Jerusalem\r\n");
strcat(line, " Parts Copyright (1990,1991,1993) - Finnish University and Research Network\r\n FUNET\r\n");
strcat(line, LICENSED_TO);
send_opcom(line); /* Inform operator */
init_communication_lines(); /* Setup the lines (open channels, etc)
and fire reads when needed. */
/* Queue the auto-restart function */
queue_timer(T_AUTO_RESTART_INTERVAL, -1, T_AUTO_RESTART);
/* Start the statistics timer */
queue_timer(T_STATS_INTERVAL, -1, T_STATS);
/* Start the automatic link (VMNET) monitor */
queue_timer(T_VMNET_INTERVAL, -1, T_VMNET_MONITOR);
#ifdef UNIX
#ifdef BSD_SIGCHLDS
# ifdef SIGCHLD
signal(SIGCHLD,handle_childs);
# else
signal(SIGCLD,handle_childs);
# endif
#else
signal(SIGCLD,SIG_IGN);
#endif
/* Do kill -1 `cat /etc/huji.pid` to raise its attention... */
signal(SIGHUP,handle_sighup); /* [mea] */
/* Do kill -USR1 `cat /etc/huji.pid` to dump statistics counters */
signal(SIGUSR1,handle_sigusr1); /* [mea] */
/* Do kill `cat /etc/huji.pid` to kill me -- SIGTERM */
signal(SIGTERM,handle_sigterm); /* [mea] */
/* PIPE closed signals.. */
signal(SIGPIPE,SIG_IGN);
#ifdef SIGPOLL
signal(SIGPOLL,SIG_IGN);
#endif
/* ALARM -- programmed timeout */
signal(SIGALRM,handle_sigalrm);
#if 0
signal(SIGSEGV,handle_sigsegv);
#ifdef SIGBUS
signal(SIGBUS,handle_sigbus);
#endif
#endif
/* XX: Lets do things with link-activation time 'debug_rescan_queue()'
calls, instead of this routine.. (Gerald Hanush) */
init_files_queue(); /* Init the in-memory file's queue */
while (MustShutDown <= 0) {
poll_sockets();
timer_ast();
}
#endif
#ifdef VMS
init_files_queue(); /* Init the in-memory file's queue */
while (MustShutDown <= 0) {
sys$hiber(); /* Sleep. All work will be done in AST mode */
if (MustShutDown <= 0)
logger(1, "MAIN, False wakeup\n");
}
#endif
/* If we got here - Shutdown the daemon (Close permanently opened files). */
close_command_mailbox();
close_route_file();
logger(0,"=======================\n");
logger(0,"Shuting down, counters:\n");
logger(0,"=======================\n");
log_line_stats();
send_opcom("FUNET-NJE, normal shutdown");
#ifdef UNIX
unlink(PID_FILE); /* Successfull shutdown will kill the PID_FILE */
if (strchr(COMMAND_MAILBOX,'/'))
unlink(COMMAND_MAILBOX);
#endif
exit(0);
}
/*
| Called after a line has signedoff. Checks whether this is a result of a
| request to shutdown after all lines has signed off (MustShutDown = -1).
| If so, scan all lines. If none is active we can shut: change MustShutDown
| to 1 (Imediate shut) and wakeup the main routine to do the real shutdown.
*/
void
can_shut_down()
{
register int i;
if (MustShutDown == 0) return; /* No need to shut down */
for (i = 0; i < MAX_LINES; i++)
if (IoLines[i].state == ACTIVE) /* Some line is still active */
return; /* Can't shutdown yet */
/* All lines are closed. Signal it */
MustShutDown = 1; /* Immediate shutdown */
#ifdef VMS
sys$wake(0,0); /* Wakeup the main routine */
#endif
}
/*======================== INIT-LINES-DB ===============================*/
/*
| Clear the line database. Init the initial values.
*/
static void
init_lines_data_base()
{
int i, j;
for (i = 0; i < ABSMAX_LINES; i++) {
IoLines[i].flags = 0;
IoLines[i].socket = -1;
IoLines[i].socketpending = -1;
IoLines[i].QueueStart = NULL;
IoLines[i].QueueEnd = NULL;
IoLines[i].MessageQstart = NULL;
IoLines[i].MessageQend = NULL;
IoLines[i].TotalErrors = 0;
IoLines[i].errors = 0;
IoLines[i].state = INACTIVE; /* They are all dead */
IoLines[i].InBCB = 0;
IoLines[i].OutBCB = 0;
IoLines[i].TimeOut = 3; /* 3 seconds */
IoLines[i].HostName[0] = 0;
IoLines[i].MaxXmitSize = 0;
IoLines[i].PMaxXmitSize = MAX_BUF_SIZE;
IoLines[i].XmitSize = 0;
IoLines[i].QueuedFiles = 0; /* No files queued */
IoLines[i].QueuedFilesWaiting = 0; /* No files queued */
#ifdef USE_XMIT_QUEUE
IoLines[i].FirstXmitEntry = 0;
IoLines[i].LastXmitEntry = 0;
#endif
IoLines[i].ActiveStreams = 0;
IoLines[i].CurrentStream = 0;
IoLines[i].FreeStreams = 1; /* Default of 1 stream */
for (j = 0; j < MAX_STREAMS; ++j) {
IoLines[i].InStreamState[j] = S_INACTIVE;
IoLines[i].OutStreamState[j] = S_INACTIVE;
IoLines[i].SizeSavedJobHeader[j] = 0;
IoLines[i].SizeSavedDatasetHeader[j] = 0;
IoLines[i].SizeSavedJobTrailer[j] = 0;
}
IoLines[i].TcpState = 0;
IoLines[i].TcpXmitSize = 0;
IoLines[i].stats.TotalIn = 0;
IoLines[i].stats.TotalOut = 0;
IoLines[i].stats.WaitIn = 0;
IoLines[i].stats.WaitOut = 0;
IoLines[i].stats.AckIn = 0;
IoLines[i].stats.AckOut = 0;
IoLines[i].stats.RetriesIn = 0;
IoLines[i].stats.RetriesOut = 0;
IoLines[i].stats.MessagesIn = 0;
IoLines[i].stats.MessagesOut = 0;
IoLines[i].sumstats.TotalIn = 0;
IoLines[i].sumstats.TotalOut = 0;
IoLines[i].sumstats.WaitIn = 0;
IoLines[i].sumstats.WaitOut = 0;
IoLines[i].sumstats.AckIn = 0;
IoLines[i].sumstats.AckOut = 0;
IoLines[i].sumstats.RetriesIn = 0;
IoLines[i].sumstats.RetriesOut = 0;
IoLines[i].sumstats.MessagesIn = 0;
IoLines[i].sumstats.MessagesOut = 0;
IoLines[i].WrFiles = 0;
IoLines[i].WrBytes = 0;
IoLines[i].RdFiles = 0;
IoLines[i].RdBytes = 0;
}
}
/* ========================== BUG_CHECK() ============================ */
/*
| Log the string, and then abort.
*/
volatile void
bug_check(string)
const char *string;
{
int i;
char line[80];
char From[20];
logger(1, "Bug check: %s\n", string);
strcpy(line,"FUNET-NJE: Aborting due to bug-check.");
send_opcom(line);
sprintf(From,"@%s", LOCAL_NAME);
for (i = 0; i < InformUsersCount; ++i)
send_nmr(From, InformUsers[i], line, strlen(line), ASCII, CMD_MSG);
close_command_mailbox();
close_route_file();
#ifdef UNIX
unlink(PID_FILE); /* Successfull shutdown will kill the PID_FILE */
if (strchr(COMMAND_MAILBOX,'/'))
unlink(COMMAND_MAILBOX);
#endif
abort();
}
/*=========================== INIT ==============================*/
/*
| Init some commonly used variables.
*/
static void
init_variables()
{
/* Create our name in EBCDIC */
E_BITnet_name_length = strlen(LOCAL_NAME);
ASCII_TO_EBCDIC(LOCAL_NAME, E_BITnet_name, E_BITnet_name_length);
PAD_BLANKS(E_BITnet_name, E_BITnet_name_length, 8);
E_BITnet_name_length = 8;
/* Init static job header fields */
memcpy(NetworkJobHeader.NJHGACCT, EightSpaces, 8); /* Blank ACCT */
memcpy(NetworkJobHeader.NJHGPASS, EightSpaces, 8);
memcpy(NetworkJobHeader.NJHGNPAS, EightSpaces, 8);
memcpy(NetworkJobHeader.NJHGXEQU, EightSpaces, 8);
memcpy(NetworkJobHeader.NJHGFORM, EightSpaces, 8);
PAD_BLANKS(NetworkJobHeader.NJHGPRGN, 0, 20);
memcpy(NetworkJobHeader.NJHGROOM, EightSpaces, 8);
memcpy(NetworkJobHeader.NJHGDEPT, EightSpaces, 8);
memcpy(NetworkJobHeader.NJHGBLDG, EightSpaces, 8);
/* Same for dataset header */
memcpy(NetworkDatasetHeader.NDH.NDHGDD, EightSpaces, 8);
memcpy(NetworkDatasetHeader.NDH.NDHGFORM, EightSpaces, 8);
memcpy(NetworkDatasetHeader.NDH.NDHGFCB, EightSpaces, 8);
memcpy(NetworkDatasetHeader.NDH.NDHGUCS, EightSpaces, 8);
memcpy(NetworkDatasetHeader.NDH.NDHGXWTR, EightSpaces, 8);
memcpy(NetworkDatasetHeader.NDH.NDHGPMDE, EightSpaces, 8);
memcpy(NetworkDatasetHeader.RSCS.NDHVDIST, EightSpaces, 8);
PAD_BLANKS(NetworkDatasetHeader.RSCS.NDHVTAGR, 0, 136);
}
/* ---------------------------------------------------------------- */
/* SIGSEGV, and SIGBUS are LOGGED with these.. */
static void
handle_sigsegv(n)
int n;
{
signal(SIGSEGV,SIG_DFL);
logger(1,"Got SIGSEGV!\n");
abort();
}
#ifdef SIGBUS
static void
handle_sigbus(n)
int n;
{
signal(SIGBUS,SIG_DFL);
logger(1,"Got SIGBUS!\n");
abort();
}
#endif