On Fri, 20 Oct 2023, RVP wrote:

/*
         printf("%d %d %s ", uid, pid, execname);
         system("pr_realpath -p %d %s", pid, copyinstr(arg0));
         printf("\n");
*/


I forgot to provide you with pr_realpath (in case you wanted the full path):

```
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* Functions */
static int do_opts(int argc, char* argv[]);
static void usage(FILE* fp);
static void error(char* fmt, ...);

/* Globals */
static struct options {
        pid_t pid;
} opts;
static char* prog;

int
main(int argc, char* argv[])
{
        char cwd[PATH_MAX];
        char buf[PATH_MAX];
        char* fname, *p;
        int idx, len, rc;

        prog = argv[0];
        rc = EXIT_FAILURE;

        idx = do_opts(argc, argv);
        argc -= idx;
        argv += idx;

        if (argc != 1) {
                usage(stderr);
                exit(rc);
        }
        fname = argv[0];

        if (opts.pid == 0)
                opts.pid = getpid();

        snprintf(buf, sizeof buf, "/proc/%d/cwd", opts.pid);
        if ((len = readlink(buf, cwd, sizeof(cwd)-1)) == -1) {
                error("%s: %s: readlink failed.", prog, buf);
                exit(rc);
        }
        cwd[len] = '\0';
        if (*fname != '/')      /* relative path */
                snprintf(buf, sizeof buf, "%s/%s", cwd, fname);
        else
                strcpy(buf, fname);
        if ((p = realpath(buf, NULL)) == NULL) {
                error("%s: %s: realpath failed.", prog, buf);
                exit(rc);
        }
        printf("%s\n", p);
        free(p);
        rc = EXIT_SUCCESS;
        exit(rc);
}

/**
 * Process program options.
 */
static int
do_opts(int argc, char* argv[])
{
        int opt;

        /* defaults */
        opts.pid = 0;           /* use own PID */

        while ((opt = getopt(argc, argv, "hp:")) != -1) {
                switch (opt) {
                case 'h':
                        usage(stdout);
                        exit(EXIT_SUCCESS);
                        break;
                case 'p':
                        opts.pid = atoi(optarg);
                        if (opts.pid <= 0) {
                                error("%s: PID must be > 0", prog);
                                exit(EXIT_FAILURE);
                        }
                        break;
                default:
                        usage(stderr);
                        exit(EXIT_FAILURE);
                        break;
                }
        }

        return optind;
}

/**
 * Print usage information.
 */
static void
usage(FILE* fp)
{
        fprintf(fp, "Usage: %s [-h] [-p PID] FILENAME\n", prog);
        fprintf(fp, "%s: Canonicalize FILENAME belonging to PID using 
realpath(3)\n", prog);
        fprintf(fp, "\n");
        fprintf(fp, "  -h        This message.\n");
        fprintf(fp, "  -p PID    Owner of FILENAME (default: self)\n");
}

/**
 * Print an error message.
 */
static void
error(char* fmt, ...)
{
        va_list ap;
        int e = errno;

        fflush(stdout);
        va_start(ap, fmt);
        vfprintf(stderr, fmt, ap);
        va_end(ap);
        if (e != 0) {
                fprintf(stderr, " (%s)", strerror(e));
                errno = 0;
        }
        fprintf(stderr, "\n");
        fflush(stderr);
}
```

You must have /proc mounted for this to work. I should make it use kinfo, but
this too was written a couple of years ago--when I was a NetBSD newbie :)

-RVP

Reply via email to