comparison cmd.c @ 22:ec01c579024a

Add fully interactive mode
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Thu, 07 Sep 2017 12:40:50 +0200
parents 5c6155c8e9b6
children 1b89066d992c
comparison
equal deleted inserted replaced
21:ee4d36c85287 22:ec01c579024a
400 400
401 401
402 return (retval); 402 return (retval);
403 } 403 }
404 404
405 static int
406 read_record_fields(struct pwm_ctx *ctx, struct record *record)
407 {
408 char group_buf[PWM_LINE_MAX] = { '\0' };
409 char title_buf[PWM_LINE_MAX] = { '\0' };
410 char username_buf[PWM_LINE_MAX] = { '\0' };
411 char password_buf[PWM_LINE_MAX] = { '\0' };
412 char notes_buf[PWM_LINE_MAX] = { '\0' };
413 char url_buf[PWM_LINE_MAX] = { '\0' };
414
415 if (io_get_line(NULL, "Group: ", 0, record->group, -1,
416 sizeof (group_buf), group_buf) == IO_SIGNAL) {
417 return (CMD_SIGNAL);
418 }
419 io_trim_nl(group_buf);
420
421 if (io_get_line(NULL, "Title: ", 0, record->title, -1,
422 sizeof (title_buf), title_buf) == IO_SIGNAL) {
423 return (CMD_SIGNAL);
424 }
425 io_trim_nl(title_buf);
426
427 if (io_get_line(NULL, "Username: ", 0, record->username, -1,
428 sizeof (username_buf), username_buf) == IO_SIGNAL) {
429 return (CMD_SIGNAL);
430 }
431 io_trim_nl(username_buf);
432
433 for (;;) {
434 switch (io_get_password("Password: ", "Confirm Password: ",
435 sizeof (password_buf), password_buf)) {
436 case IO_OK: /* FALLTHROUGH */
437 case IO_PASSWORD_EMPTY:
438 goto password_done;
439 case IO_SIGNAL:
440 return (CMD_SIGNAL);
441 case IO_PASSWORD_MISMATCH:
442 pwm_err(ctx, "passwords do not match");
443 continue;
444 }
445 }
446
447 password_done:
448 if (io_get_line(NULL, "Notes: ", 0, record->notes, -1,
449 sizeof (notes_buf), notes_buf) == IO_SIGNAL) {
450 return (CMD_SIGNAL);
451 }
452 io_trim_nl(notes_buf);
453
454 if (io_get_line(NULL, "URL: ", 0, record->url, -1, sizeof (url_buf),
455 url_buf) == IO_SIGNAL) {
456 return (CMD_SIGNAL);
457 }
458 io_trim_nl(url_buf);
459
460 free(record->group);
461 record->group = (group_buf[0] != '\0') ? xstrdup(group_buf) : NULL;
462 free(record->title);
463 record->title = (title_buf[0] != '\0') ? xstrdup(title_buf) : NULL;
464 free(record->username);
465 record->username = (username_buf[0] != '\0') ? xstrdup(username_buf) :
466 NULL;
467 /*
468 * the current password cannot be edited, keep the current password if
469 * the user pressed return or ^D instead of deleting it like other
470 * fields
471 */
472 if (password_buf[0] != '\0') {
473 free(record->password);
474 record->password = xstrdup(password_buf);
475 }
476 free(record->notes);
477 record->notes = (notes_buf[0] != '\0') ? xstrdup(notes_buf) : NULL;
478 free(record->url);
479 record->url = (url_buf[0] != '\0') ? xstrdup(url_buf) : NULL;
480
481 return (CMD_OK);
482 }
483
405 static enum cmd_return 484 static enum cmd_return
406 cmd_create(struct pwm_ctx *ctx, int argc, char *argv[]) 485 cmd_create(struct pwm_ctx *ctx, int argc, char *argv[])
407 { 486 {
487 enum cmd_return retval = CMD_ERR;
408 int i; 488 int i;
409 struct record record = { 0 }; 489 struct record *record = NULL;
410 enum field_type type; 490 enum field_type type;
411 char *value; 491 char *value;
412 492
413 if (argc < 2) { 493 if (!ctx->is_interactive && (argc < 2)) {
414 return (CMD_USAGE); 494 retval = CMD_USAGE;
415 } 495 goto out;
496 }
497
498 record = pwfile_create_record();
416 499
417 for (i = 1; i < argc; i++) { 500 for (i = 1; i < argc; i++) {
418 type = parse_arg(argv[i], field_namev, '=', &value); 501 type = parse_arg(argv[i], field_namev, '=', &value);
419 if (type == FIELD_UNKNOWN) { 502 if (type == FIELD_UNKNOWN) {
420 pwm_err(ctx, "bad field assignment \"%s\"", argv[i]); 503 pwm_err(ctx, "bad field assignment \"%s\"", argv[i]);
423 /* skip empty assignments */ 506 /* skip empty assignments */
424 continue; 507 continue;
425 } 508 }
426 switch (type) { 509 switch (type) {
427 case FIELD_GROUP: 510 case FIELD_GROUP:
428 record.group = value; 511 free(record->group);
512 record->group = xstrdup(value);
429 break; 513 break;
430 case FIELD_TITLE: 514 case FIELD_TITLE:
431 record.title = value; 515 free(record->title);
516 record->title = xstrdup(value);
432 break; 517 break;
433 case FIELD_USERNAME: 518 case FIELD_USERNAME:
434 record.username = value; 519 free(record->username);
520 record->username = xstrdup(value);
435 break; 521 break;
436 case FIELD_PASSWORD: 522 case FIELD_PASSWORD:
437 record.password = value; 523 free(record->password);
524 record->password = xstrdup(value);
438 break; 525 break;
439 case FIELD_NOTES: 526 case FIELD_NOTES:
440 record.notes = value; 527 free(record->notes);
528 record->notes = xstrdup(value);
441 break; 529 break;
442 case FIELD_URL: 530 case FIELD_URL:
443 record.url = value; 531 free(record->url);
532 record->url = xstrdup(value);
444 break; 533 break;
445 default: 534 default:
446 pwm_err(ctx, "bad field name \"%s\"", argv[i]); 535 pwm_err(ctx, "bad field name \"%s\"", argv[i]);
447 return (CMD_ERR); 536 goto out;
448 } 537 }
449 } 538 }
450 539
451 pwfile_create_record(ctx, &record); 540 if (ctx->is_interactive && (argc < 2)) {
452 541 if (read_record_fields(ctx, record) != 0) {
453 return (CMD_OK); 542 goto out;
543 }
544 }
545
546 pwfile_create_pws_record(ctx, record);
547 retval = CMD_OK;
548
549 out:
550 pwfile_destroy_record(record);
551
552 return (retval);
454 } 553 }
455 554
456 static enum cmd_return 555 static enum cmd_return
457 cmd_modify(struct pwm_ctx *ctx, int argc, char *argv[]) 556 cmd_modify(struct pwm_ctx *ctx, int argc, char *argv[])
458 { 557 {
558 int retval = CMD_ERR;
459 unsigned int id; 559 unsigned int id;
460 int i; 560 int i;
461 struct record record = { 0 }; 561 struct record *record = NULL;
462 enum field_type type; 562 enum field_type type;
463 char *value; 563 char *value;
464 564
465 if (argc < 2) { 565 if (!ctx->is_interactive && (argc < 2)) {
466 return (CMD_USAGE); 566 retval = CMD_USAGE;
567 goto out;
467 } 568 }
468 569
469 if (parse_id(argv[1], &id) != 0) { 570 if (parse_id(argv[1], &id) != 0) {
470 pwm_err(ctx, "invalid id %s", argv[1]); 571 pwm_err(ctx, "invalid id %s", argv[1]);
471 return (CMD_ERR); 572 goto out;
472 } 573 }
574 record = pwfile_get_record(ctx, id);
473 575
474 for (i = 2; i < argc; i++) { 576 for (i = 2; i < argc; i++) {
475 type = parse_arg(argv[i], field_namev, '=', &value); 577 type = parse_arg(argv[i], field_namev, '=', &value);
476 if (type == FIELD_UNKNOWN) { 578 if (type == FIELD_UNKNOWN) {
477 pwm_err(ctx, "bad field assignment \"%s\"", argv[i]); 579 pwm_err(ctx, "bad field assignment \"%s\"", argv[i]);
478 return (CMD_ERR); 580 goto out;
479 } 581 }
480 if (value[0] == '\0') { 582 if (value[0] == '\0') {
481 /* skip empty assignments */ 583 /* skip empty assignments */
482 continue; 584 continue;
483 } 585 }
484 switch (type) { 586 switch (type) {
485 case FIELD_GROUP: 587 case FIELD_GROUP:
486 record.group = value; 588 free(record->group);
589 record->group = xstrdup(value);
487 break; 590 break;
488 case FIELD_TITLE: 591 case FIELD_TITLE:
489 record.title = value; 592 free(record->title);
593 record->title = xstrdup(value);
490 break; 594 break;
491 case FIELD_USERNAME: 595 case FIELD_USERNAME:
492 record.username = value; 596 free(record->username);
597 record->username = xstrdup(value);
493 break; 598 break;
494 case FIELD_PASSWORD: 599 case FIELD_PASSWORD:
495 record.password = value; 600 free(record->password);
601 record->password = xstrdup(value);
496 break; 602 break;
497 case FIELD_NOTES: 603 case FIELD_NOTES:
498 record.notes = value; 604 free(record->notes);
605 record->notes = xstrdup(value);
499 break; 606 break;
500 case FIELD_URL: 607 case FIELD_URL:
501 record.url = value; 608 free(record->url);
609 record->url = xstrdup(value);
502 break; 610 break;
503 default: 611 default:
504 pwm_err(ctx, "bad field name \"%s\"", argv[i]); 612 pwm_err(ctx, "bad field name \"%s\"", argv[i]);
505 return (CMD_ERR); 613 goto out;
506 } 614 }
507 } 615 }
508 616
509 pwfile_modify_record(ctx, id, &record); 617 if (ctx->is_interactive && (argc < 3)) {
510 618 if (read_record_fields(ctx, record) != 0) {
511 return (CMD_OK); 619 goto out;
620 }
621 }
622
623 pwfile_modify_pws_record(ctx, id, record);
624 retval = CMD_OK;
625
626 out:
627 pwfile_destroy_record(record);
628
629 return (retval);
512 } 630 }
513 631
514 static enum cmd_return 632 static enum cmd_return
515 cmd_generatepassword(struct pwm_ctx *ctx, int argc, char *argv[]) 633 cmd_generatepassword(struct pwm_ctx *ctx, int argc, char *argv[])
516 { 634 {
631 "constraints"); 749 "constraints");
632 goto out; 750 goto out;
633 } 751 }
634 752
635 if (id != 0) { 753 if (id != 0) {
636 if (pwfile_modify_record(ctx, id, 754 if (pwfile_modify_pws_record(ctx, id,
637 &(struct record){ .password = password }) != 0) { 755 &(struct record){ .password = password }) != 0) {
638 pwm_err(ctx, "record %u does not exist", id); 756 pwm_err(ctx, "record %u does not exist", id);
639 goto out; 757 goto out;
640 } 758 }
641 retval = CMD_OK; 759 retval = CMD_OK;
661 if (parse_id(argv[1], &id) != 0) { 779 if (parse_id(argv[1], &id) != 0) {
662 pwm_err(ctx, "invalid id %s", argv[1]); 780 pwm_err(ctx, "invalid id %s", argv[1]);
663 return (CMD_ERR); 781 return (CMD_ERR);
664 } 782 }
665 783
666 if (pwfile_remove_record(ctx, id) != 0) { 784 if (pwfile_remove_pws_record(ctx, id) != 0) {
667 pwm_err(ctx, "failed to remove record %u", id); 785 pwm_err(ctx, "failed to remove record %u", id);
668 return (CMD_ERR); 786 return (CMD_ERR);
669 } 787 }
670 788
671 return (CMD_OK); 789 return (CMD_OK);
833 } 951 }
834 952
835 static enum cmd_return 953 static enum cmd_return
836 cmd_creategroup(struct pwm_ctx *ctx, int argc, char *argv[]) 954 cmd_creategroup(struct pwm_ctx *ctx, int argc, char *argv[])
837 { 955 {
838 if (argc != 2) { 956 char group_buf[PWM_LINE_MAX] = { '\0' };
957
958 if (!ctx->is_interactive && (argc != 2)) {
839 return (CMD_USAGE); 959 return (CMD_USAGE);
840 } 960 }
841 961
842 if (pwfile_create_group(ctx, argv[1]) != 0) { 962 if (ctx->is_interactive && (argc != 2)) {
843 pwm_err(ctx, "group \"%s\" already exists", argv[1]); 963 if (io_get_line(NULL, "Group: ", 0, NULL, 0,
844 return (CMD_ERR); 964 sizeof (group_buf), group_buf) == IO_SIGNAL) {
965 return (CMD_SIGNAL);
966 }
967 io_trim_nl(group_buf);
968 } else {
969 strcpy(group_buf, argv[1]);
970 }
971
972 if (group_buf[0] != '\0') {
973 if (pwfile_create_group(ctx, group_buf) != 0) {
974 pwm_err(ctx, "group \"%s\" already exists", group_buf);
975 return (CMD_ERR);
976 }
845 } 977 }
846 978
847 return (CMD_OK); 979 return (CMD_OK);
848 } 980 }
849 981