Temporary switch cc3 to the old stabs debugging format to unbreak gdb5.
[dragonfly.git] / crypto / openssh / misc.c
1 /*
2  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "includes.h"
26 RCSID("$OpenBSD: misc.c,v 1.19 2002/03/04 17:27:39 stevesk Exp $");
27
28 #include "misc.h"
29 #include "log.h"
30 #include "xmalloc.h"
31
32 /* remove newline at end of string */
33 char *
34 chop(char *s)
35 {
36         char *t = s;
37         while (*t) {
38                 if (*t == '\n' || *t == '\r') {
39                         *t = '\0';
40                         return s;
41                 }
42                 t++;
43         }
44         return s;
45
46 }
47
48 /* set/unset filedescriptor to non-blocking */
49 void
50 set_nonblock(int fd)
51 {
52         int val;
53
54         val = fcntl(fd, F_GETFL, 0);
55         if (val < 0) {
56                 error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
57                 return;
58         }
59         if (val & O_NONBLOCK) {
60                 debug2("fd %d is O_NONBLOCK", fd);
61                 return;
62         }
63         debug("fd %d setting O_NONBLOCK", fd);
64         val |= O_NONBLOCK;
65         if (fcntl(fd, F_SETFL, val) == -1)
66                 debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
67                     fd, strerror(errno));
68 }
69
70 void
71 unset_nonblock(int fd)
72 {
73         int val;
74
75         val = fcntl(fd, F_GETFL, 0);
76         if (val < 0) {
77                 error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
78                 return;
79         }
80         if (!(val & O_NONBLOCK)) {
81                 debug2("fd %d is not O_NONBLOCK", fd);
82                 return;
83         }
84         debug("fd %d clearing O_NONBLOCK", fd);
85         val &= ~O_NONBLOCK;
86         if (fcntl(fd, F_SETFL, val) == -1)
87                 debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
88                     fd, strerror(errno));
89 }
90
91 /* disable nagle on socket */
92 void
93 set_nodelay(int fd)
94 {
95         int opt;
96         socklen_t optlen;
97
98         optlen = sizeof opt;
99         if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
100                 error("getsockopt TCP_NODELAY: %.100s", strerror(errno));
101                 return;
102         }
103         if (opt == 1) {
104                 debug2("fd %d is TCP_NODELAY", fd);
105                 return;
106         }
107         opt = 1;
108         debug("fd %d setting TCP_NODELAY", fd);
109         if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
110                 error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
111 }
112
113 /* Characters considered whitespace in strsep calls. */
114 #define WHITESPACE " \t\r\n"
115
116 /* return next token in configuration line */
117 char *
118 strdelim(char **s)
119 {
120         char *old;
121         int wspace = 0;
122
123         if (*s == NULL)
124                 return NULL;
125
126         old = *s;
127
128         *s = strpbrk(*s, WHITESPACE "=");
129         if (*s == NULL)
130                 return (old);
131
132         /* Allow only one '=' to be skipped */
133         if (*s[0] == '=')
134                 wspace = 1;
135         *s[0] = '\0';
136
137         *s += strspn(*s + 1, WHITESPACE) + 1;
138         if (*s[0] == '=' && !wspace)
139                 *s += strspn(*s + 1, WHITESPACE) + 1;
140
141         return (old);
142 }
143
144 struct passwd *
145 pwcopy(struct passwd *pw)
146 {
147         struct passwd *copy = xmalloc(sizeof(*copy));
148
149         memset(copy, 0, sizeof(*copy));
150         copy->pw_name = xstrdup(pw->pw_name);
151         copy->pw_passwd = xstrdup(pw->pw_passwd);
152         copy->pw_gecos = xstrdup(pw->pw_gecos);
153         copy->pw_uid = pw->pw_uid;
154         copy->pw_gid = pw->pw_gid;
155 #ifdef HAVE_PW_EXPIRE_IN_PASSWD
156         copy->pw_expire = pw->pw_expire;
157 #endif
158 #ifdef HAVE_PW_CHANGE_IN_PASSWD
159         copy->pw_change = pw->pw_change;
160 #endif
161 #ifdef HAVE_PW_CLASS_IN_PASSWD
162         copy->pw_class = xstrdup(pw->pw_class);
163 #endif
164         copy->pw_dir = xstrdup(pw->pw_dir);
165         copy->pw_shell = xstrdup(pw->pw_shell);
166         return copy;
167 }
168
169 /*
170  * Convert ASCII string to TCP/IP port number.
171  * Port must be >0 and <=65535.
172  * Return 0 if invalid.
173  */
174 int
175 a2port(const char *s)
176 {
177         long port;
178         char *endp;
179
180         errno = 0;
181         port = strtol(s, &endp, 0);
182         if (s == endp || *endp != '\0' ||
183             (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) ||
184             port <= 0 || port > 65535)
185                 return 0;
186
187         return port;
188 }
189
190 #define SECONDS         1
191 #define MINUTES         (SECONDS * 60)
192 #define HOURS           (MINUTES * 60)
193 #define DAYS            (HOURS * 24)
194 #define WEEKS           (DAYS * 7)
195
196 /*
197  * Convert a time string into seconds; format is
198  * a sequence of:
199  *      time[qualifier]
200  *
201  * Valid time qualifiers are:
202  *      <none>  seconds
203  *      s|S     seconds
204  *      m|M     minutes
205  *      h|H     hours
206  *      d|D     days
207  *      w|W     weeks
208  *
209  * Examples:
210  *      90m     90 minutes
211  *      1h30m   90 minutes
212  *      2d      2 days
213  *      1w      1 week
214  *
215  * Return -1 if time string is invalid.
216  */
217 long
218 convtime(const char *s)
219 {
220         long total, secs;
221         const char *p;
222         char *endp;
223
224         errno = 0;
225         total = 0;
226         p = s;
227
228         if (p == NULL || *p == '\0')
229                 return -1;
230
231         while (*p) {
232                 secs = strtol(p, &endp, 10);
233                 if (p == endp ||
234                     (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
235                     secs < 0)
236                         return -1;
237
238                 switch (*endp++) {
239                 case '\0':
240                         endp--;
241                 case 's':
242                 case 'S':
243                         break;
244                 case 'm':
245                 case 'M':
246                         secs *= MINUTES;
247                         break;
248                 case 'h':
249                 case 'H':
250                         secs *= HOURS;
251                         break;
252                 case 'd':
253                 case 'D':
254                         secs *= DAYS;
255                         break;
256                 case 'w':
257                 case 'W':
258                         secs *= WEEKS;
259                         break;
260                 default:
261                         return -1;
262                 }
263                 total += secs;
264                 if (total < 0)
265                         return -1;
266                 p = endp;
267         }
268
269         return total;
270 }
271
272 char *
273 cleanhostname(char *host)
274 {
275         if (*host == '[' && host[strlen(host) - 1] == ']') {
276                 host[strlen(host) - 1] = '\0';
277                 return (host + 1);
278         } else
279                 return host;
280 }
281
282 char *
283 colon(char *cp)
284 {
285         int flag = 0;
286
287         if (*cp == ':')         /* Leading colon is part of file name. */
288                 return (0);
289         if (*cp == '[')
290                 flag = 1;
291
292         for (; *cp; ++cp) {
293                 if (*cp == '@' && *(cp+1) == '[')
294                         flag = 1;
295                 if (*cp == ']' && *(cp+1) == ':' && flag)
296                         return (cp+1);
297                 if (*cp == ':' && !flag)
298                         return (cp);
299                 if (*cp == '/')
300                         return (0);
301         }
302         return (0);
303 }
304
305 /* function to assist building execv() arguments */
306 void
307 addargs(arglist *args, char *fmt, ...)
308 {
309         va_list ap;
310         char buf[1024];
311
312         va_start(ap, fmt);
313         vsnprintf(buf, sizeof(buf), fmt, ap);
314         va_end(ap);
315
316         if (args->list == NULL) {
317                 args->nalloc = 32;
318                 args->num = 0;
319         } else if (args->num+2 >= args->nalloc)
320                 args->nalloc *= 2;
321
322         args->list = xrealloc(args->list, args->nalloc * sizeof(char *));
323         args->list[args->num++] = xstrdup(buf);
324         args->list[args->num] = NULL;
325 }
326
327 mysig_t
328 mysignal(int sig, mysig_t act)
329 {
330 #ifdef HAVE_SIGACTION
331         struct sigaction sa, osa;
332
333         if (sigaction(sig, NULL, &osa) == -1)
334                 return (mysig_t) -1;
335         if (osa.sa_handler != act) {
336                 memset(&sa, 0, sizeof(sa));
337                 sigemptyset(&sa.sa_mask);
338                 sa.sa_flags = 0;
339 #if defined(SA_INTERRUPT)
340                 if (sig == SIGALRM)
341                         sa.sa_flags |= SA_INTERRUPT;
342 #endif
343                 sa.sa_handler = act;
344                 if (sigaction(sig, &sa, NULL) == -1)
345                         return (mysig_t) -1;
346         }
347         return (osa.sa_handler);
348 #else
349         return (signal(sig, act));
350 #endif
351 }