Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "plgetopt.h"
6 #include "secutil.h"
7 #include "nssb64.h"
8 #include <errno.h>
10 #if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
11 #if !defined(WIN32)
12 extern int fread(char *, size_t, size_t, FILE*);
13 extern int fwrite(char *, size_t, size_t, FILE*);
14 extern int fprintf(FILE *, char *, ...);
15 #endif
16 #endif
18 #if defined(WIN32)
19 #include "fcntl.h"
20 #include "io.h"
21 #endif
23 static PRInt32
24 output_ascii (void *arg, const char *obuf, PRInt32 size)
25 {
26 FILE *outFile = arg;
27 int nb;
29 nb = fwrite(obuf, 1, size, outFile);
30 if (nb != size) {
31 PORT_SetError(SEC_ERROR_IO);
32 return -1;
33 }
35 return nb;
36 }
38 static SECStatus
39 encode_file(FILE *outFile, FILE *inFile)
40 {
41 NSSBase64Encoder *cx;
42 int nb;
43 SECStatus status = SECFailure;
44 unsigned char ibuf[4096];
46 cx = NSSBase64Encoder_Create(output_ascii, outFile);
47 if (!cx) {
48 return -1;
49 }
51 for (;;) {
52 if (feof(inFile)) break;
53 nb = fread(ibuf, 1, sizeof(ibuf), inFile);
54 if (nb != sizeof(ibuf)) {
55 if (nb == 0) {
56 if (ferror(inFile)) {
57 PORT_SetError(SEC_ERROR_IO);
58 goto loser;
59 }
60 /* eof */
61 break;
62 }
63 }
65 status = NSSBase64Encoder_Update(cx, ibuf, nb);
66 if (status != SECSuccess) goto loser;
67 }
69 status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
70 if (status != SECSuccess)
71 return status;
73 /*
74 * Add a trailing CRLF. Note this must be done *after* the call
75 * to Destroy above (because only then are we sure all data has
76 * been written out).
77 */
78 fwrite("\r\n", 1, 2, outFile);
79 return SECSuccess;
81 loser:
82 (void) NSSBase64Encoder_Destroy(cx, PR_TRUE);
83 return status;
84 }
86 static void Usage(char *progName)
87 {
88 fprintf(stderr,
89 "Usage: %s [-i input] [-o output]\n",
90 progName);
91 fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
92 "-i input");
93 fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
94 "-o output");
95 fprintf(stderr, "%-20s Wrap output in BEGIN/END lines and the given suffix\n",
96 "-w suffix");
97 fprintf(stderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n",
98 "");
99 exit(-1);
100 }
102 int main(int argc, char **argv)
103 {
104 char *progName;
105 SECStatus rv;
106 FILE *inFile, *outFile;
107 PLOptState *optstate;
108 PLOptStatus status;
109 char *suffix = NULL;
111 inFile = 0;
112 outFile = 0;
113 progName = strrchr(argv[0], '/');
114 if (!progName)
115 progName = strrchr(argv[0], '\\');
116 progName = progName ? progName+1 : argv[0];
118 /* Parse command line arguments */
119 optstate = PL_CreateOptState(argc, argv, "i:o:w:");
120 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
121 switch (optstate->option) {
122 default:
123 Usage(progName);
124 break;
126 case 'i':
127 inFile = fopen(optstate->value, "rb");
128 if (!inFile) {
129 fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
130 progName, optstate->value);
131 return -1;
132 }
133 break;
135 case 'o':
136 outFile = fopen(optstate->value, "wb");
137 if (!outFile) {
138 fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
139 progName, optstate->value);
140 return -1;
141 }
142 break;
144 case 'w':
145 if (!strcmp(optstate->value, "c"))
146 suffix = strdup("CERTIFICATE");
147 else
148 suffix = strdup(optstate->value);
149 break;
150 }
151 }
152 if (status == PL_OPT_BAD)
153 Usage(progName);
154 if (!inFile) {
155 #if defined(WIN32)
156 /* If we're going to read binary data from stdin, we must put stdin
157 ** into O_BINARY mode or else incoming \r\n's will become \n's.
158 */
160 int smrv = _setmode(_fileno(stdin), _O_BINARY);
161 if (smrv == -1) {
162 fprintf(stderr,
163 "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
164 progName);
165 return smrv;
166 }
167 #endif
168 inFile = stdin;
169 }
170 if (!outFile) {
171 #if defined(WIN32)
172 /* We're going to write binary data to stdout. We must put stdout
173 ** into O_BINARY mode or else outgoing \r\n's will become \r\r\n's.
174 */
176 int smrv = _setmode(_fileno(stdout), _O_BINARY);
177 if (smrv == -1) {
178 fprintf(stderr,
179 "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
180 progName);
181 return smrv;
182 }
183 #endif
184 outFile = stdout;
185 }
186 if (suffix) {
187 fprintf(outFile, "-----BEGIN %s-----\n", suffix);
188 }
189 rv = encode_file(outFile, inFile);
190 if (rv != SECSuccess) {
191 fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
192 progName, PORT_GetError(), errno);
193 return -1;
194 }
195 if (suffix) {
196 fprintf(outFile, "-----END %s-----\n", suffix);
197 }
198 return 0;
199 }