aboutsummaryrefslogtreecommitdiff
path: root/bin/pwd/pwd.c
diff options
context:
space:
mode:
authorMike Barcroft <mike@FreeBSD.org>2002-02-04 07:26:21 +0000
committerMike Barcroft <mike@FreeBSD.org>2002-02-04 07:26:21 +0000
commit7a396ef4d59ad6aacb15cb7f9d3db869a606d366 (patch)
tree12b798ceb8b93491478766e00136da21152b2bda /bin/pwd/pwd.c
parentc9fbdd0fa451fdd7796918a1ac09244ab7dcd29b (diff)
downloadsrc-7a396ef4d59ad6aacb15cb7f9d3db869a606d366.tar.gz
src-7a396ef4d59ad6aacb15cb7f9d3db869a606d366.zip
Add -L option (SUSv3) to pwd(1). Fix a bug, where realpath(1) would
complain about paths starting with `-', by not calling getopt(3). Submitted by: Tim J. Robbins <tim@robbins.dropbear.id.au> Obtained from: NetBSD (partially) MFC after: 1 month
Notes
Notes: svn path=/head/; revision=90170
Diffstat (limited to 'bin/pwd/pwd.c')
-rw-r--r--bin/pwd/pwd.c76
1 files changed, 55 insertions, 21 deletions
diff --git a/bin/pwd/pwd.c b/bin/pwd/pwd.c
index 23df46248378..a05f04effb99 100644
--- a/bin/pwd/pwd.c
+++ b/bin/pwd/pwd.c
@@ -45,31 +45,47 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
+#include <sys/types.h>
+#include <sys/stat.h>
+
#include <err.h>
+#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
+extern char *__progname;
+
+static char *getcwd_logical(void);
void usage(void);
int
main(int argc, char *argv[])
{
+ int Lflag, Pflag;
int ch;
char *p;
char buf[PATH_MAX];
- /*
- * Flags for pwd are a bit strange. The POSIX 1003.2B/D9 document
- * has an optional -P flag for physical, which is what this program
- * will produce by default. The logical flag, -L, should fail, as
- * there's no way to display a logical path after forking.
- */
- while ((ch = getopt(argc, argv, "P")) != -1)
+ if (strcmp(__progname, "realpath") == 0) {
+ if (argc != 2)
+ usage();
+ if ((p = realpath(argv[1], buf)) == NULL)
+ err(1, "%s", argv[1]);
+ (void)printf("%s\n", p);
+ exit(0);
+ }
+
+ Lflag = Pflag = 0;
+ while ((ch = getopt(argc, argv, "LP")) != -1)
switch (ch) {
+ case 'L':
+ Lflag = 1;
+ break;
case 'P':
+ Pflag = 1;
break;
case '?':
default:
@@ -78,19 +94,13 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- if (argc == 1) {
- p = realpath(argv[0], buf);
- if (p == NULL)
- err(1, "%s", argv[0]);
- (void)printf("%s\n", p);
- } else if (argc == 0) {
- p = getcwd(NULL, (size_t)0);
- if (p == NULL)
- err(1, ".");
- (void)printf("%s\n", p);
- } else {
+ if (argc != 0 || (Lflag && Pflag))
usage();
- }
+
+ p = Lflag ? getcwd_logical() : getcwd(NULL, 0);
+ if (p == NULL)
+ err(1, ".");
+ (void)printf("%s\n", p);
exit(0);
}
@@ -99,6 +109,30 @@ void
usage(void)
{
- (void)fprintf(stderr, "usage: pwd\n");
- exit(1);
+ if (strcmp(__progname, "realpath") == 0)
+ (void)fprintf(stderr, "usage: realpath [path]\n");
+ else
+ (void)fprintf(stderr, "usage: pwd [-L | -P]\n");
+ exit(1);
+}
+
+static char *
+getcwd_logical(void)
+{
+ struct stat log, phy;
+ char *pwd;
+
+ /*
+ * Check that $PWD is an absolute logical pathname referring to
+ * the current working directory.
+ */
+ if ((pwd = getenv("PWD")) != NULL && *pwd == '/') {
+ if (stat(pwd, &log) == -1 || stat(".", &phy) == -1)
+ return (NULL);
+ if (log.st_dev == phy.st_dev && log.st_ino == phy.st_ino)
+ return (pwd);
+ }
+
+ errno = ENOENT;
+ return (NULL);
}