pwd.c (2159B)
- // utils-std: Collection of commonly available Unix tools
- // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #include <limits.h> // PATH_MAX
- #include <stdbool.h>
- #include <stdio.h> // puts, perror, printf
- #include <stdlib.h> // getenv
- #include <sys/stat.h>
- #include <unistd.h> // getcwd
- const char *argv0 = "pwd";
- enum pwd
- {
- PWD_L = 0,
- PWD_P = 1,
- };
- static void
- usage(void)
- {
- fputs("Usage: pwd [-L|-P]\n", stderr);
- }
- static bool
- is_absolute(char *path)
- {
- if(!path) return false;
- if(path[0] != '/') return false;
- size_t dotlen = 0;
- for(size_t i = 1; path[i] != '\0'; i++)
- {
- switch(path[i])
- {
- case '.':
- dotlen++;
- break;
- case '/':
- if(dotlen == 1 || dotlen == 2) return false;
- dotlen = 0;
- break;
- default:
- dotlen = 0;
- break;
- }
- }
- return true;
- }
- static bool
- is_pwd(char *path)
- {
- if(!is_absolute(path)) return false;
- struct stat path_status;
- if(stat(path, &path_status) < 0) return false;
- struct stat dot_status;
- if(stat(".", &dot_status) < 0) return false;
- if(path_status.st_dev != dot_status.st_dev) return false;
- if(path_status.st_ino != dot_status.st_ino) return false;
- return true;
- }
- int
- main(int argc, char *argv[])
- {
- enum pwd mode = PWD_L;
- int c = -1;
- while((c = getopt(argc, argv, ":LP")) != -1)
- {
- switch(c)
- {
- case 'L':
- mode = PWD_L;
- break;
- case 'P':
- mode = PWD_P;
- break;
- case ':':
- fprintf(stderr, "%s: error: Missing operand for option '-%c'\n", argv0, optopt);
- usage();
- return 1;
- case '?':
- fprintf(stderr, "%s: error: Unrecognised option '-%c'\n", argv0, optopt);
- usage();
- return 1;
- }
- }
- argc -= optind;
- argv += optind;
- if(argc != 0)
- {
- usage();
- return 1;
- }
- if(mode == PWD_L)
- {
- char *pwd = getenv("PWD");
- if(is_pwd(pwd))
- {
- if(puts(pwd) < 0)
- {
- perror("pwd: error: puts");
- return 1;
- }
- return 0;
- }
- }
- char pwd[PATH_MAX] = "";
- if(getcwd(pwd, sizeof(pwd)) == NULL)
- {
- perror("pwd: error: getcwd");
- return 1;
- }
- if(puts(pwd) < 0)
- {
- perror("pwd: error: puts");
- return 1;
- }
- return 0;
- }