1/*
2 * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 *
23 * readline.c
24 */
25
26#include "readline.h"
27#include "security.h"
28
29#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <unistd.h>
35
36/* Read a line from stdin into buffer as a null terminated string.  If buffer is
37   non NULL use at most buffer_size bytes and return a pointer to buffer.  Otherwise
38   return a newly malloced buffer.
39   if EOF is read this function returns NULL.  */
40char *
41readline(char *buffer, int buffer_size)
42{
43	int ix = 0, bytes_malloced = 0;
44
45	if (!buffer)
46	{
47		bytes_malloced = 64;
48		buffer = (char *)malloc(bytes_malloced);
49		buffer_size = bytes_malloced;
50	}
51
52	for (;;++ix)
53	{
54		int ch;
55
56		if (ix == buffer_size - 1)
57		{
58			if (!bytes_malloced)
59				break;
60			bytes_malloced += bytes_malloced;
61			buffer = (char *)realloc(buffer, bytes_malloced);
62			buffer_size = bytes_malloced;
63		}
64
65		ch = getchar();
66		if (ch == EOF)
67		{
68			if (bytes_malloced)
69				free(buffer);
70			return NULL;
71		}
72		if (ch == '\n')
73			break;
74		buffer[ix] = ch;
75	}
76
77	/* 0 terminate buffer. */
78	buffer[ix] = '\0';
79
80	return buffer;
81}
82
83/* Read the file name into buffer.  On return buffer contains a newly
84   malloced buffer or length buffer_size. Return 0 on success and -1 on failure.  */
85int
86read_file(const char *name, CSSM_DATA *outData)
87{
88	int fd, result;
89	char *buffer = NULL;
90	off_t length;
91	ssize_t bytes_read;
92
93	do {
94		fd = open(name, O_RDONLY, 0);
95	} while (fd == -1 && errno == EINTR);
96
97	if (fd == -1)
98	{
99		sec_error("open %s: %s", name, strerror(errno));
100		result = -1;
101		goto loser;
102	}
103
104	length = lseek(fd, 0, SEEK_END);
105	if (length == -1)
106	{
107		sec_error("lseek %s, SEEK_END: %s", name, strerror(errno));
108		result = -1;
109		goto loser;
110	}
111
112	buffer = malloc(length);
113
114	do {
115		bytes_read = pread(fd, buffer, length, 0);
116	} while (bytes_read == -1 && errno == EINTR);
117
118	if (bytes_read == -1)
119	{
120		sec_error("pread %s: %s", name, strerror(errno));
121		result = -1;
122		goto loser;
123	}
124	if (bytes_read != (ssize_t)length)
125	{
126		sec_error("read %s: only read %d of %qu bytes", name, bytes_read, length);
127		result = -1;
128		goto loser;
129	}
130
131	do {
132		result = close(fd);
133	} while (result == -1 && errno == EINTR);
134	if (result == -1)
135	{
136		sec_error("close %s: %s", name, strerror(errno));
137		goto loser;
138	}
139
140	outData->Data = (uint8 *)buffer;
141	outData->Length = (uint32)length;
142
143	return result;
144
145loser:
146	if (buffer)
147		free(buffer);
148
149	return result;
150}
151