bore

basic core utilities (PD)
git clone git://bvnf.space/bore.git
Log | Files | Refs | README

pwd.c (1669B)


      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
#define _XOPEN_SOURCE 700
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int
main(int argc, char **argv) {
    int c, flag_L = 1;
    long size;
    while ((c = getopt(argc, argv, "LP")) != -1) {
        switch (c) {
            case 'L':
                flag_L = 1;
                break;
            case 'P':
                flag_L = 0;
                break;
            case '?':
                fprintf(stderr, "usage: %s [-L|-P]\n", argv[0]);
                return 1;
        }
    }

    if (flag_L) {
        char *cwd = getenv("PWD");
        if (cwd == NULL)
            goto flag_P;
        else if (*cwd != '/')
            goto flag_P;
        else if (strstr(cwd, "/./") != NULL)
            goto flag_P;
        else if (strstr(cwd, "/../") != NULL)
            goto flag_P;

        /* POSIX.1-2017 does not specify what to do if $PWD is longer than PATH_MAX bytes;
         * this implementation chooses to print the pathname found from PWD in this case.
         */

        puts(cwd);
        return 0;
    }

flag_P:
    size = pathconf(".", _PC_PATH_MAX);
    if (size == -1)
        size = PATH_MAX;

    char *buf = NULL;
    for (char *tmp = NULL; tmp == NULL; size += 32) {
        char *b = realloc(buf, size);
        if (b == NULL) {
            free(buf);
            perror("pwd");
            return 1;
        }
        buf = b;

        errno = 0;
        tmp = getcwd(buf, size);
        if (tmp == NULL && errno != ERANGE) {
            perror("pwd");
            free(buf);
            return 1;
        }
    }

    puts(buf);
    free(buf);
    return 0;
}