1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31
32#include <sys/param.h>
33#include <netdb.h>
34#include <netinet/in.h>
35#include <arpa/inet.h>
36#include <sys/socket.h>
37
38#include <ctype.h>
39#include <errno.h>
40#include <stdarg.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#if defined(__FreeBSD__) && !defined(NOKLDLOAD)
45#include <sys/module.h>
46#endif
47#include <termios.h>
48#ifndef __FreeBSD__
49#include <time.h>
50#endif
51#include <unistd.h>
52
53#if defined(__FreeBSD__) && !defined(NOKLDLOAD)
54#include "id.h"
55#include "log.h"
56#endif
57#include "defs.h"
58
59#define	issep(c)	((c) == '\t' || (c) == ' ')
60
61#ifdef __NetBSD__
62void
63randinit()
64{
65  srandom((time(NULL)^getpid())+random());
66}
67#endif
68
69ssize_t
70fullread(int fd, void *v, size_t n)
71{
72  size_t got, total;
73
74  for (total = 0; total < n; total += got)
75    switch ((got = read(fd, (char *)v + total, n - total))) {
76      case 0:
77        return total;
78      case -1:
79        if (errno == EINTR)
80          got = 0;
81        else
82          return -1;
83    }
84  return total;
85}
86
87static struct {
88  int mode;
89  const char *name;
90} modes[] = {
91  { PHYS_INTERACTIVE, "interactive" },
92  { PHYS_AUTO, "auto" },
93  { PHYS_DIRECT, "direct" },
94  { PHYS_DEDICATED, "dedicated" },
95  { PHYS_DDIAL, "ddial" },
96  { PHYS_BACKGROUND, "background" },
97  { PHYS_FOREGROUND, "foreground" },
98  { PHYS_ALL, "*" },
99  { 0, 0 }
100};
101
102const char *
103mode2Nam(int mode)
104{
105  int m;
106
107  for (m = 0; modes[m].mode; m++)
108    if (modes[m].mode == mode)
109      return modes[m].name;
110
111  return "unknown";
112}
113
114int
115Nam2mode(const char *name)
116{
117  int m, got, len;
118
119  len = strlen(name);
120  got = -1;
121  for (m = 0; modes[m].mode; m++)
122    if (!strncasecmp(name, modes[m].name, len)) {
123      if (modes[m].name[len] == '\0')
124	return modes[m].mode;
125      if (got != -1)
126        return 0;
127      got = m;
128    }
129
130  return got == -1 ? 0 : modes[got].mode;
131}
132
133struct in_addr
134GetIpAddr(const char *cp)
135{
136  struct in_addr ipaddr;
137
138  if (!strcasecmp(cp, "default"))
139    ipaddr.s_addr = INADDR_ANY;
140  else if (inet_aton(cp, &ipaddr) == 0) {
141    const char *ptr;
142
143    /* Any illegal characters ? */
144    for (ptr = cp; *ptr != '\0'; ptr++)
145      if (!isalnum(*ptr) && strchr("-.", *ptr) == NULL)
146        break;
147
148    if (*ptr == '\0') {
149      struct hostent *hp;
150
151      hp = gethostbyname(cp);
152      if (hp && hp->h_addrtype == AF_INET)
153        memcpy(&ipaddr, hp->h_addr, hp->h_length);
154      else
155        ipaddr.s_addr = INADDR_NONE;
156    } else
157      ipaddr.s_addr = INADDR_NONE;
158  }
159
160  return ipaddr;
161}
162
163static const struct speeds {
164  unsigned nspeed;
165  speed_t speed;
166} speeds[] = {
167#ifdef B50
168  { 50, B50, },
169#endif
170#ifdef B75
171  { 75, B75, },
172#endif
173#ifdef B110
174  { 110, B110, },
175#endif
176#ifdef B134
177  { 134, B134, },
178#endif
179#ifdef B150
180  { 150, B150, },
181#endif
182#ifdef B200
183  { 200, B200, },
184#endif
185#ifdef B300
186  { 300, B300, },
187#endif
188#ifdef B600
189  { 600, B600, },
190#endif
191#ifdef B1200
192  { 1200, B1200, },
193#endif
194#ifdef B1800
195  { 1800, B1800, },
196#endif
197#ifdef B2400
198  { 2400, B2400, },
199#endif
200#ifdef B4800
201  { 4800, B4800, },
202#endif
203#ifdef B9600
204  { 9600, B9600, },
205#endif
206#ifdef B19200
207  { 19200, B19200, },
208#endif
209#ifdef B38400
210  { 38400, B38400, },
211#endif
212#ifndef _POSIX_SOURCE
213#ifdef B7200
214  { 7200, B7200, },
215#endif
216#ifdef B14400
217  { 14400, B14400, },
218#endif
219#ifdef B28800
220  { 28800, B28800, },
221#endif
222#ifdef B57600
223  { 57600, B57600, },
224#endif
225#ifdef B76800
226  { 76800, B76800, },
227#endif
228#ifdef B115200
229  { 115200, B115200, },
230#endif
231#ifdef B230400
232  { 230400, B230400, },
233#endif
234#ifdef B460800
235  { 460800, B460800, },
236#endif
237#ifdef B921600
238  { 921600, B921600, },
239#endif
240#ifdef EXTA
241  { 19200, EXTA, },
242#endif
243#ifdef EXTB
244  { 38400, EXTB, },
245#endif
246#endif				/* _POSIX_SOURCE */
247  { 0, 0 }
248};
249
250unsigned
251SpeedToUnsigned(speed_t speed)
252{
253  const struct speeds *sp;
254
255  for (sp = speeds; sp->nspeed; sp++) {
256    if (sp->speed == speed) {
257      return sp->nspeed;
258    }
259  }
260  return 0;
261}
262
263speed_t
264UnsignedToSpeed(unsigned nspeed)
265{
266  const struct speeds *sp;
267
268  for (sp = speeds; sp->nspeed; sp++) {
269    if (sp->nspeed == nspeed) {
270      return sp->speed;
271    }
272  }
273  return B0;
274}
275
276char *
277findblank(char *p, int flags)
278{
279  int instring;
280
281  instring = 0;
282  while (*p) {
283    if (*p == '\\') {
284      if (flags & PARSE_REDUCE) {
285        memmove(p, p + 1, strlen(p));
286        if (!*p)
287          break;
288      } else
289        p++;
290    } else if (*p == '"') {
291      memmove(p, p + 1, strlen(p));
292      instring = !instring;
293      continue;
294    } else if (!instring && (issep(*p) ||
295                             (*p == '#' && !(flags & PARSE_NOHASH))))
296      return p;
297    p++;
298  }
299
300  return instring ? NULL : p;
301}
302
303int
304MakeArgs(char *script, char **pvect, int maxargs, int flags)
305{
306  int nargs;
307
308  nargs = 0;
309  while (*script) {
310    script += strspn(script, " \t");
311    if (*script == '#' && !(flags & PARSE_NOHASH)) {
312      *script = '\0';
313      break;
314    }
315    if (*script) {
316      if (nargs >= maxargs - 1)
317        break;
318      *pvect++ = script;
319      nargs++;
320      script = findblank(script, flags);
321      if (script == NULL)
322        return -1;
323      else if (!(flags & PARSE_NOHASH) && *script == '#')
324        *script = '\0';
325      else if (*script)
326        *script++ = '\0';
327    }
328  }
329  *pvect = NULL;
330  return nargs;
331}
332
333const char *
334NumStr(long val, char *buf, size_t sz)
335{
336  static char result[23];		/* handles 64 bit numbers */
337
338  if (buf == NULL || sz == 0) {
339    buf = result;
340    sz = sizeof result;
341  }
342  snprintf(buf, sz, "<%ld>", val);
343  return buf;
344}
345
346const char *
347HexStr(long val, char *buf, size_t sz)
348{
349  static char result[21];		/* handles 64 bit numbers */
350
351  if (buf == NULL || sz == 0) {
352    buf = result;
353    sz = sizeof result;
354  }
355  snprintf(buf, sz, "<0x%lx>", val);
356  return buf;
357}
358
359const char *
360ex_desc(int ex)
361{
362  static char num[12];		/* Used immediately if returned */
363  static const char * const desc[] = {
364    "normal", "start", "sock", "modem", "dial", "dead", "done",
365    "reboot", "errdead", "hangup", "term", "nodial", "nologin",
366    "redial", "reconnect"
367  };
368
369  if (ex >= 0 && ex < (int)(sizeof desc / sizeof *desc))
370    return desc[ex];
371  snprintf(num, sizeof num, "%d", ex);
372  return num;
373}
374
375void
376SetTitle(const char *title)
377{
378  if (title == NULL)
379    setproctitle(NULL);
380  else if (title[0] == '-' && title[1] != '\0')
381    setproctitle("-%s", title + 1);
382  else
383    setproctitle("%s", title);
384}
385
386fd_set *
387mkfdset()
388{
389  return (fd_set *)malloc(howmany(getdtablesize(), NFDBITS) * sizeof (fd_mask));
390}
391
392void
393zerofdset(fd_set *s)
394{
395  memset(s, '\0', howmany(getdtablesize(), NFDBITS) * sizeof (fd_mask));
396}
397
398void
399Concatinate(char *buf, size_t sz, int argc, const char *const *argv)
400{
401  int i, n;
402  unsigned pos;
403
404  *buf = '\0';
405  for (pos = i = 0; i < argc; i++) {
406    n = snprintf(buf + pos, sz - pos, "%s%s", i ? " " : "", argv[i]);
407    if (n < 0) {
408      buf[pos] = '\0';
409      break;
410    }
411    if ((pos += n) >= sz)
412      break;
413  }
414}
415
416#if defined(__FreeBSD__) && !defined(NOKLDLOAD)
417int
418loadmodules(int how, const char *module, ...)
419{
420  int loaded = 0;
421  va_list ap;
422
423  va_start(ap, module);
424  while (module != NULL) {
425    if (modfind(module) == -1) {
426      if (ID0kldload(module) == -1) {
427        if (how == LOAD_VERBOSLY)
428          log_Printf(LogWARN, "%s: Cannot load module\n", module);
429      } else
430        loaded++;
431    }
432    module = va_arg(ap, const char *);
433  }
434  va_end(ap);
435  return loaded;
436}
437#else
438int
439loadmodules(int how __unused, const char *module __unused, ...)
440{
441  return 0;
442}
443#endif
444