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/*RCSID("OpenBSD: misc.c,v 1.22 2003/09/18 08:49:45 markus Exp ");*/
26
27/* For xmalloc, xfree etc:
28 * Author: Tatu Ylonen <ylo@cs.hut.fi>
29 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
30 *                    All rights reserved
31 * Versions of malloc and friends that check their results, and never return
32 * failure (they call fatal if they encounter an error).
33 *
34 * As far as I am concerned, the code I have written for this software
35 * can be used freely for any purpose.  Any derived versions of this
36 * software must be clearly marked as such, and if the derived work is
37 * incompatible with the protocol description in the RFC file, it must be
38 * called by a name other than "ssh" or "Secure Shell".
39 */
40
41/*RCSID("OpenBSD: xmalloc.c,v 1.16 2001/07/23 18:21:46 stevesk Exp ");*/
42
43#include "includes.h"
44#include "scpmisc.h"
45
46void *
47xmalloc(size_t size)
48{
49	void *ptr;
50
51	if (size == 0) {
52		fprintf(stderr, "xmalloc: zero size\n");
53		exit(EXIT_FAILURE);
54	}
55	ptr = malloc(size);
56	if (ptr == NULL) {
57		fprintf(stderr, "xmalloc: out of memory (allocating %lu bytes)\n", (u_long) size);
58		exit(EXIT_FAILURE);
59	}
60	return ptr;
61}
62
63void *
64xrealloc(void *ptr, size_t new_size)
65{
66	void *new_ptr;
67
68	if (new_size == 0) {
69		fprintf(stderr, "xrealloc: zero size\n");
70		exit(EXIT_FAILURE);
71	}
72	if (ptr == NULL)
73		new_ptr = malloc(new_size);
74	else
75		new_ptr = realloc(ptr, new_size);
76	if (new_ptr == NULL) {
77		fprintf(stderr, "xrealloc: out of memory (new_size %lu bytes)\n", (u_long) new_size);
78		exit(EXIT_FAILURE);
79	}
80	return new_ptr;
81}
82
83void
84xfree(void *ptr)
85{
86	if (ptr == NULL) {
87		fprintf(stderr, "xfree: NULL pointer given as argument\n");
88		exit(EXIT_FAILURE);
89	}
90	free(ptr);
91}
92
93char *
94xstrdup(const char *str)
95{
96	size_t len;
97	char *cp;
98
99	len = strlen(str) + 1;
100	cp = xmalloc(len);
101	strncpy(cp, str, len);
102	return cp;
103}
104
105char *
106cleanhostname(char *host)
107{
108	if (*host == '[' && host[strlen(host) - 1] == ']') {
109		host[strlen(host) - 1] = '\0';
110		return (host + 1);
111	} else
112		return host;
113}
114
115char *
116colon(char *cp)
117{
118	int flag = 0;
119
120	if (*cp == ':')		/* Leading colon is part of file name. */
121		return (0);
122	if (*cp == '[')
123		flag = 1;
124
125	for (; *cp; ++cp) {
126		if (*cp == '@' && *(cp+1) == '[')
127			flag = 1;
128		if (*cp == ']' && *(cp+1) == ':' && flag)
129			return (cp+1);
130		if (*cp == ':' && !flag)
131			return (cp);
132		if (*cp == '/')
133			return (0);
134	}
135	return (0);
136}
137
138/* function to assist building execv() arguments */
139void
140addargs(arglist *args, char *fmt, ...)
141{
142	va_list ap;
143	char *cp;
144	u_int nalloc;
145	int r;
146
147	va_start(ap, fmt);
148	r = vasprintf(&cp, fmt, ap);
149	va_end(ap);
150	if (r == -1)
151		fatal("addargs: argument too long");
152
153	nalloc = args->nalloc;
154	if (args->list == NULL) {
155		nalloc = 32;
156		args->num = 0;
157	} else if (args->num+2 >= nalloc)
158		nalloc *= 2;
159
160	args->list = xrealloc(args->list, nalloc * sizeof(char *));
161	args->nalloc = nalloc;
162	args->list[args->num++] = cp;
163	args->list[args->num] = NULL;
164}
165
166void
167replacearg(arglist *args, u_int which, char *fmt, ...)
168{
169	va_list ap;
170	char *cp;
171	int r;
172
173	va_start(ap, fmt);
174	r = vasprintf(&cp, fmt, ap);
175	va_end(ap);
176	if (r == -1)
177		fatal("replacearg: argument too long");
178
179	if (which >= args->num)
180		fatal("replacearg: tried to replace invalid arg %d >= %d",
181		    which, args->num);
182	xfree(args->list[which]);
183	args->list[which] = cp;
184}
185
186void
187freeargs(arglist *args)
188{
189	u_int i;
190
191	if (args->list != NULL) {
192		for (i = 0; i < args->num; i++)
193			xfree(args->list[i]);
194		xfree(args->list);
195		args->nalloc = args->num = 0;
196		args->list = NULL;
197	}
198}
199
200/*
201 * NB. duplicate __progname in case it is an alias for argv[0]
202 * Otherwise it may get clobbered by setproctitle()
203 */
204char *ssh_get_progname(char *argv0)
205{
206	char *p;
207
208	if (argv0 == NULL)
209		return ("unknown");	/* XXX */
210	p = strrchr(argv0, '/');
211	if (p == NULL)
212		p = argv0;
213	else
214		p++;
215
216	return (xstrdup(p));
217}
218
219void fatal(char* fmt,...)
220{
221	va_list args;
222	va_start(args, fmt);
223	vfprintf(stderr, fmt, args);
224	va_end(args);
225	exit(255);
226}
227
228void
229sanitise_stdfd(void)
230{
231	int nullfd, dupfd;
232
233	if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
234		fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
235		exit(1);
236	}
237	while (++dupfd <= 2) {
238		/* Only clobber closed fds */
239		if (fcntl(dupfd, F_GETFL, 0) >= 0)
240			continue;
241		if (dup2(nullfd, dupfd) == -1) {
242			fprintf(stderr, "dup2: %s", strerror(errno));
243			exit(1);
244		}
245	}
246	if (nullfd > 2)
247		close(nullfd);
248}
249