diff options
author | chin <none@none> | 2007-08-17 12:01:52 -0700 |
---|---|---|
committer | chin <none@none> | 2007-08-17 12:01:52 -0700 |
commit | da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968 (patch) | |
tree | 5280d3b78e289fe9551371ab6e7f15ef9944ea14 /usr/src/lib/libcmd/common/pathchk.c | |
parent | 073dbf9103ef2a2b05d8a16e2d26db04e0374b0e (diff) | |
download | illumos-joyent-da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968.tar.gz |
6437624 RFE: Add ksh93 (as /usr/bin/ksh93) and libshell.so to OS/Net
6505835 AST tools and library (libpp) required for creating l10n messages for ksh93
PSARC/2006/550 Korn Shell 93 Integration
PSARC/2006/587 /etc/ksh.kshrc for ksh93
PSARC/2007/035 ksh93 Amendments
Contributed by Roland Mainz <roland.mainz@nrubsig.org>
--HG--
rename : usr/src/lib/libcmd/common/mapfile-vers => deleted_files/usr/src/lib/libcmd/common/mapfile-vers
rename : usr/src/lib/libcmd/common/placeholder.c => deleted_files/usr/src/lib/libcmd/common/placeholder.c
Diffstat (limited to 'usr/src/lib/libcmd/common/pathchk.c')
-rw-r--r-- | usr/src/lib/libcmd/common/pathchk.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/usr/src/lib/libcmd/common/pathchk.c b/usr/src/lib/libcmd/common/pathchk.c new file mode 100644 index 0000000000..fff22f52bf --- /dev/null +++ b/usr/src/lib/libcmd/common/pathchk.c @@ -0,0 +1,248 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1992-2007 AT&T Knowledge Ventures * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Knowledge Ventures * +* * +* A copy of the License is available at * +* http://www.opensource.org/licenses/cpl1.0.txt * +* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * pathchk + * + * Written by David Korn + */ + +static const char usage[] = +"[-?\n@(#)$Id: pathchk (AT&T Research) 2006-09-19 $\n]" +USAGE_LICENSE +"[+NAME?pathchk - check pathnames for portability]" +"[+DESCRIPTION?\bpathchk\b checks each \apathname\a to see if it " + "is valid and/or portable. A \apathname\a is valid if it " + "can be used to access or create a file without causing syntax " + "errors. A file is portable, if no truncation will result on " + "any conforming POSIX.1 implementation.]" +"[+?By default \bpathchk\b checks each component of each \apathname\a " + "based on the underlying file system. A diagnostic is written " + "to standard error for each pathname that:]{" + "[+-?Is longer than \b$(getconf PATH_MAX)\b bytes.]" + "[+-?Contains any component longer than \b$(getconf NAME_MAX)\b bytes.]" + "[+-?Contains any directory component in a directory that is " + "not searchable.]" + "[+-?Contains any character in any component that is not valid in " + "its containing directory.]" + "[+-?Is empty.]" + "}" +"[p:portability?Instead of performing length checks on the underlying " + "file system, write a diagnostic for each pathname operand that:]{" + "[+-?Is longer than \b$(getconf _POSIX_PATH_MAX)\b bytes.]" + "[+-?Contains any component longer than " + "\b$(getconf _POSIX_NAME_MAX)\b bytes.]" + "[+-?Contains any character in any component that is not in the " + "portable filename character set.]" +#if 0 + "[+-?Contains any component with \b-\b as the first character.]" +#endif + "[+-?Is empty.]" + "}" +"\n" +"\npathname ...\n" +"\n" +"[+EXIT STATUS?]{" + "[+0?All \apathname\a operands passed all of the checks.]" + "[+>0?An error occurred.]" +"}" +"[+SEE ALSO?\bgetconf\b(1), \bcreat\b(2), \bpathchk\b(2)]" +; + + +#include <cmd.h> +#include <ls.h> + +#define isport(c) (((c)>='a' && (c)<='z') || ((c)>='A' && (c)<='Z') || ((c)>='0' && (c)<='9') || (strchr("._-",(c))!=0) ) + +/* + * call pathconf and handle unlimited sizes + */ +static long mypathconf(const char *path, int op) +{ + register long r; + + static const char* ops[] = { "NAME_MAX", "PATH_MAX" }; + + errno=0; + if((r=strtol(astconf(ops[op], path, NiL), NiL, 0))<0 && errno==0) + return(LONG_MAX); + return(r); +} + +/* + * returns 1 if <path> passes test + */ +static int pathchk(char* path, int mode) +{ + register char *cp=path, *cpold; + register int c; + register long r,name_max,path_max; + char buf[2]; + + if(!*path) + { + error(2,"path is empty"); + return(0); + } + if(mode) + { + name_max = _POSIX_NAME_MAX; + path_max = _POSIX_PATH_MAX; + } + else + { + char tmp[2]; + name_max = path_max = 0; + tmp[0] = (*cp=='/'? '/': '.'); + tmp[1] = 0; + if((r=mypathconf(tmp, 0)) > _POSIX_NAME_MAX) + name_max = r; + if((r=mypathconf(tmp, 1)) > _POSIX_PATH_MAX) + path_max = r; + if(*cp!='/') + { + if(name_max==0||path_max==0) + { + if(!(cpold = getcwd((char*)0, 0)) && errno == EINVAL && (cpold = newof(0, char, PATH_MAX, 0)) && !getcwd(cpold, PATH_MAX)) + { + free(cpold); + cpold = 0; + } + if(cpold) + { + cp = cpold + strlen(cpold); + while(name_max==0 || path_max==0) + { + if(cp>cpold) + while(--cp>cpold && *cp=='/'); + *++cp = 0; + if(name_max==0 && (r=mypathconf(cpold, 0)) > _POSIX_NAME_MAX) + name_max = r; + if(path_max==0 && (r=mypathconf(cpold, 1)) > _POSIX_PATH_MAX) + path_max=r; + if(--cp==cpold) + { + free(cpold); + break; + } + while(*cp!='/') + cp--; + } + cp=path; + } + } + while(*cp=='/') + cp++; + } + if(name_max==0) + name_max=_POSIX_NAME_MAX; + if(path_max==0) + path_max=_POSIX_PATH_MAX; + while(*(cpold=cp)) + { + while((c= *cp++) && c!='/'); + if((cp-cpold) > name_max) + goto err; + errno=0; + cp[-1] = 0; + r = mypathconf(path, 0); + if((cp[-1]=c)==0) + cp--; + else while(*cp=='/') + cp++; + if(r>=0) + name_max=(r<_POSIX_NAME_MAX?_POSIX_NAME_MAX:r); + else if(errno==EINVAL) + continue; +#ifdef ENAMETOOLONG + else if(errno==ENAMETOOLONG) + { + error(2,"%s: pathname too long",path); + return(0); + } +#endif /*ENAMETOOLONG*/ + else + break; + } + } + while(*(cpold=cp)) + { + if(mode && *cp == '-') + { + error(2,"%s: path component begins with '-'",path,fmtquote(buf, NiL, "'", 1, 0)); + return(0); + } + while((c= *cp++) && c!='/') + if(mode && !isport(c)) + { + buf[0] = c; + buf[1] = 0; + error(2,"%s: '%s' not in portable character set",path,fmtquote(buf, NiL, "'", 1, 0)); + return(0); + } + if((cp-cpold) > name_max) + goto err; + if(c==0) + break; + while(*cp=='/') + cp++; + } + if((cp-path) >= path_max) + { + error(2,"%s: pathname too long",path); + return(0); + } + return(1); +err: + error(2,"%s: component name %.*s too long",path,cp-cpold-1,cpold); + return(0); +} + +int +b_pathchk(int argc, char** argv, void* context) +{ + register int n, mode=0; + register char *cp; + + cmdinit(argc, argv, context, ERROR_CATALOG, 0); + while (n = optget(argv, usage)) switch (n) + { + case 'p': + mode = 1; + break; + case ':': + error(2, "%s", opt_info.arg); + break; + case '?': + error(ERROR_usage(2), "%s", opt_info.arg); + break; + } + argv += opt_info.index; + if(*argv==0 || error_info.errors) + error(ERROR_usage(2),"%s", optusage((char*)0)); + while(cp = *argv++) + { + if(!pathchk(cp,mode)) + error_info.errors=1; + } + return(error_info.errors); +} |