10e42dee6Sartem /*
20e42dee6Sartem * CDDL HEADER START
30e42dee6Sartem *
40e42dee6Sartem * The contents of this file are subject to the terms of the
50e42dee6Sartem * Common Development and Distribution License (the "License").
60e42dee6Sartem * You may not use this file except in compliance with the License.
70e42dee6Sartem *
80e42dee6Sartem * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90e42dee6Sartem * or http://www.opensolaris.org/os/licensing.
100e42dee6Sartem * See the License for the specific language governing permissions
110e42dee6Sartem * and limitations under the License.
120e42dee6Sartem *
130e42dee6Sartem * When distributing Covered Code, include this CDDL HEADER in each
140e42dee6Sartem * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150e42dee6Sartem * If applicable, add the following below this CDDL HEADER, with the
160e42dee6Sartem * fields enclosed by brackets "[]" replaced with your own identifying
170e42dee6Sartem * information: Portions Copyright [yyyy] [name of copyright owner]
180e42dee6Sartem *
190e42dee6Sartem * CDDL HEADER END
200e42dee6Sartem */
210e42dee6Sartem /*
22*88ecc943SGeorge Wilson * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230e42dee6Sartem * Use is subject to license terms.
240e42dee6Sartem */
250e42dee6Sartem
260e42dee6Sartem #include <fcntl.h>
270e42dee6Sartem #include <stdio.h>
280e42dee6Sartem #include <stdlib.h>
290e42dee6Sartem #include <sys/types.h>
300e42dee6Sartem #include <sys/stat.h>
310e42dee6Sartem #include <unistd.h>
320e42dee6Sartem #include <libintl.h>
330e42dee6Sartem #include <locale.h>
340e42dee6Sartem #include <string.h>
350e42dee6Sartem #include <strings.h>
360e42dee6Sartem #include <errno.h>
370e42dee6Sartem #include <dirent.h>
380e42dee6Sartem #include <dlfcn.h>
390e42dee6Sartem #include <sys/wait.h>
400e42dee6Sartem #include <sys/fstyp.h>
41ca29f3daSprabahar #include <sys/dkio.h>
42ca29f3daSprabahar #include <sys/param.h>
430e42dee6Sartem #include <libfstyp.h>
440e42dee6Sartem #include <sys/dktp/fdisk.h>
450e42dee6Sartem #include <sys/fs/pc_label.h>
460e42dee6Sartem
47f5ac0e94Smc208700@nadesico #include "libadm.h"
48f5ac0e94Smc208700@nadesico
490e42dee6Sartem #define FSTYP_LIBFS_DIR "/usr/lib/fs"
500e42dee6Sartem
510e42dee6Sartem static const char *getmodfsname();
520e42dee6Sartem static char *getexecpathname();
530e42dee6Sartem static boolean_t dos_to_dev(char *path, char **devpath, int *num);
54ca29f3daSprabahar static boolean_t find_dos_drive(int fd, int num, off_t *offset);
550e42dee6Sartem static void run_legacy_cmds(int fd, char *device, int vflag);
560e42dee6Sartem static int run_cmd(char *path, char *arg0, char *arg1, char *arg2);
570e42dee6Sartem
580e42dee6Sartem
590e42dee6Sartem static void
usage(void)600e42dee6Sartem usage(void)
610e42dee6Sartem {
620e42dee6Sartem (void) fprintf(stderr, gettext("Usage: fstyp [-av] <device>\n"));
630e42dee6Sartem exit(1);
640e42dee6Sartem }
650e42dee6Sartem
660e42dee6Sartem int
main(int argc,char ** argv)670e42dee6Sartem main(int argc, char **argv)
680e42dee6Sartem {
690e42dee6Sartem int fd = -1;
700e42dee6Sartem int c;
710e42dee6Sartem int aflag = 0;
720e42dee6Sartem int vflag = 0;
730e42dee6Sartem int indent = 0;
740e42dee6Sartem char *devpath;
750e42dee6Sartem boolean_t is_dos;
76ca29f3daSprabahar int dos_num;
770e42dee6Sartem off_t offset = 0;
780e42dee6Sartem nvlist_t *attr = NULL;
790e42dee6Sartem fstyp_handle_t h = NULL;
800e42dee6Sartem const char *modfsname;
810e42dee6Sartem const char *fsname;
820e42dee6Sartem int error = FSTYP_ERR_NO_MATCH;
830e42dee6Sartem
840e42dee6Sartem (void) setlocale(LC_ALL, "");
850e42dee6Sartem
860e42dee6Sartem #if !defined(TEXT_DOMAIN)
870e42dee6Sartem #define TEXT_DOMAIN "SYS_TEST"
880e42dee6Sartem #endif
890e42dee6Sartem (void) textdomain(TEXT_DOMAIN);
900e42dee6Sartem
910e42dee6Sartem while ((c = getopt(argc, argv, "av")) != -1) {
920e42dee6Sartem switch (c) {
930e42dee6Sartem case 'a':
940e42dee6Sartem aflag = 1;
950e42dee6Sartem break;
960e42dee6Sartem case 'v':
970e42dee6Sartem vflag = 1;
980e42dee6Sartem break;
990e42dee6Sartem default:
1000e42dee6Sartem usage();
1010e42dee6Sartem break;
1020e42dee6Sartem }
1030e42dee6Sartem }
1040e42dee6Sartem
1050e42dee6Sartem argv += optind;
1060e42dee6Sartem argc -= optind;
1070e42dee6Sartem
1080e42dee6Sartem if (argc != 1) {
1090e42dee6Sartem usage();
1100e42dee6Sartem }
1110e42dee6Sartem
1120e42dee6Sartem modfsname = getmodfsname();
1130e42dee6Sartem
1140e42dee6Sartem /*
1150e42dee6Sartem * Open device, find partition offset if requested
1160e42dee6Sartem */
1170e42dee6Sartem if (!(is_dos = dos_to_dev(argv[0], &devpath, &dos_num))) {
1180e42dee6Sartem devpath = argv[0];
1190e42dee6Sartem }
1200e42dee6Sartem if ((fd = open(devpath, O_RDONLY)) < 0) {
1210e42dee6Sartem error = FSTYP_ERR_DEV_OPEN;
1220e42dee6Sartem goto out;
1230e42dee6Sartem }
1240e42dee6Sartem if (is_dos) {
125ca29f3daSprabahar if (!find_dos_drive(fd, dos_num, &offset)) {
1260e42dee6Sartem error = FSTYP_ERR_NO_PARTITION;
1270e42dee6Sartem goto out;
1280e42dee6Sartem }
1290e42dee6Sartem }
1300e42dee6Sartem
1310e42dee6Sartem /*
1320e42dee6Sartem * Use libfstyp to identify filesystem
1330e42dee6Sartem */
1340e42dee6Sartem if ((error = fstyp_init(fd, offset, NULL, &h)) != 0) {
1350e42dee6Sartem goto out;
1360e42dee6Sartem }
1370e42dee6Sartem if ((error = fstyp_ident(h, modfsname, &fsname)) != 0) {
1380e42dee6Sartem fstyp_fini(h);
1390e42dee6Sartem h = NULL;
1400e42dee6Sartem
1410e42dee6Sartem run_legacy_cmds(fd, argv[0], vflag);
1420e42dee6Sartem
1430e42dee6Sartem goto out;
1440e42dee6Sartem }
1450e42dee6Sartem
1460e42dee6Sartem (void) printf("%s\n", fsname);
1470e42dee6Sartem
1480e42dee6Sartem /*
1490e42dee6Sartem * Output additional info if requested
1500e42dee6Sartem */
1510e42dee6Sartem if (vflag) {
1520e42dee6Sartem error = fstyp_dump(h, stdout, stderr);
1530e42dee6Sartem }
1540e42dee6Sartem if (aflag || (vflag && (error == FSTYP_ERR_NOP))) {
1550e42dee6Sartem if ((error = fstyp_get_attr(h, &attr)) != 0) {
1560e42dee6Sartem goto out;
1570e42dee6Sartem }
1580e42dee6Sartem dump_nvlist(attr, indent);
1590e42dee6Sartem }
1600e42dee6Sartem
1610e42dee6Sartem out:
1620e42dee6Sartem if (error != 0) {
1630e42dee6Sartem (void) fprintf(stderr, gettext("unknown_fstyp (%s)\n"),
1640e42dee6Sartem fstyp_strerror(h, error));
1650e42dee6Sartem }
1660e42dee6Sartem if (h != NULL) {
1670e42dee6Sartem fstyp_fini(h);
1680e42dee6Sartem }
1690e42dee6Sartem if (fd >= 0) {
1700e42dee6Sartem (void) close(fd);
1710e42dee6Sartem }
1720e42dee6Sartem if (devpath != argv[0]) {
1730e42dee6Sartem free(devpath);
1740e42dee6Sartem }
1750e42dee6Sartem return (error);
1760e42dee6Sartem
1770e42dee6Sartem }
1780e42dee6Sartem
1790e42dee6Sartem /*
1800e42dee6Sartem * If the executable is a fs-specific hardlink, /usr/lib/fs/<fsname>/fstyp,
1810e42dee6Sartem * return that fsname; otherwise return NULL.
1820e42dee6Sartem */
1830e42dee6Sartem static const char *
getmodfsname()1840e42dee6Sartem getmodfsname()
1850e42dee6Sartem {
1860e42dee6Sartem static char fsname_buf[FSTYPSZ + 1];
1870e42dee6Sartem char *fsname = NULL;
1880e42dee6Sartem char *path;
1890e42dee6Sartem char *p;
1900e42dee6Sartem int len;
1910e42dee6Sartem
1920e42dee6Sartem if ((path = getexecpathname()) == NULL) {
1930e42dee6Sartem return (NULL);
1940e42dee6Sartem }
1950e42dee6Sartem if ((p = strrchr(path, '/')) != NULL) {
1960e42dee6Sartem *p = '\0';
1970e42dee6Sartem if ((p = strrchr(path, '/')) != NULL) {
1980e42dee6Sartem *p++ = '\0';
1990e42dee6Sartem len = strlen(p);
2000e42dee6Sartem if ((strcmp(path, FSTYP_LIBFS_DIR) == 0) &&
2010e42dee6Sartem (len > 0) && (len < sizeof (fsname_buf))) {
2020e42dee6Sartem (void) strlcpy(fsname_buf, p,
2030e42dee6Sartem sizeof (fsname_buf));
2040e42dee6Sartem fsname = fsname_buf;
2050e42dee6Sartem }
2060e42dee6Sartem }
2070e42dee6Sartem }
2080e42dee6Sartem free(path);
2090e42dee6Sartem return (fsname);
2100e42dee6Sartem }
2110e42dee6Sartem
2120e42dee6Sartem /*
2130e42dee6Sartem * Return executable's absolute pathname
2140e42dee6Sartem */
2150e42dee6Sartem static char *
getexecpathname()2160e42dee6Sartem getexecpathname()
2170e42dee6Sartem {
2180e42dee6Sartem size_t size;
2190e42dee6Sartem const char *execname;
2200e42dee6Sartem char *cwd;
2210e42dee6Sartem char *path;
2220e42dee6Sartem char *rpath;
2230e42dee6Sartem
2240e42dee6Sartem size = pathconf(".", _PC_PATH_MAX) + 1;
2250e42dee6Sartem path = malloc(size);
2260e42dee6Sartem rpath = malloc(size);
2270e42dee6Sartem cwd = getcwd(NULL, size);
2280e42dee6Sartem if ((path == NULL) || (rpath == NULL) || (cwd == NULL)) {
2290e42dee6Sartem goto out;
2300e42dee6Sartem }
2310e42dee6Sartem execname = getexecname();
2320e42dee6Sartem
2330e42dee6Sartem if (execname[0] == '/') {
2340e42dee6Sartem (void) snprintf(path, size, "%s", execname);
2350e42dee6Sartem } else {
2360e42dee6Sartem (void) snprintf(path, size, "%s/%s", cwd, execname);
2370e42dee6Sartem }
2380e42dee6Sartem if (realpath(path, rpath) == NULL) {
2390e42dee6Sartem free(rpath);
2400e42dee6Sartem rpath = NULL;
2410e42dee6Sartem }
2420e42dee6Sartem
2430e42dee6Sartem out:
2440e42dee6Sartem if (path != NULL) {
2450e42dee6Sartem free(path);
2460e42dee6Sartem }
2470e42dee6Sartem if (cwd != NULL) {
2480e42dee6Sartem free(cwd);
2490e42dee6Sartem }
2500e42dee6Sartem return (rpath);
2510e42dee6Sartem }
2520e42dee6Sartem
2530e42dee6Sartem /*
2540e42dee6Sartem * Separates dos notation device spec into device and drive number
2550e42dee6Sartem */
2560e42dee6Sartem static boolean_t
dos_to_dev(char * path,char ** devpath,int * num)2570e42dee6Sartem dos_to_dev(char *path, char **devpath, int *num)
2580e42dee6Sartem {
2590e42dee6Sartem char *p;
2600e42dee6Sartem
2610e42dee6Sartem if ((p = strrchr(path, ':')) == NULL) {
2620e42dee6Sartem return (B_FALSE);
2630e42dee6Sartem }
2640e42dee6Sartem if ((*num = atoi(p + 1)) == 0) {
2650e42dee6Sartem return (B_FALSE);
2660e42dee6Sartem }
2670e42dee6Sartem p[0] = '\0';
268f5ac0e94Smc208700@nadesico *devpath = getfullrawname(path);
2690e42dee6Sartem p[0] = ':';
270f5ac0e94Smc208700@nadesico if (*devpath != NULL && **devpath == '\0') {
271f5ac0e94Smc208700@nadesico free(*devpath);
272f5ac0e94Smc208700@nadesico *devpath = NULL;
273f5ac0e94Smc208700@nadesico }
2740e42dee6Sartem return (*devpath != NULL);
2750e42dee6Sartem }
2760e42dee6Sartem
2770e42dee6Sartem static boolean_t
is_dos_drive(uchar_t type)2780e42dee6Sartem is_dos_drive(uchar_t type)
2790e42dee6Sartem {
2802d700530Sartem return ((type == DOSOS12) || (type == DOSOS16) ||
2812d700530Sartem (type == DOSHUGE) || (type == FDISK_WINDOWS) ||
2822d700530Sartem (type == FDISK_EXT_WIN) || (type == FDISK_FAT95) ||
2832d700530Sartem (type == DIAGPART));
2840e42dee6Sartem }
2850e42dee6Sartem
2860e42dee6Sartem static boolean_t
is_dos_extended(uchar_t id)2870e42dee6Sartem is_dos_extended(uchar_t id)
2880e42dee6Sartem {
2890e42dee6Sartem return ((id == EXTDOS) || (id == FDISK_EXTLBA));
2900e42dee6Sartem }
2910e42dee6Sartem
2920e42dee6Sartem struct part_find_s {
2930e42dee6Sartem int num;
2940e42dee6Sartem int count;
2950e42dee6Sartem int systid;
2960e42dee6Sartem int r_systid;
297342440ecSPrasad Singamsetty uint32_t r_relsect;
298342440ecSPrasad Singamsetty uint32_t r_numsect;
2990e42dee6Sartem };
3000e42dee6Sartem
3010e42dee6Sartem enum { WALK_CONTINUE, WALK_TERMINATE };
3020e42dee6Sartem
3030e42dee6Sartem /*
3040e42dee6Sartem * Walk partition tables and invoke a callback for each.
3050e42dee6Sartem */
3060e42dee6Sartem static void
walk_partitions(int fd,uint32_t startsec,off_t secsz,int (* f)(void *,int,uint32_t,uint32_t),void * arg)307342440ecSPrasad Singamsetty walk_partitions(int fd, uint32_t startsec, off_t secsz,
308342440ecSPrasad Singamsetty int (*f)(void *, int, uint32_t, uint32_t), void *arg)
3090e42dee6Sartem {
3100e42dee6Sartem uint32_t buf[1024/4];
3110e42dee6Sartem int bufsize = 1024;
3120e42dee6Sartem struct mboot *mboot = (struct mboot *)&buf[0];
3130e42dee6Sartem struct ipart ipart[FD_NUMPART];
314342440ecSPrasad Singamsetty uint32_t sec = startsec;
315342440ecSPrasad Singamsetty uint32_t lastsec = sec + 1;
316342440ecSPrasad Singamsetty uint32_t relsect;
3170e42dee6Sartem int ext = 0;
3180e42dee6Sartem int systid;
3190e42dee6Sartem boolean_t valid;
3200e42dee6Sartem int i;
3210e42dee6Sartem
3220e42dee6Sartem while (sec != lastsec) {
323ca29f3daSprabahar if (pread(fd, buf, bufsize, (off_t)sec * secsz) != bufsize) {
3240e42dee6Sartem break;
3250e42dee6Sartem }
3260e42dee6Sartem lastsec = sec;
3270e42dee6Sartem if (ltohs(mboot->signature) != MBB_MAGIC) {
3280e42dee6Sartem break;
3290e42dee6Sartem }
3300e42dee6Sartem bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart));
3310e42dee6Sartem
3320e42dee6Sartem for (i = 0; i < FD_NUMPART; i++) {
3330e42dee6Sartem systid = ipart[i].systid;
3340e42dee6Sartem relsect = sec + ltohi(ipart[i].relsect);
3350e42dee6Sartem if (systid == 0) {
3360e42dee6Sartem continue;
3370e42dee6Sartem }
3380e42dee6Sartem valid = B_TRUE;
3390e42dee6Sartem if (is_dos_extended(systid) && (sec == lastsec)) {
3400e42dee6Sartem sec = startsec + ltohi(ipart[i].relsect);
3410e42dee6Sartem if (ext++ == 0) {
3420e42dee6Sartem relsect = startsec = sec;
3430e42dee6Sartem } else {
3440e42dee6Sartem valid = B_FALSE;
3450e42dee6Sartem }
3460e42dee6Sartem }
3470e42dee6Sartem if (valid && f(arg, ipart[i].systid, relsect,
3480e42dee6Sartem ltohi(ipart[i].numsect)) == WALK_TERMINATE) {
3490e42dee6Sartem return;
3500e42dee6Sartem }
3510e42dee6Sartem }
3520e42dee6Sartem }
3530e42dee6Sartem }
3540e42dee6Sartem
3550e42dee6Sartem static int
find_dos_drive_cb(void * arg,int systid,uint32_t relsect,uint32_t numsect)356342440ecSPrasad Singamsetty find_dos_drive_cb(void *arg, int systid, uint32_t relsect, uint32_t numsect)
3570e42dee6Sartem {
3580e42dee6Sartem struct part_find_s *p = arg;
3590e42dee6Sartem
3600e42dee6Sartem if (is_dos_drive(systid)) {
3610e42dee6Sartem if (++p->count == p->num) {
3620e42dee6Sartem p->r_relsect = relsect;
3630e42dee6Sartem p->r_numsect = numsect;
3640e42dee6Sartem p->r_systid = systid;
3650e42dee6Sartem return (WALK_TERMINATE);
3660e42dee6Sartem }
3670e42dee6Sartem }
3680e42dee6Sartem
3690e42dee6Sartem return (WALK_CONTINUE);
3700e42dee6Sartem }
3710e42dee6Sartem
3720e42dee6Sartem /*
373ca29f3daSprabahar * Given a dos drive number, return its relative offset in the drive.
3740e42dee6Sartem */
3750e42dee6Sartem static boolean_t
find_dos_drive(int fd,int num,off_t * offset)376ca29f3daSprabahar find_dos_drive(int fd, int num, off_t *offset)
3770e42dee6Sartem {
378ca29f3daSprabahar struct dk_minfo mi;
379ca29f3daSprabahar off_t secsz;
3800e42dee6Sartem struct part_find_s p = { 0, 0, 0, 0, 0, 0 };
3810e42dee6Sartem
3820e42dee6Sartem p.num = num;
3830e42dee6Sartem
384ca29f3daSprabahar /*
385ca29f3daSprabahar * It is possible that the media we are dealing with can have different
386ca29f3daSprabahar * sector size than the default 512 bytes. Query the driver and check
387ca29f3daSprabahar * whether the media has different sector size.
388ca29f3daSprabahar */
389ca29f3daSprabahar if (ioctl(fd, DKIOCGMEDIAINFO, &mi) < 0)
390ca29f3daSprabahar secsz = DEV_BSIZE;
391ca29f3daSprabahar else
392ca29f3daSprabahar secsz = mi.dki_lbsize;
393ca29f3daSprabahar
3940e42dee6Sartem if (num > 0) {
395ca29f3daSprabahar walk_partitions(fd, 0, secsz, find_dos_drive_cb, &p);
3960e42dee6Sartem if (p.count == num) {
397ca29f3daSprabahar *offset = secsz * (off_t)p.r_relsect;
3980e42dee6Sartem return (B_TRUE);
3990e42dee6Sartem }
4000e42dee6Sartem }
4010e42dee6Sartem
4020e42dee6Sartem return (B_FALSE);
4030e42dee6Sartem }
4040e42dee6Sartem
4050e42dee6Sartem /*
4060e42dee6Sartem * libfstyp identification failed: as a last resort, try to
4070e42dee6Sartem * find and run legacy /usr/lib/fs/<fsname>/fstyp commands.
4080e42dee6Sartem */
4090e42dee6Sartem static void
run_legacy_cmds(int fd,char * device,int vflag)4100e42dee6Sartem run_legacy_cmds(int fd, char *device, int vflag)
4110e42dee6Sartem {
4120e42dee6Sartem char *lib_dir = FSTYP_LIBFS_DIR;
4130e42dee6Sartem char *path;
4140e42dee6Sartem long name_max;
4150e42dee6Sartem DIR *dirp;
4160e42dee6Sartem struct dirent *dp_mem, *dp;
4170e42dee6Sartem struct stat st;
4180e42dee6Sartem fstyp_handle_t h;
4190e42dee6Sartem int error;
4200e42dee6Sartem char *arg1, *arg2;
4210e42dee6Sartem
4220e42dee6Sartem if (vflag) {
4230e42dee6Sartem arg1 = "-v";
4240e42dee6Sartem arg2 = device;
4250e42dee6Sartem } else {
4260e42dee6Sartem arg1 = device;
4270e42dee6Sartem arg2 = NULL;
4280e42dee6Sartem }
4290e42dee6Sartem
4300e42dee6Sartem if ((dirp = opendir(lib_dir)) == NULL) {
4310e42dee6Sartem return;
4320e42dee6Sartem }
4330e42dee6Sartem
4340e42dee6Sartem name_max = pathconf(lib_dir, _PC_NAME_MAX);
4350e42dee6Sartem path = calloc(1, name_max + 1);
4360e42dee6Sartem dp = dp_mem = calloc(1, sizeof (struct dirent) + name_max + 1);
4370e42dee6Sartem if ((path == NULL) || (dp_mem == NULL)) {
4380e42dee6Sartem goto out;
4390e42dee6Sartem }
4400e42dee6Sartem
4410e42dee6Sartem while ((readdir_r(dirp, dp, &dp) == 0) && (dp != NULL)) {
4420e42dee6Sartem if (dp->d_name[0] == '.') {
4430e42dee6Sartem continue;
4440e42dee6Sartem }
4450e42dee6Sartem (void) snprintf(path, name_max, "%s/%s", lib_dir, dp->d_name);
4460e42dee6Sartem
4470e42dee6Sartem /* it's legacy if there's no libfstyp module for it */
4480e42dee6Sartem error = fstyp_init(fd, 0, path, &h);
4490e42dee6Sartem if (error != FSTYP_ERR_MOD_NOT_FOUND) {
4500e42dee6Sartem if (error == 0) {
4510e42dee6Sartem fstyp_fini(h);
4520e42dee6Sartem }
4530e42dee6Sartem continue;
4540e42dee6Sartem }
4550e42dee6Sartem
4560e42dee6Sartem /* file must exist and be executable */
4570e42dee6Sartem (void) snprintf(path, name_max,
4580e42dee6Sartem "%s/%s/fstyp", lib_dir, dp->d_name);
4590e42dee6Sartem if ((stat(path, &st) < 0) ||
4600e42dee6Sartem ((st.st_mode & S_IXUSR) == 0)) {
4610e42dee6Sartem continue;
4620e42dee6Sartem }
4630e42dee6Sartem
4640e42dee6Sartem if ((error = run_cmd(path, "fstyp", arg1, arg2)) == 0) {
4650e42dee6Sartem exit(0);
4660e42dee6Sartem }
4670e42dee6Sartem }
4680e42dee6Sartem
4690e42dee6Sartem out:
4700e42dee6Sartem if (dp_mem != NULL) {
4710e42dee6Sartem free(dp_mem);
4720e42dee6Sartem }
4730e42dee6Sartem if (path != NULL) {
4740e42dee6Sartem free(path);
4750e42dee6Sartem }
4760e42dee6Sartem (void) closedir(dirp);
4770e42dee6Sartem }
4780e42dee6Sartem
4790e42dee6Sartem static int
run_cmd(char * path,char * arg0,char * arg1,char * arg2)4800e42dee6Sartem run_cmd(char *path, char *arg0, char *arg1, char *arg2)
4810e42dee6Sartem {
4820e42dee6Sartem pid_t pid;
4830e42dee6Sartem int status = 1;
4840e42dee6Sartem
4850e42dee6Sartem pid = fork();
4860e42dee6Sartem if (pid < 0) {
4870e42dee6Sartem return (1);
4880e42dee6Sartem } else if (pid == 0) {
4890e42dee6Sartem /* child */
4900e42dee6Sartem (void) execl(path, arg0, arg1, arg2, 0);
4910e42dee6Sartem exit(1);
4920e42dee6Sartem }
4930e42dee6Sartem /* parent */
4940e42dee6Sartem (void) wait(&status);
4950e42dee6Sartem return (status);
4960e42dee6Sartem }
497