Commit | Line | Data |
---|---|---|
d6fe8fca C |
1 | /* |
2 | * Network Interface Machine Server | |
3 | * | |
4 | * Frank Pronk | |
5 | * Copyright (c) 1984 | |
6 | */ | |
7 | ||
8 | #include <sys/types.h> | |
9 | #include <sys/socket.h> | |
10 | #include <sys/time.h> | |
11 | ||
12 | #include <signal.h> | |
13 | #include <errno.h> | |
14 | #include <setjmp.h> | |
15 | #include <sgtty.h> | |
16 | #include <pwd.h> | |
17 | ||
18 | #include "../h/x29.h" | |
19 | ||
20 | #include "buf.h" | |
21 | #include "nim.h" | |
22 | ||
23 | extern char chartab[128]; | |
24 | ||
25 | jmp_buf JmpBuf; /* non-local goto buffer for interval timer */ | |
26 | short PtyFd = -1, NetFd = -1; | |
27 | short LogFd = -1; | |
28 | char *LogDev; | |
29 | short TimerOn; /* interval timer armed */ | |
30 | char Banner[] = "NIM daemon\r"; | |
31 | extern int errno; | |
32 | char *TraceFile; /* trace file name */ | |
33 | char *PtyName; | |
34 | struct bufhd ptyoqueue, netoqueue; | |
35 | struct buf *packet; | |
36 | char user_name[50]; | |
37 | ||
38 | struct netinfo NetInfo = { CCITT1980, NX29_1980_PARMS, 128 }; | |
39 | ||
40 | struct PtyPacket { | |
41 | char p_type; | |
42 | char p_data[1]; /* usually more than one byte */ | |
43 | }; | |
44 | ||
45 | char *x25err(); | |
46 | ||
47 | main(argc, argv) | |
48 | register char **argv; | |
49 | { | |
50 | register int s; | |
51 | register char *p; | |
52 | int on = 1, uid; | |
53 | struct passwd *pw; | |
54 | ||
55 | #ifdef waterloo | |
56 | /* | |
57 | * If this host doesn't support X.25, give up. | |
58 | */ | |
59 | s = socket(AF_CCITT, SOCK_STREAM, 0); | |
60 | if (s < 0 && errno == EPROTONOSUPPORT) { | |
61 | fprint(2, "nimd: X.25 is not supported on this machine\n"); | |
62 | exit(1); | |
63 | } | |
64 | close(s); | |
65 | #endif | |
66 | ||
67 | for (argv++; argc > 1; argc--, argv++) | |
68 | if (**argv == '-') | |
69 | for (p = *argv+1; *p; p++) | |
70 | switch (*p) { | |
71 | case 'c': | |
72 | if (argc > 1) { | |
73 | argc--; argv++; | |
74 | if (strcmp (*argv, "1978") == 0) { | |
75 | NetInfo.n_nparms = NX29_1978_PARMS; | |
76 | break; | |
77 | } else if (strcmp (*argv, "1980") == 0) { | |
78 | NetInfo.n_nparms = NX29_1980_PARMS; | |
79 | break; | |
80 | } | |
81 | } | |
82 | fatal ("1978 or 1980 expected after -c"); | |
83 | break; | |
84 | ||
85 | case 't': | |
86 | if (argc > 1) { | |
87 | argc--; argv++; | |
88 | TraceFile = *argv; | |
89 | } else | |
90 | fatal ("trace file name expected"); | |
91 | break; | |
92 | ||
93 | default: | |
94 | fatal("usage: nimd [-c ccitt-date] [-h size] [-n size] [-t trace_file] pty_name"); | |
95 | } | |
96 | else | |
97 | PtyName = *argv; | |
98 | ||
99 | if (PtyName == 0) | |
100 | fatal ("No pseudo-tty specified"); | |
101 | ||
102 | if (fork()) | |
103 | exit(0); | |
104 | for (s = 0; s < 10; s++) | |
105 | (void) close(s); | |
106 | (void) open("/", 0); | |
107 | (void) dup2(0, 1); | |
108 | (void) dup2(0, 2); | |
109 | { int tt = open("/dev/tty", 2); | |
110 | if (tt > 0) { | |
111 | ioctl(tt, TIOCNOTTY, (char *)0); | |
112 | close(tt); | |
113 | } | |
114 | } | |
115 | ||
116 | OpenLog (); | |
117 | packet = getbuf (MAXPSIZ); | |
118 | ResetBufs (); | |
119 | signal (SIGPIPE, SIG_IGN); | |
120 | ||
121 | for (;;) { | |
122 | int bits; | |
123 | ||
124 | if ((PtyFd = open (PtyName, 2)) < 0) | |
125 | fatal (x25err(PtyName)); | |
126 | ioctl (PtyFd, FIONBIO, (char *)&on); | |
127 | ioctl (PtyFd, TIOCPKT, (char *)&on); | |
128 | ioctl (PtyFd, TIOCREMOTE, (char *)&on); | |
129 | bits = (1 << PtyFd); | |
130 | select (16, (int *)0, &bits, (int *)0, (struct timeval *)0); | |
131 | sleep (1); /* wait for pty to settle down */ | |
132 | #ifdef TIOCGSUID | |
133 | /* | |
134 | * Get the slave's uid. | |
135 | */ | |
136 | uid = -1; | |
137 | if (ioctl(PtyFd, TIOCGSUID, &uid) < 0) { | |
138 | perror("nimd: ioctl TIOCGSUID"); | |
139 | close(PtyFd); | |
140 | continue; | |
141 | } | |
142 | if (uid < 0 || (pw = getpwuid(uid)) == 0) { | |
143 | message("nimd: uid %d: Who are you?\n", uid); | |
144 | close(PtyFd); | |
145 | continue; | |
146 | } | |
147 | strcpy(user_name, pw->pw_name); | |
148 | /* | |
149 | * Set effective uid to the slave | |
150 | * so he/she will be charged for X.25 usage. | |
151 | */ | |
152 | setreuid(0, pw->pw_uid); | |
153 | #endif | |
154 | nim (); | |
155 | sleep (1); /* wait for slave to disconnect */ | |
156 | setreuid(0, 0); | |
157 | CloseLog(); OpenLog(); /* allow log rollover */ | |
158 | } | |
159 | /*NOTREACHED*/ | |
160 | } | |
161 | ||
162 | fatal (msg) | |
163 | char *msg; | |
164 | { | |
165 | OpenLog (); | |
166 | log ("%s", msg); | |
167 | print ("nimd: %s\n", msg); | |
168 | exit (1); | |
169 | } | |
170 | ||
171 | /*VARARGS*/ | |
172 | message(fmt, a1, a2, a3, a4, a5) | |
173 | char *fmt; | |
174 | { | |
175 | char buf[128]; | |
176 | ||
177 | sprint (buf, fmt, a1, a2, a3, a4, a5); | |
178 | ToPty (buf, strlen (buf), FROMNIM); | |
179 | } | |
180 | ||
181 | error() | |
182 | { | |
183 | register char *errp; | |
184 | ||
185 | errp = x25err ((char *)0); | |
186 | log (errp); | |
187 | message ("nimd: %s\r", errp); | |
188 | } | |
189 | ||
190 | ||
191 | /* | |
192 | * Main loop. Select from pty and network, and | |
193 | * hand data to nim receiver. | |
194 | */ | |
195 | ||
196 | nim() | |
197 | { | |
198 | register int len; | |
199 | char buf[MAXPSIZ]; | |
200 | int on = 1, ibits, obits, first = 1; | |
201 | ||
202 | InitProfile (DEFAULT_PROFILE); | |
203 | message (Banner); | |
204 | State = ST_COMMAND; | |
205 | OpenLog (); | |
206 | if (user_name[0]) | |
207 | log("slave connect: %s", user_name); | |
208 | else | |
209 | log ("slave connect"); | |
210 | ||
211 | for (;;) { | |
212 | (void) setjmp (JmpBuf); | |
213 | if (first) { | |
214 | obits = (1 << PtyFd); | |
215 | ibits = 0; | |
216 | first = 0; | |
217 | goto do_io; | |
218 | } | |
219 | ibits = obits = 0; | |
220 | ||
221 | /* | |
222 | * Never look for input if there's still | |
223 | * stuff in the corresponding output buffer | |
224 | */ | |
225 | ||
226 | if (PtyFd >= 0) | |
227 | if (!QEMPTY(&ptyoqueue)) | |
228 | obits |= (1 << PtyFd); | |
229 | else | |
230 | if (NetFd >= 0 && State == ST_DATA) | |
231 | ibits |= (1 << NetFd); | |
232 | ||
233 | if (!QEMPTY(&netoqueue) && NetFd >= 0) { | |
234 | if (!OutputBlocked) | |
235 | obits |= (1 << NetFd); | |
236 | } else | |
237 | if (PtyFd >= 0) | |
238 | ibits |= (1 << PtyFd); | |
239 | ||
240 | if (ibits == 0 && obits == 0) /* nothing to do; go home */ | |
241 | break; | |
242 | ||
243 | if (State & ST_COMMAND) { | |
244 | struct timeval TimeOut; | |
245 | ||
246 | TimeOut.tv_sec = 60; | |
247 | TimeOut.tv_usec = 0; | |
248 | if (select (16, &ibits, &obits, (int *)0, &TimeOut) <= 0) { | |
249 | log ("slave inactivity timeout"); | |
250 | break; | |
251 | } | |
252 | } else { | |
253 | if (TimerOn) | |
254 | sigsetmask (0); | |
255 | (void) select (16, &ibits, &obits, (int *)0, (struct timeval *)0); | |
256 | if (TimerOn) | |
257 | sigsetmask (1 << (SIGALRM -1 )); | |
258 | } | |
259 | ||
260 | do_io: | |
261 | /* | |
262 | * Something to read from the network... | |
263 | */ | |
264 | if (ibits & (1 << NetFd)) | |
265 | if ((len = ReadAndTrace(NetFd, buf, MAXPSIZ, "net rx")) == 0) { | |
266 | if (errno != EWOULDBLOCK) | |
267 | NetworkError (); | |
268 | } else | |
269 | FromNet (buf, len); | |
270 | ||
271 | /* | |
272 | * Something to read from the pty... | |
273 | */ | |
274 | if (ibits & (1 << PtyFd)) | |
275 | if ((len = ReadAndTrace (PtyFd, buf, NetInfo.n_psize+1, "pty rx")) == 0) { | |
276 | if (errno != EWOULDBLOCK) { | |
277 | close (PtyFd); | |
278 | PtyFd = -1; | |
279 | } | |
280 | } else | |
281 | FromPty ((struct PtyPacket *)buf, len); | |
282 | ||
283 | if (obits & (1<<NetFd)) { | |
284 | if (FlushQueue (NetFd, &netoqueue, "net tx") < 0 && | |
285 | errno != EWOULDBLOCK) | |
286 | NetworkError (); | |
287 | } | |
288 | ||
289 | if (obits & (1 << PtyFd)) | |
290 | if (FlushQueue (PtyFd, &ptyoqueue, "pty tx") < 0 && | |
291 | errno != EWOULDBLOCK) { | |
292 | close (PtyFd); | |
293 | PtyFd = -1; | |
294 | } | |
295 | } | |
296 | cleanup (); | |
297 | } | |
298 | ||
299 | ReadAndTrace (fd, buf, len, who) | |
300 | char *buf, *who; | |
301 | { | |
302 | register int bytes; | |
303 | ||
304 | bytes = read (fd, buf, len); | |
305 | if (bytes <= 0) | |
306 | return (0); | |
307 | NimTrace (who, buf, bytes); | |
308 | return (bytes); | |
309 | } | |
310 | ||
311 | NetworkError () | |
312 | { | |
313 | ||
314 | error (); | |
315 | State = ST_COMMAND; | |
316 | close (NetFd); | |
317 | NetFd = -1; | |
318 | message (Banner); | |
319 | } | |
320 | ||
321 | cleanup () | |
322 | { | |
323 | log ("slave disconnect"); | |
324 | close (NetFd); | |
325 | close (PtyFd); | |
326 | NetFd = PtyFd = -1; | |
327 | if (TimerOn) | |
328 | ClearTimer (); | |
329 | ResetBufs (); | |
330 | } | |
331 | ||
332 | ResetBufs () | |
333 | { | |
334 | InitQueue (&ptyoqueue); | |
335 | InitQueue (&netoqueue); | |
336 | RESET (packet); | |
337 | } | |
338 | ||
339 | ToPty (str, len, from) | |
340 | register char *str; | |
341 | { | |
342 | register char *end = str + len, c, c1; | |
343 | register struct buf *bp = 0; | |
344 | register int lfcode; | |
345 | ||
346 | while (str < end) { | |
347 | c = *str++; | |
348 | c1 = c & 0177; | |
349 | if (CurrentX29Parms[X29_AUX_DEV_CONTROL_CODE]) { | |
350 | if (c1 == 023) { | |
351 | OutputBlocked++; | |
352 | continue; | |
353 | } | |
354 | if (c1 == 021) { | |
355 | OutputBlocked = 0; | |
356 | continue; | |
357 | } | |
358 | } | |
359 | if (ptyoqueue.b_count > 256) | |
360 | continue; | |
361 | if (bp == 0) | |
362 | bp = getbuf (MAXPSIZ); | |
363 | PUTCHAR (c, bp); | |
364 | if (SIZE (bp) >= MAXPSIZ-1) { | |
365 | enqueue (bp, &ptyoqueue); | |
366 | bp = 0; | |
367 | } | |
368 | if (c1 != '\r' || (lfcode = CurrentX29Parms[X29_LF_AFTER_CR]) <= 0) | |
369 | continue; | |
370 | if ((lfcode & 01) && from == FROMNET || | |
371 | (lfcode & 04) && from == FROMPTY || | |
372 | from == FROMNIM) | |
373 | PUTCHAR ('\n', bp); | |
374 | } | |
375 | if (bp) | |
376 | enqueue (bp, &ptyoqueue); | |
377 | } | |
378 | ||
379 | FromPty(pp, len) | |
380 | register struct PtyPacket *pp; | |
381 | { | |
382 | register int echo; | |
383 | register struct buf *tp = packet; | |
384 | register char *cp, c; | |
385 | char c1; | |
386 | ||
387 | if (pp->p_type != TIOCPKT_DATA) { /* fetch control byte */ | |
388 | PtyControl (pp); | |
389 | return; | |
390 | } | |
391 | if (State & ST_UGLY_50_BAUD_BREAK_IN_PROGRESS) | |
392 | return; | |
393 | cp = pp->p_data; | |
394 | echo = CurrentX29Parms[X29_ECHO_CODE] > 0 && ptyoqueue.b_count < 256; | |
395 | while (cp < ((char *)pp)+len) { | |
396 | c = (c1 = *cp++) & 0177; | |
397 | if (State & ST_ESCSEEN && C_TYPE(c) != C_ESCAPE) | |
398 | EnterCommandState (); | |
399 | switch (C_TYPE(c)) { | |
400 | case C_ERASE: | |
401 | if (!ISEMPTY(tp)) { | |
402 | tp->b_top--; | |
403 | if (echo) | |
404 | if (c == '\b') | |
405 | ToPty ("\b \b", 3, FROMPTY); | |
406 | else | |
407 | ToPty (&c1, 1, FROMPTY); | |
408 | } | |
409 | continue; | |
410 | ||
411 | case C_KILL: | |
412 | RESET (tp); | |
413 | if (echo) | |
414 | ToPty ("*poof*\r", 7, FROMPTY); | |
415 | continue; | |
416 | ||
417 | case C_DISPLAY: | |
418 | ToPty (tp->b_bot, SIZE (tp), FROMPTY); | |
419 | continue; | |
420 | ||
421 | case C_ESCAPE: | |
422 | if ((State & (ST_COMMAND|ST_ESCSEEN)) == 0) { | |
423 | State |= ST_ESCSEEN; | |
424 | continue; | |
425 | } | |
426 | State &= ~ST_ESCSEEN; | |
427 | /* fall through */ | |
428 | ||
429 | default: | |
430 | if (State & ST_COMMAND) { | |
431 | if (c == '\r') { | |
432 | if (echo) | |
433 | ToPty (&c1, 1, FROMPTY); | |
434 | PUTCHAR ('\0', tp); | |
435 | FlushQueue (PtyFd, &ptyoqueue, "pty tx"); | |
436 | NimCommand (tp->b_bot); | |
437 | RESET(tp); | |
438 | continue; | |
439 | } | |
440 | if (SIZE (tp) < MAXPSIZ-1) { | |
441 | PUTCHAR (c, tp); | |
442 | if (echo) | |
443 | ToPty (&c1, 1, FROMPTY); | |
444 | } else | |
445 | /* ToPty ("\007", 1, FROMPTY)*/; | |
446 | } else { | |
447 | PUTCHAR (c1, tp); | |
448 | if (echo) | |
449 | ToPty (&c1, 1, FROMPTY); | |
450 | if (ISFORWARD(c) || SIZE (tp) >= NetInfo.n_psize) { | |
451 | ForwardPacket (); | |
452 | continue; | |
453 | } | |
454 | } | |
455 | } | |
456 | } | |
457 | if (!ISEMPTY (tp) && (State & ST_COMMAND) == 0) | |
458 | SetTimer (); | |
459 | } | |
460 | ||
461 | PtyControl(pp) | |
462 | register struct PtyPacket *pp; | |
463 | { | |
464 | #ifdef notdef | |
465 | if ((pp->p_type & (TIOCPKT_FLUSHWRITE|TIOCPKT_FLUSHREAD)) == | |
466 | (TIOCPKT_FLUSHWRITE|TIOCPKT_FLUSHREAD)) { /* break indication from pty */ | |
467 | if (State & ST_COMMAND) | |
468 | RESET (packet); | |
469 | else | |
470 | Break (CurrentX29Parms[X29_BREAK_PROCEDURE_CODE]); | |
471 | return; | |
472 | } | |
473 | #endif | |
474 | #ifdef TIOCPKT_IOCTL | |
475 | if (pp->p_type & TIOCPKT_IOCTL) { /* some kind of set tty done by slave */ | |
476 | static short UnixToX29Speed[] = { | |
477 | 0, 10, 5, 0, 1, 6, 8, 2, 4, 3, /* B0 thru B1200 */ | |
478 | 12, 13, 14, 15, 16 /* B2400 thru EXTB */ | |
479 | }; | |
480 | struct sgttyb sg; | |
481 | ||
482 | ioctl(PtyFd, TIOCGETP, (char *)&sg); | |
483 | if (sg.sg_ospeed == B50) { | |
484 | State |= ST_UGLY_50_BAUD_BREAK_IN_PROGRESS; | |
485 | return; | |
486 | } | |
487 | CurrentX29Parms[X29_TRANSMISSION_SPEED_CODE] | |
488 | = UnixToX29Speed[sg.sg_ospeed]; | |
489 | if (State & ST_UGLY_50_BAUD_BREAK_IN_PROGRESS && sg.sg_ospeed != B50) { | |
490 | State &= ~ST_UGLY_50_BAUD_BREAK_IN_PROGRESS; | |
491 | if (State & ST_COMMAND) | |
492 | RESET (packet); | |
493 | else | |
494 | Break (CurrentX29Parms[X29_BREAK_PROCEDURE_CODE]); | |
495 | } | |
496 | } | |
497 | #endif | |
498 | } | |
499 | ||
500 | EnterCommandState () | |
501 | { | |
502 | State &= ~ST_ESCSEEN; | |
503 | State |= ST_COMMAND | ST_ESCCOMM; | |
504 | ForwardPacket (); | |
505 | } | |
506 | ||
507 | ExitDataState (cause) | |
508 | char *cause; | |
509 | { | |
510 | ResetBufs (); | |
511 | close (NetFd); | |
512 | NetFd = -1; | |
513 | State = ST_COMMAND; | |
514 | OutputBlocked = 0; | |
515 | CurrentX29Parms[X29_DISCARD_OUTPUT_CODE] = 0; | |
516 | message ("nimd: Call cleared - %s\r", cause); | |
517 | log ("Call cleared - %s", cause); | |
518 | } | |
519 | ||
520 | ForwardPacket () | |
521 | { | |
522 | register struct buf *bp, *tp = packet; | |
523 | ||
524 | if (!ISEMPTY(tp) && (State & ST_COMMAND) == 0) { | |
525 | AddParity (tp->b_bot, SIZE (tp)); | |
526 | bp = getbuf (SIZE (tp) + 1); | |
527 | PUTCHAR(0, bp); | |
528 | BufCopy(tp, bp); | |
529 | enqueue (bp, &netoqueue); | |
530 | } | |
531 | RESET (tp); | |
532 | if (TimerOn) | |
533 | ClearTimer (); | |
534 | } | |
535 | ||
536 | ToNet (pp, len) | |
537 | struct packet *pp; | |
538 | { | |
539 | register struct buf *bp; | |
540 | ||
541 | /* | |
542 | * round buffer size up to a multiple of 64 bytes | |
543 | * to reduce accumulation of small and usually | |
544 | * useless buffers in the free list. This speeds | |
545 | * up malloc(). | |
546 | */ | |
547 | bp = getbuf ((len + 63) & ~63); | |
548 | bcopy ((char *)pp, bp->b_bot, len); | |
549 | bp->b_top = bp->b_bot + len; | |
550 | enqueue (bp, &netoqueue); | |
551 | } | |
552 | ||
553 | timeout() | |
554 | { | |
555 | TimerOn = 0; | |
556 | ForwardPacket (); | |
557 | longjmp (JmpBuf, 0); | |
558 | } | |
559 | ||
560 | SetTimer () | |
561 | { | |
562 | register int t; | |
563 | struct itimerval itv; | |
564 | ||
565 | if (TimerOn || (t = CurrentX29Parms[X29_IDLE_TIMER_CODE]) <= 0) | |
566 | return; | |
567 | itv.it_interval.tv_sec = 0; | |
568 | itv.it_interval.tv_usec = 0; | |
569 | itv.it_value.tv_sec = t / 20; | |
570 | itv.it_value.tv_usec = t % 20 * 1000000 / 20; | |
571 | signal (SIGALRM, SIG_IGN); /* cancel possible pending signal */ | |
572 | signal (SIGALRM, timeout); | |
573 | sigsetmask (1 << (SIGALRM - 1)); | |
574 | TimerOn++; | |
575 | setitimer (ITIMER_REAL, &itv, (struct itimerval *)0); | |
576 | } | |
577 | ||
578 | ClearTimer () | |
579 | { | |
580 | struct itimerval itv; | |
581 | ||
582 | signal (SIGALRM, SIG_IGN); | |
583 | bzero ((char *)&itv, sizeof (itv)); | |
584 | setitimer (ITIMER_REAL, &itv, (struct itimerval *)0); | |
585 | TimerOn = 0; | |
586 | } | |
587 | ||
588 | FromNet (bp, len) | |
589 | char *bp; | |
590 | { | |
591 | if ((*bp & Q_BIT) == 0) { | |
592 | register struct x25packet *xp = (struct x25packet *)bp; | |
593 | ||
594 | if (CurrentX29Parms[X29_DISCARD_OUTPUT_CODE] == 0) { | |
595 | AddParity (xp->p_x25data, len - 1); | |
596 | ToPty (xp->p_x25data, len - 1, FROMNET); | |
597 | } | |
598 | return; | |
599 | } | |
600 | X29ControlMessage ((struct x29packet *)bp, len); | |
601 | } | |
602 | ||
603 | SendX25Interrupt() | |
604 | { | |
605 | char c = 0x77; | |
606 | ||
607 | send (NetFd, &c, 1, MSG_OOB); | |
608 | } | |
609 | ||
610 | #ifdef fastidious /* we need stdio */ | |
611 | /* | |
612 | * Sorry about this... | |
613 | * Defining this dummy procedure prevents the stdio package | |
614 | * (about 17K bytes worth) from being loaded. This program | |
615 | * does not require any support from the 4.2bsd stdio library. | |
616 | */ | |
617 | ||
618 | #ifdef vax | |
619 | _cleanup() | |
620 | { | |
621 | } | |
622 | #endif | |
623 | #endif | |
624 | ||
625 | NimTrace(who, bp, n) | |
626 | char *who, *bp; | |
627 | { | |
628 | static int fd; | |
629 | ||
630 | if (TraceFile == 0) | |
631 | return; | |
632 | if(fd <= 0 && (fd = creat(TraceFile, 0640)) < 0) | |
633 | return; | |
634 | DisplayPacketContents (fd, who, bp, n); | |
635 | } | |
636 | ||
637 | OpenLog () | |
638 | { | |
639 | ||
640 | if (LogFd >= 0) | |
641 | return; | |
642 | if (LogDev = rindex (PtyName, '/')) | |
643 | LogDev++; | |
644 | else | |
645 | LogDev = PtyName; | |
646 | if ((LogFd = open (LOGFILE, 1)) >= 0) | |
647 | return; | |
648 | LogFd = creat (LOGFILE, 0640); | |
649 | } | |
650 | ||
651 | CloseLog() | |
652 | { | |
653 | if (LogFd >= 0) { | |
654 | close(LogFd); | |
655 | LogFd = -1; | |
656 | } | |
657 | } | |
658 | ||
659 | /*VARARGS*/ | |
660 | log(fmt, a1, a2, a3, a4, a5) | |
661 | char *fmt; | |
662 | { | |
663 | register char *DateTime; | |
664 | char format[128], *ctime (); | |
665 | time_t t; | |
666 | ||
667 | if (LogFd < 0) | |
668 | return; | |
669 | (void) time (&t); | |
670 | DateTime = ctime (&t); | |
671 | DateTime[19] = '\0'; | |
672 | sprint (format, "%s %s %s\n", DateTime+4, LogDev, fmt); | |
673 | lseek (LogFd, (long)0, 2); | |
674 | fprint (LogFd, format, a1, a2, a3, a4, a5); | |
675 | } | |
676 | ||
677 | LogPacket (bp, len) | |
678 | char *bp; | |
679 | { | |
680 | if (LogFd < 0) | |
681 | return; | |
682 | DisplayPacketContents (LogFd, "net rx", bp, len); | |
683 | } | |
684 | ||
685 | DisplayPacketContents (fd, from, pp, len) | |
686 | char *from; | |
687 | register char *pp; | |
688 | register int len; | |
689 | { | |
690 | register int first = 1; | |
691 | char buf[128]; | |
692 | ||
693 | lseek (fd, (long)0, 2); | |
694 | do { | |
695 | ConvertToOctal (pp, len, buf); | |
696 | if (first) { | |
697 | fprint (fd, "%s[%d]\t%s\n", from, len, buf); | |
698 | first = 0; | |
699 | } else | |
700 | fprint (fd, "\t\t%s\n", buf); | |
701 | ConvertToAscii (pp, len, buf); | |
702 | fprint (fd, "\t\t%s\n", buf); | |
703 | pp += 16; | |
704 | len -= 16; | |
705 | } while (len > 0); | |
706 | } | |
707 | ||
708 | ConvertToOctal (start, len, bp) | |
709 | register char *start, *bp; | |
710 | { | |
711 | register char *cp; | |
712 | ||
713 | if (len > 16) | |
714 | len = 16; | |
715 | for (cp = start; cp - start < len; cp++) { | |
716 | *bp++ = ((*cp & 0300) >> 6) + '0'; | |
717 | *bp++ = ((*cp & 070) >> 3) + '0'; | |
718 | *bp++ = (*cp & 07) + '0'; | |
719 | *bp++ = ' '; | |
720 | } | |
721 | bp[-1] = '\0'; | |
722 | } | |
723 | ||
724 | ConvertToAscii (start, len, bp) | |
725 | register char *start, *bp; | |
726 | { | |
727 | register char *cp; | |
728 | ||
729 | if (len > 16) | |
730 | len = 16; | |
731 | for (cp = start; cp - start < len; cp++) { | |
732 | *bp++ = ' '; | |
733 | switch (*cp) { | |
734 | case '\b': | |
735 | *bp++ = '\\'; | |
736 | *bp++ = 'b'; | |
737 | break; | |
738 | ||
739 | case '\t': | |
740 | *bp++ = '\\'; | |
741 | *bp++ = 't'; | |
742 | break; | |
743 | ||
744 | case '\n': | |
745 | *bp++ = '\\'; | |
746 | *bp++ = 'n'; | |
747 | break; | |
748 | ||
749 | case '\f': | |
750 | *bp++ = '\\'; | |
751 | *bp++ = 'f'; | |
752 | break; | |
753 | ||
754 | case '\r': | |
755 | *bp++ = '\\'; | |
756 | *bp++ = 'r'; | |
757 | break; | |
758 | ||
759 | default: | |
760 | *bp++ = ' '; | |
761 | if ((*cp&0177) > ' ' && (*cp&0177) < 0177) | |
762 | *bp++ = *cp; | |
763 | else | |
764 | *bp++ = ' '; | |
765 | } | |
766 | *bp++ = ' '; | |
767 | } | |
768 | bp[-1] = '\0'; | |
769 | } |