Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include "nss.h"
9 #include "secutil.h"
10 #include "pk11pub.h"
11 #include "cert.h"
13 typedef struct commandDescriptStr {
14 int required;
15 char *arg;
16 char *des;
17 } commandDescript;
19 enum optionNames {
20 opt_liborder = 0,
21 opt_mainDB,
22 opt_lib1DB,
23 opt_lib2DB,
24 opt_mainRO,
25 opt_lib1RO,
26 opt_lib2RO,
27 opt_mainCMD,
28 opt_lib1CMD,
29 opt_lib2CMD,
30 opt_mainTokNam,
31 opt_lib1TokNam,
32 opt_lib2TokNam,
33 opt_oldStyle,
34 opt_verbose,
35 opt_summary,
36 opt_help,
37 opt_last
38 };
41 static const
42 secuCommandFlag options_init[] =
43 {
44 { /* opt_liborder */ 'o', PR_TRUE, "1M2zmi", PR_TRUE, "order" },
45 { /* opt_mainDB */ 'd', PR_TRUE, 0, PR_FALSE, "main_db" },
46 { /* opt_lib1DB */ '1', PR_TRUE, 0, PR_FALSE, "lib1_db" },
47 { /* opt_lib2DB */ '2', PR_TRUE, 0, PR_FALSE, "lib2_db" },
48 { /* opt_mainRO */ 'r', PR_FALSE, 0, PR_FALSE, "main_readonly" },
49 { /* opt_lib1RO */ 0, PR_FALSE, 0, PR_FALSE, "lib1_readonly" },
50 { /* opt_lib2RO */ 0, PR_FALSE, 0, PR_FALSE, "lib2_readonly" },
51 { /* opt_mainCMD */ 'c', PR_TRUE, 0, PR_FALSE, "main_command" },
52 { /* opt_lib1CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib1_command" },
53 { /* opt_lib2CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib2_command" },
54 { /* opt_mainTokNam */'t', PR_TRUE, 0, PR_FALSE, "main_token_name" },
55 { /* opt_lib1TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib1_token_name" },
56 { /* opt_lib2TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib2_token_name" },
57 { /* opt_oldStype */ 's', PR_FALSE, 0, PR_FALSE, "oldStype" },
58 { /* opt_verbose */ 'v', PR_FALSE, 0, PR_FALSE, "verbose" },
59 { /* opt_summary */ 'z', PR_FALSE, 0, PR_FALSE, "summary" },
60 { /* opt_help */ 'h', PR_FALSE, 0, PR_FALSE, "help" }
61 };
63 static const
64 commandDescript options_des[] =
65 {
66 { /* opt_liborder */ PR_FALSE, "initOrder",
67 " Specifies the order of NSS initialization and shutdown. Order is\n"
68 " given as a string where each character represents either an init or\n"
69 " a shutdown of the main program or one of the 2 test libraries\n"
70 " (library 1 and library 2). The valid characters are as follows:\n"
71 " M Init the main program\n 1 Init library 1\n"
72 " 2 Init library 2\n"
73 " m Shutdown the main program\n i Shutdown library 1\n"
74 " z Shutdown library 2\n" },
75 { /* opt_mainDB */ PR_TRUE, "nss_db",
76 " Specified the directory to open the nss database for the main\n"
77 " program. Must be specified if \"M\" is given in the order string\n"},
78 { /* opt_lib1DB */ PR_FALSE, "nss_db",
79 " Specified the directory to open the nss database for library 1.\n"
80 " Must be specified if \"1\" is given in the order string\n"},
81 { /* opt_lib2DB */ PR_FALSE, "nss_db",
82 " Specified the directory to open the nss database for library 2.\n"
83 " Must be specified if \"2\" is given in the order string\n"},
84 { /* opt_mainRO */ PR_FALSE, NULL,
85 " Open the main program's database read only.\n" },
86 { /* opt_lib1RO */ PR_FALSE, NULL,
87 " Open library 1's database read only.\n" },
88 { /* opt_lib2RO */ PR_FALSE, NULL,
89 " Open library 2's database read only.\n" },
90 { /* opt_mainCMD */ PR_FALSE, "nss_command",
91 " Specifies the NSS command to execute in the main program.\n"
92 " Valid commands are: \n"
93 " key_slot, list_slots, list_certs, add_cert, none.\n"
94 " Default is \"none\".\n" },
95 { /* opt_lib1CMD */ PR_FALSE, "nss_command",
96 " Specifies the NSS command to execute in library 1.\n" },
97 { /* opt_lib2CMD */ PR_FALSE, "nss_command",
98 " Specifies the NSS command to execute in library 2.\n" },
99 { /* opt_mainTokNam */PR_FALSE, "token_name",
100 " Specifies the name of PKCS11 token for the main program's "
101 "database.\n" },
102 { /* opt_lib1TokNam */PR_FALSE, "token_name",
103 " Specifies the name of PKCS11 token for library 1's database.\n" },
104 { /* opt_lib2TokNam */PR_FALSE, "token_name",
105 " Specifies the name of PKCS11 token for library 2's database.\n" },
106 { /* opt_oldStype */ PR_FALSE, NULL,
107 " Use NSS_Shutdown rather than NSS_ShutdownContext in the main\n"
108 " program.\n" },
109 { /* opt_verbose */ PR_FALSE, NULL,
110 " Noisily output status to standard error\n" },
111 { /* opt_summarize */ PR_FALSE, NULL,
112 "report a summary of the test results\n" },
113 { /* opt_help */ PR_FALSE, NULL, " give this message\n" }
114 };
116 /*
117 * output our short help (table driven). (does not exit).
118 */
119 static void
120 short_help(const char *prog)
121 {
122 int count = opt_last;
123 int i,words_found;
125 /* make sure all the tables are up to date before we allow compiles to
126 * succeed */
127 PR_STATIC_ASSERT(sizeof(options_init)/sizeof(secuCommandFlag) == opt_last);
128 PR_STATIC_ASSERT(sizeof(options_init)/sizeof(secuCommandFlag) ==
129 sizeof(options_des)/sizeof(commandDescript));
131 /* print the base usage */
132 fprintf(stderr,"usage: %s ",prog);
133 for (i=0, words_found=0; i < count; i++) {
134 if (!options_des[i].required) {
135 fprintf(stderr,"[");
136 }
137 if (options_init[i].longform) {
138 fprintf(stderr, "--%s", options_init[i].longform);
139 words_found++;
140 } else {
141 fprintf(stderr, "-%c", options_init[i].flag);
142 }
143 if (options_init[i].needsArg) {
144 if (options_des[i].arg) {
145 fprintf(stderr," %s",options_des[i].arg);
146 } else {
147 fprintf(stderr," arg");
148 }
149 words_found++;
150 }
151 if (!options_des[i].required) {
152 fprintf(stderr,"]");
153 }
154 if (i < count-1 ) {
155 if (words_found >= 5) {
156 fprintf(stderr,"\n ");
157 words_found=0;
158 } else {
159 fprintf(stderr," ");
160 }
161 }
162 }
163 fprintf(stderr,"\n");
164 }
166 /*
167 * print out long help. like short_help, this does not exit
168 */
169 static void
170 long_help(const char *prog)
171 {
172 int i;
173 int count = opt_last;
175 short_help(prog);
176 /* print the option descriptions */
177 fprintf(stderr,"\n");
178 for (i=0; i < count; i++) {
179 fprintf(stderr," ");
180 if (options_init[i].flag) {
181 fprintf(stderr, "-%c", options_init[i].flag);
182 if (options_init[i].longform) {
183 fprintf(stderr,",");
184 }
185 }
186 if (options_init[i].longform) {
187 fprintf(stderr,"--%s", options_init[i].longform);
188 }
189 if (options_init[i].needsArg) {
190 if (options_des[i].arg) {
191 fprintf(stderr," %s",options_des[i].arg);
192 } else {
193 fprintf(stderr," arg");
194 }
195 if (options_init[i].arg) {
196 fprintf(stderr," (default = \"%s\")",options_init[i].arg);
197 }
198 }
199 fprintf(stderr,"\n%s",options_des[i].des);
200 }
201 }
203 /*
204 * record summary data
205 */
206 struct bufferData {
207 char * data; /* lowest address of the buffer */
208 char * next; /* pointer to the next element on the buffer */
209 int len; /* length of the buffer */
210 };
212 /* our actual buffer. If data is NULL, then all append ops
213 * except are noops */
214 static struct bufferData buffer= { NULL, NULL, 0 };
216 #define CHUNK_SIZE 1000
218 /*
219 * get our initial data. and set the buffer variables up. on failure,
220 * just don't initialize the buffer.
221 */
222 static void
223 initBuffer(void)
224 {
225 buffer.data = PORT_Alloc(CHUNK_SIZE);
226 if (!buffer.data) {
227 return;
228 }
229 buffer.next = buffer.data;
230 buffer.len = CHUNK_SIZE;
231 }
233 /*
234 * grow the buffer. If we can't get more data, record a 'D' in the second
235 * to last record and allow the rest of the data to overwrite the last
236 * element.
237 */
238 static void
239 growBuffer(void)
240 {
241 char *new = PORT_Realloc(buffer.data, buffer.len + CHUNK_SIZE);
242 if (!new) {
243 buffer.data[buffer.len-2] = 'D'; /* signal malloc failure in summary */
244 /* buffer must always point to good memory if it exists */
245 buffer.next = buffer.data + (buffer.len -1);
246 return;
247 }
248 buffer.next = new + (buffer.next-buffer.data);
249 buffer.data = new;
250 buffer.len += CHUNK_SIZE;
251 }
253 /*
254 * append a label, doubles as appending a single character.
255 */
256 static void
257 appendLabel(char label)
258 {
259 if (!buffer.data) {
260 return;
261 }
263 *buffer.next++ = label;
264 if (buffer.data+buffer.len >= buffer.next) {
265 growBuffer();
266 }
267 }
269 /*
270 * append a string onto the buffer. The result will be <string>
271 */
272 static void
273 appendString(char *string)
274 {
275 if (!buffer.data) {
276 return;
277 }
279 appendLabel('<');
280 while (*string) {
281 appendLabel(*string++);
282 }
283 appendLabel('>');
284 }
286 /*
287 * append a bool, T= true, F=false
288 */
289 static void
290 appendBool(PRBool bool)
291 {
292 if (!buffer.data) {
293 return;
294 }
296 if (bool) {
297 appendLabel('t');
298 } else {
299 appendLabel('f');
300 }
301 }
303 /*
304 * append a single hex nibble.
305 */
306 static void
307 appendHex(unsigned char nibble)
308 {
309 if (nibble <= 9) {
310 appendLabel('0'+nibble);
311 } else {
312 appendLabel('a'+nibble-10);
313 }
314 }
316 /*
317 * append a secitem as colon separated hex bytes.
318 */
319 static void
320 appendItem(SECItem *item)
321 {
322 int i;
324 if (!buffer.data) {
325 return;
326 }
328 appendLabel(':');
329 for (i=0; i < item->len; i++) {
330 unsigned char byte=item->data[i];
331 appendHex(byte >> 4);
332 appendHex(byte & 0xf);
333 appendLabel(':');
334 }
335 }
337 /*
338 * append a 32 bit integer (even on a 64 bit platform).
339 * for simplicity append it as a hex value, full extension with 0x prefix.
340 */
341 static void
342 appendInt(unsigned int value)
343 {
344 int i;
346 if (!buffer.data) {
347 return;
348 }
350 appendLabel('0');
351 appendLabel('x');
352 value = value & 0xffffffff; /* only look at the buttom 8 bytes */
353 for (i=0; i < 8; i++) {
354 appendHex(value >> 28 );
355 value = value << 4;
356 }
357 }
359 /* append a trust flag */
360 static void
361 appendFlags(unsigned int flag)
362 {
363 char trust[10];
364 char *cp=trust;
366 trust[0] = 0;
367 printflags(trust, flag);
368 while (*cp) {
369 appendLabel(*cp++);
370 }
371 }
373 /*
374 * dump our buffer out with a result= flag so we can find it easily.
375 * free the buffer as a side effect.
376 */
377 static void
378 dumpBuffer(void)
379 {
380 if (!buffer.data) {
381 return;
382 }
384 appendLabel(0); /* terminate */
385 printf("\nresult=%s\n",buffer.data);
386 PORT_Free(buffer.data);
387 buffer.data = buffer.next = NULL;
388 buffer.len = 0;
389 }
392 /*
393 * usage, like traditional usage, automatically exit
394 */
395 static void
396 usage(const char *prog)
397 {
398 short_help(prog);
399 dumpBuffer();
400 exit(1);
401 }
403 /*
404 * like usage, except prints the long version of help
405 */
406 static void
407 usage_long(const char *prog)
408 {
409 long_help(prog);
410 dumpBuffer();
411 exit(1);
412 }
414 static const char *
415 bool2String(PRBool bool)
416 {
417 return bool ? "true" : "false";
418 }
420 /*
421 * print out interesting info about the given slot
422 */
423 void
424 print_slot(PK11SlotInfo *slot, int log)
425 {
426 if (log) {
427 fprintf(stderr, "* Name=%s Token_Name=%s present=%s, ro=%s *\n",
428 PK11_GetSlotName(slot), PK11_GetTokenName(slot),
429 bool2String(PK11_IsPresent(slot)),
430 bool2String(PK11_IsReadOnly(slot)));
431 }
432 appendLabel('S');
433 appendString(PK11_GetTokenName(slot));
434 appendBool(PK11_IsPresent(slot));
435 appendBool(PK11_IsReadOnly(slot));
436 }
438 /*
439 * list all our slots
440 */
441 void
442 do_list_slots(const char *progName, int log)
443 {
444 PK11SlotList *list;
445 PK11SlotListElement *le;
447 list= PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL);
448 if (list == NULL) {
449 fprintf(stderr,"ERROR: no tokens found %s\n",
450 SECU_Strerror(PORT_GetError()));
451 appendLabel('S');
452 appendString("none");
453 return;
454 }
456 for (le= PK11_GetFirstSafe(list); le;
457 le = PK11_GetNextSafe(list,le,PR_TRUE)) {
458 print_slot(le->slot, log);
459 }
460 PK11_FreeSlotList(list);
461 }
463 static PRBool
464 sort_CN(CERTCertificate *certa, CERTCertificate *certb, void *arg)
465 {
466 char *commonNameA, *commonNameB;
467 int ret;
469 commonNameA = CERT_GetCommonName(&certa->subject);
470 commonNameB = CERT_GetCommonName(&certb->subject);
472 if (commonNameA == NULL) {
473 PORT_Free(commonNameB);
474 return PR_TRUE;
475 }
476 if (commonNameB == NULL) {
477 PORT_Free(commonNameA);
478 return PR_FALSE;
479 }
480 ret = PORT_Strcmp(commonNameA,commonNameB);
481 PORT_Free(commonNameA);
482 PORT_Free(commonNameB);
483 return (ret < 0) ? PR_TRUE: PR_FALSE;
484 }
486 /*
487 * list all the certs
488 */
489 void
490 do_list_certs(const char *progName, int log)
491 {
492 CERTCertList *list;
493 CERTCertList *sorted;
494 CERTCertListNode *node;
495 CERTCertTrust trust;
496 int i;
498 list = PK11_ListCerts(PK11CertListUnique, NULL);
499 if (list == NULL) {
500 fprintf(stderr,"ERROR: no certs found %s\n",
501 SECU_Strerror(PORT_GetError()));
502 appendLabel('C');
503 appendString("none");
504 return;
505 }
507 sorted = CERT_NewCertList();
508 if (sorted == NULL) {
509 fprintf(stderr,"ERROR: no certs found %s\n",
510 SECU_Strerror(PORT_GetError()));
511 appendLabel('C');
512 appendLabel('E');
513 appendInt(PORT_GetError());
514 return;
515 }
517 /* sort the list */
518 for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node,list);
519 node = CERT_LIST_NEXT(node)) {
520 CERT_AddCertToListSorted(sorted, node->cert, sort_CN, NULL);
521 }
524 for (node = CERT_LIST_HEAD(sorted); !CERT_LIST_END(node,sorted);
525 node = CERT_LIST_NEXT(node)) {
526 CERTCertificate *cert = node->cert;
527 char *commonName;
529 SECU_PrintCertNickname(node, stderr);
530 if (log) {
531 fprintf(stderr, "* Slot=%s*\n", cert->slot ?
532 PK11_GetTokenName(cert->slot) : "none");
533 fprintf(stderr, "* Nickname=%s*\n", cert->nickname);
534 fprintf(stderr, "* Subject=<%s>*\n", cert->subjectName);
535 fprintf(stderr, "* Issuer=<%s>*\n", cert->issuerName);
536 fprintf(stderr, "* SN=");
537 for (i=0; i < cert->serialNumber.len; i++) {
538 if (i!=0) fprintf(stderr,":");
539 fprintf(stderr, "%02x",cert->serialNumber.data[0]);
540 }
541 fprintf(stderr," *\n");
542 }
543 appendLabel('C');
544 commonName = CERT_GetCommonName(&cert->subject);
545 appendString(commonName?commonName:"*NoName*");
546 PORT_Free(commonName);
547 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
548 appendFlags(trust.sslFlags);
549 appendFlags(trust.emailFlags);
550 appendFlags(trust.objectSigningFlags);
551 }
552 }
553 CERT_DestroyCertList(list);
555 }
557 /*
558 * need to implement yet... try to add a new certificate
559 */
560 void
561 do_add_cert(const char *progName, int log)
562 {
563 PORT_Assert(/* do_add_cert not implemented */ 0);
564 }
566 /*
567 * display the current key slot
568 */
569 void
570 do_key_slot(const char *progName, int log)
571 {
572 PK11SlotInfo *slot = PK11_GetInternalKeySlot();
573 if (!slot) {
574 fprintf(stderr,"ERROR: no internal key slot found %s\n",
575 SECU_Strerror(PORT_GetError()));
576 appendLabel('K');
577 appendLabel('S');
578 appendString("none");
579 }
580 print_slot(slot, log);
581 PK11_FreeSlot(slot);
582 }
584 /*
585 * execute some NSS command.
586 */
587 void
588 do_command(const char *label, int initialized, secuCommandFlag *command,
589 const char *progName, int log)
590 {
591 char * command_string;
592 if (!initialized) {
593 return;
594 }
596 if (command->activated) {
597 command_string = command->arg;
598 } else {
599 command_string = "none";
600 }
602 if (log) {
603 fprintf(stderr, "*Executing nss command \"%s\" for %s*\n",
604 command_string,label);
605 }
607 /* do something */
608 if (PORT_Strcasecmp(command_string, "list_slots") == 0) {
609 do_list_slots(progName, log);
610 } else if (PORT_Strcasecmp(command_string, "list_certs") == 0) {
611 do_list_certs(progName, log);
612 } else if (PORT_Strcasecmp(command_string, "add_cert") == 0) {
613 do_add_cert(progName, log);
614 } else if (PORT_Strcasecmp(command_string, "key_slot") == 0) {
615 do_key_slot(progName, log);
616 } else if (PORT_Strcasecmp(command_string, "none") != 0) {
617 fprintf(stderr, ">> Unknown command (%s)\n", command_string);
618 appendLabel('E');
619 appendString("bc");
620 usage_long(progName);
621 }
623 }
626 /*
627 * functions do handle
628 * different library initializations.
629 */
630 static int main_initialized;
631 static int lib1_initialized;
632 static int lib2_initialized;
634 void
635 main_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
636 int readOnly, const char *progName, int log)
637 {
638 SECStatus rv;
639 if (log) {
640 fprintf(stderr,"*NSS_Init for the main program*\n");
641 }
642 appendLabel('M');
643 if (!db->activated) {
644 fprintf(stderr, ">> No main_db has been specified\n");
645 usage(progName);
646 }
647 if (main_initialized) {
648 fprintf(stderr,"Warning: Second initialization of Main\n");
649 appendLabel('E');
650 appendString("2M");
651 }
652 if (tokNam->activated) {
653 PK11_ConfigurePKCS11(NULL, NULL, NULL, tokNam->arg,
654 NULL, NULL, NULL, NULL, 0, 0);
655 }
656 rv = NSS_Initialize(db->arg, "", "", "",
657 NSS_INIT_NOROOTINIT|(readOnly?NSS_INIT_READONLY:0));
658 if (rv != SECSuccess) {
659 appendLabel('E');
660 appendInt(PORT_GetError());
661 fprintf(stderr,">> %s\n", SECU_Strerror(PORT_GetError()));
662 dumpBuffer();
663 exit(1);
664 }
665 main_initialized = 1;
666 }
668 void
669 main_Do(secuCommandFlag *command, const char *progName, int log)
670 {
671 do_command("main", main_initialized, command, progName, log);
672 }
674 void
675 main_Shutdown(int old_style, const char *progName, int log)
676 {
677 SECStatus rv;
678 appendLabel('N');
679 if (log) {
680 fprintf(stderr,"*NSS_Shutdown for the main program*\n");
681 }
682 if (!main_initialized) {
683 fprintf(stderr,"Warning: Main shutdown without corresponding init\n");
684 }
685 if (old_style) {
686 rv = NSS_Shutdown();
687 } else {
688 rv = NSS_ShutdownContext(NULL);
689 }
690 fprintf(stderr, "Shutdown main state = %d\n", rv);
691 if (rv != SECSuccess) {
692 appendLabel('E');
693 appendInt(PORT_GetError());
694 fprintf(stderr,"ERROR: %s\n", SECU_Strerror(PORT_GetError()));
695 }
696 main_initialized = 0;
697 }
699 /* common library init */
700 NSSInitContext *
701 lib_Init(const char *lableString, char label, int initialized,
702 secuCommandFlag *db, secuCommandFlag *tokNam, int readonly,
703 const char *progName, int log)
704 {
705 NSSInitContext *ctxt;
706 NSSInitParameters initStrings;
707 NSSInitParameters *initStringPtr = NULL;
709 appendLabel(label);
710 if (log) {
711 fprintf(stderr,"*NSS_Init for %s*\n", lableString);
712 }
714 if (!db->activated) {
715 fprintf(stderr, ">> No %s_db has been specified\n", lableString);
716 usage(progName);
717 }
718 if (initialized) {
719 fprintf(stderr,"Warning: Second initialization of %s\n", lableString);
720 }
721 if (tokNam->activated) {
722 PORT_Memset(&initStrings, 0, sizeof(initStrings));
723 initStrings.length = sizeof(initStrings);
724 initStrings.dbTokenDescription = tokNam->arg;
725 initStringPtr = &initStrings;
726 }
727 ctxt = NSS_InitContext(db->arg, "", "", "", initStringPtr,
728 NSS_INIT_NOROOTINIT|(readonly?NSS_INIT_READONLY:0));
729 if (ctxt == NULL) {
730 appendLabel('E');
731 appendInt(PORT_GetError());
732 fprintf(stderr,">> %s\n",SECU_Strerror(PORT_GetError()));
733 dumpBuffer();
734 exit(1);
735 }
736 return ctxt;
737 }
739 /* common library shutdown */
740 void
741 lib_Shutdown(const char *labelString, char label, NSSInitContext *ctx,
742 int initialize, const char *progName, int log)
743 {
744 SECStatus rv;
745 appendLabel(label);
746 if (log) {
747 fprintf(stderr,"*NSS_Shutdown for %s\n*", labelString);
748 }
749 if (!initialize) {
750 fprintf(stderr,"Warning: %s shutdown without corresponding init\n",
751 labelString);
752 }
753 rv = NSS_ShutdownContext(ctx);
754 fprintf(stderr, "Shutdown %s state = %d\n", labelString, rv);
755 if (rv != SECSuccess) {
756 appendLabel('E');
757 appendInt(PORT_GetError());
758 fprintf(stderr,"ERROR: %s\n", SECU_Strerror(PORT_GetError()));
759 }
760 }
763 static NSSInitContext *lib1_context;
764 static NSSInitContext *lib2_context;
765 void
766 lib1_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
767 int readOnly, const char *progName, int log)
768 {
769 lib1_context = lib_Init("lib1", '1', lib1_initialized, db, tokNam,
770 readOnly, progName, log);
771 lib1_initialized = 1;
772 }
774 void
775 lib2_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
776 int readOnly, const char *progName, int log)
777 {
778 lib2_context = lib_Init("lib2", '2', lib2_initialized,
779 db, tokNam, readOnly, progName, log);
780 lib2_initialized = 1;
781 }
783 void
784 lib1_Do(secuCommandFlag *command, const char *progName, int log)
785 {
786 do_command("lib1", lib1_initialized, command, progName, log);
787 }
789 void
790 lib2_Do(secuCommandFlag *command, const char *progName, int log)
791 {
792 do_command("lib2", lib2_initialized, command, progName, log);
793 }
795 void
796 lib1_Shutdown(const char *progName, int log)
797 {
798 lib_Shutdown("lib1", 'I', lib1_context, lib1_initialized, progName, log);
799 lib1_initialized = 0;
800 /* don't clear lib1_Context, so we can test multiple attempts to close
801 * the same context produces correct errors*/
802 }
804 void
805 lib2_Shutdown(const char *progName, int log)
806 {
807 lib_Shutdown("lib2", 'Z', lib2_context, lib2_initialized, progName, log);
808 lib2_initialized = 0;
809 /* don't clear lib2_Context, so we can test multiple attempts to close
810 * the same context produces correct errors*/
811 }
813 int
814 main(int argc, char **argv)
815 {
816 SECStatus rv;
817 secuCommand libinit;
818 char *progName;
819 char *order;
820 secuCommandFlag *options;
821 int log = 0;
823 progName = strrchr(argv[0], '/');
824 progName = progName ? progName+1 : argv[0];
826 libinit.numCommands = 0;
827 libinit.commands = 0;
828 libinit.numOptions = opt_last;
829 options = (secuCommandFlag *)PORT_Alloc(sizeof(options_init));
830 if (options == NULL) {
831 fprintf(stderr, ">> %s:Not enough free memory to run command\n",
832 progName);
833 exit(1);
834 }
835 PORT_Memcpy(options, options_init, sizeof(options_init));
836 libinit.options = options;
838 rv = SECU_ParseCommandLine(argc, argv, progName, & libinit);
839 if (rv != SECSuccess) {
840 usage(progName);
841 }
843 if (libinit.options[opt_help].activated) {
844 long_help(progName);
845 exit (0);
846 }
848 log = libinit.options[opt_verbose].activated;
849 if (libinit.options[opt_summary].activated) {
850 initBuffer();
851 }
853 order = libinit.options[opt_liborder].arg;
854 if (!order) {
855 usage(progName);
856 }
858 if (log) {
859 fprintf(stderr,"* initializing with order \"%s\"*\n", order);
860 }
862 for (;*order; order++) {
863 switch (*order) {
864 case 'M':
865 main_Init(&libinit.options[opt_mainDB],
866 &libinit.options[opt_mainTokNam],
867 libinit.options[opt_mainRO].activated,
868 progName, log);
869 break;
870 case '1':
871 lib1_Init(&libinit.options[opt_lib1DB],
872 &libinit.options[opt_lib1TokNam],
873 libinit.options[opt_lib1RO].activated,
874 progName,log);
875 break;
876 case '2':
877 lib2_Init(&libinit.options[opt_lib2DB],
878 &libinit.options[opt_lib2TokNam],
879 libinit.options[opt_lib2RO].activated,
880 progName,log);
881 break;
882 case 'm':
883 main_Shutdown(libinit.options[opt_oldStyle].activated,
884 progName, log);
885 break;
886 case 'i':
887 lib1_Shutdown(progName, log);
888 break;
889 case 'z':
890 lib2_Shutdown(progName, log);
891 break;
892 default:
893 fprintf(stderr,">> Unknown init/shutdown command \"%c\"", *order);
894 usage_long(progName);
895 }
896 main_Do(&libinit.options[opt_mainCMD], progName, log);
897 lib1_Do(&libinit.options[opt_lib1CMD], progName, log);
898 lib2_Do(&libinit.options[opt_lib2CMD], progName, log);
899 }
901 if (NSS_IsInitialized()) {
902 appendLabel('X');
903 fprintf(stderr, "Warning: NSS is initialized\n");
904 }
905 dumpBuffer();
907 exit(0);
908 }