Mercurial > projects > pwm
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 |