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