Hello! There is a code
char cwd[1024]; getcwd(cwd, sizeof(cwd)); When called, returns: /home/example/exampledir/ . How to replace /home/example with ~/ if this is the user's home directory.
Slightly expand:
#include <stdio.h> #include <string.h> #include <stdlib.h> char * cwd2home( char * path, size_t path_length ) { char cwd[PATH_MAX]; char * home = getenv( "HOME" ); size_t home_length = strlen( home ); getcwd( cwd, sizeof(cwd) ); if( !strncmp( cwd, home, home_length ) ) { strncpy( path, "~", path_length ); strncat( path, cwd + home_length, path_length - sizeof("~") ); } else { strncpy( path, cwd, path_length ); } path[path_length-1] = 0; return path; } int main() { char path[PATH_MAX]; printf( "%s\n", cwd2home(path, sizeof(path)) ); return 0; } Just in case, (it seems to me that it would be more careful with checks and perhaps somehow even corresponds to man getcwd ) I would write (name for the function better think up yourself):
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pwd.h> #include <unistd.h> char * get2cwd (char *buf, size_t size) { if (buf = getcwd(buf, size)) { struct passwd *p = getpwuid(getuid()); char *home; if (p && (home = p->pw_dir)) { int home_len = strlen(home), cwdlen = strlen(buf); if (home_len < cwdlen && buf[home_len] == '/' && strncmp(buf, home, home_len) == 0) { memmove(buf + 1, buf + home_len, cwdlen - home_len + 1); *buf = '~'; } } else perror(p ? "no home" : "getpwuid(getuid())"); } return buf; } Update
About get_current_dir_name() , words in manpage
PWD is set
and doubts @klopp (see comments), is it possible to use it.
As promised yesterday, I looked at the code from eglibc-2.11.1 / io / getdirname.c
/* Return a malloc'd string containing the current directory name. If the environment variable `PWD' is set, and its value is correct, that value is used. */ char * get_current_dir_name (void) { char *pwd; struct stat64 dotstat, pwdstat; pwd = getenv ("PWD"); if (pwd != NULL && stat64 (".", &dotstat) == 0 && stat64 (pwd, &pwdstat) == 0 && pwdstat.st_dev == dotstat.st_dev && pwdstat.st_ino == dotstat.st_ino) /* The PWD value is correct. Use it. */ return __strdup (pwd); return __getcwd ((char *) NULL, 0); } IMHO everything is obvious. If a "." and getenv ("PWD") is the same table of contents, then we take the extracted path by someone else (well, of course, the shell), otherwise we call the costly system call - getcwd.
(If everyone understands why expensive is great, if not, ask (look for yourself too, and better calculate the correct answer) and discuss here whether this can be accelerated.
And then, I see something quite here beginner hackers disappeared. The impression that nothing is interesting to anyone).
get_current_dir_name() and / or getenv("PWD") is not worth it, although it is simpler. - user6550getenv("PWD") ? I do not understand this at all. / In fact, this ( get2cwd() ) has the same prototype as that of getcwd() and works completely independently of the shell that sets environment variables (we are repelling ourselves from the performer’s uid, and if necessary, you can easily change to euid) . - avpget_current_dir_name() instead of getcwd() , so as not to bother with the size of the buffer. But he stopped: in fact, she takes the PWD environment. And this variable does not change if chdir() occurs inside the program. In the case of getcwd() all programmatic directory changes are tracked correctly. - user6550get_current_dir() works absolutely true regardless of PWD and the sequence of calls to chdir inside the process. - avpget_current_dir_name() to the Update response. - avpSource: https://ru.stackoverflow.com/questions/419125/
All Articles
getenv("HOME")? - user6550char? - user26699~in the first byte ofcwd[](after all the necessary comparisons-calculations), and the tail ofcwd(the part of the path inside$HOME) to shift (read man memmove ) tocwd + 1- avp