diff options
| -rw-r--r-- | src/implementation.c | 150 | ||||
| -rw-r--r-- | src/implementation.h | 16 | ||||
| -rw-r--r-- | src/main.c | 373 | 
3 files changed, 295 insertions, 244 deletions
| diff --git a/src/implementation.c b/src/implementation.c index 17b2c9a..334b7e1 100644 --- a/src/implementation.c +++ b/src/implementation.c @@ -1,10 +1,12 @@  #include <stdio.h>  #include <stdlib.h> +#include <libgen.h>  #include <unistd.h>  #include <termios.h>  #include <string.h>  #include <time.h>  #include <errno.h> +#include <sys/stat.h>  #include "handerror.h"  #include "easydir.h" @@ -50,38 +52,46 @@ static void copyText(char *password)  	#endif  } -void checkForbiddenPaths(char *path) // check two dot in path +/* check two dot in path */ +int checkForbiddenPaths(char *path)  { +	int i, length;  	int firstdot = 0; -	for(int i=0; i < strlen(path); i++) +	for(i = 0, length = strlen(path); i < length; i++)  	{ -		if(path[i] == '.') -			firstdot ? printError("Error: please, don't use forbidden paths\n") : firstdot++; +		if(path[i] == '.') { +			if(firstdot) +				return 1; +			firstdot++; +		}  		else firstdot = 0;  	} +	return 0;  } -char *getGPGKey(char *dest, size_t size) +char *getGPGKey()  { +	int size_gpgkey = sizeof(char) * GPG_PUBLICKEY_MAXLENGTH; +	char *pub_gpgkey = malloc(size_gpgkey + sizeof(char)); +  	FILE *fileGPG = fopen(".gpg-key", "r");  	if(fileGPG == NULL) { -		if(errno == ENOENT) printError("error: No GPG key exists. Use \"lpass init\"."); +		if(errno == ENOENT) +			printError("error: No GPG key exists. Use \"lpass init\".");  		callError(121);  	} -	if(!fgets(dest, size, fileGPG)) { +	if(!fgets(pub_gpgkey, size_gpgkey, fileGPG)) {  		callError(122);  	}  	fclose(fileGPG); -	return dest; +	return pub_gpgkey;  }  char* getPassword(char *path_pass, char *password, size_t size, int flag_copy)  { -	int size_gpgkey = sizeof(char) * GPG_PUBLICKEY_MAXLENGTH; -	char *public_gpgkey = (char *) malloc(size_gpgkey); -	getGPGKey(public_gpgkey, size_gpgkey); +	char *public_gpgkey = getGPGKey();  	char *arguments[] = {"gpg", "-d", "--quiet", "-r", public_gpgkey, "-o", path_pass, gPath_pass, NULL};  	easyFork("gpg", arguments); @@ -112,90 +122,74 @@ void nonvisibleEnter(int status)  	tcsetattr(0, TCSANOW, &term_settings);  } -void insertPass(char *add_path, char *password, int flag_copy) +static void mkdir_recursive(const char *path)  { -	/* add_path = banks/france/[number] -	gPath_pass = banks/france/[number].gpg -	gPath_subdir = banks/france */ +	char *subpath, *fullpath; -	int size_gpgkey = sizeof(char) * GPG_PUBLICKEY_MAXLENGTH; -	char *public_gpgkey = (char *) malloc(size_gpgkey); -	getGPGKey(public_gpgkey, size_gpgkey); +	fullpath = strdup(path); +	subpath = dirname(fullpath); +	if(subpath[0] != '.') +		mkdir_recursive(subpath); -	char *mkdir_arg[] = {"mkdir", "-p", gPath_subdir, NULL}; -	easyFork("mkdir", mkdir_arg); +	mkdir(path, S_IRWXU); +	free(fullpath); +} + +int insertPass(char *path, char *password, int flag_copy) +{ +	char *public_gpgkey = getGPGKey(); + +	// create directories +	char *tmp, *dirs_path; +	tmp = strdup(path); +	dirs_path = dirname(tmp); +	if(dirs_path[0] != '.') +		mkdir_recursive(dirs_path); +	free(tmp);  	// create file, copy password there -	FILE *filePass; -	filePass = fopen(add_path, "w");	 -	if(filePass == NULL) { -		callError(108); +	FILE *file_pass; +	file_pass = fopen(path, "w");	 +	if(file_pass == NULL) { +		free(public_gpgkey); +		return 1;  	} -	fputs(password, filePass); -	fclose(filePass); +	fputs(password, file_pass); +	fclose(file_pass); -	if(flag_copy) copyText(password); +	if(flag_copy) +		copyText(password);  	// encryption -	char *encrypt_arg[] = {"gpg", "--quiet", "--yes", "-r", public_gpgkey, "-e", add_path, NULL}; +	char *encrypt_arg[] = {"gpg", "--quiet", "--yes", "-r", public_gpgkey, "-e", path, NULL};  	easyFork("gpg", encrypt_arg); -	remove(add_path); +	remove(path);  	free(public_gpgkey); +	return 0;  } -char *typePass(char *text, char *dest, int minlen, int maxlen) +char *getInput(int minlen, int maxlen)  { -	printf("%s", text); -	if(fgets(dest, sizeof(char)*maxlen, stdin) == NULL) { -		nonvisibleEnter(0); -		printError("lpass: Unexpected end of file\n"); -	} +	size_t size = sizeof(char) * maxlen; +	char *pass = malloc(size + sizeof(char)); // +1 for '\0' +	int len; -	int len = strlen(dest); -	if(len < minlen || len > maxlen) { -		nonvisibleEnter(0); -		printError("lpass: incorrect password\n"); -	} -	 -	if(dest[len-1] == '\n') { -		dest[len-1] = '\0'; +	if(fgets(pass, size, stdin) == NULL) { +		free(pass); +		return NULL;  	} -	#if defined(DEBUG) -		printf("%s", dest); -	#endif - -	printf("\n"); // for new line -	return dest; -} - -int userEnterPassword(int minlen, int maxlen, char *path_insert, int flag_echo, int flag_copy) -{ -	char *pass_one = malloc(sizeof(char) * maxlen); -	int rvalue = 0; -	if(!flag_echo) { -		char *pass_two = malloc(sizeof(char) * maxlen); - -		nonvisibleEnter(1); // change terminal work -		typePass("Type your password: ", pass_one, minlen, maxlen); -		typePass("Type your password again: ", pass_two, minlen, maxlen); -		nonvisibleEnter(0); - -		if(strcmp(pass_one, pass_two) == 0) { -			insertPass(path_insert, pass_one, flag_copy); -			rvalue = 1; -		} -		free(pass_two); -	} -	else { -		typePass("Type your password: ", pass_one, minlen, maxlen); -		insertPass(path_insert, pass_one, flag_copy); -		rvalue = 1; +	len = strlen(pass); +	if(len < minlen) { +		free(pass); +		return NULL;  	} -	free(pass_one); -	return rvalue; +	if(pass[len-1] == '\n') +		pass[len-1] = '\0'; + +	return pass;  }  char *generatePassword(char *dest, int amount) @@ -230,13 +224,13 @@ int getOverwriteAnswer(char *path)  		switch(answer)  		{  			case 'Y': -			case 'y': return 1; +			case 'y': return OW_YES;  			case 'N': -			case 'n': return 0; +			case 'n': return OW_NO;  			case EOF: printError("Error: Unexpected end of file\n");  			default: { printf("Overwrite? (Y/N) "); break; }  		}  	} -	return -1; +	return 2;  } diff --git a/src/implementation.h b/src/implementation.h index 52f4dc7..bcb6985 100644 --- a/src/implementation.h +++ b/src/implementation.h @@ -1,15 +1,19 @@  #ifndef IMPLEMENTATION_H  #define IMPLEMENTATION_H -#define GPG_PUBLICKEY_MAXLENGTH 1025 // +1 for '\0' +#define GPG_PUBLICKEY_MAXLENGTH 1024 -void checkForbiddenPaths(char *path); -char *getGPGKey(char *dest, size_t size); +enum asnwers { +	OW_YES = 0, +	OW_NO = 1, +}; + +int checkForbiddenPaths(char *path); +char *getGPGKey();  char* getPassword(char *path_pass, char *password, size_t size, int flag_copy);  void nonvisibleEnter(int status); -void insertPass(char *add_path, char *password, int flag_copy); -char *typePass(char *text, char *dest, int minlen, int maxlen); -int userEnterPassword(int minlen, int maxlen, char *path_insert, int flag_echo, int flag_copy); +int insertPass(char *path, char *password, int flag_copy); +char *getInput(int minlen, int maxlen);  char *generatePassword(char *dest, int amount);  int getOverwriteAnswer(char *path); @@ -21,13 +21,17 @@  #include "implementation.h"  #include "exec-cmd.h" +enum constants { +	maxlen_texteditor = 16, +	minlen_pass = 1, +	maxlen_pass = 128, +	stdlen_pass = 14 +}; +  #define VERSION "1.0c"  #define DATE_RELEASE "14 January, 2021"  #define STANDARD_TEXTEDITOR "vim"  #define MAXLEN_TEXTEDITOR 16 -#define MINLEN_PASSWORD 1 -#define MAXLEN_PASSWORD 128 -#define STANDARD_AMOUNT_GENERATE_SYMBOLS 14  #define LOCKPASS_DIR ".lock-password/"  #define GPGKEY_FILE ".gpg-key" @@ -47,7 +51,7 @@  #ifdef DEBUG  	#define dbgprint(...) fprintf(stderr, "Debug: " __VA_ARGS__)  #else -	#define dbgprint(...) ; +	#define dbgprint(...)  #endif  struct cmd_struct { @@ -91,7 +95,8 @@ int cmd_init(int argc, char *argv[])  {  	const char description[] = "init gpg-key\n";  	char *gpg_key = argv[2]; -	if(gpg_key == NULL) usageprint("%s", description); +	if(gpg_key == NULL) +		usageprint("%s", description);  	// create .gpg-key in storage  	FILE *filekey = fopen(GPGKEY_FILE, "w");	 @@ -105,6 +110,88 @@ int cmd_init(int argc, char *argv[])  	return 0;  } +int cmd_insert(int argc, char *argv[]) +{ +	const char description[] = "insert [-ecf] passname\n"; +	int flag_echo = 0, flag_force = 0, flag_copy = 0, result; +	const struct option long_options[] = { +		{"echo", no_argument, NULL, 'e'}, +		{"force", no_argument, NULL, 'f'}, +		{"copy", no_argument, NULL, 'c'}, +		{NULL, 0, NULL, 0} +	}; + +	while((result = getopt_long(argc, argv, "efc", long_options, NULL)) != -1) { +		switch(result) { +			case 'e': { flag_echo = 1; break; } +			case 'f': { flag_force = 1; break; } +			case 'c': { flag_copy = 1; break; } +			default: usageprint("%s", description); +		} +	} + +	if(optind < argc) optind++; // for skip "insert" +	dbgprint("passname: %s\n", argv[optind]); + +	char *path = argv[optind]; +	if(path == NULL) +		usageprint("%s", description); + +	result = checkForbiddenPaths(path); +	if(result) +		errprint("You have used forbidden paths\n"); + +	if(checkFileExist(path) == F_SUCCESS) { +		if(!flag_force) { +			if(getOverwriteAnswer(path) != OW_YES) +				return 1; +		} +	} + +	char *f_pass; +	if(!flag_echo) { +		char *s_pass; +		nonvisibleEnter(1); // change terminal work + +		fputs("Type your password: ", stdout); +		f_pass = getInput(minlen_pass, maxlen_pass); +		fputs("\n", stdout); +		if(f_pass == NULL) { +			nonvisibleEnter(0); +			errprint("Incorrect password"); +		} + +		fputs("Type your password again: ", stdout); +		s_pass = getInput(minlen_pass, maxlen_pass); +		fputs("\n", stdout); +		nonvisibleEnter(0); +		if(s_pass == NULL) { +			free(f_pass); +			errprint("Incorrect password"); +		} + +		if(strcmp(f_pass, s_pass) != 0) { +			free(f_pass); +			free(s_pass); +			errprint("Password do not match"); +		} +		free(s_pass); +	} +	else { +		fputs("Type your password: ", stdout); +		f_pass = getInput(minlen_pass, maxlen_pass); +		if(f_pass == NULL) +			errprint("Incorrect password"); +	} + +	result = insertPass(path, f_pass, flag_copy); +	if(result) +		errprint("Can't add password to LockPassword"); + +	printf("Password added successfully for %s\n", path); +	return 0; +} +  int cmd_edit(int argc, char *argv[])  {  	const char description[] = "edit [-t=text-editor] passname\n"; @@ -132,13 +219,14 @@ int cmd_edit(int argc, char *argv[])  	}  	if(optind < argc) optind++; // for skip "edit" -	dbgprint("passname: %s\n", argv[optind]); - +	char *path_to_password = argv[optind];  	if(argv[optind] == NULL)  		usageprint("%s", description); -	char *path_to_password = argv[optind]; +	dbgprint("passname: %s\n", argv[optind]); -	checkForbiddenPaths(path_to_password); +	result = checkForbiddenPaths(path_to_password); +	if(result) +		errprint("You have used forbidden paths\n");  	globalSplitPath(path_to_password);  	result = checkFileExist(gPath_pass); @@ -167,9 +255,7 @@ int cmd_edit(int argc, char *argv[])  	// end configure  	// decryption -	int size_gpgkey = sizeof(char) * GPG_PUBLICKEY_MAXLENGTH; -	char *public_gpgkey = (char *) malloc(size_gpgkey); -	getGPGKey(public_gpgkey, size_gpgkey); +	char *public_gpgkey = getGPGKey();  	char *decrypt_arg[] = {"gpg", "-d", "--quiet", "-r", public_gpgkey, "-o", path_to_password, gPath_pass, NULL};  	easyFork("gpg", decrypt_arg); @@ -179,8 +265,8 @@ int cmd_edit(int argc, char *argv[])  	easyFork(text_editor, editor_arg);  	// delete '\n' and paste good pass -	char password[MAXLEN_PASSWORD]; -	fileCropLineFeed(path_to_password, password, MAXLEN_PASSWORD); +	char password[maxlen_pass]; +	fileCropLineFeed(path_to_password, password, maxlen_pass);  	FILE *file = fopen(path_to_password, "w");	  	if(file == NULL) callError(108); @@ -196,72 +282,10 @@ int cmd_edit(int argc, char *argv[])  	return 0;  } -int cmd_move(int argc, char *argv[]) -{ -	/* we have a two situation: -	1) mv file file -	2) mv file directory */ -	 -	const char description[] = "mv [-f] old-path new-path\n"; -	const struct option long_options[] = { -		{"force", no_argument, NULL, 'f'}, -		{NULL, 0, NULL, 0} -	}; - -	int result, flag_force = 0; -	while((result = getopt_long(argc, argv, "f", long_options, NULL)) != -1) { -		switch(result) { -			case 'f': { flag_force = 1; break; } -			default: usageprint("%s", description); -		} -	} - -	if(optind < argc) optind++; // for skip "move" -	if(!argv[optind] || !argv[optind+1]) -		usageprint("%s", description); -	dbgprint("old-path: %s\n", argv[optind]); -	dbgprint("new-path: %s\n", argv[optind+1]); - -	char *old_path = argv[optind]; -	checkForbiddenPaths(old_path); -	globalSplitPath(old_path); -	result = checkFileExist(gPath_pass); -	if(result != F_SUCCESS) { -		if(result == F_ISDIR) errprint("It is a directory\n"); -		errprint("No such file exists\n"); -	} - -	char *old_path_gpg = gPath_pass; -	char *old_path_subdir = gPath_subdir; - -	char *new_path = argv[optind+1]; -	checkForbiddenPaths(new_path); -	globalSplitPath(new_path); - -	if(checkFileExist(new_path) == F_ISDIR) -		; -	else if(checkFileExist(gPath_pass) == F_SUCCESS) { -		if(!flag_force) { -			if(getOverwriteAnswer(new_path) != 1) -				return 1; -		} -		new_path = gPath_pass; -	} -	else errprint("No such new-path exists\n"); - -	char *arguments[] = {"mv", "-f", old_path_gpg, new_path, NULL}; -	easyFork("mv", arguments); - -	rmdir(old_path_subdir); -	free(old_path_subdir); -	free(old_path_gpg); -	return 0; -} -  int cmd_generate(int argc, char *argv[])  {  	const char description[] = "generate [-l=pass-length] [-f] passname\n"; -	int pass_length = STANDARD_AMOUNT_GENERATE_SYMBOLS; +	int pass_length = stdlen_pass;  	int flag_force = 0, flag_copy = 0, result;  	const struct option long_options[] = {  		{"length", required_argument, NULL, 'l'}, @@ -287,15 +311,17 @@ int cmd_generate(int argc, char *argv[])  		usageprint("%s", description);  	char *path_to_password = argv[optind]; -	if(pass_length < MINLEN_PASSWORD || pass_length > MAXLEN_PASSWORD) +	if(pass_length < minlen_pass || pass_length > maxlen_pass)  		errprint("You typed an incorrect number\n"); -	checkForbiddenPaths(path_to_password); +	result = checkForbiddenPaths(path_to_password); +	if(result) +		errprint("You have used forbidden paths\n");  	globalSplitPath(path_to_password);  	if(checkFileExist(gPath_pass) == F_SUCCESS) {  		if(!flag_force) { -			if(getOverwriteAnswer(path_to_password) != 1) +			if(getOverwriteAnswer(path_to_password) != OW_YES)  				return 1;  		}  	} @@ -304,77 +330,139 @@ int cmd_generate(int argc, char *argv[])  	char gpass[pass_length];  	generatePassword(gpass, pass_length); -	insertPass(path_to_password, gpass, flag_copy); +	result = insertPass(path_to_password, gpass, flag_copy); +	if(result) +		errprint("Can't add password to LockPassword"); +  	if(!flag_copy) printf("Generated password: %s\n", gpass);  	printf("Password added successfully for %s\n", path_to_password);  	return 0;  } -int cmd_insert(int argc, char *argv[]) +int cmd_remove(int argc, char *argv[])  { -	const char description[] = "insert [-ecf] passname\n"; -	int flag_echo = 0, flag_force = 0, flag_copy = 0, result; +	const char description[] = "rm passname\n"; +	int result; +	char *path = argv[2]; +	if(!path) +		usageprint("%s", description); + +	result = checkForbiddenPaths(path); +	if(result) +		errprint("You have used forbidden paths\n"); +	globalSplitPath(path); + +	result = checkFileExist(gPath_pass); +	if(result != F_SUCCESS) { +		if(result == F_ISDIR) errprint("It is a directory\n"); +		errprint("No such file exists\n"); +	} + +	if(unlink(gPath_pass) == 0) +		rmdir(gPath_subdir); +	return 0; +} + +int cmd_move(int argc, char *argv[]) +{ +	/* we have a two situation: +	1) mv file file +	2) mv file directory */ +	 +	const char description[] = "mv [-f] old-path new-path\n";  	const struct option long_options[] = { -		{"echo", no_argument, NULL, 'e'},  		{"force", no_argument, NULL, 'f'}, -		{"copy", no_argument, NULL, 'c'},  		{NULL, 0, NULL, 0}  	}; -	while((result = getopt_long(argc, argv, "efc", long_options, NULL)) != -1) { +	int result, flag_force = 0; +	while((result = getopt_long(argc, argv, "f", long_options, NULL)) != -1) {  		switch(result) { -			case 'e': { flag_echo = 1; break; }  			case 'f': { flag_force = 1; break; } -			case 'c': { flag_copy = 1; break; }  			default: usageprint("%s", description);  		}  	} -	if(optind < argc) optind++; // for skip "insert" -	dbgprint("passname: %s\n", argv[optind]); - -	if(argv[optind] == NULL) +	if(optind < argc) optind++; // for skip "move" +	if(!argv[optind] || !argv[optind+1])  		usageprint("%s", description); -	char *path_to_password = argv[optind]; +	dbgprint("old-path: %s\n", argv[optind]); +	dbgprint("new-path: %s\n", argv[optind+1]); -	checkForbiddenPaths(path_to_password); -	globalSplitPath(path_to_password); +	char *old_path = argv[optind]; +	result = checkForbiddenPaths(old_path); +	if(result) +		errprint("You have used forbidden paths\n"); +	globalSplitPath(old_path); +	result = checkFileExist(gPath_pass); +	if(result != F_SUCCESS) { +		if(result == F_ISDIR) errprint("It is a directory\n"); +		errprint("No such file exists\n"); +	} -	if(checkFileExist(gPath_pass) == F_SUCCESS) { +	char *old_path_gpg = gPath_pass; +	char *old_path_subdir = gPath_subdir; + +	char *new_path = argv[optind+1]; +	result = checkForbiddenPaths(new_path); +	if(result) +		errprint("You have used forbidden paths\n"); +	globalSplitPath(new_path); + +	if(checkFileExist(new_path) == F_ISDIR) +		; +	else if(checkFileExist(gPath_pass) == F_SUCCESS) {  		if(!flag_force) { -			if(getOverwriteAnswer(path_to_password) != 1) +			if(getOverwriteAnswer(new_path) != OW_YES)  				return 1;  		} +		new_path = gPath_pass;  	} -			 -	if(userEnterPassword(MINLEN_PASSWORD, MAXLEN_PASSWORD, -			path_to_password, flag_echo, flag_copy) == 1) { -		printf("Password added successfully for %s\n", path_to_password); -	} -	else -		printf("Passwords do not match\n"); +	else errprint("No such new-path exists\n"); + +	char *arguments[] = {"mv", "-f", old_path_gpg, new_path, NULL}; +	easyFork("mv", arguments); + +	rmdir(old_path_subdir); +	free(old_path_subdir); +	free(old_path_gpg);  	return 0;  } -int cmd_remove(int argc, char *argv[]) +int cmd_help(int argc, char *argv[])  { -	const char description[] = "rm passname\n"; -	int res; -	char *path = argv[2]; -	if(!path) -		usageprint("%s", description); +	printf("Synopsis:\n" +		"\tlpass [command] [arguments] ...\n" -	checkForbiddenPaths(path); -	globalSplitPath(path); +		"Commands:\n" +		"\tinit gpg-key\n" +		"\t\tInitialize the password manager using the passed gpg-key.\n" +		"\tinsert [-e, --echo] [-c, --copy] [-f, --force] passname\n" +		"\t\tAdd the specified passname to the password manager.\n" +		"\tedit [-t, --text-editor=text-editor] passname\n" +		"\t\tOpen the specified passname in a text editor, waiting for changes.\n" +		"\tgenerate [-l, --length=pass-length] [-c, --copy] [-f, --force] passname\n" +		"\t\tGenerate a random password and write it in passname.\n" +		"\tmv [-f, --force] old-path new-path\n" +		"\t\tMove/rename old-path to new-path.\n" +		"\trm passname\n" +		"\t\tRemove the passname you specified from the password manager.\n" +		"\thelp\n" +		"\t\tPrint help information about commands and the application itself.\n" +		"\tversion\n" +		"\t\tPrint version information.\n" -	res = checkFileExist(gPath_pass); -	if(res != F_SUCCESS) { -		if(res == F_ISDIR) errprint("It is a directory\n"); -		errprint("No such file exists\n"); -	} +		"\nMore information may be found in the lpass(1) man page.\n"); +	return 0; +} -	if(unlink(gPath_pass) == 0) -		rmdir(gPath_subdir); +int cmd_version(int argc, char *argv[]) +{ +	printf("LockPassword v%s\n" +		"Release date: %s\n\n" +		"Code was written by Joursoir\n" +		"This is free and unencumbered software released into the public domain.\n\n", +		VERSION, DATE_RELEASE);  	return 0;  } @@ -396,9 +484,11 @@ int cmd_showtree(int argc, char *argv[])  	}  	if(argv[optind]) { +		result = checkForbiddenPaths(argv[optind]); +		if(result) +			errprint("You have used forbidden paths\n");  		path = malloc(sizeof(char) * (strlen(argv[optind]) + 1));  		strcpy(path, argv[optind]); -		checkForbiddenPaths(path);  	}  	else {  		path = malloc(sizeof(char) * 2); @@ -430,8 +520,8 @@ int cmd_showtree(int argc, char *argv[])  		if(checkFileExist(gPath_pass) == F_SUCCESS)  		{ -			char password[MAXLEN_PASSWORD]; -			getPassword(path, password, sizeof(char)*MAXLEN_PASSWORD, flag_copy); +			char password[maxlen_pass]; +			getPassword(path, password, sizeof(char)*maxlen_pass, flag_copy);  			if(!flag_copy) printf("%s\n", password);  		}  		else errprint("%s is not in the password storage\n", path); @@ -441,43 +531,6 @@ int cmd_showtree(int argc, char *argv[])  	return 0;  } -int cmd_help(int argc, char *argv[]) -{ -	printf("Synopsis:\n" -		"\tlpass [command] [arguments] ...\n" - -		"Commands:\n" -		"\tinit gpg-key\n" -		"\t\tInitialize the password manager using the passed gpg-key.\n" -		"\tinsert [-e, --echo] [-c, --copy] [-f, --force] passname\n" -		"\t\tAdd the specified passname to the password manager.\n" -		"\tedit [-t, --text-editor=text-editor] passname\n" -		"\t\tOpen the specified passname in a text editor, waiting for changes.\n" -		"\tgenerate [-l, --length=pass-length] [-c, --copy] [-f, --force] passname\n" -		"\t\tGenerate a random password and write it in passname.\n" -		"\tmv [-f, --force] old-path new-path\n" -		"\t\tMove/rename old-path to new-path.\n" -		"\trm passname\n" -		"\t\tRemove the passname you specified from the password manager.\n" -		"\thelp\n" -		"\t\tPrint help information about commands and the application itself.\n" -		"\tversion\n" -		"\t\tPrint version information.\n" - -		"\nMore information may be found in the lpass(1) man page.\n"); -	return 0; -} - -int cmd_version(int argc, char *argv[]) -{ -	printf("LockPassword v%s\n" -		"Release date: %s\n\n" -		"Code was written by Joursoir\n" -		"This is free and unencumbered software released into the public domain.\n\n", -		VERSION, DATE_RELEASE); -	return 0; -} -  static struct cmd_struct *get_cmd(const char *name)  {  	struct cmd_struct *ptr; | 
