/* getpath.c Copyright (c) Kapteyn Laboratorium Groningen 1992 All Rights Reserved. #> getpath.dc2 Function: GETPATH Purpose: Gets full pathname of a file. It tries to resolve links. Category: FILES File: getpath.c Author: K.G. Begeman Use: INTEGER GETPATH( PATH ) Input/Output CHARACTER*(*) GETPATH 0: success. -1: cannot get entry from password file. -2: full pathname too long for PATH. PATH On input, the filename for which the full path is wanted, on output, the full pathname. Warnings: Only works on UNIX systems. Updates: Jun 10, 1992: KGB Document created. #< Fortran to C interface: @ integer function getpath( character ) */ #include "stddef.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #if defined(__GNUC__) && defined(_CONVEX_SOURCE) #define fgetpwent(x) fgetpwent(FILE *) #endif #define getpwnam GETPWNAM #define getpwuid GETPWUID #include #undef getpwnam #undef getpwuid #include "gipsyc.h" #include "nelc.h" #if defined(__sysv__) extern char *getcwd( char *path, int size ); #else extern char *getwd( char *path ); #define getcwd(path,size) getwd(path) #endif fint getpath_c( fchar path ) { char file1[FILENAME_MAX+1]; /* buffer for input path */ char file2[FILENAME_MAX+1]; /* buffer for output path */ char file3[FILENAME_MAX+1]; /* path with links resolved */ char *o, *p; /* pointers */ int l = nelc_c( path ); /* length of path */ int readlink( ); /* reads links */ strncpy( file1, path.a, l ); /* copy input path */ file1[l] = '\0'; /* terminate with zero */ /* * remove // */ while ((p = strstr( file1, "//")) != NULL) { if (p[2]) { strcpy( p, &p[1] ); } else { p[1] = '\0'; } } if (file1[0] == '~') { /* a tilde operation */ for (p = file2, o = &file1[1]; *o && *o != '/'; *p++ = *o++); *p = '\0'; /* terminate */ if (file2[0] == '\0') { /* no username attached */ char *home = getenv( "home" ); /* translate 'home' */ if (home != NULL) { /* translation ok */ strcpy( file2, home ); /* path = home */ } else { /* get if from password file */ int getuid( ); /* .. by uid */ struct passwd *pw; /* passwd struct */ struct passwd *getpwuid( ); /* .. */ pw = getpwuid( getuid( ) ); /* get entry */ if (pw == NULL) return( -1 ); /* error */ strcpy( file2, pw->pw_dir ); /* path = home */ } } else { /* username found */ struct passwd *pw; /* passwd struct */ struct passwd *getpwnam( ); /* .. */ pw = getpwnam( file2 ); /* get entry */ if (pw == NULL) return( -1 ); /* error */ strcpy( file2, pw->pw_dir ); /* path from password file */ } strcat( file2, o ); /* append rest */ } else if (file1[0] != '/') { /* relative path */ getcwd( file2, FILENAME_MAX + 1 ); /* get current directory */ if (file1[0] == '.' && file1[1] == '/') { /* replace */ strcat( file2, &file1[1] ); /* append rest */ } else { /* put cwd in front */ strcat( file2, "/" ); /* with a slash */ strcat( file2, file1 ); /* append rest */ } } else { /* starts at root */ strcpy( file2, file1 ); /* copy */ } /* * Now we need to check for /.. */ while ((p = strstr( file2, "/.." )) != NULL) { for ( o = p; --o > file2 && *o != '/';); if (p[3]) { strcpy( o, &p[3] ); } else { o[0] = '\0'; } } /* * Next try to find links, and resolve them. */ p = strtok( file2, "/" ); file3[0] = '\0'; while (p != NULL) { strcat( file3, "/" ); strcat( file3, p ); l = readlink( file3, file1, FILENAME_MAX ); if (l != -1) { file1[l] = '\0'; strcpy( file3, file1 ); } p = strtok( NULL, "/" ); } if (!file3[0]) strcpy( file3, "/" ); /* add a slash */ l = strlen( file3 ); /* length of output path */ if (l > path.l) { /* does not fit in */ return( -2 ); /* error */ } else { /* copy */ int i; for (i = 0; i < l; i++) { path.a[i] = file3[i]; } while (i < path.l) path.a[i++] = ' '; /* append blanks */ return( 0 ); } } #if defined(TESTBED) #include "cmain.h" int cmain( int argc, char *argv[] ) { char buf[FILENAME_MAX+1]; fchar path; int argi; for (argi = 1; argi < argc; argi++) { fint r; int i; strcpy( buf, argv[argi] ); for (i = strlen( buf ); i < (sizeof(buf) - 1); buf[i++] = ' '); path.a = buf; path.l = FILENAME_MAX; if (!(r = getpath_c( path ))) { printf( "%35s %35.*s\n", argv[argi], nelc_c( path ), path.a ); } else { printf( "getpath error = \n", r ); } } return( 0 ); } #endif