Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

245 lines
5.7 KiB
C

static char sccsid[] = "@(#)76 1.7 src/bos/usr/bin/pathchk/pathchk.c, cmdposix, bos41B, 9504A 12/19/94 12:25:42";
/*
* COMPONENT_NAME: (CMDPOSIX) commands required by Posix 1003.2
*
* FUNCTIONS: pathchk
*
* ORIGINS: 27
*
* This module contains IBM CONFIDENTIAL code. -- (IBM
* Confidential Restricted when combined with the aggregated
* modules for this product)
* SOURCE MATERIALS
* (C) COPYRIGHT International Business Machines Corp. 1990,1994
* All Rights Reserved
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*
*/
#include <stdlib.h>
#include <locale.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/access.h>
#include <nl_types.h>
#include "pathchk_msg.h"
static nl_catd catd;
#define MSGSTR(Num, Str) catgets(catd, MS_PATHCHK, Num, Str)
extern char *optarg;
extern int optind;
static int exit_status = 0;
main(argc, argv)
int argc;
char **argv;
{
int j = 1;
char *pathname;
register c;
int pflag = 0;
setlocale(LC_ALL, "");
catd = catopen(MF_PATHCHK, NL_CAT_LOCALE);
while ( (c = getopt(argc, argv, "p") ) != EOF) {
switch(c) {
case 'p':
pflag++;
break;
case '?':
default:
fprintf(stderr, MSGSTR(USAGE, "usage pathchk [-p] pathname\n"));
exit_status = 1;
}
}
if (pflag) {
while (optind < argc) {
check_posix(argv[optind]);
optind++;
}
}
else {
while ( j < argc )
check_path(argv[j++]);
}
exit(exit_status);
}
/*
* Function: check_posix(pathname)
*
* Description: checks pathname length and component length
* against limits as defined by Posix. It also checks for
* illegal characters in the portable filename character set,
* defined by Posix.
*/
static check_posix(pathname)
char *pathname;
{
char *ptr, *ptr2, *s3;
static char buf[PATH_MAX];
int mbcnt;
wchar_t wc_ptr;
char mbchar[10];
if (strlen(pathname) > _POSIX_PATH_MAX) {
fprintf(stderr, MSGSTR(POSIX_PATH, "pathname %s exceeds _POSIX_PATH_MAX %d\n"), pathname, _POSIX_PATH_MAX);
exit_status++;
}
strcpy(buf, pathname);
ptr = buf;
while (*ptr != '\0') {
if (*ptr == '/') ptr++;
if ( (ptr2 = strchr(ptr, '/')) != NULL) {
*ptr2 = '\0';
if (strlen(ptr) > _POSIX_NAME_MAX) {
fprintf(stderr, MSGSTR(POSIX_NAME, "name %s exceeds _POSIX_NAME_MAX %d\n"), ptr, _POSIX_NAME_MAX);
exit_status++;
}
}
else {
if (strlen(ptr) > _POSIX_NAME_MAX) {
fprintf(stderr, MSGSTR(POSIX_NAME, "name %s exceeds _POSIX_NAME_MAX %d\n"), ptr, _POSIX_NAME_MAX);
exit_status++;
}
break;
}
ptr = ptr2;
ptr++;
}
s3 = pathname;
for (; *s3 != '\0'; s3++) {
if ( (( (*s3 < 0x61 ) && (*s3 != 0x5f)) || ( *s3 > 0x7a)) &&
(( *s3 < 0x41) || (*s3 > 0x5a)) &&
(( *s3 < 0x30) || (*s3 > 0x39)) &&
(( *s3 < 0x2d) || (*s3 > 0x2f)) ) {
if ( (mbcnt = mblen(s3, MB_CUR_MAX)) > 0) {
mbtowc(&wc_ptr, s3, MB_CUR_MAX);
if (iswprint(wc_ptr)) {
strncpy(mbchar, s3, mbcnt);
mbchar[mbcnt]='\0';
fprintf(stderr, "%s ", mbchar);
s3 += mbcnt - 1;
}
else
fprintf(stderr, "0x%2.2x ", *s3);
}
else
fprintf(stderr, "0x%2.2x ", *s3);
fprintf(stderr, MSGSTR(CHAR_SET, "is not in portable filename character set for %s\n"), pathname);
exit_status++;
}
}
return;
}
/*
* check_path is the default path of the pathchk function, this
* checks for pathnames not to exceed the filesystems maximum
* and for components not to exceed filesystems maximum. It also
* checks for search permission on that directory/file.
*/
static check_path(pathname)
char *pathname;
{
char *ptr, *ptr2, *s3;
char file_access[PATH_MAX];
long namemax;
static char buf[PATH_MAX];
static char tbuf[PATH_MAX];
int createable, absolute;
if (strlen(pathname) > PATH_MAX) {
fprintf( stderr, MSGSTR(PATHN_MAX, "pathname %s exceeds PATH_MAX %d\n"), pathname, PATH_MAX);
exit_status++;
}
/*
* NAME_MAX is not defined in limits.h
* must call pathconf to gets value, since
* pathconf returns -1 if file doesn't exist
* we need to keep going until we get a valid number
* for namemax
*/
strcpy(buf, pathname);
absolute = (*pathname == '/');
/* If the pathname is a relative path name then we must */
/* append the current directory so that pathconf will */
/* succeed. */
if (!absolute) {
if (!getcwd(tbuf,PATH_MAX))
perror("getcwd");
strcat(tbuf,"/");
strcat(tbuf,buf);
strcpy(buf,tbuf);
}
while ( (namemax = pathconf(buf, _PC_NAME_MAX) )== -1 ) {
if ( (s3 = strrchr(buf, '/')) == NULL )
break;
if (s3 == buf)
buf[1] = '\0';
else
*s3 = '\0';
}
*file_access = '\0';
createable = (access(absolute ? "/" : ".", W_ACC|X_ACC) == 0);
strcpy(buf, pathname);
ptr = buf;
while (*ptr != '\0') {
if (*ptr == '/') ptr++;
if ( ( ptr2 = strchr(ptr, '/')) != NULL)
*ptr2 = '\0';
if (strlen(ptr) > namemax) {
fprintf(stderr, MSGSTR(NAME_MAX,
"name %s exceeds NAME_MAX %d\n"), ptr, namemax);
exit_status++;
}
/* check for search permission,
* note the file does not have to
* exist, we can ignore ENOENT
*/
if (*file_access != '\0' || absolute)
strcat(file_access, "/");
strcat(file_access, ptr);
if (access(file_access, E_ACC) == -1) {
if (errno == ENOENT && createable)
/* ENOENT errno is ok */
;
else {
fprintf(stderr, "pathchk: %s ", file_access);
perror("access");
exit_status++;
}
} else {
createable = (access(file_access, W_ACC|X_ACC) == 0);
}
if (ptr2 == NULL)
break;
ptr = ptr2;
ptr++;
}
return;
}