BSD 4_3_Net_2 development
[unix-history] / usr / src / contrib / isode / support / tsapd.c
CommitLineData
9319b3c3
C
1/* tsapd.c - OSI transport listener */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/support/RCS/tsapd.c,v 7.12 91/02/22 09:46:59 mrose Interim $";
5#endif
6
7/*
8 * $Header: /f/osi/support/RCS/tsapd.c,v 7.12 91/02/22 09:46:59 mrose Interim $
9 *
10 *
11 * $Log: tsapd.c,v $
12 * Revision 7.12 91/02/22 09:46:59 mrose
13 * Interim 6.8
14 *
15 * Revision 7.11 90/12/19 09:16:14 mrose
16 * touch-up
17 *
18 * Revision 7.10 90/12/17 22:13:27 mrose
19 * -call
20 *
21 * Revision 7.9 90/12/11 10:52:29 mrose
22 * lock-and-load
23 *
24 * Revision 7.8 90/11/05 14:10:32 mrose
25 * oops
26 *
27 * Revision 7.7 90/10/30 14:25:32 mrose
28 * update
29 *
30 * Revision 7.6 90/10/29 18:37:25 mrose
31 * updates
32 *
33 * Revision 7.5 90/10/16 11:21:04 mrose
34 * update
35 *
36 * Revision 7.4 90/10/15 22:54:26 mrose
37 * typo
38 *
39 * Revision 7.3 90/10/15 18:18:47 mrose
40 * iaed
41 *
42 * Revision 7.2 90/07/09 14:51:00 mrose
43 * sync
44 *
45 * Revision 7.1 90/02/19 13:09:53 mrose
46 * update
47 *
48 * Revision 7.0 89/11/23 22:27:46 mrose
49 * Release 6.0
50 *
51 */
52
53/*
54 * NOTICE
55 *
56 * Acquisition, use, and distribution of this module and related
57 * materials are subject to the restrictions of a license agreement.
58 * Consult the Preface in the User's Manual for the full terms of
59 * this agreement.
60 *
61 */
62
63
64#include <errno.h>
65#include <signal.h>
66#include <stdio.h>
67#include <varargs.h>
68#include "manifest.h"
69#include <sys/ioctl.h>
70#include <sys/stat.h>
71#ifdef BSD42
72#include <sys/file.h>
73#endif
74#ifdef SYS5
75#include <fcntl.h>
76#endif
77#ifndef X_OK
78#define X_OK 1
79#endif
80
81#ifdef IAE
82#include <quipu/util.h>
83#include <quipu/bind.h>
84#include <quipu/list.h>
85#include <quipu/ds_search.h>
86
87#define NOGOSIP
88#endif
89
90#ifndef NOGOSIP
91#include "rosap.h"
92#include "rtsap.h"
93#include "psap2.h"
94#include "ssap.h"
95#endif
96#include "tpkt.h"
97
98#ifdef TCP
99#include "internet.h"
100#endif
101#ifdef X25
102#include "x25.h"
103#endif
104#ifdef TP4
105#include "tp4.h"
106#endif
107#ifndef IAE
108#include "isoservent.h"
109#endif
110#include "tailor.h"
111
112/* \f */
113
114static int debug = 0;
115static int nbits = FD_SETSIZE;
116
117static LLog _pgm_log = {
118#ifndef IAE
119 "tsapd.log",
120#else
121 "iaed.log",
122#endif
123 NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE,
124 LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK
125};
126LLog *pgm_log = &_pgm_log;
127
128static char *pgmname = "tsapd";
129static char myhost[BUFSIZ];
130
131static int tcpservice = 1;
132static int x25service = 1;
133static int bridgeservice = 1;
134static int tp4service = 1;
135
136static int *services[] = {
137 &tp4service, &tcpservice, &x25service, &bridgeservice
138};
139
140
141#define NTADDRS FD_SETSIZE
142
143static int listening = 0;
144
145static struct TSAPaddr *tz;
146static struct TSAPaddr tas[NTADDRS];
147
148
149#ifdef IAE
150#define IAETIME (24 * 60 * 60L)
151
152static int isbound = 0;
153static int main_dsa = NOTOK;
154static int referral_dsa = NOTOK;
155
156static long nextime;
157
158static DN userdn = NULL;
159static char passwd[DBA_MAX_PASSWD_LEN];
160
161static AttributeType t_ev;
162static AttributeType t_pa;
163
164static struct ds_search_arg search_arg;
165
166struct IAEntry {
167 struct TSAPaddr is_addr;
168
169 char *is_vector;
170 char **is_vec;
171 char **is_tail;
172};
173
174#define NENTRIES 100
175static struct IAEntry *iz;
176static struct IAEntry iae[NENTRIES];
177
178
179int str2dnY ();
180
181
182extern int dsa_ad;
183extern int dsa_dead;
184extern char *local_dit;
185extern struct PSAPaddr dsa_bound;
186
187extern int as_print (), dn_print (), de_print (), fi_print ();
188#endif
189
190
191void adios (), advise ();
192void ts_advise ();
193
194#ifdef NOGOSIP
195#define ssapd NULLIFP
196#else
197int ssapd (), psapd ();
198#endif
199
200
201extern int errno;
202
203#ifdef IAE
204long time ();
205#endif
206
207/* \f */
208
209/* ARGSUSED */
210
211main (argc, argv, envp)
212int argc;
213char **argv,
214 **envp;
215{
216 int failed,
217 vecp;
218 char *vec[4];
219 register struct TSAPaddr *ta;
220 struct TSAPdisconnect tds;
221 register struct TSAPdisconnect *td = &tds;
222
223 arginit (argv);
224 envinit ();
225
226 failed = 0;
227
228 for (ta = tas; ta < tz; ta++) {
229 register struct NSAPaddr *na;
230
231 if (ta -> ta_naddr) {
232 if (((na = ta -> ta_addrs) -> na_stack < 0
233 || na -> na_stack
234 >= sizeof services / sizeof services[0]))
235 adios (NULLCP, "unknown network type 0x%x", na -> na_stack);
236 }
237 else
238 na = NULLNA;
239
240 if (!*services[na ? na -> na_stack : NA_NSAP])
241 continue;
242
243 advise (LLOG_NOTICE, NULLCP, "listening on %s", taddr2str (ta));
244
245 if (TNetListen (ta, td) == NOTOK) {
246 ts_advise (td, LLOG_EXCEPTIONS, "TNetListen failed");
247 failed++;
248 }
249 else
250 listening++;
251 }
252
253 if (!listening)
254 adios (NULLCP, failed ? "no successful listens"
255 : "no network services selected");
256
257 for (;;) {
258#ifdef IAE
259 int secs;
260 long now;
261
262 (void) time (&now);
263 now++;
264
265 if ((secs = (int) (nextime - now)) <= 0) {
266 search_directory (0);
267
268 secs = IAETIME;
269 }
270#else
271#define secs NOTOK
272#endif
273
274 if (TNetAccept (&vecp, vec, 0, NULLFD, NULLFD, NULLFD, secs, td)
275 == NOTOK) {
276 ts_advise (td, LLOG_EXCEPTIONS, "TNetAccept failed");
277 continue;
278 }
279
280 if (vecp <= 0)
281 continue;
282
283 if (debug)
284 break;
285
286 switch (TNetFork (vecp, vec, td)) {
287 case OK:
288#ifdef IAE
289 (void) signal (SIGHUP, SIG_DFL);
290#endif
291 ll_hdinit (pgm_log, pgmname);
292 break;
293
294 case NOTOK:
295 ts_advise (td, LLOG_EXCEPTIONS, "TNetFork failed");
296 default:
297 continue;
298 }
299 break;
300 }
301
302 tsapd (vecp, vec);
303}
304
305/* \f */
306
307static char buffer1[4096];
308static char buffer2[32768];
309
310
311static int tsapd (vecp, vec)
312int vecp;
313char **vec;
314{
315 char buffer[BUFSIZ];
316#ifndef IAE
317 register struct isoservent *is;
318#else
319 register struct IAEntry *is;
320#endif
321 struct tsapblk *tb;
322 struct TSAPstart tss;
323 register struct TSAPstart *ts = &tss;
324 struct TSAPdisconnect tds;
325 register struct TSAPdisconnect *td = &tds;
326 IFP hook;
327
328/* begin UGLY */
329 (void) strcpy (buffer1, vec[1]);
330 (void) strcpy (buffer2, vec[2]);
331/* end UGLY */
332
333 if (TInit (vecp, vec, ts, td) == NOTOK) {
334 ts_advise (td, LLOG_EXCEPTIONS, "T-CONNECT.INDICATION");
335 return;
336 }
337
338/* used to print this in ssapd()... */
339 advise (LLOG_NOTICE, NULLCP,
340 "T-CONNECT.INDICATION: <%d, %s, %s, %d, %d>",
341 ts -> ts_sd,
342 taddr2str (&ts -> ts_calling), taddr2str (&ts -> ts_called),
343 ts -> ts_expedited, ts -> ts_tsdusize);
344
345 hook = ssapd;
346 if (ts -> ts_called.ta_selectlen) {
347#ifndef IAE
348 if ((is = getisoserventbyselector ("tsap", ts -> ts_called.ta_selector,
349 ts -> ts_called.ta_selectlen))
350 == NULL) {
351#else
352 for (is = iae; is < iz; is++)
353 if (is -> is_addr.ta_selectlen == ts -> ts_called.ta_selectlen
354 && bcmp (is -> is_addr.ta_selector,
355 ts -> ts_called.ta_selector,
356 is -> is_addr.ta_selectlen) == 0)
357 break;
358 if (is >= iz) {
359#endif
360 (void) sprintf (buffer, "OSI service tsap/%s not found",
361 sel2str (ts -> ts_called.ta_selector,
362 ts -> ts_called.ta_selectlen, 1));
363 goto out;
364 }
365 }
366 else
367#ifndef IAE
368 if (hook == NULLIFP
369 || (is = getisoserventbyname ("session", "tsap")) == NULL)
370#endif
371 {
372 (void) strcpy (buffer, "default session service not found");
373 goto out;
374 }
375
376#ifndef IAE
377 *is -> is_tail++ = buffer1;
378 *is -> is_tail++ = buffer2;
379 *is -> is_tail = NULL;
380#else
381 is -> is_tail[0] = buffer1;
382 is -> is_tail[1] = buffer2;
383 is -> is_tail[2] = NULL;
384#endif
385
386 if (tb = findtblk (ts -> ts_sd))
387 tb -> tb_fd = NOTOK;
388 switch (hook ? (*hook) (is, td) : OK) {
389 case NOTOK:
390 ts_advise (td, LLOG_EXCEPTIONS, "service not started at tsap");
391 case DONE:
392 exit (1);
393 /* NOTREACHED */
394
395 case OK:
396 default:
397 (void) setperms (is);
398 (void) execv (*is -> is_vec, is -> is_vec);
399 (void) sprintf (buffer, "unable to exec %s: %s",
400 *is -> is_vec, sys_errname (errno));
401 SLOG (pgm_log, LLOG_FATAL, NULLCP, ("%s", buffer));
402 break;
403 }
404
405out: ;
406 advise (LLOG_EXCEPTIONS, NULLCP, "%s", buffer);
407 if (strlen (buffer) >= TD_SIZE)
408 buffer[0] = NULL;
409 (void) TDiscRequest (ts -> ts_sd, buffer, strlen (buffer) + 1, td);
410
411 exit (1);
412}
413
414/* \f */
415
416static int setperms (is)
417#ifndef IAE
418register struct isoservent *is;
419#else
420register struct IAEntry *is;
421#endif
422{
423 struct stat st;
424
425 if (stat (*is -> is_vec, &st) == NOTOK) {
426 (void) setgid (1);
427 (void) setuid (1);
428 }
429 else {
430 (void) setgid (st.st_gid);
431 (void) setuid (st.st_uid);
432 }
433}
434
435/* \f */
436
437static void ts_advise (td, code, event)
438register struct TSAPdisconnect *td;
439int code;
440char *event;
441{
442 char buffer[BUFSIZ];
443
444 if (td -> td_cc > 0)
445 (void) sprintf (buffer, "[%s] %*.*s",
446 TErrString (td -> td_reason),
447 td -> td_cc, td -> td_cc, td -> td_data);
448 else
449 (void) sprintf (buffer, "[%s]", TErrString (td -> td_reason));
450
451 advise (code, NULLCP, "%s: %s", event, buffer);
452}
453
454/* \f */
455
456#ifndef NOGOSIP
457static int ssapd (is, td)
458register struct isoservent *is;
459register struct TSAPdisconnect *td;
460{
461 int sd;
462 struct TSAPstart tss;
463 register struct TSAPstart *ts = &tss;
464 struct SSAPindication sis;
465 register struct SSAPabort *sa = &sis.si_abort;
466
467 if (strcmp (is -> is_entity, "session")
468 || strcmp (is -> is_provider, "tsap"))
469 return OK;
470
471 if (TInit (is -> is_tail - is -> is_vec, is -> is_vec, ts, td) == NOTOK)
472 return NOTOK;
473
474 sd = ts -> ts_sd;
475
476 if (TConnResponse (sd, &ts -> ts_called, ts -> ts_expedited, NULLCP, 0,
477 NULLQOS, td) == NOTOK)
478 return NOTOK;
479
480 if (SExec (ts, &sis, psapd, setperms) == NOTOK) {
481 advise (LLOG_EXCEPTIONS, NULLCP, "service not started at ssap: %s",
482 SErrString (sa -> sa_reason));
483 if (sa -> sa_cc > 0)
484 advise (LLOG_EXCEPTIONS, NULLCP, " %*.*s",
485 sa -> sa_cc, sa -> sa_cc, sa -> sa_data);
486
487 SAFREE (sa);
488 }
489
490 return DONE;
491}
492
493/* \f */
494
495#define RMASK \
496 "\020\01HALFDUPLEX\02DUPLEX\03EXPEDITED\04MINORSYNC\05MAJORSYNC\06RESYNC\
497\07ACTIVITY\010NEGOTIATED\011CAPABILITY\012EXCEPTIONS\013TYPEDATA"
498
499
500static int psapd (is, si)
501register struct isoservent *is;
502register struct SSAPindication *si;
503{
504 struct SSAPstart sss;
505 register struct SSAPstart *ss = &sss;
506 struct PSAPindication pis;
507 register struct PSAPabort *pa = &pis.pi_abort;
508 struct RtSAPindication rtis;
509 register struct RtSAPabort *rta = &rtis.rti_abort;
510 struct RoSAPindication rois;
511 register struct RoSAPpreject *rop = &rois.roi_preject;
512
513 if (strcmp (is -> is_provider, "ssap"))
514 return OK;
515
516 if (strcmp (is -> is_entity, "presentation")
517 && strcmp (is -> is_entity, "rts")
518 && strcmp (is -> is_entity, "ros"))
519 return OK;
520
521/* begin UGLY */
522 (void) strcpy (buffer1, *(is -> is_tail - 2));
523 (void) strcpy (buffer2, *(is -> is_tail - 1));
524/* end UGLY */
525 if (SInit (is -> is_tail - is -> is_vec, is -> is_vec, ss, si) == NOTOK)
526 return NOTOK;
527 advise (LLOG_NOTICE, NULLCP,
528 "S-CONNECT.INDICATION: <%d, %s, %s, %s, %s, %ld, %d>",
529 ss -> ss_sd, sprintref (&ss -> ss_connect),
530 saddr2str (&ss -> ss_calling), saddr2str (&ss -> ss_called),
531 sprintb (ss -> ss_requirements, RMASK), ss -> ss_isn,
532 ss -> ss_ssdusize);
533
534 if (strcmp (is -> is_entity, "presentation") == 0) {
535 if (PExec (ss, &pis, buffer1, buffer2, NULLIFP, setperms) == NOTOK) {
536 advise (LLOG_EXCEPTIONS, NULLCP,
537 "service not started at psap: %s",
538 PErrString (pa -> pa_reason));
539 if (pa -> pa_cc > 0)
540 advise (LLOG_EXCEPTIONS, NULLCP, " %*.*s",
541 pa -> pa_cc, pa -> pa_cc, pa -> pa_data);
542 }
543
544 return DONE;
545 }
546
547 if (strcmp (is -> is_entity, "rts") == 0) {
548 if (RtExec (ss, &rtis, buffer1, buffer2, NULLIFP, setperms) == NOTOK) {
549 advise (LLOG_EXCEPTIONS, NULLCP,
550 "service not started at rtsap: %s",
551 RtErrString (rta -> rta_reason));
552 if (rta -> rta_cc > 0)
553 advise (LLOG_EXCEPTIONS, NULLCP, " %*.*s",
554 rta -> rta_cc, rta -> rta_cc, rta -> rta_data);
555 }
556 }
557 else {
558 if (RoExec (ss, &rois, buffer1, buffer2, NULLIFP, setperms) == NOTOK) {
559 advise (LLOG_EXCEPTIONS, NULLCP,
560 "service not started at rosap: %s",
561 RoErrString (rop -> rop_reason));
562 if (rop -> rop_cc > 0)
563 advise (LLOG_EXCEPTIONS, NULLCP, " %*.*s",
564 rop -> rop_cc, rop -> rop_cc, rop -> rop_data);
565 }
566 }
567
568 return DONE;
569}
570#endif
571
572/* \f */
573
574#ifndef IAE
575static arginit (vec)
576char **vec;
577{
578 int rflag;
579 register char *ap;
580#ifdef TCP
581 int port;
582 struct NSAPaddr *tcp_na;
583 register struct servent *sp;
584#endif
585#ifdef X25
586 struct NSAPaddr *x25_na;
587#endif
588#ifdef BRIDGE_X25
589 struct NSAPaddr *bridge_na;
590#endif
591#ifdef TP4
592 register struct isoservent *is;
593#endif
594 struct stat st;
595
596 if (pgmname = rindex (*vec, '/'))
597 pgmname++;
598 if (pgmname == NULL || *pgmname == NULL)
599 pgmname = *vec;
600
601 isodetailor (pgmname, 0);
602 ll_hdinit (pgm_log, pgmname);
603
604 rflag = 0;
605
606 (void) strcpy (myhost, TLocalHostName ());
607
608 bzero ((char *) tas, sizeof tas);
609 tz = tas;
610
611#ifdef TCP
612 if (!(ts_stacks & TS_TCP))
613 tcpservice = 0;
614 if ((sp = getservbyname ("tsap", "tcp")) == NULL
615 && (sp = getservbyname ("iso-tsap", "tcp")) == NULL)
616 advise (LLOG_EXCEPTIONS, NULLCP, "tcp/tsap: unknown service");
617
618 tcp_na = tz -> ta_addrs;
619 tcp_na -> na_stack = NA_TCP;
620 tcp_na -> na_community = ts_comm_tcp_default;
621 tcp_na -> na_domain[0] = NULL;
622 tcp_na -> na_port = sp ? sp -> s_port : htons ((u_short) 102);
623 tz -> ta_naddr = 1;
624
625 tz++;
626#endif
627
628#ifdef X25
629 if (!(ts_stacks & TS_X25))
630 x25service = 0;
631
632 x25_na = tz -> ta_addrs;
633 x25_na -> na_stack = NA_X25;
634 x25_na -> na_community = ts_comm_x25_default;
635 if (x25_local_dte && *x25_local_dte) {
636 (void) strcpy (x25_na -> na_dte, x25_local_dte);
637 x25_na -> na_dtelen = strlen (x25_na -> na_dte);
638 }
639 if (x25_local_pid && *x25_local_pid)
640 x25_na -> na_pidlen =
641 str2sel (x25_local_pid, -1, x25_na -> na_pid, NPSIZE);
642 tz -> ta_naddr = 1;
643
644 tz++;
645#endif
646
647#ifdef BRIDGE_X25
648 if (!(ts_stacks & TS_BRG))
649 bridgeservice = 0;
650
651 bridge_na = tz -> ta_addrs;
652 bridge_na -> na_stack = NA_BRG;
653 bridge_na -> na_community = ts_comm_x25_default;
654 if (x25_bridge_listen && *x25_bridge_listen) {
655 (void) strcpy (bridge_na -> na_dte, x25_bridge_listen);
656 bridge_na -> na_dtelen = strlen (bridge_na -> na_dte);
657 }
658 if (x25_bridge_pid && *x25_bridge_pid)
659 bridge_na -> na_pidlen =
660 str2sel (x25_bridge_pid, -1, bridge_na -> na_pid, NPSIZE);
661 tz -> ta_naddr = 1;
662
663 tz++;
664#endif
665
666#ifdef TP4
667 if (!(ts_stacks & TS_TP4))
668 tp4service = 0;
669
670 (void) setisoservent (0);
671 while (is = getisoservent ())
672 if (strcmp (is -> is_provider, "tsap") == 0
673 && (strcmp (*is -> is_vec, "tsapd-bootstrap") == 0
674 || access (*is -> is_vec, X_OK) != NOTOK)) {
675 if (strcmp (is -> is_entity, "isore") == 0)
676 continue;
677
678 if (tz >= tas + NTADDRS) {
679 advise (LLOG_EXCEPTIONS, NULLCP,
680 "too many services, starting with %s",
681 is -> is_entity);
682 break;
683 }
684
685 bcopy (is -> is_selector, tz -> ta_selector,
686 tz -> ta_selectlen = is -> is_selectlen);
687 tz -> ta_naddr = 0;
688
689 tz++;
690 }
691 (void) endisoservent ();
692#endif
693
694 for (vec++; ap = *vec; vec++) {
695 if (*ap == '-')
696 switch (*++ap) {
697 case 'd':
698 debug++;
699 continue;
700
701 case 't':
702 ts_stacks = TS_TCP;
703 tcpservice = 1;
704 x25service = bridgeservice = tp4service = 0;
705 continue;
706
707 case 'x':
708 ts_stacks = TS_X25;
709 x25service = 1;
710 tcpservice = bridgeservice = tp4service = 0;
711 continue;
712
713 case 'z':
714 ts_stacks = TS_TP4;
715 tp4service = 1;
716 tcpservice = x25service = bridgeservice = 0;
717 continue;
718
719 case 'b':
720 ts_stacks = TS_BRG;
721 bridgeservice = 1;
722 tcpservice = x25service = tp4service = 0;
723 continue;
724
725 case 'r':
726 rflag = 1;
727 continue;
728
729#ifdef TCP
730 case 'p':
731 if ((ap = *++vec) == NULL
732 || *ap == '-'
733 || (port = atoi (ap)) <= 0)
734 adios (NULLCP, "usage: %s -p portno", pgmname);
735 tcp_na -> na_port = htons ((u_short) port);
736 continue;
737#endif
738
739#ifdef X25
740 /* This permits listening on a specific subaddress. */
741 case 'a':
742 if ((ap = *++vec) == NULL || *ap == '-')
743 adios (NULLCP, "usage: %s -a x121address", pgmname);
744 (void) strcpy (x25_na -> na_dte, ap);
745 x25_na -> na_dtelen = strlen (ap);
746 continue;
747
748 /* This permits listening on a specific protocol id.
749 In fact, SunLink X.25 lets you listen on a protocol
750 id mask, but let's keep it simple. */
751 case 'i':
752 if ((ap = *++vec) == NULL || *ap == '-' )
753 adios (NULLCP, "usage: %s -i pid", pgmname);
754 x25_na -> na_pidlen =
755 str2sel (ap, -1, x25_na -> na_pid, NPSIZE);
756 continue;
757#endif
758
759#ifdef BRIDGE_X25
760 case 'A':
761 if ((ap = *++vec) == NULL ||
762 *ap == '-')
763 adios (NULLCP, "usage: %s -A x121address", pgmname);
764 (void) strcpy (bridge_na -> na_dte, ap);
765 bridge_na -> na_dtelen = strlen (ap);
766 continue;
767
768 case 'I':
769 if ((ap = *++vec) == NULL || *ap == '-')
770 adios (NULLCP, "usage: %s -I pid", pgmname);
771 bridge_na -> na_pidlen =
772 str2sel (ap, -1, bridge_na -> na_pid, NPSIZE);
773 continue;
774#endif
775
776 default:
777 adios (NULLCP, "-%s: unknown switch", ap);
778 }
779
780 adios (NULLCP, "usage: %s [switches]", pgmname);
781 }
782
783 if (!rflag
784 && getuid () == 0
785 && stat (ap = isodefile ("isoservices", 0), &st) != NOTOK
786 && st.st_uid != 0)
787 adios (NULLCP, "%s not owned by root", ap);
788}
789
790/* \f */
791
792#else
793static arginit (vec)
794char **vec;
795{
796 int argp,
797 options;
798 register char *ap;
799 char base[BUFSIZ],
800 **argptr,
801 *args[4];
802
803 if (pgmname = rindex (*vec, '/'))
804 pgmname++;
805 if (pgmname == NULL || *pgmname == NULL)
806 pgmname = *vec;
807
808 isodetailor (pgmname, 0);
809 ll_hdinit (pgm_log, pgmname);
810
811 quipu_syntaxes ();
812
813 argp = 0;
814 args[argp++] = pgmname;
815 for (argptr = vec, argptr++; ap = *argptr; argptr++) {
816 if (*ap == '-')
817 switch (*++ap) {
818 case 'D':
819 case 'u':
820 case 'p':
821 if ((ap = *++argptr) == NULL || *ap == '-')
822 break;
823 continue;
824
825 case 'c':
826 if ((ap = *++argptr) == NULL || *ap == '-')
827 break;
828 args[argp++] = "-c";
829 args[argp++] = ap;
830 break;
831
832 default:
833 continue;
834 }
835
836 break;
837 }
838 args[argp] = NULLCP;
839
840 dsap_init (&argp, (argptr = args, &argptr));
841
842 (void) strcpy (myhost, TLocalHostName ());
843 (void) strcpy (base, local_dit);
844
845 if (!(ts_stacks & TS_TCP))
846 tcpservice = 0;
847 if (!(ts_stacks & TS_X25))
848 x25service = 0;
849 if (!(ts_stacks & TS_BRG))
850 bridgeservice = 0;
851 if (!(ts_stacks & TS_TP4))
852 tp4service = 0;
853
854 options = SVC_OPT_PREFERCHAIN;
855 userdn = NULLDN, passwd[0] = NULL;
856 for (vec++; ap = *vec; vec++) {
857 if (*ap == '-')
858 switch (*++ap) {
859 case 'd':
860 debug++;
861 ll_dbinit (pgm_log, pgmname);
862 continue;
863
864 case 't':
865 ts_stacks = TS_TCP;
866 tcpservice = 1;
867 x25service = bridgeservice = tp4service = 0;
868 continue;
869
870 case 'x':
871 ts_stacks = TS_X25;
872 x25service = 1;
873 tcpservice = bridgeservice = tp4service = 0;
874 continue;
875
876 case 'z':
877 ts_stacks = TS_TP4;
878 tp4service = 1;
879 tcpservice = x25service = bridgeservice = 0;
880 continue;
881
882 case 'b':
883 ts_stacks = TS_BRG;
884 bridgeservice = 1;
885 tcpservice = x25service = tp4service = 0;
886 continue;
887
888 case 'r': /* ignored... */
889 continue;
890
891 case 'D':
892 if ((ap = *++vec) == NULL || *ap == '-')
893 adios (NULLCP, "usage: %s -D DIT", pgmname);
894 if (*ap == '@')
895 (void) strcpy (base, ap);
896 else
897 (void) sprintf (base, "%s@%s", local_dit, ap);
898 continue;
899
900 case 'm':
901 options |= SVC_OPT_DONTUSECOPY;
902 continue;
903
904 case 'c':
905 if ((ap = *++vec) == NULL || *ap == '-')
906 adios (NULLCP, "usage: %s -c DSA-name-or-address",
907 pgmname);
908 continue;
909
910 case 'u':
911 if ((ap = *++vec) == NULL || *ap == '-')
912 adios (NULLCP, "usage: %s -u username", pgmname);
913 if ((userdn = str2dn (*ap != '@' ? ap : ap + 1)) == NULLDN)
914 adios (NULLCP, "invalid DN for username: %s", ap);
915 bzero ((char *) ap, strlen (ap));
916 continue;
917
918 case 'p':
919 if ((ap = *++vec) == NULL || *ap == '-')
920 adios (NULLCP, "usage: %s -p password", pgmname);
921 (void) strcpy (passwd, ap);
922 bzero ((char *) ap, strlen (ap));
923 continue;
924
925 default:
926 adios (NULLCP, "-%s: unknown switch", ap);
927 }
928
929 adios (NULLCP, "usage: %s [switches]", pgmname);
930 }
931
932 {
933 Attr_Sequence as;
934 AttributeType t_oc;
935 DN local_dn;
936 register Filter fi;
937 register struct ds_search_arg *sa = &search_arg;
938
939 if ((t_ev = str2AttrT ("execVector")) == NULL)
940 adios (NULLCP, "unknown attribute type \"%s\"", "execVector");
941 if ((t_oc = str2AttrT ("objectClass")) == NULL)
942 adios (NULLCP, "unknown attribute type \"%s\"", "objectClass");
943 if ((t_pa = str2AttrT ("presentationAddress")) == NULL)
944 adios (NULLCP, "unknown attribute type \"%s\"",
945 "presentationAddress");
946
947 if (str2dnY (*base != '@' ? base : base + 1, &local_dn) == NOTOK)
948 adios (NULLCP, "DIT subtree invalid: \"%s\"", base);
949
950 fi = filter_alloc ();
951 bzero ((char *) fi, sizeof *fi);
952
953 fi -> flt_type = FILTER_ITEM;
954 fi -> FUITEM.fi_type = FILTERITEM_EQUALITY;
955 fi -> FUITEM.UNAVA.ava_type = AttrT_cpy (t_oc);
956 if ((fi -> FUITEM.UNAVA.ava_value =
957 str2AttrV ("iSODEApplicationEntity",
958 fi -> FUITEM.UNAVA.ava_type -> oa_syntax))
959 == NULL)
960 adios (NULLCP, "unknown attribute value \"%s\" for \"%s\"",
961 "iSODEApplicationEntity", "objectClass");
962
963 as = as_merge (as_comp_new (AttrT_cpy (t_ev), NULLAV, NULLACL_INFO),
964 as_comp_new (AttrT_cpy (t_pa), NULLAV, NULLACL_INFO));
965
966 bzero ((char *) sa, sizeof *sa);
967
968 sa -> sra_common.ca_servicecontrol.svc_options = options;
969 sa -> sra_common.ca_servicecontrol.svc_timelimit = SVC_NOTIMELIMIT;
970 sa -> sra_common.ca_servicecontrol.svc_sizelimit = SVC_NOSIZELIMIT;
971 sa -> sra_baseobject = local_dn;
972 sa -> sra_subset = SRA_WHOLESUBTREE;
973 sa -> sra_filter = fi;
974 sa -> sra_searchaliases = TRUE;
975 sa -> sra_eis.eis_allattributes = FALSE;
976 sa -> sra_eis.eis_select = as;
977 sa -> sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES;
978
979 search_directory (1);
980 }
981}
982
983/* \f */
984
985static search_directory (firstime)
986int firstime;
987{
988 int i;
989 register struct ds_search_arg *sa = &search_arg;
990 struct ds_search_result search_result;
991 register struct ds_search_result *sr = &search_result;
992 struct DSError error;
993 register struct DSError *se = &error;
994 register EntryInfo *ptr;
995 register struct IAEntry *ia;
996 register struct TSAPaddr *ta,
997 *tb,
998 *ty;
999 struct TSAPaddr tys[NTADDRS];
1000
1001 advise (LLOG_NOTICE, NULLCP,
1002 "searching directory for iSODEApplicationEntity objects");
1003
1004 while (rebind_to_directory () == NOTOK) {
1005 if (!firstime)
1006 return;
1007
1008 if (debug)
1009 advise (LLOG_DEBUG, NULLCP, "sleeping for 5 minutes...");
1010 sleep ((unsigned) 5 * 60);
1011 }
1012
1013 for (;;) {
1014 if (debug) {
1015 pslog (pgm_log, LLOG_DEBUG, "performing subtree search of",
1016 dn_print, (caddr_t) sa -> sra_baseobject);
1017 pslog (pgm_log, LLOG_DEBUG, " for", fi_print,
1018 (caddr_t) sa -> sra_filter);
1019 }
1020
1021 if (ds_search (sa, se, sr) == DS_OK)
1022 break;
1023 if (do_error (se) == NOTOK) {
1024 if (!firstime)
1025 return;
1026
1027 adios (NULLCP, "search failed");
1028 }
1029
1030 sa -> sra_baseobject =
1031 se -> ERR_REFERRAL.DSE_ref_candidates -> cr_name;
1032 }
1033
1034 if (sr -> srr_correlated != TRUE)
1035 correlate_search_results (sr);
1036
1037 if (!firstime)
1038 for (ia = iae; ia < iz; ia++) {
1039 free (ia -> is_vector);
1040 free (ia -> is_vec[0]);
1041 free ((char *) ia -> is_vec);
1042 }
1043
1044 bzero ((char *) iae, sizeof iae);
1045 iz = iae;
1046
1047 bzero ((char *) tys, sizeof tys);
1048 ty = tys;
1049
1050 i = 0;
1051 for (ptr = sr -> CSR_entries; ptr; ptr = ptr -> ent_next) {
1052 Attr_Sequence eptr;
1053 AV_Sequence avs;
1054
1055 if (iz >= iae + NENTRIES) {
1056 pslog (pgm_log, LLOG_EXCEPTIONS,
1057 "too many services, starting with", dn_print,
1058 (caddr_t) ptr -> ent_dn);
1059 break;
1060 }
1061
1062 if (debug) {
1063 pslog (pgm_log, LLOG_DEBUG, "processing", dn_print,
1064 (caddr_t) ptr -> ent_dn);
1065 pslog (pgm_log, LLOG_DEBUG, " attributes", as_print,
1066 (caddr_t) ptr -> ent_attr);
1067 }
1068
1069 for (eptr = ptr -> ent_attr; eptr; eptr = eptr -> attr_link) {
1070 if (AttrT_cmp (eptr -> attr_type, t_pa) == 0) {
1071 if (avs = eptr -> attr_value) {
1072 register struct PSAPaddr *pa =
1073 (struct PSAPaddr *) avs -> avseq_av.av_struct;
1074
1075 if ((ta = &pa -> pa_addr.sa_addr) -> ta_selectlen == 0
1076 || pa -> pa_selectlen > 0
1077 || pa -> pa_addr.sa_selectlen > 0)
1078 continue;
1079
1080 iz -> is_addr = *ta; /* struct copy */
1081 }
1082
1083 continue;
1084 }
1085
1086 if (AttrT_cmp (eptr -> attr_type, t_ev) == 0) {
1087 if (avs = eptr -> attr_value) {
1088 int vecp;
1089 register char **vp;
1090 char *cp,
1091 *evec[NVEC + NSLACK + 1];
1092
1093 cp = (char *) avs -> avseq_av.av_struct;
1094 if ((iz -> is_vector =
1095 malloc ((unsigned) (strlen (cp) + 1)))
1096 == NULL)
1097 adios (NULLCP, "out of memory allocating iaeVector");
1098 (void) strcpy (iz -> is_vector, cp);
1099
1100 if ((vecp = str2vec (iz -> is_vector, evec)) < 1)
1101 goto losing_iae;
1102 if ((iz -> is_vec =
1103 (char **) calloc ((unsigned) (vecp + 3),
1104 sizeof *iz -> is_vec))
1105 == NULL)
1106 adios (NULLCP, "out of memory allocating execVector");
1107 iz -> is_tail = iz -> is_vec, vp = evec;
1108 while (*iz -> is_tail++ = *vp++)
1109 continue;
1110 iz -> is_tail--;
1111
1112 if (access (cp = isodefile (iz -> is_vec[0], 1), X_OK)
1113 == NOTOK) {
1114 advise (LLOG_EXCEPTIONS, cp, "unable to find program");
1115 iz -> is_vec[0] = NULL;
1116 goto losing_iae;
1117 }
1118 if ((iz -> is_vec[0] =
1119 malloc ((unsigned) (strlen (cp) + 1)))
1120 == NULL)
1121 adios (NULLCP, "out of memory allocating pgmVector");
1122 (void) strcpy (iz -> is_vec[0], cp);
1123 }
1124 continue;
1125 }
1126 }
1127 if ((ta = &iz -> is_addr) -> ta_selectlen == 0
1128 || iz -> is_vector == NULL) {
1129 pslog (pgm_log, LLOG_EXCEPTIONS, "invalid entry", dn_print,
1130 (caddr_t) ptr -> ent_dn);
1131
1132losing_iae: ;
1133 if (iz -> is_vector)
1134 free (iz -> is_vector);
1135 if (iz -> is_vec) {
1136 if (iz -> is_vec[0])
1137 free (iz -> is_vec[0]);
1138 free ((char *) iz -> is_vec);
1139 }
1140 bzero ((char *) iz, sizeof *iz);
1141 continue;
1142 }
1143
1144 if (ta -> ta_naddr == 0)
1145 *ty++ = *ta; /* struct copy */
1146 else {
1147 register int n = ta -> ta_naddr;
1148 register struct NSAPaddr *na = ta -> ta_addrs;
1149
1150 for (; n > 0; na++, n--) {
1151 for (tb = tys; tb < ty; tb++)
1152 if (tb -> ta_naddr != 0
1153 && bcmp ((char *) na, (char *) tb -> ta_addrs,
1154 sizeof *na) == 0)
1155 break;
1156 if (tb >= ty) {
1157 if (na -> na_type == NA_NSAP)
1158 bcopy (ta -> ta_selector, ty -> ta_selector,
1159 ty -> ta_selectlen = ta -> ta_selectlen);
1160 else
1161 ty -> ta_selectlen = 0;
1162 ty -> ta_naddr = 1;
1163 ty -> ta_addrs[0] = *na; /* struct copy */
1164
1165 ty++;
1166 }
1167 }
1168 }
1169
1170 for (ia = iae; ia < iz; ia++) {
1171 tb = &ia -> is_addr;
1172
1173 if (ta -> ta_selectlen == tb -> ta_selectlen
1174 && bcmp (ta -> ta_selector, tb -> ta_selector,
1175 ta -> ta_selectlen) == 0) {
1176 char buffer[BUFSIZ];
1177
1178 (void) strcpy (buffer, taddr2str (tb));
1179 advise (LLOG_EXCEPTIONS, NULLCP,
1180 "two services with the same transport selector: %s and %s",
1181 buffer, taddr2str (ta));
1182 pslog (pgm_log, LLOG_EXCEPTIONS, "starting with", dn_print,
1183 (caddr_t) ptr -> ent_dn);
1184 adios (NULLCP, "you lose big");
1185 }
1186 }
1187
1188 iz++, i++;
1189 }
1190
1191 if (sr -> CSR_cr) {
1192 advise (LLOG_EXCEPTIONS, NULLCP,
1193 "partial results only (not all DSAs could be reached)");
1194 }
1195 else
1196 if (sr -> CSR_limitproblem != LSR_NOLIMITPROBLEM) {
1197 advise (LLOG_EXCEPTIONS, NULLCP, "%s limit exceeded",
1198 sr -> CSR_limitproblem == LSR_TIMELIMITEXCEEDED
1199 ? "time"
1200 : sr -> CSR_limitproblem == LSR_SIZELIMITEXCEEDED
1201 ? "size" : "administrative");
1202 }
1203
1204 if (i == 0)
1205 adios (NULLCP, "search failed to find anything");
1206 else
1207 if (debug)
1208 advise (LLOG_DEBUG, NULLCP, "%d match%s found",
1209 i, i != 1 ? "es" : "");
1210
1211 dn_free (sr -> CSR_object);
1212 entryinfo_free (sr -> CSR_entries, 0);
1213 crefs_free (sr -> CSR_cr);
1214
1215 (void) unbind_from_directory ();
1216
1217 if (!firstime) {
1218 int failed = 0;
1219 struct TSAPdisconnect tds;
1220
1221 for (ta = tas; ta < tz; ta++) {
1222 for (tb = tys; tb < ty; tb++)
1223 if (bcmp ((char *) ta, (char *) tb, sizeof *ta) == 0)
1224 break;
1225 if (tb >= ty) {
1226 advise (LLOG_NOTICE, NULLCP, "closing %s", taddr2str (ta));
1227
1228 if (TNetClose (ta, &tds) == NOTOK)
1229 ts_advise (&tds, LLOG_EXCEPTIONS, "TNetClose failed");
1230
1231 listening--;
1232 }
1233 }
1234
1235 for (ta = tys; ta < ty; ta++) {
1236 for (tb = tas; tb < tz; tb++)
1237 if (bcmp ((char *) ta, (char *) tb, sizeof *ta) == 0)
1238 break;
1239 if (tb >= tz) {
1240 register struct NSAPaddr *na;
1241
1242 if (ta -> ta_naddr) {
1243 if (((na = ta -> ta_addrs) -> na_stack < 0
1244 || na -> na_stack
1245 >= sizeof services / sizeof services[0]))
1246 adios (NULLCP, "unknown network type 0x%x",
1247 na -> na_stack);
1248 }
1249 else
1250 na = NULLNA;
1251
1252 if (!*services[na ? na -> na_stack : NA_NSAP])
1253 continue;
1254
1255 advise (LLOG_NOTICE, NULLCP, "listening on %s",
1256 taddr2str (ta));
1257
1258 if (TNetListen (ta, &tds) == NOTOK) {
1259 ts_advise (&tds, LLOG_EXCEPTIONS, "TNetListen failed");
1260 failed++;
1261 }
1262 else
1263 listening++;
1264 }
1265 }
1266
1267 if (!listening)
1268 adios (NULLCP, failed ? "no successful listens"
1269 : "no network services selected");
1270
1271 }
1272 bzero ((char *) tas, sizeof tas);
1273 tz = tas;
1274
1275 for (ta = tys; ta < ty; *tz++ = *ta++) /* struct copy */
1276 continue;
1277
1278 if (debug) {
1279 advise (LLOG_DEBUG, NULLCP, "application entitites...");
1280 for (ia = iae; ia < iz; ia++)
1281 advise (LLOG_DEBUG, NULLCP, " addr=%s vector=%s",
1282 taddr2str (&ia -> is_addr), ia -> is_vector);
1283
1284 advise (LLOG_DEBUG, NULLCP, "transport addresses...");
1285 for (ta = tas; ta < tz; ta++)
1286 advise (LLOG_DEBUG, NULLCP, " addr=%s", taddr2str (ta));
1287 }
1288
1289 (void) time (&nextime);
1290 nextime += IAETIME;
1291}
1292
1293/* \f */
1294
1295static bind_to_directory ()
1296{
1297 struct ds_bind_arg bind_arg,
1298 bind_result;
1299 register struct ds_bind_arg *ba = &bind_arg,
1300 *br = &bind_result;
1301 struct ds_bind_error bind_error;
1302 register struct ds_bind_error *be = &bind_error;
1303 static int very_first_time = 1;
1304
1305 (void) unbind_from_directory ();
1306
1307 make_bind_args (ba, br, be);
1308
1309 if (debug)
1310 advise (LLOG_DEBUG, NULLCP, "connecting to DSA...");
1311
1312 if (secure_ds_bind (ba, be, br) != DS_OK) {
1313 if (very_first_time)
1314 very_first_time = 0;
1315 else
1316 advise (LLOG_EXCEPTIONS, NULLCP, "unable to connect: %s",
1317 be -> dbe_type == DBE_TYPE_SECURITY ? "security error"
1318 : "DSA unavailable");
1319
1320 isbound = 0;
1321
1322 return;
1323 }
1324 very_first_time = 0;
1325 dn_free (br -> dba_dn);
1326
1327 main_dsa = dsap_ad;
1328
1329 advise (LLOG_NOTICE, NULLCP, "connected to %s", pa2str (&dsa_bound));
1330
1331 isbound = 1;
1332}
1333
1334/* \f */
1335
1336static int rebind_to_directory ()
1337{
1338 if (referral_dsa != NOTOK) {
1339 if (debug)
1340 advise (LLOG_DEBUG, NULLCP, "dap_unbind from referral dsa");
1341
1342 (void) dap_unbind (referral_dsa);
1343 referral_dsa = NOTOK;
1344 dsap_ad = main_dsa;
1345 }
1346
1347 if (!isbound)
1348 (void) bind_to_directory ();
1349
1350 return (isbound ? OK : NOTOK);
1351}
1352
1353/* \f */
1354
1355static int make_bind_args (ba, br, be)
1356register struct ds_bind_arg *ba,
1357 *br;
1358register struct ds_bind_error *be;
1359{
1360 bzero ((char *) ba, sizeof *ba);
1361 bzero ((char *) br, sizeof *br);
1362 bzero ((char *) be, sizeof *be);
1363
1364 ba -> dba_version = DBA_VERSION_V1988;
1365 if (ba -> dba_dn = userdn)
1366 ba -> dba_auth_type = DBA_AUTH_SIMPLE;
1367 if (ba -> dba_passwd_len = strlen (passwd))
1368 (void) strcpy (ba -> dba_passwd, passwd);
1369}
1370
1371/* \f */
1372
1373static int unbind_from_directory ()
1374{
1375 int wasbound;
1376
1377 if (wasbound = isbound) {
1378 if (referral_dsa != NOTOK) {
1379 if (debug)
1380 advise (LLOG_DEBUG, NULLCP, "dap_unbind from referral dsa");
1381
1382 (void) dap_unbind (referral_dsa);
1383 referral_dsa = NOTOK;
1384 dsap_ad = main_dsa;
1385 }
1386
1387 (void) ds_unbind ();
1388 isbound = 0;
1389 }
1390
1391 dsa_dead = 0;
1392
1393 return wasbound;
1394}
1395
1396/* \f */
1397
1398static int do_error (de)
1399register struct DSError *de;
1400{
1401 if (de -> dse_type == DSE_REFERRAL
1402 && de -> ERR_REFERRAL.DSE_ref_candidates) {
1403 register struct access_point *ap;
1404 struct ds_bind_arg bind_arg,
1405 bind_result;
1406 register struct ds_bind_arg *ba = &bind_arg,
1407 *br = &bind_result;
1408 struct ds_bind_error bind_error;
1409 register struct ds_bind_error *be = &bind_error;
1410
1411 ap = de -> ERR_REFERRAL.DSE_ref_candidates -> cr_accesspoints;
1412
1413 if (referral_dsa != NOTOK) {
1414 if (debug)
1415 advise (LLOG_DEBUG, NULLCP, "dap_unbind from referral dsa");
1416
1417 (void) dap_unbind (referral_dsa);
1418 referral_dsa = NOTOK;
1419 dsap_ad = main_dsa;
1420 }
1421
1422 make_bind_args (ba, br, be);
1423
1424 pslog (pgm_log, LLOG_NOTICE, "referring to", dn_print,
1425 (caddr_t) ap -> ap_name);
1426
1427 if (dap_bind (&referral_dsa, ba, be, br, ap -> ap_address) != DS_OK) {
1428 advise (LLOG_EXCEPTIONS, NULLCP, "unable to connect: %s",
1429 be -> dbe_type == DBE_TYPE_SECURITY ? "security error"
1430 : "DSA unavailable");
1431
1432 dsap_ad = main_dsa;
1433
1434 ds_error_free (de);
1435 return NOTOK;
1436 }
1437 dsap_ad = referral_dsa;
1438
1439 if (debug)
1440 advise (LLOG_DEBUG, NULLCP, "referral in progress");
1441
1442 ds_error_free (de);
1443 return OK;
1444 }
1445
1446 pslog (pgm_log, LLOG_EXCEPTIONS, "DAP error:", de_print, (caddr_t) de);
1447
1448 if (dsa_dead) {
1449 dsa_dead = 0;
1450
1451 if (referral_dsa != NOTOK) {
1452 if (debug)
1453 advise (LLOG_DEBUG, NULLCP, "dap_unbind from referral dsa");
1454
1455 (void) dap_unbind (referral_dsa);
1456 referral_dsa = NOTOK;
1457 dsap_ad = main_dsa;
1458 }
1459 else
1460 (void) unbind_from_directory ();
1461 }
1462
1463 return NOTOK;
1464}
1465
1466/* \f */
1467
1468int str2dnY (str, dn)
1469char *str;
1470DN *dn;
1471{
1472 if (*str == NULL) {
1473 *dn = NULLDN;
1474 return OK;
1475 }
1476
1477 return ((*dn = str2dn (str)) != NULLDN ? OK : NOTOK);
1478}
1479
1480/* \f */
1481
1482#ifdef BSD42
1483/* ARGSUSED */
1484#endif
1485
1486static SFD hupser (sig)
1487int sig;
1488{
1489#ifndef BSD42
1490 (void) signal (sig, hupser);
1491#endif
1492
1493 search_directory (0);
1494}
1495#endif
1496
1497/* \f */
1498
1499static envinit () {
1500 int i,
1501 sd;
1502
1503 nbits = getdtablesize ();
1504
1505 if (debug == 0 && !(debug = isatty (2))) {
1506 for (i = 0; i < 5; i++) {
1507 switch (fork ()) {
1508 case NOTOK:
1509 sleep (5);
1510 continue;
1511
1512 case OK:
1513 break;
1514
1515 default:
1516 _exit (0);
1517 }
1518 break;
1519 }
1520
1521 (void) chdir ("/");
1522
1523 if ((sd = open ("/dev/null", O_RDWR)) == NOTOK)
1524 adios ("/dev/null", "unable to read");
1525 if (sd != 0)
1526 (void) dup2 (sd, 0), (void) close (sd);
1527 (void) dup2 (0, 1);
1528 (void) dup2 (0, 2);
1529
1530#ifdef SETSID
1531 if (setsid () == NOTOK)
1532 advise (LLOG_EXCEPTIONS, "failed", "setsid");
1533#endif
1534#ifdef TIOCNOTTY
1535 if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
1536 (void) ioctl (sd, TIOCNOTTY, NULLCP);
1537 (void) close (sd);
1538 }
1539#else
1540#ifdef SYS5
1541 (void) setpgrp ();
1542 (void) signal (SIGINT, SIG_IGN);
1543 (void) signal (SIGQUIT, SIG_IGN);
1544#endif
1545#endif
1546 }
1547 else
1548 ll_dbinit (pgm_log, pgmname);
1549
1550#ifndef sun /* damn YP... */
1551 for (sd = 3; sd < nbits; sd++)
1552 if (pgm_log -> ll_fd != sd)
1553 (void) close (sd);
1554#endif
1555
1556 (void) signal (SIGPIPE, SIG_IGN);
1557
1558 ll_hdinit (pgm_log, pgmname);
1559 advise (LLOG_NOTICE, NULLCP, "starting");
1560
1561#ifdef IAE
1562 (void) signal (SIGHUP, hupser);
1563#endif
1564}
1565
1566/* \f ERRORS */
1567
1568#ifndef lint
1569void adios (va_alist)
1570va_dcl
1571{
1572 va_list ap;
1573
1574 va_start (ap);
1575
1576 _ll_log (pgm_log, LLOG_FATAL, ap);
1577
1578 va_end (ap);
1579
1580 _exit (1);
1581}
1582#else
1583/* VARARGS */
1584
1585void adios (what, fmt)
1586char *what,
1587 *fmt;
1588{
1589 adios (what, fmt);
1590}
1591#endif
1592
1593
1594#ifndef lint
1595void advise (va_alist)
1596va_dcl
1597{
1598 int code;
1599 va_list ap;
1600
1601 va_start (ap);
1602
1603 code = va_arg (ap, int);
1604
1605 _ll_log (pgm_log, code, ap);
1606
1607 va_end (ap);
1608}
1609#else
1610/* VARARGS */
1611
1612void advise (code, what, fmt)
1613char *what,
1614 *fmt;
1615int code;
1616{
1617 advise (code, what, fmt);
1618}
1619#endif