readline.c
1 /* 2 * Copyright (c) 2003-2004,2012,2014 Apple 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_cssm.h" 27 #include "security_tool.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. */ 40 char * 41 readline(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. */ 85 int 86 read_file(const char *name, CSSM_DATA *outData) 87 { 88 int fd = -1, 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((size_t)length); 113 114 do { 115 bytes_read = pread(fd, buffer, (size_t) 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 result = close(fd); 132 if (result) { 133 sec_error("close"); 134 goto loser; 135 } 136 137 outData->Data = (uint8 *)buffer; 138 outData->Length = (uint32)length; 139 140 return result; 141 142 loser: 143 if (fd != -1) { 144 close(fd); 145 } 146 if (buffer) { 147 free(buffer); 148 } 149 150 return result; 151 }