@@ 1,3 1,4 @@
+#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <stdio.h>
@@ 7,34 8,77 @@
static void
usage(void)
{
- fprintf(stderr, "usage: pwd [-L|-P]");
+ fputs("usage: pwd [-L|-P]\n", stderr);
}
int
-main(int argc, char *argv[])
+physical(void)
+{
+ size_t sz = PATH_MAX;
+ char *buf = malloc(sz);
+ if (!buf) {
+ fputs("FATAL: out of memory\n", stderr);
+ return 1;
+ }
+
+ for (;;) {
+ if (getcwd(buf, sz) != NULL) {
+ break;
+ }
+ switch (errno) {
+ case ERANGE:
+ sz *= 2;
+ buf = realloc(buf, sz);
+ if (!buf) {
+ fputs("FATAL: out of memory\n", stderr);
+ return 1;
+ }
+ continue;
+ default:
+ perror("getcwd");
+ return 1;
+ }
+ }
+
+ puts(buf);
+ return 0;
+}
+
+int
+logical(void)
{
- char *pwd = NULL;
+ char *pwd = getenv("PWD");
+ if (!pwd) {
+ return physical();
+ }
+ /* TODO: if any components of pwd are . or .., return physical() */
+ puts(pwd);
+ return 0;
+}
+int
+main(int argc, char *argv[])
+{
+ enum { PHYSICAL, LOGICAL } kind = LOGICAL;
char opt;
+ /* last option specified takes precedence */
while ((opt = getopt(argc, argv, "LP")) != -1) {
switch (opt) {
case 'P':
+ kind = PHYSICAL;
break;
case 'L':
+ kind = LOGICAL;
break;
default:
usage();
return 1;
}
}
-
- pwd = getcwd(pwd, 0);
-
- if (pwd == NULL) {
- return 1;
- }
- printf("%s\n", pwd);
-
- return 0;
+ if (kind == PHYSICAL) {
+ return physical();
+ } else {
+ return logical();
+ }
}
@@ 12,13 12,13 @@ should_work() (
)
should_handle_symlink() (
- cd "$TMPDIR/dir-f"
+ cd "$TMPDIR/dir-s"
ct="$(pwd -L)"
- [ "$ct" = "$TMPDIR/dir-f" ]
+ [ "$ct" = "$TMPDIR/dir-s" ]
)
should_resolve_symlink() (
- cd "$TMPDIR/dir-f"
+ cd "$TMPDIR/dir-s"
ct="$(pwd -P)"
[ "$ct" = "$TMPDIR/dir-f" ]
)