1 /* syssub.c
2 System information subroutines.
3
4 Copyright (C) 1992, 1993, 1995, 2002 Ian Lance Taylor
5
6 This file is part of the Taylor UUCP uuconf library.
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License
10 as published by the Free Software Foundation; either version 2 of
11 the License, or (at your option) any later version.
12
13 This library 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 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21
22 The author of the program may be contacted at ian@airs.com.
23 */
24
25 #include "uucnfi.h"
26
27 #if USE_RCS_ID
28 const char _uuconf_syssub_rcsid[] = "$FreeBSD$";
29 #endif
30
31 #include <errno.h>
32
33 /* This macro operates on every string (char *) field in struct
34 uuconf_system. */
35 #define SYSTEM_STRINGS(OP) \
36 do \
37 { \
38 OP (uuconf_zname); \
39 OP (uuconf_zalternate); \
40 OP (uuconf_zdebug); \
41 OP (uuconf_zmax_remote_debug); \
42 OP (uuconf_zphone); \
43 OP (uuconf_zcall_login); \
44 OP (uuconf_zcall_password); \
45 OP (uuconf_zcalled_login); \
46 OP (uuconf_zprotocols); \
47 OP (uuconf_zpubdir); \
48 OP (uuconf_zlocalname); \
49 } \
50 while (0)
51
52 /* This macro operates on every string array (char **) field in struct
53 uuconf_system. */
54 #define SYSTEM_STRING_ARRAYS(OP) \
55 do \
56 { \
57 OP (uuconf_pzalias); \
58 OP (uuconf_pzlocal_send); \
59 OP (uuconf_pzremote_send); \
60 OP (uuconf_pzlocal_receive); \
61 OP (uuconf_pzremote_receive); \
62 OP (uuconf_pzpath); \
63 OP (uuconf_pzcmds); \
64 OP (uuconf_pzforward_from); \
65 OP (uuconf_pzforward_to); \
66 OP (uuconf_schat.uuconf_pzchat); \
67 OP (uuconf_schat.uuconf_pzprogram); \
68 OP (uuconf_schat.uuconf_pzfail); \
69 OP (uuconf_scalled_chat.uuconf_pzchat); \
70 OP (uuconf_scalled_chat.uuconf_pzprogram); \
71 OP (uuconf_scalled_chat.uuconf_pzfail); \
72 } \
73 while (0)
74
75 /* This macro operations on every timespan pointer (struct
76 uuconf_timespan *) in struct uuconf_system. */
77 #define SYSTEM_TIMESPANS(OP) \
78 do \
79 { \
80 OP (uuconf_qtimegrade); \
81 OP (uuconf_qcalltimegrade); \
82 OP (uuconf_qcalledtimegrade); \
83 OP (uuconf_qcall_local_size); \
84 OP (uuconf_qcall_remote_size); \
85 OP (uuconf_qcalled_local_size); \
86 OP (uuconf_qcalled_remote_size); \
87 } \
88 while (0)
89
90 /* This macro operates on every boolean value (of type int, although
91 some type int are not boolean) field in uuconf_system. */
92 #define SYSTEM_BOOLEANS(OP) \
93 do \
94 { \
95 OP (uuconf_fcall); \
96 OP (uuconf_fcalled); \
97 OP (uuconf_fcallback); \
98 OP (uuconf_fsequence); \
99 OP (uuconf_fsend_request); \
100 OP (uuconf_frec_request); \
101 OP (uuconf_fcall_transfer); \
102 OP (uuconf_fcalled_transfer); \
103 OP (uuconf_schat.uuconf_fstrip); \
104 OP (uuconf_scalled_chat.uuconf_fstrip); \
105 } \
106 while (0)
107
108 /* This macro operates on every generic integer (type int or long) in
109 uuconf_system. */
110 #define SYSTEM_INTEGERS(OP) \
111 do \
112 { \
113 OP (uuconf_cmax_retries); \
114 OP (uuconf_csuccess_wait); \
115 OP (uuconf_ibaud); \
116 OP (uuconf_ihighbaud); \
117 OP (uuconf_cfree_space); \
118 OP (uuconf_schat.uuconf_ctimeout); \
119 OP (uuconf_scalled_chat.uuconf_ctimeout); \
120 OP (uuconf_cmax_file_time); \
121 } \
122 while (0)
123
124 /* There is no macro for uuconf_qalternate, uuconf_zport,
125 uuconf_qport, uuconf_qproto_params, or uuconf_palloc. */
126
127 /* Clear the contents of a struct uuconf_system. */
128
129 void
_uuconf_uclear_system(q)130 _uuconf_uclear_system (q)
131 struct uuconf_system *q;
132 {
133 #define CLEAR(x) q->x = (char *) &_uuconf_unset
134 SYSTEM_STRINGS (CLEAR);
135 #undef CLEAR
136 #define CLEAR(x) q->x = (char **) &_uuconf_unset
137 SYSTEM_STRING_ARRAYS (CLEAR);
138 #undef CLEAR
139 #define CLEAR(x) q->x = (struct uuconf_timespan *) &_uuconf_unset
140 SYSTEM_TIMESPANS (CLEAR);
141 #undef CLEAR
142 #define CLEAR(x) q->x = -1
143 SYSTEM_BOOLEANS (CLEAR);
144 SYSTEM_INTEGERS (CLEAR);
145 #undef CLEAR
146 q->uuconf_qalternate = NULL;
147 q->uuconf_zport = (char *) &_uuconf_unset;
148 q->uuconf_qport = (struct uuconf_port *) &_uuconf_unset;
149 q->uuconf_qproto_params = (struct uuconf_proto_param *) &_uuconf_unset;
150 q->uuconf_palloc = NULL;
151 }
152
153 /* Default the contents of one struct uuconf_system to the contents of
154 another. This default alternate by alternate. Any additional
155 alternates in q default to the last alternate of qdefault. If the
156 faddalternates arguments is TRUE, additional alternates or qdefault
157 are added to q; these alternates are copies of the first alternate
158 of q, and defaults are set from the additional alternates of
159 qdefault. */
160
161 int
_uuconf_isystem_default(qglobal,qset,qdefault,faddalternates)162 _uuconf_isystem_default (qglobal, qset, qdefault, faddalternates)
163 struct sglobal *qglobal;
164 struct uuconf_system *qset;
165 struct uuconf_system *qdefault;
166 boolean faddalternates;
167 {
168 struct uuconf_system *qalt;
169
170 if (qset->uuconf_palloc != qdefault->uuconf_palloc)
171 qset->uuconf_palloc =
172 _uuconf_pmalloc_block_merge (qset->uuconf_palloc,
173 qdefault->uuconf_palloc);
174
175 /* If we are adding alternates from the default, make sure we have
176 at least as many alternates in qset as we do in qdefault. Each
177 new alternate we create gets initialized to the first alternate
178 of the system. */
179 if (faddalternates)
180 {
181 struct uuconf_system **pq, *qdef;
182
183 for (qdef = qdefault, pq = &qset;
184 qdef != NULL;
185 qdef = qdef->uuconf_qalternate, pq = &(*pq)->uuconf_qalternate)
186 {
187 if (*pq == NULL)
188 {
189 *pq = ((struct uuconf_system *)
190 uuconf_malloc (qset->uuconf_palloc,
191 sizeof (struct uuconf_system)));
192 if (*pq == NULL)
193 {
194 qglobal->ierrno = errno;
195 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
196 }
197 **pq = *qset;
198 (*pq)->uuconf_qalternate = NULL;
199 }
200 }
201 }
202
203 for (qalt = qset; qalt != NULL; qalt = qalt->uuconf_qalternate)
204 {
205 #define DEFAULT(x) \
206 if (qalt->x == (char *) &_uuconf_unset) qalt->x = qdefault->x
207 SYSTEM_STRINGS (DEFAULT);
208 #undef DEFAULT
209 #define DEFAULT(x) \
210 if (qalt->x == (char **) &_uuconf_unset) qalt->x = qdefault->x
211 SYSTEM_STRING_ARRAYS (DEFAULT);
212 #undef DEFAULT
213 #define DEFAULT(x) \
214 if (qalt->x == (struct uuconf_timespan *) &_uuconf_unset) \
215 qalt->x = qdefault->x
216 SYSTEM_TIMESPANS (DEFAULT);
217 #undef DEFAULT
218 #define DEFAULT(x) if (qalt->x < 0) qalt->x = qdefault->x
219 SYSTEM_BOOLEANS (DEFAULT);
220 SYSTEM_INTEGERS (DEFAULT);
221 #undef DEFAULT
222
223 /* We only copy over zport if both zport and qport are NULL,
224 because otherwise a default zport would override a specific
225 qport. */
226 if (qalt->uuconf_zport == (char *) &_uuconf_unset
227 && qalt->uuconf_qport == (struct uuconf_port *) &_uuconf_unset)
228 qalt->uuconf_zport = qdefault->uuconf_zport;
229 if (qalt->uuconf_qport == (struct uuconf_port *) &_uuconf_unset)
230 qalt->uuconf_qport = qdefault->uuconf_qport;
231
232 if (qalt->uuconf_qproto_params
233 == (struct uuconf_proto_param *) &_uuconf_unset)
234 qalt->uuconf_qproto_params = qdefault->uuconf_qproto_params;
235 else if (qdefault->uuconf_qproto_params != NULL)
236 {
237 int cnew, ca;
238 struct uuconf_proto_param *qd, *qa;
239
240 /* Merge in the default protocol parameters, so that a
241 system with 'g' protocol parameters won't lose the
242 default 'i' protocol parameters. */
243 ca = 0;
244 cnew = 0;
245 for (qd = qdefault->uuconf_qproto_params;
246 qd->uuconf_bproto != '\0';
247 qd++)
248 {
249 int c;
250
251 c = 0;
252 for (qa = qalt->uuconf_qproto_params;
253 (qa->uuconf_bproto != '\0'
254 && qa->uuconf_bproto != qd->uuconf_bproto);
255 qa++)
256 ++c;
257 if (qa->uuconf_bproto == '\0')
258 {
259 ++cnew;
260 ca = c;
261 }
262 }
263
264 if (cnew > 0)
265 {
266 struct uuconf_proto_param *qnew;
267
268 qnew = ((struct uuconf_proto_param *)
269 uuconf_malloc (qset->uuconf_palloc,
270 ((ca + cnew + 1)
271 * sizeof (struct uuconf_proto_param))));
272 if (qnew == NULL)
273 {
274 qglobal->ierrno = errno;
275 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
276 }
277 memcpy ((pointer) qnew, (pointer) qalt->uuconf_qproto_params,
278 ca * sizeof (struct uuconf_proto_param));
279 cnew = 0;
280 for (qd = qdefault->uuconf_qproto_params;
281 qd->uuconf_bproto != '\0';
282 qd++)
283 {
284 for (qa = qalt->uuconf_qproto_params;
285 (qa->uuconf_bproto != '\0'
286 && qa->uuconf_bproto != qd->uuconf_bproto);
287 qa++)
288 ;
289 if (qa->uuconf_bproto == '\0')
290 {
291 qnew[ca + cnew] = *qd;
292 ++cnew;
293 }
294 }
295 qnew[ca + cnew].uuconf_bproto = '\0';
296 uuconf_free (qset->uuconf_palloc, qalt->uuconf_qproto_params);
297 qalt->uuconf_qproto_params = qnew;
298 }
299 }
300
301 if (qdefault->uuconf_qalternate != NULL)
302 qdefault = qdefault->uuconf_qalternate;
303 }
304
305 return UUCONF_SUCCESS;
306 }
307
308 /* Put in the basic defaults. This ensures that the fields are valid
309 on every uuconf_system structure. */
310
311 int
_uuconf_isystem_basic_default(qglobal,q)312 _uuconf_isystem_basic_default (qglobal, q)
313 struct sglobal *qglobal;
314 register struct uuconf_system *q;
315 {
316 int iret;
317
318 iret = UUCONF_SUCCESS;
319
320 for (; q != NULL && iret == UUCONF_SUCCESS; q = q->uuconf_qalternate)
321 {
322 /* The default of 26 allowable retries is traditional. */
323 if (q->uuconf_cmax_retries < 0)
324 q->uuconf_cmax_retries = 26;
325 if (q->uuconf_schat.uuconf_pzchat == (char **) &_uuconf_unset)
326 {
327 q->uuconf_schat.uuconf_pzchat = NULL;
328 iret = _uuconf_iadd_string (qglobal, (char *) "\"\"", FALSE,
329 FALSE,
330 &q->uuconf_schat.uuconf_pzchat,
331 q->uuconf_palloc);
332 if (iret != UUCONF_SUCCESS)
333 return iret;
334 iret = _uuconf_iadd_string (qglobal, (char *) "\\r\\c", FALSE,
335 FALSE,
336 &q->uuconf_schat.uuconf_pzchat,
337 q->uuconf_palloc);
338 if (iret != UUCONF_SUCCESS)
339 return iret;
340 iret = _uuconf_iadd_string (qglobal, (char *) "ogin:", FALSE,
341 FALSE,
342 &q->uuconf_schat.uuconf_pzchat,
343 q->uuconf_palloc);
344 if (iret != UUCONF_SUCCESS)
345 return iret;
346 iret = _uuconf_iadd_string (qglobal, (char *) "-BREAK", FALSE,
347 FALSE,
348 &q->uuconf_schat.uuconf_pzchat,
349 q->uuconf_palloc);
350 if (iret != UUCONF_SUCCESS)
351 return iret;
352 iret = _uuconf_iadd_string (qglobal, (char *) "-ogin:", FALSE,
353 FALSE,
354 &q->uuconf_schat.uuconf_pzchat,
355 q->uuconf_palloc);
356 if (iret != UUCONF_SUCCESS)
357 return iret;
358 iret = _uuconf_iadd_string (qglobal, (char *) "-BREAK", FALSE,
359 FALSE,
360 &q->uuconf_schat.uuconf_pzchat,
361 q->uuconf_palloc);
362 if (iret != UUCONF_SUCCESS)
363 return iret;
364 iret = _uuconf_iadd_string (qglobal, (char *) "-ogin:", FALSE,
365 FALSE,
366 &q->uuconf_schat.uuconf_pzchat,
367 q->uuconf_palloc);
368 if (iret != UUCONF_SUCCESS)
369 return iret;
370 iret = _uuconf_iadd_string (qglobal, (char *) "\\L", FALSE,
371 FALSE,
372 &q->uuconf_schat.uuconf_pzchat,
373 q->uuconf_palloc);
374 if (iret != UUCONF_SUCCESS)
375 return iret;
376 iret = _uuconf_iadd_string (qglobal, (char *) "word:", FALSE,
377 FALSE,
378 &q->uuconf_schat.uuconf_pzchat,
379 q->uuconf_palloc);
380 if (iret != UUCONF_SUCCESS)
381 return iret;
382 iret = _uuconf_iadd_string (qglobal, (char *) "\\P", FALSE,
383 FALSE,
384 &q->uuconf_schat.uuconf_pzchat,
385 q->uuconf_palloc);
386 if (iret != UUCONF_SUCCESS)
387 return iret;
388 }
389 if (q->uuconf_schat.uuconf_ctimeout < 0)
390 q->uuconf_schat.uuconf_ctimeout = 10;
391 if (q->uuconf_schat.uuconf_fstrip < 0)
392 q->uuconf_schat.uuconf_fstrip = TRUE;
393 if (q->uuconf_scalled_chat.uuconf_ctimeout < 0)
394 q->uuconf_scalled_chat.uuconf_ctimeout = 60;
395 if (q->uuconf_scalled_chat.uuconf_fstrip < 0)
396 q->uuconf_scalled_chat.uuconf_fstrip = TRUE;
397 if (q->uuconf_fsend_request < 0)
398 q->uuconf_fsend_request = TRUE;
399 if (q->uuconf_frec_request < 0)
400 q->uuconf_frec_request = TRUE;
401 if (q->uuconf_fcall_transfer < 0)
402 q->uuconf_fcall_transfer = TRUE;
403 if (q->uuconf_fcalled_transfer < 0)
404 q->uuconf_fcalled_transfer = TRUE;
405 if (q->uuconf_pzlocal_send == (char **) &_uuconf_unset)
406 {
407 q->uuconf_pzlocal_send = NULL;
408 iret = _uuconf_iadd_string (qglobal, (char *) ZROOTDIR, FALSE,
409 FALSE, &q->uuconf_pzlocal_send,
410 q->uuconf_palloc);
411 if (iret != UUCONF_SUCCESS)
412 return iret;
413 }
414 if (q->uuconf_pzremote_send == (char **) &_uuconf_unset)
415 {
416 q->uuconf_pzremote_send = NULL;
417 iret = _uuconf_iadd_string (qglobal, (char *) "~", FALSE, FALSE,
418 &q->uuconf_pzremote_send,
419 q->uuconf_palloc);
420 if (iret != UUCONF_SUCCESS)
421 return iret;
422 }
423 if (q->uuconf_pzlocal_receive == (char **) &_uuconf_unset)
424 {
425 q->uuconf_pzlocal_receive = NULL;
426 iret = _uuconf_iadd_string (qglobal, (char *) "~", FALSE, FALSE,
427 &q->uuconf_pzlocal_receive,
428 q->uuconf_palloc);
429 if (iret != UUCONF_SUCCESS)
430 return iret;
431 }
432 if (q->uuconf_pzremote_receive == (char **) &_uuconf_unset)
433 {
434 q->uuconf_pzremote_receive = NULL;
435 iret = _uuconf_iadd_string (qglobal, (char *) "~", FALSE, FALSE,
436 &q->uuconf_pzremote_receive,
437 q->uuconf_palloc);
438 if (iret != UUCONF_SUCCESS)
439 return iret;
440 }
441
442 if (q->uuconf_pzpath == (char **) &_uuconf_unset)
443 {
444 char *zdup;
445 char **pz;
446 size_t csplit;
447 int c;
448
449 zdup = (char *) uuconf_malloc (q->uuconf_palloc, sizeof CMDPATH);
450 if (zdup == NULL)
451 {
452 qglobal->ierrno = errno;
453 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
454 }
455
456 memcpy ((pointer) zdup, (pointer) CMDPATH, sizeof CMDPATH);
457 pz = NULL;
458 csplit = 0;
459 if ((c = _uuconf_istrsplit (zdup, '\0', &pz, &csplit)) < 0)
460 {
461 qglobal->ierrno = errno;
462 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
463 }
464 q->uuconf_pzpath = (char **) uuconf_malloc (q->uuconf_palloc,
465 ((c + 1)
466 * sizeof (char *)));
467 if (q->uuconf_pzpath == NULL)
468 {
469 qglobal->ierrno = errno;
470 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
471 }
472 memcpy ((pointer) q->uuconf_pzpath, (pointer) pz,
473 c * sizeof (char *));
474 q->uuconf_pzpath[c] = NULL;
475 free ((pointer) pz);
476 }
477
478 if (q->uuconf_pzcmds == (char **) &_uuconf_unset)
479 {
480 q->uuconf_pzcmds = ((char **)
481 uuconf_malloc (q->uuconf_palloc,
482 3 * sizeof (const char *)));
483 if (q->uuconf_pzcmds == NULL)
484 {
485 qglobal->ierrno = errno;
486 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
487 }
488 q->uuconf_pzcmds[0] = (char *) "rnews";
489 q->uuconf_pzcmds[1] = (char *) "rmail";
490 q->uuconf_pzcmds[2] = NULL;
491 }
492
493 if (q->uuconf_cfree_space < 0)
494 q->uuconf_cfree_space = DEFAULT_FREE_SPACE;
495
496 if (q->uuconf_zpubdir == (const char *) &_uuconf_unset)
497 q->uuconf_zpubdir = qglobal->qprocess->zpubdir;
498
499 #define SET(x) if (q->x == (char *) &_uuconf_unset) q->x = NULL
500 SYSTEM_STRINGS(SET);
501 #undef SET
502 #define SET(x) if (q->x == (char **) &_uuconf_unset) q->x = NULL
503 SYSTEM_STRING_ARRAYS(SET);
504 #undef SET
505 #define SET(x) \
506 if (q->x == (struct uuconf_timespan *) &_uuconf_unset) q->x = NULL
507 SYSTEM_TIMESPANS (SET);
508 #undef SET
509 #define SET(x) if (q->x < 0) q->x = 0
510 SYSTEM_BOOLEANS (SET);
511 SYSTEM_INTEGERS (SET);
512 #undef SET
513
514 if (q->uuconf_zport == (char *) &_uuconf_unset)
515 q->uuconf_zport = NULL;
516 if (q->uuconf_qport == (struct uuconf_port *) &_uuconf_unset)
517 q->uuconf_qport = NULL;
518 if (q->uuconf_qproto_params
519 == (struct uuconf_proto_param *) &_uuconf_unset)
520 q->uuconf_qproto_params = NULL;
521 }
522
523 return iret;
524 }
525