Commit | Line | Data |
---|---|---|
41c799d4 C |
1 | /* tli.c |
2 | Code to handle TLI connections. | |
3 | ||
3469b437 | 4 | Copyright (C) 1992, 1993, 1994 Ian Lance Taylor |
41c799d4 C |
5 | |
6 | This file is part of the Taylor UUCP package. | |
7 | ||
8 | This program is free software; you can redistribute it and/or | |
9 | modify it under the terms of the GNU General Public License as | |
10 | published by the Free Software Foundation; either version 2 of the | |
11 | License, or (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
21 | ||
22 | The author of the program may be contacted at ian@airs.com or | |
3469b437 | 23 | c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139. |
41c799d4 C |
24 | */ |
25 | ||
26 | #include "uucp.h" | |
27 | ||
28 | #if USE_RCS_ID | |
3469b437 | 29 | const char tli_rcsid[] = "$Id: tli.c,v 1.15 1994/01/30 20:59:40 ian Rel $"; |
41c799d4 C |
30 | #endif |
31 | ||
32 | #if HAVE_TLI | |
33 | ||
34 | #include "sysdep.h" | |
35 | #include "uudefs.h" | |
36 | #include "uuconf.h" | |
37 | #include "conn.h" | |
38 | #include "system.h" | |
39 | ||
40 | #include <errno.h> | |
41 | ||
42 | #if HAVE_SYS_IOCTL_H | |
43 | #include <sys/ioctl.h> | |
44 | #endif | |
45 | ||
46 | #if HAVE_TIUSER_H | |
47 | #include <tiuser.h> | |
48 | #else | |
49 | #if HAVE_XTI_H | |
50 | #include <xti.h> | |
51 | #else | |
52 | #if HAVE_SYS_TLI_H | |
53 | #include <sys/tli.h> | |
54 | #endif | |
55 | #endif | |
56 | #endif | |
57 | ||
58 | #if HAVE_STROPTS_H | |
59 | #include <stropts.h> | |
60 | #endif | |
61 | ||
62 | #if HAVE_FCNTL_H | |
63 | #include <fcntl.h> | |
64 | #else | |
65 | #if HAVE_SYS_FILE_H | |
66 | #include <sys/file.h> | |
67 | #endif | |
68 | #endif | |
69 | ||
70 | #ifndef O_RDONLY | |
71 | #define O_RDONLY 0 | |
72 | #define O_WRONLY 1 | |
73 | #define O_RDWR 2 | |
74 | #endif | |
75 | ||
76 | #ifndef FD_CLOEXEC | |
77 | #define FD_CLOEXEC 1 | |
78 | #endif | |
79 | ||
80 | /* The arguments to t_alloca have two different names. I want the | |
81 | SVID ones, not the XPG3 ones. */ | |
82 | #ifndef T_BIND | |
83 | #define T_BIND T_BIND_STR | |
84 | #endif | |
85 | #ifndef T_CALL | |
86 | #define T_CALL T_CALL_STR | |
87 | #endif | |
88 | ||
89 | /* Hopefully these externs will not cause any trouble. This is how | |
90 | they are shown in the SVID. */ | |
91 | extern int t_errno; | |
92 | extern char *t_errlist[]; | |
93 | extern int t_nerr; | |
94 | ||
3469b437 | 95 | #ifndef HAVE_TIUSER_H |
41c799d4 C |
96 | #ifndef t_alloc |
97 | extern pointer t_alloc (); | |
98 | #endif | |
3469b437 | 99 | #endif |
41c799d4 C |
100 | \f |
101 | /* This code handles TLI connections. It's Unix specific. It's | |
102 | largely based on code from Unix Network Programming, by W. Richard | |
103 | Stevens. */ | |
104 | \f | |
105 | /* Local functions. */ | |
106 | static const char *ztlierror P((void)); | |
107 | static void utli_free P((struct sconnection *qconn)); | |
108 | static boolean ftli_push P((struct sconnection *qconn)); | |
109 | static boolean ftli_open P((struct sconnection *qconn, long ibaud, | |
110 | boolean fwait)); | |
111 | static boolean ftli_close P((struct sconnection *qconn, | |
112 | pointer puuconf, | |
113 | struct uuconf_dialer *qdialer, | |
114 | boolean fsuccess)); | |
41c799d4 C |
115 | static boolean ftli_dial P((struct sconnection *qconn, pointer puuconf, |
116 | const struct uuconf_system *qsys, | |
117 | const char *zphone, | |
118 | struct uuconf_dialer *qdialer, | |
119 | enum tdialerfound *ptdialer)); | |
120 | \f | |
121 | /* The command table for a TLI connection. */ | |
122 | static const struct sconncmds stlicmds = | |
123 | { | |
124 | utli_free, | |
125 | NULL, /* pflock */ | |
126 | NULL, /* pfunlock */ | |
127 | ftli_open, | |
128 | ftli_close, | |
41c799d4 C |
129 | ftli_dial, |
130 | fsysdep_conn_read, | |
131 | fsysdep_conn_write, | |
132 | fsysdep_conn_io, | |
133 | NULL, /* pfbreak */ | |
134 | NULL, /* pfset */ | |
135 | NULL, /* pfcarrier */ | |
136 | fsysdep_conn_chat, | |
137 | NULL /* pibaud */ | |
138 | }; | |
139 | \f | |
140 | /* Get a TLI error string. */ | |
141 | ||
142 | static const char * | |
143 | ztlierror () | |
144 | { | |
145 | if (t_errno == TSYSERR) | |
146 | return strerror (errno); | |
147 | if (t_errno < 0 || t_errno >= t_nerr) | |
148 | return "Unknown TLI error"; | |
149 | return t_errlist[t_errno]; | |
150 | } | |
151 | \f | |
3469b437 AC |
152 | /* Initialize a TLI connection. This may be called with qconn->qport |
153 | NULL, when opening standard input as a TLI connection. */ | |
41c799d4 C |
154 | |
155 | boolean | |
156 | fsysdep_tli_init (qconn) | |
157 | struct sconnection *qconn; | |
158 | { | |
159 | struct ssysdep_conn *q; | |
160 | ||
161 | q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn)); | |
162 | q->o = -1; | |
3469b437 AC |
163 | q->ord = -1; |
164 | q->owr = -1; | |
41c799d4 C |
165 | q->zdevice = NULL; |
166 | q->iflags = -1; | |
3469b437 | 167 | q->iwr_flags = -1; |
41c799d4 C |
168 | q->fterminal = FALSE; |
169 | q->ftli = TRUE; | |
170 | q->ibaud = 0; | |
171 | ||
172 | qconn->psysdep = (pointer) q; | |
173 | qconn->qcmds = &stlicmds; | |
174 | return TRUE; | |
175 | } | |
176 | ||
177 | /* Free a TLI connection. */ | |
178 | ||
179 | static void | |
180 | utli_free (qconn) | |
181 | struct sconnection *qconn; | |
182 | { | |
183 | xfree (qconn->psysdep); | |
184 | } | |
185 | \f | |
186 | /* Push all desired modules onto a TLI stream. If the user requests a | |
187 | STREAMS connection without giving a list of modules, we just push | |
188 | tirdwr. If the I_PUSH ioctl is not defined on this system, we just | |
189 | ignore any list of modules. */ | |
190 | ||
191 | static boolean | |
192 | ftli_push (qconn) | |
193 | struct sconnection *qconn; | |
194 | { | |
195 | #ifdef I_PUSH | |
196 | ||
197 | struct ssysdep_conn *qsysdep; | |
198 | ||
199 | qsysdep = (struct ssysdep_conn *) qconn->psysdep; | |
200 | ||
201 | if (qconn->qport->uuconf_u.uuconf_stli.uuconf_pzpush != NULL) | |
202 | { | |
203 | char **pz; | |
204 | ||
205 | for (pz = qconn->qport->uuconf_u.uuconf_stli.uuconf_pzpush; | |
206 | *pz != NULL; | |
207 | pz++) | |
208 | { | |
209 | if (ioctl (qsysdep->o, I_PUSH, *pz) < 0) | |
210 | { | |
211 | ulog (LOG_ERROR, "ioctl (I_PUSH, %s): %s", *pz, | |
212 | strerror (errno)); | |
213 | return FALSE; | |
214 | } | |
215 | } | |
216 | } | |
217 | else if (qconn->qport->uuconf_u.uuconf_stli.uuconf_fstream) | |
218 | { | |
219 | if (ioctl (qsysdep->o, I_PUSH, "tirdwr") < 0) | |
220 | { | |
221 | ulog (LOG_ERROR, "ioctl (I_PUSH, tirdwr): %s", | |
222 | strerror (errno)); | |
223 | return FALSE; | |
224 | } | |
225 | } | |
226 | ||
227 | /* If we have just put the connection into stream mode, we must turn | |
228 | off the TLI flag to avoid using TLI calls on it. */ | |
229 | if (qconn->qport->uuconf_u.uuconf_stli.uuconf_fstream) | |
230 | qsysdep->ftli = FALSE; | |
231 | ||
232 | #endif /* defined (I_PUSH) */ | |
233 | ||
234 | return TRUE; | |
235 | } | |
236 | \f | |
237 | /* Open a TLI connection. If the fwait argument is TRUE, we are | |
238 | running as a server. Otherwise we are just trying to reach another | |
239 | system. */ | |
240 | ||
241 | static boolean | |
242 | ftli_open (qconn, ibaud, fwait) | |
243 | struct sconnection *qconn; | |
244 | long ibaud; | |
245 | boolean fwait; | |
246 | { | |
247 | struct ssysdep_conn *qsysdep; | |
248 | const char *zdevice; | |
249 | char *zfreedev; | |
250 | const char *zservaddr; | |
251 | char *zfreeaddr; | |
252 | struct t_bind *qtbind; | |
253 | struct t_call *qtcall; | |
254 | ||
255 | /* Unlike most other device types, we don't bother to call | |
256 | ulog_device here, because fconn_open calls it with the name of | |
257 | the port anyhow. */ | |
258 | ||
259 | qsysdep = (struct ssysdep_conn *) qconn->psysdep; | |
260 | ||
261 | zdevice = qconn->qport->uuconf_u.uuconf_stli.uuconf_zdevice; | |
262 | if (zdevice == NULL) | |
263 | zdevice = qconn->qport->uuconf_zname; | |
264 | ||
265 | zfreedev = NULL; | |
266 | if (*zdevice != '/') | |
267 | { | |
268 | zfreedev = zbufalc (sizeof "/dev/" + strlen (zdevice)); | |
269 | sprintf (zfreedev, "/dev/%s", zdevice); | |
270 | zdevice = zfreedev; | |
271 | } | |
272 | ||
273 | qsysdep->o = t_open (zdevice, O_RDWR, (struct t_info *) NULL); | |
274 | if (qsysdep->o < 0) | |
275 | { | |
276 | ulog (LOG_ERROR, "t_open (%s): %s", zdevice, ztlierror ()); | |
277 | ubuffree (zfreedev); | |
278 | return FALSE; | |
279 | } | |
280 | ||
281 | if (fcntl (qsysdep->o, F_SETFD, | |
282 | fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0) | |
283 | { | |
284 | ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); | |
285 | ubuffree (zfreedev); | |
286 | (void) t_close (qsysdep->o); | |
287 | qsysdep->o = -1; | |
288 | return FALSE; | |
289 | } | |
290 | ||
291 | qsysdep->iflags = fcntl (qsysdep->o, F_GETFL, 0); | |
292 | if (qsysdep->iflags < 0) | |
293 | { | |
294 | ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); | |
295 | ubuffree (zfreedev); | |
296 | (void) t_close (qsysdep->o); | |
297 | qsysdep->o = -1; | |
298 | return FALSE; | |
299 | } | |
300 | ||
3469b437 AC |
301 | /* We save our process ID in the qconn structure. This is checked |
302 | in ftli_close. */ | |
303 | qsysdep->ipid = getpid (); | |
304 | ||
41c799d4 C |
305 | /* If we aren't waiting for a connection, we can bind to any local |
306 | address, and then we're finished. */ | |
307 | if (! fwait) | |
308 | { | |
309 | ubuffree (zfreedev); | |
310 | if (t_bind (qsysdep->o, (struct t_bind *) NULL, | |
311 | (struct t_bind *) NULL) < 0) | |
312 | { | |
313 | ulog (LOG_ERROR, "t_bind: %s", ztlierror ()); | |
314 | (void) t_close (qsysdep->o); | |
315 | qsysdep->o = -1; | |
316 | return FALSE; | |
317 | } | |
318 | return TRUE; | |
319 | } | |
320 | ||
321 | /* Run as a server and wait for a new connection. The code in | |
322 | uucico.c has already detached us from our controlling terminal. | |
323 | From this point on if the server gets an error we exit; we only | |
324 | return if we have received a connection. It would be more robust | |
325 | to respawn the server if it fails; someday. */ | |
326 | qtbind = (struct t_bind *) t_alloc (qsysdep->o, T_BIND, T_ALL); | |
327 | if (qtbind == NULL) | |
328 | ulog (LOG_FATAL, "t_alloc (T_BIND): %s", ztlierror ()); | |
329 | ||
330 | zservaddr = qconn->qport->uuconf_u.uuconf_stli.uuconf_zservaddr; | |
331 | if (zservaddr == NULL) | |
332 | ulog (LOG_FATAL, "Can't run as TLI server; no server address"); | |
333 | ||
334 | zfreeaddr = zbufcpy (zservaddr); | |
335 | qtbind->addr.len = cescape (zfreeaddr); | |
336 | if (qtbind->addr.len > qtbind->addr.maxlen) | |
337 | ulog (LOG_FATAL, "%s: TLI server address too long (max %d)", | |
338 | zservaddr, qtbind->addr.maxlen); | |
339 | memcpy (qtbind->addr.buf, zfreeaddr, qtbind->addr.len); | |
340 | ubuffree (zfreeaddr); | |
341 | ||
342 | qtbind->qlen = 5; | |
343 | ||
344 | if (t_bind (qsysdep->o, qtbind, (struct t_bind *) NULL) < 0) | |
345 | ulog (LOG_FATAL, "t_bind (%s): %s", zservaddr, ztlierror ()); | |
346 | ||
347 | (void) t_free ((pointer) qtbind, T_BIND); | |
348 | ||
349 | qtcall = (struct t_call *) t_alloc (qsysdep->o, T_CALL, T_ALL); | |
350 | if (qtcall == NULL) | |
351 | ulog (LOG_FATAL, "t_alloc (T_CALL): %s", ztlierror ()); | |
352 | ||
353 | while (! FGOT_SIGNAL ()) | |
354 | { | |
355 | int onew; | |
356 | pid_t ipid; | |
357 | ||
358 | DEBUG_MESSAGE0 (DEBUG_PORT, | |
359 | "ftli_open: Waiting for connections"); | |
360 | ||
361 | if (t_listen (qsysdep->o, qtcall) < 0) | |
362 | ulog (LOG_FATAL, "t_listen: %s", ztlierror ()); | |
363 | ||
364 | onew = t_open (zdevice, O_RDWR, (struct t_info *) NULL); | |
365 | if (onew < 0) | |
366 | ulog (LOG_FATAL, "t_open (%s): %s", zdevice, ztlierror ()); | |
367 | ||
368 | if (fcntl (onew, F_SETFD, | |
369 | fcntl (onew, F_GETFD, 0) | FD_CLOEXEC) < 0) | |
370 | ulog (LOG_FATAL, "fcntl (FD_CLOEXEC): %s", strerror (errno)); | |
371 | ||
372 | if (t_bind (onew, (struct t_bind *) NULL, (struct t_bind *) NULL) < 0) | |
373 | ulog (LOG_FATAL, "t_bind: %s", ztlierror ()); | |
374 | ||
375 | if (t_accept (qsysdep->o, onew, qtcall) < 0) | |
376 | { | |
377 | /* We may have received a disconnect. */ | |
378 | if (t_errno != TLOOK) | |
379 | ulog (LOG_FATAL, "t_accept: %s", ztlierror ()); | |
380 | if (t_rcvdis (qsysdep->o, (struct t_discon *) NULL) < 0) | |
381 | ulog (LOG_FATAL, "t_rcvdis: %s", ztlierror ()); | |
382 | (void) t_close (onew); | |
383 | continue; | |
384 | } | |
385 | ||
386 | DEBUG_MESSAGE0 (DEBUG_PORT, | |
387 | "ftli_open: Got connection; forking"); | |
388 | ||
389 | ipid = ixsfork (); | |
390 | if (ipid < 0) | |
391 | ulog (LOG_FATAL, "fork: %s", strerror (errno)); | |
392 | if (ipid == 0) | |
393 | { | |
394 | ulog_close (); | |
395 | ||
396 | (void) t_close (qsysdep->o); | |
397 | qsysdep->o = onew; | |
398 | ||
399 | /* Push any desired modules. */ | |
400 | if (! ftli_push (qconn)) | |
401 | _exit (EXIT_FAILURE); | |
402 | ||
403 | /* Now we fork and let our parent die, so that we become | |
404 | a child of init. This lets the main server code wait | |
405 | for its child and then continue without accumulating | |
406 | zombie children. */ | |
407 | ipid = ixsfork (); | |
408 | if (ipid < 0) | |
409 | { | |
410 | ulog (LOG_ERROR, "fork: %s", strerror (errno)); | |
411 | _exit (EXIT_FAILURE); | |
412 | } | |
413 | ||
414 | if (ipid != 0) | |
415 | _exit (EXIT_SUCCESS); | |
416 | ||
417 | ulog_id (getpid ()); | |
418 | ||
419 | return TRUE; | |
420 | } | |
421 | ||
422 | (void) t_close (onew); | |
423 | ||
424 | /* Now wait for the child. */ | |
425 | (void) ixswait ((unsigned long) ipid, (const char *) NULL); | |
426 | } | |
427 | ||
428 | /* We got a signal. */ | |
429 | usysdep_exit (FALSE); | |
430 | ||
431 | /* Avoid compiler warnings. */ | |
432 | return FALSE; | |
433 | } | |
434 | \f | |
435 | /* Close the port. */ | |
436 | ||
437 | /*ARGSUSED*/ | |
438 | static boolean | |
439 | ftli_close (qconn, puuconf, qdialer, fsuccess) | |
440 | struct sconnection *qconn; | |
441 | pointer puuconf; | |
442 | struct uuconf_dialer *qdialer; | |
443 | boolean fsuccess; | |
444 | { | |
445 | struct ssysdep_conn *qsysdep; | |
446 | boolean fret; | |
447 | ||
448 | qsysdep = (struct ssysdep_conn *) qconn->psysdep; | |
449 | ||
450 | fret = TRUE; | |
451 | if (qsysdep->o >= 0) | |
452 | { | |
453 | if (qsysdep->ftli) | |
454 | { | |
455 | if (t_close (qsysdep->o) < 0) | |
456 | { | |
457 | ulog (LOG_ERROR, "t_close: %s", ztlierror ()); | |
458 | fret = FALSE; | |
459 | } | |
460 | } | |
461 | else | |
462 | { | |
463 | if (close (qsysdep->o) < 0) | |
464 | { | |
465 | ulog (LOG_ERROR, "close: %s", strerror (errno)); | |
466 | fret = FALSE; | |
467 | } | |
468 | } | |
469 | ||
470 | qsysdep->o = -1; | |
471 | } | |
472 | ||
3469b437 AC |
473 | /* If the current pid is not the one we used to open the port, then |
474 | we must have forked up above and we are now the child. In this | |
475 | case, we are being called from within the fendless loop in | |
476 | uucico.c. We return FALSE to force the loop to end and the child | |
477 | to exit. This should be handled in a cleaner fashion. */ | |
478 | if (qsysdep->ipid != getpid ()) | |
479 | fret = FALSE; | |
41c799d4 | 480 | |
3469b437 | 481 | return fret; |
41c799d4 C |
482 | } |
483 | \f | |
484 | /* Dial out on a TLI port, so to speak: connect to a remote computer. */ | |
485 | ||
486 | /*ARGSUSED*/ | |
487 | static boolean | |
488 | ftli_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound) | |
489 | struct sconnection *qconn; | |
490 | pointer puuconf; | |
491 | const struct uuconf_system *qsys; | |
492 | const char *zphone; | |
493 | struct uuconf_dialer *qdialer; | |
494 | enum tdialerfound *ptdialerfound; | |
495 | { | |
496 | struct ssysdep_conn *qsysdep; | |
497 | char **pzdialer; | |
498 | const char *zaddr; | |
499 | struct t_call *qtcall; | |
500 | char *zescape; | |
501 | ||
502 | qsysdep = (struct ssysdep_conn *) qconn->psysdep; | |
503 | ||
504 | *ptdialerfound = DIALERFOUND_FALSE; | |
505 | ||
506 | pzdialer = qconn->qport->uuconf_u.uuconf_stli.uuconf_pzdialer; | |
507 | if (*pzdialer == NULL) | |
508 | pzdialer = NULL; | |
509 | ||
510 | /* If the first dialer is "TLI" or "TLIS", we use the first token | |
511 | (pzdialer[1]) as the address to connect to. */ | |
512 | zaddr = zphone; | |
513 | if (pzdialer != NULL | |
514 | && (strcmp (pzdialer[0], "TLI") == 0 | |
515 | || strcmp (pzdialer[0], "TLIS") == 0)) | |
516 | { | |
517 | if (pzdialer[1] == NULL) | |
518 | ++pzdialer; | |
519 | else | |
520 | { | |
521 | if (strcmp (pzdialer[1], "\\D") != 0 | |
522 | && strcmp (pzdialer[1], "\\T") != 0) | |
523 | zaddr = pzdialer[1]; | |
524 | pzdialer += 2; | |
525 | } | |
526 | } | |
527 | ||
528 | if (zaddr == NULL) | |
529 | { | |
530 | ulog (LOG_ERROR, "No address for TLI connection"); | |
531 | return FALSE; | |
532 | } | |
533 | ||
534 | qtcall = (struct t_call *) t_alloc (qsysdep->o, T_CALL, T_ADDR); | |
535 | if (qtcall == NULL) | |
536 | { | |
537 | ulog (LOG_ERROR, "t_alloc (T_CALL): %s", ztlierror ()); | |
538 | return FALSE; | |
539 | } | |
540 | ||
541 | zescape = zbufcpy (zaddr); | |
542 | qtcall->addr.len = cescape (zescape); | |
543 | if (qtcall->addr.len > qtcall->addr.maxlen) | |
544 | { | |
545 | ulog (LOG_ERROR, "%s: TLI address too long (max %d)", zaddr, | |
546 | qtcall->addr.maxlen); | |
547 | ubuffree (zescape); | |
548 | return FALSE; | |
549 | } | |
550 | memcpy (qtcall->addr.buf, zescape, qtcall->addr.len); | |
551 | ubuffree (zescape); | |
552 | ||
553 | if (t_connect (qsysdep->o, qtcall, (struct t_call *) NULL) < 0) | |
554 | { | |
555 | if (t_errno != TLOOK) | |
556 | ulog (LOG_ERROR, "t_connect: %s", ztlierror ()); | |
557 | else | |
558 | { | |
559 | if (t_rcvdis (qsysdep->o, (struct t_discon *) NULL) < 0) | |
560 | ulog (LOG_ERROR, "t_rcvdis: %s", ztlierror ()); | |
561 | else | |
562 | ulog (LOG_ERROR, "Connection refused"); | |
563 | } | |
564 | return FALSE; | |
565 | } | |
566 | ||
567 | /* We've connected to the remote. Push any desired modules. */ | |
568 | if (! ftli_push (qconn)) | |
569 | return FALSE; | |
570 | ||
3469b437 AC |
571 | /* Handle the rest of the dialer sequence. */ |
572 | if (pzdialer != NULL && *pzdialer != NULL) | |
41c799d4 | 573 | { |
3469b437 AC |
574 | if (! fconn_dial_sequence (qconn, puuconf, pzdialer, qsys, zphone, |
575 | qdialer, ptdialerfound)) | |
576 | return FALSE; | |
41c799d4 C |
577 | } |
578 | ||
579 | return TRUE; | |
580 | } | |
581 | ||
582 | #endif /* HAVE_TLI */ |