From 2b69c40e8060934c115922c012737bd471956f09 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Tue, 5 Oct 1999 22:58:32 +0000 Subject: [PATCH] More stuff works. -Erik --- Makefile | 4 +- applets/busybox.c | 4 +- busybox.c | 4 +- busybox.def.h | 11 +- cat.c | 8 +- chgrp.c | 89 ------ chown.c | 156 +++++++---- chroot.c | 73 +++-- clear.c | 26 +- console-tools/clear.c | 26 +- coreutils/cat.c | 8 +- coreutils/chgrp.c | 89 ------ coreutils/chown.c | 156 +++++++---- coreutils/chroot.c | 73 +++-- internal.h | 109 ++++---- utility.c | 744 ++++---------------------------------------------- utility.h | 73 ----- 17 files changed, 488 insertions(+), 1165 deletions(-) delete mode 100644 chgrp.c delete mode 100644 coreutils/chgrp.c delete mode 100644 utility.h diff --git a/Makefile b/Makefile index bef25a3..62c4ac6 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ CFLAGS=-Wall -O2 -fomit-frame-pointer -fno-builtin -D_GNU_SOURCE # For debugging only #CFLAGS=-Wall -g -D_GNU_SOURCE LIBRARIES=-lc -OBJECTS=$(shell ./busybox.obj) utility.o +OBJECTS=$(shell ./busybox.sh) utility.o CFLAGS+= -DBB_VER='"$(VERSION)"' CFLAGS+= -DBB_BT='"$(BUILDTIME)"' @@ -36,3 +36,5 @@ distclean: clean - rm -f busybox force: + +$(OBJECTS): busybox.def.h Makefile diff --git a/applets/busybox.c b/applets/busybox.c index b7b2b60..08ba88d 100644 --- a/applets/busybox.c +++ b/applets/busybox.c @@ -16,14 +16,12 @@ static const struct Applet applets[] = { #ifdef BB_CAT //bin {"cat", cat_more_main}, #endif -#ifdef BB_CHGRP //bin - {"chgrp", chgrp_main}, -#endif #ifdef BB_CHMOD //bin {"chmod", chmod_main}, #endif #ifdef BB_CHOWN //bin {"chown", chown_main}, + {"chgrp", chown_main}, #endif #ifdef BB_CHROOT //sbin {"chroot", chroot_main}, diff --git a/busybox.c b/busybox.c index b7b2b60..08ba88d 100644 --- a/busybox.c +++ b/busybox.c @@ -16,14 +16,12 @@ static const struct Applet applets[] = { #ifdef BB_CAT //bin {"cat", cat_more_main}, #endif -#ifdef BB_CHGRP //bin - {"chgrp", chgrp_main}, -#endif #ifdef BB_CHMOD //bin {"chmod", chmod_main}, #endif #ifdef BB_CHOWN //bin {"chown", chown_main}, + {"chgrp", chown_main}, #endif #ifdef BB_CHROOT //sbin {"chroot", chroot_main}, diff --git a/busybox.def.h b/busybox.def.h index ad6480a..7d49ed0 100644 --- a/busybox.def.h +++ b/busybox.def.h @@ -6,11 +6,10 @@ //#define BB_BLOCK_DEVICE #define BB_BUSYBOX #define BB_CAT -#define BB_CHGRP //#define BB_CHMOD -//#define BB_CHOWN -//#define BB_CHROOT -//#define BB_CLEAR +#define BB_CHOWN +#define BB_CHROOT +#define BB_CLEAR //#define BB_CP //#define BB_DATE //#define BB_DD @@ -19,7 +18,7 @@ //#define BB_DMESG //#define BB_DUTMP //#define BB_DYADIC -//#define BB_FALSE +#define BB_FALSE //#define BB_FDFLUSH //#define BB_FIND //#define BB_FINDMOUNT @@ -56,7 +55,7 @@ //#define BB_SYNC //#define BB_TAR //#define BB_TOUCH -//#define BB_TRUE +#define BB_TRUE //#define BB_UMOUNT //#define BB_UPDATE //#define BB_UTILITY diff --git a/cat.c b/cat.c index 12faf55..0f2460e 100644 --- a/cat.c +++ b/cat.c @@ -31,7 +31,7 @@ extern int cat_more_main(int argc, char **argv) if (argc < 2) { fprintf(stderr, "Usage: %s %s", *argv, cat_usage); - return 1; + return(FALSE); } argc--; argv++; @@ -39,8 +39,8 @@ extern int cat_more_main(int argc, char **argv) while (argc-- > 0) { file = fopen(*argv, "r"); if (file == NULL) { - name_and_error(*argv); - return 1; + perror(*argv); + return(FALSE); } while ((c = getc(file)) != EOF) putc(c, stdout); @@ -50,5 +50,5 @@ extern int cat_more_main(int argc, char **argv) argc--; argv++; } - return 0; + return(TRUE); } diff --git a/chgrp.c b/chgrp.c deleted file mode 100644 index 038c665..0000000 --- a/chgrp.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Mini chgrp implementation for busybox - * - * Copyright (C) 1998 by Erik Andersen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "internal.h" -#include -#include - -const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n" - "Change the group membership of each FILE to GROUP.\n" - "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; - -int chgrp_main(int argc, char **argv) -{ - const char *cp; - int gid; - struct group *grp; - struct stat statBuf; - - if (argc < 2) { - fprintf(stderr, "Usage: %s %s", *argv, chgrp_usage); - return 1; - } - argc--; - argv++; - - cp = argv[1]; - if (isDecimal(*cp)) { - gid = 0; - while (isDecimal(*cp)) - gid = gid * 10 + (*cp++ - '0'); - if (*cp) { - fprintf(stderr, "Bad gid value\n"); - return -1; - } - } else { - grp = getgrnam(cp); - if (grp == NULL) { - fprintf(stderr, "Unknown group name\n"); - return -1; - } - gid = grp->gr_gid; - } - argc--; - argv++; - while (argc-- > 1) { - argv++; - if ((stat(*argv, &statBuf) < 0) || - (chown(*argv, statBuf.st_uid, gid) < 0)) { - perror(*argv); - } - } - return 1; -} - - - - - - - - - -#if 0 -int -recursive(const char *fileName, BOOL followLinks, const char *pattern, - int (*fileAction) (const char *fileName, - const struct stat * statbuf), - int (*dirAction) (const char *fileName, - const struct stat * statbuf)) - -#endif diff --git a/chown.c b/chown.c index a611f92..fc0c242 100644 --- a/chown.c +++ b/chown.c @@ -1,63 +1,125 @@ -#include "internal.h" -#include -#include -#include +/* + * Mini chown/chgrp implementation for busybox + * + * Copyright (C) 1998 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + #include +#include +#include +#include "internal.h" -const char chown_usage[] = "chown [-R] user-name file [file ...]\n" -"\n\tThe group list is kept in the file /etc/groups.\n\n" -"\t-R:\tRecursively change the mode of all files and directories\n" -"\t\tunder the argument directory."; -int -parse_user_name(const char * s, struct FileInfo * i) -{ - struct passwd * p; - char * dot = strchr(s, '.'); +static int uid=-1; +static int gid=0; +static int chownApp; +static char* invocationName=NULL; - if (! dot ) - dot = strchr(s, ':'); - if ( dot ) - *dot = '\0'; +const char chgrp_usage[] = "[OPTION]... GROUP FILE...\n" + "Change the group membership of each FILE to GROUP.\n" + "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; +const char chown_usage[] = "[OPTION]... OWNER[.[GROUP] FILE...\n" + "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n" + "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; - if ( (p = getpwnam(s)) == 0 ) { - fprintf(stderr, "%s: no such user.\n", s); - return 1; - } - i->userID = p->pw_uid; - - if ( dot ) { - struct group * g = getgrnam(++dot); - if ( g == 0 ) { - fprintf(stderr, "%s: no such group.\n", dot); - return 1; - } - i->groupID = g->gr_gid; - i->changeGroupID = 1; - } - return 0; + + +static int fileAction(const char *fileName) +{ + struct stat statBuf; + if ((stat(fileName, &statBuf) < 0) || + (chown(fileName, + ((chownApp==TRUE)? uid: statBuf.st_uid), + gid) < 0)) { + perror(fileName); + return( TRUE); + } + return( FALSE); } -extern int -chown_main(struct FileInfo * i, int argc, char * * argv) +int chown_main(int argc, char **argv) { - int status; + struct group *grp; + struct passwd *pwd; + int recursiveFlag=FALSE; + char *groupName; - while ( argc >= 3 && strcmp("-R", argv[1]) == 0 ) { - i->recursive = 1; - argc--; - argv++; - } - if ( (status = parse_user_name(argv[1], i)) != 0 ) - return status; + chownApp = (strcmp(*argv, "chown")==0)? TRUE : FALSE; - argv++; + if (argc < 2) { + fprintf(stderr, "Usage: %s %s", *argv, + (chownApp==TRUE)? chown_usage : chgrp_usage); + return( FALSE); + } + invocationName=*argv; + argc--; + argv++; + + /* Parse options */ + while (**argv == '-') { + while (*++(*argv)) switch (**argv) { + case 'R': + recursiveFlag = TRUE; + break; + default: + fprintf(stderr, "Unknown option: %c\n", **argv); + return( FALSE); + } argc--; + argv++; + } + + /* Find the selected group */ + groupName = strchr(*argv, '.'); + if ( chownApp==TRUE && groupName ) + *groupName++ = '\0'; + else + groupName = *argv; + grp = getgrnam(groupName); + if (grp == NULL) { + fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName); + return( FALSE); + } + gid = grp->gr_gid; - i->changeUserID = 1; - i->complainInPostProcess = 1; + /* Find the selected user (if appropriate) */ + if (chownApp==TRUE) { + pwd = getpwnam(*argv); + if (pwd == NULL) { + fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv); + return( FALSE); + } + uid = pwd->pw_uid; + } - return monadic_main(i, argc, argv); + /* Ok, ready to do the deed now */ + if (argc <= 1) { + fprintf(stderr, "%s: too few arguments", invocationName); + return( FALSE); + } + while (argc-- > 1) { + argv++; + if (recursiveFlag==TRUE) + recursiveAction( *argv, TRUE, fileAction, fileAction); + else + fileAction( *argv); + } + return(TRUE); } diff --git a/chroot.c b/chroot.c index ca0bfcf..d395494 100644 --- a/chroot.c +++ b/chroot.c @@ -1,32 +1,65 @@ +/* + * Mini chroot implementation for busybox + * + * Copyright (C) 1998 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + #include "internal.h" #include #include -const char chroot_usage[] = "chroot directory [command]\n" - "Run a command with special root directory.\n"; +static const char chroot_usage[] = "NEWROOT [COMMAND...]\n" +"Run COMMAND with root directory set to NEWROOT.\n"; + + -extern int -chroot_main (struct FileInfo *i, int argc, char **argv) +int chroot_main(int argc, char **argv) { - char *prog; + if (argc < 2) { + fprintf(stderr, "Usage: %s %s", *argv, chroot_usage); + return( FALSE); + } + argc--; + argv++; - if (chroot (argv[1])) - { - name_and_error ("cannot chroot to that directory"); - return 1; + fprintf(stderr, "new root: %s\n", *argv); + + if (chroot (*argv) || (chdir ("/"))) { + perror("cannot chroot"); + return( FALSE); } - if (argc > 2) - { - execvp (argv[2], argv + 2); + + argc--; + argv++; + if (argc >= 1) { + fprintf(stderr, "command: %s\n", *argv); + execvp (*argv, argv); } - else - { - prog = getenv ("SHELL"); - if (!prog) - prog = "/bin/sh"; - execlp (prog, prog, NULL); + else { + char *prog; + prog = getenv ("SHELL"); + if (!prog) + prog = "/bin/sh"; + fprintf(stderr, "no command. running: %s\n", prog); + execlp (prog, prog, NULL); } - name_and_error ("cannot exec"); - return 1; + perror("cannot exec"); + return(FALSE); } + diff --git a/clear.c b/clear.c index 21a890c..c0c94d0 100644 --- a/clear.c +++ b/clear.c @@ -1,12 +1,30 @@ +/* + * Mini clear implementation for busybox + * + * Copyright (C) 1998 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + #include "internal.h" #include -const char clear_usage[] = "clear\n" -"\n" -"\tClears the screen.\n"; extern int -clear_main(struct FileInfo * i, int argc, char * * argv) +clear_main(int argc, char** argv) { printf("\033[H\033[J"); return 0; diff --git a/console-tools/clear.c b/console-tools/clear.c index 21a890c..c0c94d0 100644 --- a/console-tools/clear.c +++ b/console-tools/clear.c @@ -1,12 +1,30 @@ +/* + * Mini clear implementation for busybox + * + * Copyright (C) 1998 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + #include "internal.h" #include -const char clear_usage[] = "clear\n" -"\n" -"\tClears the screen.\n"; extern int -clear_main(struct FileInfo * i, int argc, char * * argv) +clear_main(int argc, char** argv) { printf("\033[H\033[J"); return 0; diff --git a/coreutils/cat.c b/coreutils/cat.c index 12faf55..0f2460e 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c @@ -31,7 +31,7 @@ extern int cat_more_main(int argc, char **argv) if (argc < 2) { fprintf(stderr, "Usage: %s %s", *argv, cat_usage); - return 1; + return(FALSE); } argc--; argv++; @@ -39,8 +39,8 @@ extern int cat_more_main(int argc, char **argv) while (argc-- > 0) { file = fopen(*argv, "r"); if (file == NULL) { - name_and_error(*argv); - return 1; + perror(*argv); + return(FALSE); } while ((c = getc(file)) != EOF) putc(c, stdout); @@ -50,5 +50,5 @@ extern int cat_more_main(int argc, char **argv) argc--; argv++; } - return 0; + return(TRUE); } diff --git a/coreutils/chgrp.c b/coreutils/chgrp.c deleted file mode 100644 index 038c665..0000000 --- a/coreutils/chgrp.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Mini chgrp implementation for busybox - * - * Copyright (C) 1998 by Erik Andersen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "internal.h" -#include -#include - -const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n" - "Change the group membership of each FILE to GROUP.\n" - "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; - -int chgrp_main(int argc, char **argv) -{ - const char *cp; - int gid; - struct group *grp; - struct stat statBuf; - - if (argc < 2) { - fprintf(stderr, "Usage: %s %s", *argv, chgrp_usage); - return 1; - } - argc--; - argv++; - - cp = argv[1]; - if (isDecimal(*cp)) { - gid = 0; - while (isDecimal(*cp)) - gid = gid * 10 + (*cp++ - '0'); - if (*cp) { - fprintf(stderr, "Bad gid value\n"); - return -1; - } - } else { - grp = getgrnam(cp); - if (grp == NULL) { - fprintf(stderr, "Unknown group name\n"); - return -1; - } - gid = grp->gr_gid; - } - argc--; - argv++; - while (argc-- > 1) { - argv++; - if ((stat(*argv, &statBuf) < 0) || - (chown(*argv, statBuf.st_uid, gid) < 0)) { - perror(*argv); - } - } - return 1; -} - - - - - - - - - -#if 0 -int -recursive(const char *fileName, BOOL followLinks, const char *pattern, - int (*fileAction) (const char *fileName, - const struct stat * statbuf), - int (*dirAction) (const char *fileName, - const struct stat * statbuf)) - -#endif diff --git a/coreutils/chown.c b/coreutils/chown.c index a611f92..fc0c242 100644 --- a/coreutils/chown.c +++ b/coreutils/chown.c @@ -1,63 +1,125 @@ -#include "internal.h" -#include -#include -#include +/* + * Mini chown/chgrp implementation for busybox + * + * Copyright (C) 1998 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + #include +#include +#include +#include "internal.h" -const char chown_usage[] = "chown [-R] user-name file [file ...]\n" -"\n\tThe group list is kept in the file /etc/groups.\n\n" -"\t-R:\tRecursively change the mode of all files and directories\n" -"\t\tunder the argument directory."; -int -parse_user_name(const char * s, struct FileInfo * i) -{ - struct passwd * p; - char * dot = strchr(s, '.'); +static int uid=-1; +static int gid=0; +static int chownApp; +static char* invocationName=NULL; - if (! dot ) - dot = strchr(s, ':'); - if ( dot ) - *dot = '\0'; +const char chgrp_usage[] = "[OPTION]... GROUP FILE...\n" + "Change the group membership of each FILE to GROUP.\n" + "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; +const char chown_usage[] = "[OPTION]... OWNER[.[GROUP] FILE...\n" + "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n" + "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; - if ( (p = getpwnam(s)) == 0 ) { - fprintf(stderr, "%s: no such user.\n", s); - return 1; - } - i->userID = p->pw_uid; - - if ( dot ) { - struct group * g = getgrnam(++dot); - if ( g == 0 ) { - fprintf(stderr, "%s: no such group.\n", dot); - return 1; - } - i->groupID = g->gr_gid; - i->changeGroupID = 1; - } - return 0; + + +static int fileAction(const char *fileName) +{ + struct stat statBuf; + if ((stat(fileName, &statBuf) < 0) || + (chown(fileName, + ((chownApp==TRUE)? uid: statBuf.st_uid), + gid) < 0)) { + perror(fileName); + return( TRUE); + } + return( FALSE); } -extern int -chown_main(struct FileInfo * i, int argc, char * * argv) +int chown_main(int argc, char **argv) { - int status; + struct group *grp; + struct passwd *pwd; + int recursiveFlag=FALSE; + char *groupName; - while ( argc >= 3 && strcmp("-R", argv[1]) == 0 ) { - i->recursive = 1; - argc--; - argv++; - } - if ( (status = parse_user_name(argv[1], i)) != 0 ) - return status; + chownApp = (strcmp(*argv, "chown")==0)? TRUE : FALSE; - argv++; + if (argc < 2) { + fprintf(stderr, "Usage: %s %s", *argv, + (chownApp==TRUE)? chown_usage : chgrp_usage); + return( FALSE); + } + invocationName=*argv; + argc--; + argv++; + + /* Parse options */ + while (**argv == '-') { + while (*++(*argv)) switch (**argv) { + case 'R': + recursiveFlag = TRUE; + break; + default: + fprintf(stderr, "Unknown option: %c\n", **argv); + return( FALSE); + } argc--; + argv++; + } + + /* Find the selected group */ + groupName = strchr(*argv, '.'); + if ( chownApp==TRUE && groupName ) + *groupName++ = '\0'; + else + groupName = *argv; + grp = getgrnam(groupName); + if (grp == NULL) { + fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName); + return( FALSE); + } + gid = grp->gr_gid; - i->changeUserID = 1; - i->complainInPostProcess = 1; + /* Find the selected user (if appropriate) */ + if (chownApp==TRUE) { + pwd = getpwnam(*argv); + if (pwd == NULL) { + fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv); + return( FALSE); + } + uid = pwd->pw_uid; + } - return monadic_main(i, argc, argv); + /* Ok, ready to do the deed now */ + if (argc <= 1) { + fprintf(stderr, "%s: too few arguments", invocationName); + return( FALSE); + } + while (argc-- > 1) { + argv++; + if (recursiveFlag==TRUE) + recursiveAction( *argv, TRUE, fileAction, fileAction); + else + fileAction( *argv); + } + return(TRUE); } diff --git a/coreutils/chroot.c b/coreutils/chroot.c index ca0bfcf..d395494 100644 --- a/coreutils/chroot.c +++ b/coreutils/chroot.c @@ -1,32 +1,65 @@ +/* + * Mini chroot implementation for busybox + * + * Copyright (C) 1998 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + #include "internal.h" #include #include -const char chroot_usage[] = "chroot directory [command]\n" - "Run a command with special root directory.\n"; +static const char chroot_usage[] = "NEWROOT [COMMAND...]\n" +"Run COMMAND with root directory set to NEWROOT.\n"; + + -extern int -chroot_main (struct FileInfo *i, int argc, char **argv) +int chroot_main(int argc, char **argv) { - char *prog; + if (argc < 2) { + fprintf(stderr, "Usage: %s %s", *argv, chroot_usage); + return( FALSE); + } + argc--; + argv++; - if (chroot (argv[1])) - { - name_and_error ("cannot chroot to that directory"); - return 1; + fprintf(stderr, "new root: %s\n", *argv); + + if (chroot (*argv) || (chdir ("/"))) { + perror("cannot chroot"); + return( FALSE); } - if (argc > 2) - { - execvp (argv[2], argv + 2); + + argc--; + argv++; + if (argc >= 1) { + fprintf(stderr, "command: %s\n", *argv); + execvp (*argv, argv); } - else - { - prog = getenv ("SHELL"); - if (!prog) - prog = "/bin/sh"; - execlp (prog, prog, NULL); + else { + char *prog; + prog = getenv ("SHELL"); + if (!prog) + prog = "/bin/sh"; + fprintf(stderr, "no command. running: %s\n", prog); + execlp (prog, prog, NULL); } - name_and_error ("cannot exec"); - return 1; + perror("cannot exec"); + return(FALSE); } + diff --git a/internal.h b/internal.h index e658d3b..75e5503 100644 --- a/internal.h +++ b/internal.h @@ -1,3 +1,26 @@ +/* + * Busybox main header file + * + * Copyright (C) 1998 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ #ifndef _INTERNAL_H_ #define _INTERNAL_H_ @@ -13,8 +36,8 @@ typedef int BOOL; #define STDIN 0 #define STDOUT 1 -#define FALSE ((BOOL) 0) -#define TRUE ((BOOL) 1) +#define FALSE ((BOOL) 1) +#define TRUE ((BOOL) 0) #define PATH_LEN 1024 #define BUF_SIZE 8192 @@ -129,60 +152,36 @@ parse_mode( extern int parse_user_name(const char* string, struct FileInfo * i); -extern const char block_device_usage[]; -extern const char chgrp_usage[]; -extern const char chmod_usage[]; -extern const char chown_usage[]; -extern const char chroot_usage[]; -extern const char clear_usage[]; -extern const char cp_usage[]; -extern const char date_usage[]; -extern const char dd_usage[]; -extern const char df_usage[]; -extern const char dmesg_usage[]; -extern const char dutmp_usage[]; -extern const char false_usage[]; -extern const char fdflush_usage[]; -extern const char find_usage[]; -extern const char grep_usage[]; -extern const char halt_usage[]; -extern const char init_usage[]; -extern const char kill_usage[]; -extern const char length_usage[]; -extern const char ln_usage[]; -extern const char loadkmap_usage[]; -extern const char losetup_usage[]; -extern const char ls_usage[]; -extern const char math_usage[]; -extern const char makedevs_usage[]; -extern const char mkdir_usage[]; -extern const char mknod_usage[]; -extern const char mkswap_usage[]; -extern const char mnc_usage[]; -extern const char more_usage[]; -extern const char mount_usage[]; -extern const char mt_usage[]; -extern const char mv_usage[]; -extern const char printf_usage[]; -extern const char pwd_usage[]; -extern const char reboot_usage[]; -extern const char rm_usage[]; -extern const char rmdir_usage[]; -extern const char scan_partitions_usage[]; -extern const char sleep_usage[]; -extern const char tar_usage[]; -extern const char swapoff_usage[]; -extern const char swapon_usage[]; -extern const char sync_usage[]; -extern const char touch_usage[]; -extern const char tput_usage[]; -extern const char true_usage[]; -extern const char tryopen_usage[]; -extern const char umount_usage[]; -extern const char update_usage[]; -extern const char zcat_usage[]; -extern const char gzip_usage[]; +/* + * A chunk of data. + * Chunks contain data which is allocated as needed, but which is + * not freed until all of the data needs freeing, such as at + * the beginning of the next command. + */ +typedef struct chunk CHUNK; +#define CHUNK_INIT_SIZE 4 + +struct chunk { + CHUNK *next; + char data[CHUNK_INIT_SIZE]; /* actually of varying length */ +}; + +const char *modeString(int mode); +const char *timeString(time_t timeVal); +BOOL isDirectory(const char *name); +BOOL isDevice(const char *name); +BOOL copyFile(const char *srcName, const char *destName, BOOL setModes); +const char *buildName(const char *dirName, const char *fileName); +BOOL makeString(int argc, const char **argv, char *buf, int bufLen); +char *getChunk(int size); +char *chunkstrdup(const char *str); +void freeChunks(void); +int fullWrite(int fd, const char *buf, int len); +int fullRead(int fd, char *buf, int len); +int recursiveAction(const char *fileName, BOOL followLinks, + int (*fileAction) (const char *fileName), + int (*dirAction) (const char *fileName)); #endif diff --git a/utility.c b/utility.c index 6825971..a516355 100644 --- a/utility.c +++ b/utility.c @@ -22,7 +22,16 @@ * */ -#include "utility.h" +#include "internal.h" +#include +#include +#include +#include +//#include +//#include +#include +#include +#include #if 0 @@ -54,13 +63,6 @@ join_paths(char * buffer, const char * a, const char * b) static CHUNK * chunkList; -extern void -name_and_error(const char * name) -{ - fprintf(stderr, "%s: %s\n", name, strerror(errno)); -} - - /* * Return the standard ls-like mode string from a file mode. @@ -130,36 +132,6 @@ modeString(int mode) /* - * Get the time string to be used for a file. - * This is down to the minute for new files, but only the date for old files. - * The string is returned from a static buffer, and so is overwritten for - * each call. - */ -const char * -timeString(time_t timeVal) -{ - time_t now; - char * str; - static char buf[26]; - - time(&now); - - str = ctime(&timeVal); - - strcpy(buf, &str[4]); - buf[12] = '\0'; - - if ((timeVal > now) || (timeVal < now - 365*24*60*60L)) - { - strcpy(&buf[7], &str[20]); - buf[11] = '\0'; - } - - return buf; -} - - -/* * Return TRUE if a fileName is a directory. * Nonexistant files return FALSE. */ @@ -325,624 +297,6 @@ buildName(const char * dirName, const char * fileName) /* - * Expand the wildcards in a fileName wildcard pattern, if any. - * Returns an argument list with matching fileNames in sorted order. - * The expanded names are stored in memory chunks which can later all - * be freed at once. The returned list is only valid until the next - * call or until the next command. Returns zero if the name is not a - * wildcard, or returns the count of matched files if the name is a - * wildcard and there was at least one match, or returns -1 if either - * no fileNames matched or there was an allocation error. - */ -int -expandWildCards(const char * fileNamePattern, const char *** retFileTable) -{ - const char * last; - const char * cp1; - const char * cp2; - const char * cp3; - char * str; - DIR * dirp; - struct dirent * dp; - int dirLen; - int newFileTableSize; - char ** newFileTable; - char dirName[PATH_LEN]; - - static int fileCount; - static int fileTableSize; - static char ** fileTable; - - /* - * Clear the return values until we know their final values. - */ - fileCount = 0; - *retFileTable = NULL; - - /* - * Scan the file name pattern for any wildcard characters. - */ - cp1 = strchr(fileNamePattern, '*'); - cp2 = strchr(fileNamePattern, '?'); - cp3 = strchr(fileNamePattern, '['); - - /* - * If there are no wildcard characters then return zero to - * indicate that there was actually no wildcard pattern. - */ - if ((cp1 == NULL) && (cp2 == NULL) && (cp3 == NULL)) - return 0; - - /* - * There are wildcards in the specified filename. - * Get the last component of the file name. - */ - last = strrchr(fileNamePattern, '/'); - - if (last) - last++; - else - last = fileNamePattern; - - /* - * If any wildcards were found before the last filename component - * then return an error. - */ - if ((cp1 && (cp1 < last)) || (cp2 && (cp2 < last)) || - (cp3 && (cp3 < last))) - { - fprintf(stderr, - "Wildcards only implemented for last file name component\n"); - - return -1; - } - - /* - * Assume at first that we are scanning the current directory. - */ - dirName[0] = '.'; - dirName[1] = '\0'; - - /* - * If there was a directory given as part of the file name then - * copy it and null terminate it. - */ - if (last != fileNamePattern) - { - memcpy(dirName, fileNamePattern, last - fileNamePattern); - dirName[last - fileNamePattern - 1] = '\0'; - - if (dirName[0] == '\0') - { - dirName[0] = '/'; - dirName[1] = '\0'; - } - } - - /* - * Open the directory containing the files to be checked. - */ - dirp = opendir(dirName); - - if (dirp == NULL) - { - perror(dirName); - - return -1; - } - - /* - * Prepare the directory name for use in making full path names. - */ - dirLen = strlen(dirName); - - if (last == fileNamePattern) - { - dirLen = 0; - dirName[0] = '\0'; - } - else if (dirName[dirLen - 1] != '/') - { - dirName[dirLen++] = '/'; - dirName[dirLen] = '\0'; - } - - /* - * Find all of the files in the directory and check them against - * the wildcard pattern. - */ - while ((dp = readdir(dirp)) != NULL) - { - /* - * Skip the current and parent directories. - */ - if ((strcmp(dp->d_name, ".") == 0) || - (strcmp(dp->d_name, "..") == 0)) - { - continue; - } - - /* - * If the file name doesn't match the pattern then skip it. - */ - if (!match(dp->d_name, last)) - continue; - - /* - * This file name is selected. - * See if we need to reallocate the file name table. - */ - if (fileCount >= fileTableSize) - { - /* - * Increment the file table size and reallocate it. - */ - newFileTableSize = fileTableSize + EXPAND_ALLOC; - - newFileTable = (char **) realloc((char *) fileTable, - (newFileTableSize * sizeof(char *))); - - if (newFileTable == NULL) - { - fprintf(stderr, "Cannot allocate file list\n"); - closedir(dirp); - - return -1; - } - - fileTable = newFileTable; - fileTableSize = newFileTableSize; - } - - /* - * Allocate space for storing the file name in a chunk. - */ - str = getChunk(dirLen + strlen(dp->d_name) + 1); - - if (str == NULL) - { - fprintf(stderr, "No memory for file name\n"); - closedir(dirp); - - return -1; - } - - /* - * Save the file name in the chunk. - */ - if (dirLen) - memcpy(str, dirName, dirLen); - - strcpy(str + dirLen, dp->d_name); - - /* - * Save the allocated file name into the file table. - */ - fileTable[fileCount++] = str; - } - - /* - * Close the directory and check for any matches. - */ - closedir(dirp); - - if (fileCount == 0) - { - fprintf(stderr, "No matches\n"); - - return -1; - } - - /* - * Sort the list of file names. - */ - qsort((void *) fileTable, fileCount, sizeof(char *), nameSort); - - /* - * Return the file list and count. - */ - *retFileTable = (const char **) fileTable; - - return fileCount; -} - - -/* - * Sort routine for list of fileNames. - */ -int -nameSort(const void * p1, const void * p2) -{ - const char ** s1; - const char ** s2; - - s1 = (const char **) p1; - s2 = (const char **) p2; - - return strcmp(*s1, *s2); -} - - - -/* - * Routine to see if a text string is matched by a wildcard pattern. - * Returns TRUE if the text is matched, or FALSE if it is not matched - * or if the pattern is invalid. - * * matches zero or more characters - * ? matches a single character - * [abc] matches 'a', 'b' or 'c' - * \c quotes character c - * Adapted from code written by Ingo Wilken. - */ -BOOL -match(const char * text, const char * pattern) -{ - const char * retryPat; - const char * retryText; - int ch; - BOOL found; - - retryPat = NULL; - retryText = NULL; - - while (*text || *pattern) - { - ch = *pattern++; - - switch (ch) - { - case '*': - retryPat = pattern; - retryText = text; - break; - - case '[': - found = FALSE; - - while ((ch = *pattern++) != ']') - { - if (ch == '\\') - ch = *pattern++; - - if (ch == '\0') - return FALSE; - - if (*text == ch) - found = TRUE; - } - - if (!found) - { - pattern = retryPat; - text = ++retryText; - } - - /* fall into next case */ - - case '?': - if (*text++ == '\0') - return FALSE; - - break; - - case '\\': - ch = *pattern++; - - if (ch == '\0') - return FALSE; - - /* fall into next case */ - - default: - if (*text == ch) - { - if (*text) - text++; - break; - } - - if (*text) - { - pattern = retryPat; - text = ++retryText; - break; - } - - return FALSE; - } - - if (pattern == NULL) - return FALSE; - } - - return TRUE; -} - - -/* - * Take a command string and break it up into an argc, argv list while - * handling quoting and wildcards. The returned argument list and - * strings are in static memory, and so are overwritten on each call. - * The argument list is ended with a NULL pointer for convenience. - * Returns TRUE if successful, or FALSE on an error with a message - * already output. - */ -BOOL -makeArgs(const char * cmd, int * retArgc, const char *** retArgv) -{ - const char * argument; - char * cp; - char * cpOut; - char * newStrings; - const char ** fileTable; - const char ** newArgTable; - int newArgTableSize; - int fileCount; - int len; - int ch; - int quote; - BOOL quotedWildCards; - BOOL unquotedWildCards; - - static int stringsLength; - static char * strings; - static int argCount; - static int argTableSize; - static const char ** argTable; - - /* - * Clear the returned values until we know them. - */ - argCount = 0; - *retArgc = 0; - *retArgv = NULL; - - /* - * Copy the command string into a buffer that we can modify, - * reallocating it if necessary. - */ - len = strlen(cmd) + 1; - - if (len > stringsLength) - { - newStrings = realloc(strings, len); - - if (newStrings == NULL) - { - fprintf(stderr, "Cannot allocate string\n"); - - return FALSE; - } - - strings = newStrings; - stringsLength = len; - } - - memcpy(strings, cmd, len); - cp = strings; - - /* - * Keep parsing the command string as long as there are any - * arguments left. - */ - while (*cp) - { - /* - * Save the beginning of this argument. - */ - argument = cp; - cpOut = cp; - - /* - * Reset quoting and wildcarding for this argument. - */ - quote = '\0'; - quotedWildCards = FALSE; - unquotedWildCards = FALSE; - - /* - * Loop over the string collecting the next argument while - * looking for quoted strings or quoted characters, and - * remembering whether there are any wildcard characters - * in the argument. - */ - while (*cp) - { - ch = *cp++; - - /* - * If we are not in a quote and we see a blank then - * this argument is done. - */ - if (isBlank(ch) && (quote == '\0')) - break; - - /* - * If we see a backslash then accept the next - * character no matter what it is. - */ - if (ch == '\\') - { - ch = *cp++; - - /* - * Make sure there is a next character. - */ - if (ch == '\0') - { - fprintf(stderr, - "Bad quoted character\n"); - - return FALSE; - } - - /* - * Remember whether the quoted character - * is a wildcard. - */ - if (isWildCard(ch)) - quotedWildCards = TRUE; - - *cpOut++ = ch; - - continue; - } - - /* - * If we see one of the wildcard characters then - * remember whether it was seen inside or outside - * of quotes. - */ - if (isWildCard(ch)) - { - if (quote) - quotedWildCards = TRUE; - else - unquotedWildCards = TRUE; - } - - /* - * If we were in a quote and we saw the same quote - * character again then the quote is done. - */ - if (ch == quote) - { - quote = '\0'; - - continue; - } - - /* - * If we weren't in a quote and we see either type - * of quote character, then remember that we are - * now inside of a quote. - */ - if ((quote == '\0') && ((ch == '\'') || (ch == '"'))) - { - quote = ch; - - continue; - } - - /* - * Store the character. - */ - *cpOut++ = ch; - } - - /* - * Make sure that quoting is terminated properly. - */ - if (quote) - { - fprintf(stderr, "Unmatched quote character\n"); - - return FALSE; - } - - /* - * Null terminate the argument if it had shrunk, and then - * skip over all blanks to the next argument, nulling them - * out too. - */ - if (cp != cpOut) - *cpOut = '\0'; - - while (isBlank(*cp)) - *cp++ = '\0'; - - /* - * If both quoted and unquoted wildcards were used then - * complain since we don't handle them properly. - */ - if (quotedWildCards && unquotedWildCards) - { - fprintf(stderr, - "Cannot use quoted and unquoted wildcards\n"); - - return FALSE; - } - - /* - * Expand the argument into the matching filenames or accept - * it as is depending on whether there were any unquoted - * wildcard characters in it. - */ - if (unquotedWildCards) - { - /* - * Expand the argument into the matching filenames. - */ - fileCount = expandWildCards(argument, &fileTable); - - /* - * Return an error if the wildcards failed to match. - */ - if (fileCount < 0) - return FALSE; - - if (fileCount == 0) - { - fprintf(stderr, "Wildcard expansion error\n"); - - return FALSE; - } - } - else - { - /* - * Set up to only store the argument itself. - */ - fileTable = &argument; - fileCount = 1; - } - - /* - * Now reallocate the argument table to hold the file name. - */ - if (argCount + fileCount >= argTableSize) - { - newArgTableSize = argCount + fileCount + 1; - - newArgTable = (const char **) realloc(argTable, - (sizeof(const char *) * newArgTableSize)); - - if (newArgTable == NULL) - { - fprintf(stderr, "No memory for arg list\n"); - - return FALSE; - } - - argTable = newArgTable; - argTableSize = newArgTableSize; - } - - /* - * Copy the new arguments to the end of the old ones. - */ - memcpy((void *) &argTable[argCount], (const void *) fileTable, - (sizeof(const char **) * fileCount)); - - /* - * Add to the argument count. - */ - argCount += fileCount; - } - - /* - * Null terminate the argument list and return it. - */ - argTable[argCount] = NULL; - - *retArgc = argCount; - *retArgv = argTable; - - return TRUE; -} - - -/* * Make a NULL-terminated string out of an argc, argv pair. * Returns TRUE if successful, or FALSE if the string is too long, * with an error message given. This does not handle spaces within @@ -1114,15 +468,14 @@ fullRead(int fd, char * buf, int len) /* - * Read all of the supplied buffer from a file. - * This does multiple reads as necessary. - * Returns the amount read, or -1 on an error. - * A short read is returned on an end of file. + * Walk down all the directories under the specified + * location, and do something (something specified + * by the fileAction and dirAction function pointers). */ int -recursive( const char *fileName, BOOL followLinks, const char* pattern, - int (*fileAction)(const char* fileName, const struct stat* statbuf), - int (*dirAction)(const char* fileName, const struct stat* statbuf)) +recursiveAction( const char *fileName, BOOL followLinks, + int (*fileAction)(const char* fileName), + int (*dirAction)(const char* fileName)) { int status; struct stat statbuf; @@ -1135,45 +488,44 @@ recursive( const char *fileName, BOOL followLinks, const char* pattern, if (status < 0) { perror(fileName); - return( -1); + return( FALSE); } - if (S_ISREG(statbuf.st_mode)) { - if (match(fileName, pattern)) { - if (fileAction==NULL) - fprintf( stdout, "%s\n", fileName); - else - return(fileAction(fileName, &statbuf)); + if (S_ISDIR(statbuf.st_mode)) { + DIR *dir; + dir = opendir(fileName); + if (!dir) { + perror(fileName); + return(FALSE); } - } - else if (S_ISDIR(statbuf.st_mode)) { - if (dirAction==NULL) { - DIR *dir; - if (! match(fileName, pattern)) - return 1; - dir = opendir(fileName); - if (!dir) { - perror(fileName); - return( -1); - } - while ((next = readdir (dir)) != NULL) { - status = recursive(fileName, followLinks, pattern, fileAction, dirAction); - if (status < 0) { - closedir(dir); - return(status); - } - } - status = closedir (dir); - if (status < 0) { - perror(fileName); - return( -1); - } + while ((next = readdir (dir)) != NULL) { + char nextFile[NAME_MAX]; + if ( (strcmp(next->d_name, "..") == 0) || (strcmp(next->d_name, ".") == 0) ) { + continue; + } + sprintf(nextFile, "%s/%s", fileName, next->d_name); + status = recursiveAction(nextFile, followLinks, fileAction, dirAction); + if (status < 0) { + closedir(dir); + return(FALSE); + } + } + status = closedir (dir); + if (status < 0) { + perror(fileName); + return( FALSE); } + if (dirAction==NULL) + return(TRUE); else - return(dirAction(fileName, &statbuf)); + return(dirAction(fileName)); + } + else { + if (fileAction==NULL) + return(TRUE); + else + return(fileAction(fileName)); } - return( 1); - } diff --git a/utility.h b/utility.h deleted file mode 100644 index 7b275ba..0000000 --- a/utility.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Utility routines. - * - * Copyright (C) 1998 by Erik Andersen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * - */ - -#include "internal.h" -#include -#include -#include -#include -//#include -//#include -#include -#include -#include - -/* - * A chunk of data. - * Chunks contain data which is allocated as needed, but which is - * not freed until all of the data needs freeing, such as at - * the beginning of the next command. - */ -typedef struct chunk CHUNK; -#define CHUNK_INIT_SIZE 4 - -struct chunk { - CHUNK *next; - char data[CHUNK_INIT_SIZE]; /* actually of varying length */ -}; - -const char *modeString(int mode); -const char *timeString(time_t timeVal); -BOOL isDirectory(const char *name); -BOOL isDevice(const char *name); -BOOL copyFile(const char *srcName, const char *destName, BOOL setModes); -const char *buildName(const char *dirName, const char *fileName); -BOOL match(const char *text, const char *pattern); -BOOL makeArgs(const char *cmd, int *retArgc, const char ***retArgv); -BOOL makeString(int argc, const char **argv, char *buf, int bufLen); -char *getChunk(int size); -char *chunkstrdup(const char *str); -void freeChunks(void); -int fullWrite(int fd, const char *buf, int len); -int fullRead(int fd, char *buf, int len); -int -recursive(const char *fileName, BOOL followLinks, const char *pattern, - int (*fileAction) (const char *fileName, - const struct stat * statbuf), - int (*dirAction) (const char *fileName, - const struct stat * statbuf)); - -int nameSort(const void *p1, const void *p2); -int expandWildCards(const char *fileNamePattern, - const char ***retFileTable); -- 2.7.4