]> andersk Git - gssapi-openssh.git/blob - openssh/misc.c
merged OpenSSH 3.7.1p2 to trunk
[gssapi-openssh.git] / 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.22 2003/09/18 08:49:45 markus 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         debug2("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         debug2("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 /* Characters considered as quotations. */
117 #define QUOTES "'\""
118
119 /* return next token in configuration line */
120 char *
121 strdelim(char **s)
122 {
123         char *old, *p, *q;
124         int wspace = 0;
125
126         if (*s == NULL)
127                 return NULL;
128
129         old = *s;
130
131         if ((q=strchr(QUOTES, (int) *old)) && *q)
132         {
133             /* find next quote character, point old to start of quoted
134              * string */
135             for (p = ++old;*p && *p!=*q; p++)
136                  ;
137             
138             /* find start of next token */
139             *s = (*p) ? p + strspn(p + 1, WHITESPACE) + 1 : NULL;
140             
141             /* terminate 'old' token */
142             *p = '\0';
143             return (old);
144         }
145
146         *s = strpbrk(*s, WHITESPACE "=");
147         if (*s == NULL)
148                 return (old);
149
150         /* Allow only one '=' to be skipped */
151         if (*s[0] == '=')
152                 wspace = 1;
153         *s[0] = '\0';
154
155         *s += strspn(*s + 1, WHITESPACE) + 1;
156         if (*s[0] == '=' && !wspace)
157                 *s += strspn(*s + 1, WHITESPACE) + 1;
158
159         return (old);
160 }
161
162 struct passwd *
163 pwcopy(struct passwd *pw)
164 {
165         struct passwd *copy = xmalloc(sizeof(*copy));
166
167         memset(copy, 0, sizeof(*copy));
168         copy->pw_name = xstrdup(pw->pw_name);
169         copy->pw_passwd = xstrdup(pw->pw_passwd);
170         copy->pw_gecos = xstrdup(pw->pw_gecos);
171         copy->pw_uid = pw->pw_uid;
172         copy->pw_gid = pw->pw_gid;
173 #ifdef HAVE_PW_EXPIRE_IN_PASSWD
174         copy->pw_expire = pw->pw_expire;
175 #endif
176 #ifdef HAVE_PW_CHANGE_IN_PASSWD
177         copy->pw_change = pw->pw_change;
178 #endif
179 #ifdef HAVE_PW_CLASS_IN_PASSWD
180         copy->pw_class = xstrdup(pw->pw_class);
181 #endif
182         copy->pw_dir = xstrdup(pw->pw_dir);
183         copy->pw_shell = xstrdup(pw->pw_shell);
184         return copy;
185 }
186
187 /*
188  * Convert ASCII string to TCP/IP port number.
189  * Port must be >0 and <=65535.
190  * Return 0 if invalid.
191  */
192 int
193 a2port(const char *s)
194 {
195         long port;
196         char *endp;
197
198         errno = 0;
199         port = strtol(s, &endp, 0);
200         if (s == endp || *endp != '\0' ||
201             (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) ||
202             port <= 0 || port > 65535)
203                 return 0;
204
205         return port;
206 }
207
208 #define SECONDS         1
209 #define MINUTES         (SECONDS * 60)
210 #define HOURS           (MINUTES * 60)
211 #define DAYS            (HOURS * 24)
212 #define WEEKS           (DAYS * 7)
213
214 /*
215  * Convert a time string into seconds; format is
216  * a sequence of:
217  *      time[qualifier]
218  *
219  * Valid time qualifiers are:
220  *      <none>  seconds
221  *      s|S     seconds
222  *      m|M     minutes
223  *      h|H     hours
224  *      d|D     days
225  *      w|W     weeks
226  *
227  * Examples:
228  *      90m     90 minutes
229  *      1h30m   90 minutes
230  *      2d      2 days
231  *      1w      1 week
232  *
233  * Return -1 if time string is invalid.
234  */
235 long
236 convtime(const char *s)
237 {
238         long total, secs;
239         const char *p;
240         char *endp;
241
242         errno = 0;
243         total = 0;
244         p = s;
245
246         if (p == NULL || *p == '\0')
247                 return -1;
248
249         while (*p) {
250                 secs = strtol(p, &endp, 10);
251                 if (p == endp ||
252                     (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
253                     secs < 0)
254                         return -1;
255
256                 switch (*endp++) {
257                 case '\0':
258                         endp--;
259                 case 's':
260                 case 'S':
261                         break;
262                 case 'm':
263                 case 'M':
264                         secs *= MINUTES;
265                         break;
266                 case 'h':
267                 case 'H':
268                         secs *= HOURS;
269                         break;
270                 case 'd':
271                 case 'D':
272                         secs *= DAYS;
273                         break;
274                 case 'w':
275                 case 'W':
276                         secs *= WEEKS;
277                         break;
278                 default:
279                         return -1;
280                 }
281                 total += secs;
282                 if (total < 0)
283                         return -1;
284                 p = endp;
285         }
286
287         return total;
288 }
289
290 char *
291 cleanhostname(char *host)
292 {
293         if (*host == '[' && host[strlen(host) - 1] == ']') {
294                 host[strlen(host) - 1] = '\0';
295                 return (host + 1);
296         } else
297                 return host;
298 }
299
300 char *
301 colon(char *cp)
302 {
303         int flag = 0;
304
305         if (*cp == ':')         /* Leading colon is part of file name. */
306                 return (0);
307         if (*cp == '[')
308                 flag = 1;
309
310         for (; *cp; ++cp) {
311                 if (*cp == '@' && *(cp+1) == '[')
312                         flag = 1;
313                 if (*cp == ']' && *(cp+1) == ':' && flag)
314                         return (cp+1);
315                 if (*cp == ':' && !flag)
316                         return (cp);
317                 if (*cp == '/')
318                         return (0);
319         }
320         return (0);
321 }
322
323 /* function to assist building execv() arguments */
324 void
325 addargs(arglist *args, char *fmt, ...)
326 {
327         va_list ap;
328         char buf[1024];
329         int nalloc;
330
331         va_start(ap, fmt);
332         vsnprintf(buf, sizeof(buf), fmt, ap);
333         va_end(ap);
334
335         nalloc = args->nalloc;
336         if (args->list == NULL) {
337                 nalloc = 32;
338                 args->num = 0;
339         } else if (args->num+2 >= nalloc)
340                 nalloc *= 2;
341
342         args->list = xrealloc(args->list, nalloc * sizeof(char *));
343         args->nalloc = nalloc;
344         args->list[args->num++] = xstrdup(buf);
345         args->list[args->num] = NULL;
346 }
This page took 0.060199 seconds and 5 git commands to generate.