~emersion/mrsh-dev

pwd: implement -L and -P v1 PROPOSED

Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~emersion/mrsh-dev/%3C20190902021141.24913-1-sir%40cmpwn.com%3E/mbox | git am -3
Learn more about email & git

[PATCH] pwd: implement -L and -P Export this patch

Note that this is mostly a placation, because mrsh manages the PWD
variable and ensures that none of the conditions -P or -L are meant to
address will occur.
---
 builtin/pwd.c | 54 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 9 deletions(-)

diff --git a/builtin/pwd.c b/builtin/pwd.c
index 370cf91..37d8ffe 100644
--- a/builtin/pwd.c
@@ -1,22 +1,32 @@
-#define _POSIX_C_SOURCE 200809L
+#define _XOPEN_SOURCE 500
+#include <assert.h>
+#include <limits.h>
 #include <mrsh/getopt.h>
 #include <mrsh/shell.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <strings.h>
 #include "builtin.h"
 
 static const char pwd_usage[] = "usage: pwd [-L|-P]\n";
 
 int builtin_pwd(struct mrsh_state *state, int argc, char *argv[]) {
+	bool use_realpath = false;
+
+	const char *pwd = mrsh_env_get(state, "PWD", NULL);
+	assert(pwd != NULL);
+
 	mrsh_optind = 0;
 	int opt;
 	while ((opt = mrsh_getopt(argc, argv, ":LP")) != -1) {
 		switch (opt) {
 		case 'L':
+			assert(strlen(pwd) <= PATH_MAX);
+			/* fallthrough */
 		case 'P':
-			// TODO implement `-L` and `-P`
-			fprintf(stderr, "pwd: `-L` and `-P` not yet implemented\n");
-			return 1;
+			use_realpath = true;
+			break;
 		default:
 			fprintf(stderr, "pwd: unknown option -- %c\n", mrsh_optopt);
 			fprintf(stderr, pwd_usage);
@@ -28,11 +38,37 @@ int builtin_pwd(struct mrsh_state *state, int argc, char *argv[]) {
 		return 1;
 	}
 
-	const char *pwd = mrsh_env_get(state, "PWD", NULL);
-	if (pwd == NULL) {
-		fprintf(stderr, "pwd: Cannot return current directory as PWD was unset\n");
-		return 1;
+	char path[PATH_MAX + 1];
+	if (use_realpath) {
+		if (realpath(pwd, path) == NULL) {
+			perror("pwd");
+			return 1;
+		}
+		puts(path);
+	} else {
+		path[0] = '\0';
+
+		char *_pwd = strdup(pwd);
+		char *part = strtok(_pwd, "/");
+		while (part != NULL) {
+			if (part[0] == '\0') {
+				continue;
+			}
+			if (part[0] == '.' && part[1] == '\0') {
+				continue;
+			}
+			if (part[0] == '.' && part[1] == '.' && part[2] == '\0') {
+				char *last = rindex(path, '/');
+				*last = '\0';
+			}
+			strcat(path, "/");
+			strcat(path, part);
+			part = strtok(NULL, "/");
+		}
+
+		free(_pwd);
+		puts(path);
 	}
-	puts(pwd);
+
 	return 0;
 }
-- 
2.23.0
View this thread in the archives