[Fedora-directory-commits] esc/src/app/eginstall Makefile, NONE, 1.1 eginstall.c, NONE, 1.1 instlib.c, NONE, 1.1 instlib.h, NONE, 1.1

Jack Magne (jmagne) fedora-directory-commits at redhat.com
Wed Jul 25 20:15:22 UTC 2007


Author: jmagne

Update of /cvs/dirsec/esc/src/app/eginstall
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv15643

Added Files:
	Makefile eginstall.c instlib.c instlib.h 
Log Message:
Initial revision.


--- NEW FILE Makefile ---
#! gmake
#
# BEGIN COPYRIGHT BLOCK
# 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; version 2 of the License.
#
# 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.
#
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK

CORE_DEPTH = ../../..
include $(CORE_DEPTH)/coreconf/config.mk
DIST = $(CORE_DEPTH)/dist/$(OBJDIR_NAME)

ifeq ($(OS_ARCH), WINNT)
WINNT = 1
endif

ifeq ($(OS_ARCH), Darwin)
MACOS = 1
endif 

ifndef BUILD_OPT
ifdef WINNT
CFLAGS = -Z7
else
CFLAGS = -g
endif
CFLAGS += -DDEBUG
endif


ifdef WINNT
LIBS = \
	version.lib \
	Setupapi.lib \
	Advapi32.lib \
	$(NULL)

all: $(OBJDIR_NAME)/eginstall.exe


import:
	@echo "Nothing to Import"

clean:
	rm -f $(OBJDIR_NAME)/eginstall.exe $(OBJDIR_NAME)/eginstall.obj

libs: $(OBJDIR_NAME)/eginstall.exe


install:
	mkdir -p $(DIST)/coolkey_drivers/egate/
	cp $(OBJDIR_NAME)/eginstall.exe $(DIST)/coolkey_drivers/egate/


$(OBJDIR_NAME)/eginstall.exe: $(OBJDIR_NAME)/eginstall.obj
	mkdir -p $(OBJDIR_NAME)
	cl $(CFLAGS) -o $(OBJDIR_NAME)/eginstall.exe $(OBJDIR_NAME)/eginstall.obj $(LIBS)
# /link /subsystem:WINDOWS
	editbin /subsystem:WINDOWS $(OBJDIR_NAME)/eginstall.exe

$(OBJDIR_NAME)/eginstall.obj: eginstall.c
	mkdir -p $(OBJDIR_NAME)
	cl -c -Fo$@ -DWINDOWS $(CFLAGS) eginstall.c

else
# MAC & Linux PC/SC-lite installer

ifdef MACOS
LIBS +=  -framework  Security -framework Carbon
CFLAGS += -DMAC
RESTART = $(OBJDIR_NAME)/pcscd_restart
endif

COMMON_OBJS=$(OBJDIR_NAME)/instlib.o

all: $(OBJDIR_NAME)/eginstall $(RESTART)

import:
	@echo "Nothing to Import"


clean:
	rm -f $(OBJDIR_NAME)/eginstall $(COMMON_OBJS) $(OBJDIR_NAME)/eginstall.o $(OBJDIR_NAME)/pcscd_restart.sh $(OBJDIR_NAME)/pcscd_restart $(OBJDIR_NAME)/pcscd_restart.o

libs: $(OBJDIR_NAME)/eginstall $(RESTART)

install: libs
	mkdir -p $(DIST)/coolkey_drivers/
	cp $(OBJDIR_NAME)/eginstall $(DIST)/coolkey_drivers/
ifdef MACOS
	cp $(OBJDIR_NAME)/pcscd_restart $(DIST)/coolkey_drivers/
	rm -f $(OBJDIR_NAME)/"COOL Key Install"
	ln $(OBJDIR_NAME)/eginstall $(OBJDIR_NAME)/"COOL Key Install"
	rm -f $(DIST)/coolkey_drivers/"COOL Key Install"
	ln $(DIST)/coolkey_drivers/eginstall $(DIST)/coolkey_drivers/"COOL Key Install"
endif

$(OBJDIR_NAME)/%.o: %.c
	mkdir -p $(OBJDIR_NAME)
	cc -c -o $@ $(CFLAGS)  $<

$(OBJDIR_NAME)/eginstall: $(OBJDIR_NAME)/eginstall.o $(COMMON_OBJS)
	mkdir -p $(OBJDIR_NAME)
	cc -o $(OBJDIR_NAME)/eginstall $< $(COMMON_OBJS) $(LIBS)

$(OBJDIR_NAME)/pcscd_restart: $(OBJDIR_NAME)/pcscd_restart.o $(COMMON_OBJS)
	mkdir -p $(OBJDIR_NAME)
	cc -o $(OBJDIR_NAME)/pcscd_restart $< $(COMMON_OBJS) $(LIBS)


$(OBJDIR_NAME)/pcscd_restart.sh:	pcscd_restart.sh.$(OS_ARCH)
	cp $< $@

endif

export:
	@echo "Nothing to Export"


--- NEW FILE eginstall.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
 * * Copyright (C) 2005 Red Hat, Inc.
 * * All rights reserved.
 **
 ** This library is free software; you can redistribute it and/or
 ** modify it under the terms of the GNU Lesser General Public
 ** License as published by the Free Software Foundation version
 ** 2.1 of the License.
 **
 ** This library 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
 ** Lesser General Public License for more details.
 **
 ** You should have received a copy of the GNU Lesser General Public
 ** License along with this library; if not, write to the Free Software
 ** Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 ** ***** END COPYRIGHT BLOCK *****/


#define LOGFILE "inst.log"

#ifdef WIN32 
#define INITGUID 1
#include <windows.h>
#include <stdio.h>
#include <setupapi.h>
#include <direct.h>
#include <time.h>
#include <winver.h>

#define DRIVER_COUNT 4
/* This structure defines that descriptor used for each egate driver.
 * the data described in the structure is static.
 */
typedef struct _driverInfo {
    char *devClass;		/* microsoft device class */
    char *infFile;		/* original inf file escribing the device */
    char *instFile;		/* file in the installation */
    char *deviceID;		/* Typical Device ID */
    DWORD createFlags;		/* Flags for hand creating device */
    BOOL devClassUnique;	/* true only if class is unique for egate */
    BOOL doInstall;		/* this driver should be installed */
    BOOL handInstall;
} DriverInfo;

/* dynamically determined driver information */
typedef struct _dyDriverInfo {
    char *oemFile;		/* new OEM file */
    char destPath[MAX_PATH];
} DyDriverInfo;

static const DriverInfo driverInfo[DRIVER_COUNT] = {
/* Egate PCSC device. Maps to a virtual reader. These are managed by
   The Egate bus driver. */
 { "SmartCardReader", "egaterdr.inf", "egaterdr.sys", 
			"EGATEBUS", 0, FALSE, TRUE, FALSE },
/* Driver handling the actual card driver. This one is managed by the
   plug and play handler. The first card is supposed to install the
   EgateBus handler */
 { "EgateCard", "egate.inf", "egate.sys", 
			"USB\\VID_0973&PID_0001", 0, TRUE, TRUE, FALSE },
/* Egatebus is the Reader Enumerator. It starts new readers as necessary. */
 { "Egatebus", "egatebus.inf", "egatebus.sys", 
			"EGATEBUS", DICD_GENERATE_ID, TRUE, TRUE, TRUE },
/* Unknown driver is necessary for uninstall. If an egate device was inserted
   before any egate drivers were installed, an Unknown device will have been
   created. We need to remove it before we start our install */
 { "Unknown", "none.inf", "none.sys", 
			"USB\\VID_0973&PID_0001", 0, FALSE, FALSE, FALSE },
};

static DyDriverInfo dyDriverInfo[DRIVER_COUNT] = { 0 };

#define FILE_COUNT 8
static const char *deviceFileList[FILE_COUNT] = {
 "drivers\\egate.sys",
 "drivers\\egateraw.sys",
 "egdrvins1.dll",
 "egdrvins.dll",
 "slbmqp98.dll",
 "slbmgpg.dll",
 "drivers\\egatebus.sys",
 "drivers\\egaterdr.sys",
};

static char infFilePath[MAX_PATH];
static char logFilePath[MAX_PATH];

BOOL useOS = FALSE;

typedef unsigned long TIME;


void
profile(FILE *logFile, BOOL doProfile, char  *message, void *arg, TIME last, TIME *retCurrent)
{
    static TIME epoc = 0;
    TIME current;

    if (!doProfile) {
 	return;
    }
    current  = GetTickCount();

    if (epoc == 0) {
	epoc = current;
    }
    if (retCurrent) {
	*retCurrent = current;
    }
    if (!message) {
	return;
    }
    fprintf(logFile,"@TIME:");
    fprintf(logFile, message, arg); 
    fprintf(logFile," %d ms (%d ms total)\n",  current - last, current - epoc);
}

 

#include <dbt.h>

DEFINE_GUID(IDD_CLASS_EGATECARD,0x555e05a3,0x904c,0x42cf,0xae,0xf4,
                0xee,0x40,0x35,0xec,0x63,0x62);
DEFINE_GUID(IDD_CLASS_EGATERDR,0x50dd5230,0xba8a,0x11d1,0xbf,0x5d,
                0x00,0x00,0xf8,0x05,0xf5,0x30);
DEFINE_GUID(IDD_CLASS_EGATEBUS,0x9510ee5d,0x9613,0x439a,0xad,0xb9,
                0xe4,0xde,0xa5,0xa6,0xb6,0x53);

static void
usage(char *prog)
{
    fprintf(stderr,"usage: %s [-F][-q][-9][-u][-c][-p][-O][-l logfile] [egate_path]\n",prog);
    fprintf(stderr,"\tu uninstall\tc clean\n");
    fprintf(stderr,"\tp profile\tO use slow OS calls\n");
    fprintf(stderr,"\tq quiet\n");
    fprintf(stderr,"\tF and 9 reserved for future use\n");
    return;
}

/* Utility printing functions */

/* capture the window's error string */
static void
winPerror(FILE *outFile, DWORD error, const char *msgString)
{
     char buffer[256];
     char *cp;
     DWORD ret;

     fprintf(outFile,"*** %s: ",msgString);
     sprintf(buffer,"Format message problem, error = %d (0x%x)\n", error, error);

     ret=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, buffer, 
							sizeof(buffer), NULL);
     for (cp=buffer; *cp; cp++) {
	if (*cp == '\r') *cp = ' ';
     }
     fprintf(outFile, buffer);
}


#ifdef DEBUG
/* pretty raw dump a buffer in hex and ascii */
#define MAX_ROWS 16
void
dump(FILE *logFile, void *p, int len)
{
    unsigned char *c = (char *)p;
    char string[MAX_ROWS+1];
    int i,j;

 fprintf(logFile,"Dumping buffer %x size=%d\n",p,len);
    for (i=0, j=0; i< len ; i++,j++) {
	if (j >= MAX_ROWS) {
	   string[MAX_ROWS] = 0;
	   fprintf(logFile," %s\n",string);
	   j=0;
	}
	fprintf(logFile,"%02x ",c[i]);
	string[j] =  (char) (c[i] >= ' ' && c[i] <0x7f) ? c[i] : '.' ;
    }
    if (j && j < MAX_ROWS) {
	string[j]= 0;
	for (; j < MAX_ROWS; j++) {
	    fprintf(logFile,"   ");
	}
	fprintf(logFile," %s\n",string);
    }
}

/* dump an InfInformation buffer */
void
printInf(FILE *logFile, const PSP_INF_INFORMATION sp_inf, DWORD len)
{
    char *style = NULL;

    switch (sp_inf->InfStyle) {
[...2099 lines suppressed...]
	   Copy("/etc/reader.conf","/etc/_reader.conf", 0644);
	}
    } else {
	(void)RmFile("/etc/_reader.conf");
    }
    sprintf(buf,"%s/slbEGate.bundle",path);
    install_path = strdup(buf);
    if (egate_path) {
	unsigned long current_version, install_version;
	current_version = GetBundleVersion(egate_path);
	install_version = GetBundleVersion(install_path);
	if (current_version <= install_version) {
	    RmFile("/etc/reader.conf");
	    syslog(LOG_INFO,"Replacing version %d with version %d of %s\n",
				current_version, install_version, "slbEGate.bundle");
	} else {
	    syslog(LOG_INFO,
	    	    "Newer version of E-Gate already installed"
	    	    "(oldversion = %d, newversion = %d)\n",
			current_version, install_version);
	    skip_reader_conf = 1;
	}
	free(egate_path);
    }

    if (!skip_reader_conf) {
	/* 
	 * we use _reader.conf so that we don't wind up with a partially
	 * updated file that we can't later recover from.
	 */

    if(!IsTiger)
    {    
        int readerfd;
        readerfd = open("/etc/_reader.conf", O_CREAT|O_APPEND|O_WRONLY, 0644);
        if (readerfd < 0) {
	    syslog(LOG_ERR,
		"Couldn't open /etc/_reader.conf for update err=%d (%s)\n", 
				errno, strerror(errno));
	    return RDRCNF_ERR(errno);
        }
	rc = write(readerfd, readerConf, sizeof(readerConf)-1);
	if (rc < 0) {
	    syslog(LOG_ERR,
		"Write Failure on /etc/_reader.conf err=%d (%s) fd=%d\n", 
				errno, strerror(errno), readerfd);
	    return RDRCNF_ERR(errno);
        } else if (rc < sizeof(readerConf)-1) {
	    syslog(LOG_ERR,"only wrote %d bytes to /etc/_reader.conf\n", rc);
	    return RDRCNF_ERR(errno);
	}
	close(readerfd);

        
    }

     #ifdef MAC

        // Install in same place whether Panther or Tiger
        rc = Cpdir(install_path,TigerLibPath);

     #else

	rc = Cpdir(install_path,"/etc/reader/slbEGate.bundle");

     #endif

	if (rc < 0) {
	    syslog(LOG_ERR, "Failed to copy egate driver %s"
		" to slbEGate.bundle err=%d (%s)\n", install_path,
				errno, strerror(errno));
	    return RDRCNF_ERR(errno);
	}

        if(!IsTiger)
        {
	    (void)RmFile("/etc/reader.conf");
	    rc = rename("/etc/_reader.conf","/etc/reader.conf");
	    if (rc < 0) {
	        syslog(LOG_ERR, "Failed to rename /etc/_reader.conf"
	        	" to /etc/reader.conf err=%d\n", errno, strerror(errno));
	     return RDRCNF_ERR(errno);
            }

        }

	syslog(LOG_INFO, "Installed egate. ");
    } 

    pid = FindProcessByName("pcscd");

    /* If nothing to install, don't restart pcscd */
    if (skip_reader_conf && pid != -1) {
	syslog(LOG_INFO, 
	   "Nothing new to install, pcscd running: skip restarting pcscd\n");
	return return_code;
    }


    if (pid != -1) {
	syslog(LOG_INFO,"Killing PCSCD process id %d\n", pid);

	kill( pid, SIGTERM );
	/* wait 10 seconds for the process to die */
	rc = WaitForProcessDeath(pid,10);
	if (rc == PROCESS_ALIVE) {
	   kill(pid, SIGKILL);
	   rc = WaitForProcessDeath(pid,10);
	}
	if (rc != PROCESS_DEAD) {
	   syslog(LOG_ERR,"PCSCD still running!!!");
	   return RESTART_ERR(errno);
	}
    }

    if (FileExists("/tmp/pcsc")) {
	/* clean up old pcsc files */
	syslog(LOG_INFO,"Cleaning up Old PCSC Files\n");
	rc = RmDir("/tmp/pcsc");
	if (rc != 0) {
	   syslog(LOG_ERR,"Failed to clean up /tmp/pcsc\n");
	   return_code =  CLEANUP_ERR(errno);
	}
    }

    /* now start pcscd */
#ifdef MAC
    if(!IsTiger)
    {
        rc = system("/usr/sbin/pcscd");
    }
    else
    {
        rc = 0;
        syslog(LOG_INFO,"Tiger 10.4.2 and later, does not  start /usr/sbin/pcscd \n");

    }
#else
    rc = system("/usr/local/sbin/pcscd");
#endif
    if (rc < 0) {
	syslog(LOG_ERR,"Could't restart PCSCD err=%d (%s)\n",
						errno, strerror(errno));
	return_code =  EXEC_ERR(errno);
   }

#ifdef MAC
    /* TODO this needs to be done for linux */
    /* copy the restart command to /usr/sbin */
    sprintf(buf,"%s/pcscd_restart",path);

    /* do we need to verify a hash to make sure we are installing
     * the correct pcscd_restart program? */

    /* copy restart to /usr/sbin. We do this because once we install it,
     * it cannot be removed unless the user becomes root. This allows the
     * user to move around the photon installation without loosing the
     * restart program. */
    rc = Copy(buf,"/usr/sbin/pcscd_restart",0755);
    if (rc < 0) {
	/* not fatal.. */
        syslog(LOG_INFO,"Couldn't copy pcscd_restart to /usr/sbin err=%d\n",
									errno);
    } else {
	rc = Setuid("/usr/sbin/pcscd_restart");
	if (rc < 0) {
	    /* not fatal... */
            syslog(LOG_INFO,"Couldn't setuid on pcscd_restart err=%d\n", errno);
	}
    }


    /* make sure the restart code works */

    if(!isTigerDotTwo)
    {
        rc = SetupSystemBoot();
        if (rc < 0) {
	/* not fatal.. */
            syslog(LOG_INFO,"Couldn't setup restart on boot err=%d\n",errno);
        }
    }
    else
    {
        syslog(LOG_INFO,"Tiger 10.4.2 and later, don't do SetupSystemBoot to setup restart on boot.\n");

        rc = RemoveSystemBoot();

        if( rc < 0)
        {
            syslog(LOG_INFO,"Couldn't remove restart on boot err=%d\n",errno);
        }

    }
#endif

    syslog(LOG_INFO,"Installation complete. return_code=%d\n",return_code);
    return return_code;
}
#endif


--- NEW FILE instlib.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
 ** * Copyright (C) 2005 Red Hat, Inc.
 ** * All rights reserved.
 ***
 *** This library is free software; you can redistribute it and/or
 *** modify it under the terms of the GNU Lesser General Public
 *** License as published by the Free Software Foundation version
 *** 2.1 of the License.
 ***
 *** This library 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
 *** Lesser General Public License for more details.
 ***
 *** You should have received a copy of the GNU Lesser General Public
 *** License along with this library; if not, write to the Free Software
 *** Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *** ***** END COPYRIGHT BLOCK *****/

/* MAC & Linux */

#ifndef WIN32


#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <fts.h>
#include <sys/sysctl.h>

#include "instlib.h"

#define LOWER(c) (isalpha(c) ? tolower(c) : c)
int HasString(const char *target,const char *search) {
    char c = LOWER(*search);
    int len = strlen(search);
    for  ( ; *target; target++) {
	if (LOWER(*target) == c) {
	    if (strncasecmp(target,search,len) == 0) {
		return 1;
	    }
	}
    }
    return 0;
}

int IsDirectory(const char *dir)
{
    struct stat sbuf;
    int rc;

    rc = stat(dir,&sbuf);
    if (rc == 0) {
	return ((sbuf.st_mode & S_IFDIR) == S_IFDIR);
    }
    return 0;
}


int FileExists(const char *file)
{
    struct stat sbuf;
    int rc;

    rc = stat(file,&sbuf);
    if (rc == 0) {
	return 1;
    }
    return 0;
}

#define MAX_RECURSE_LEVEL 15
#define DIR_MODE 0755
/*
 * Create a directory. Create any missing or broken 
 * components we need along the way. If we already have a
 * directory, return success.
 */
int Makedir(const char *directory, int level, int mode)
{
   int rc;
   char *buf, *cp;

   /* prevent arbitrary stack overflow */
   if (level > MAX_RECURSE_LEVEL) {
	errno = ENAMETOOLONG;
	return -1;
   }
   umask(0);

   /* just try it first */
   rc = mkdir(directory,DIR_MODE);
   if (rc != 0) {
	if (errno == EEXIST) {
	    if (IsDirectory(directory)) {
		/* we have a directory, use it */
		return 0;
	    } else  { /* must be a file */
		/* remove the file and try again */
		rc = RmFile(directory);
		if (rc == 0) {
			rc = mkdir(directory, mode);
		}
		return rc;
	    }
	}
	/* if we fail because on of the subdirectory entries was a
	 * file, or one of the subdirectory entries didn't exist,
	 * move back one component and try the whole thing again
	 */
	if ((errno != ENOENT) && (errno != ENOTDIR)) {
	    return rc;
	}
	buf = (char *)malloc(strlen(directory)+1);
	strcpy(buf,directory);
	if (cp = strrchr(buf,'/')) {
	    *cp = 0;
	    rc = Makedir(buf,level+1, mode);
	    if (rc == 0) {
	     	rc = mkdir(directory, mode);
	     }
	 }
	free(buf);
    }
    return rc;
}

#define INFO_FILE "/Contents/Info.plist"
#define MAX_VERSION_TYPES 3
/* try to find the version number. NOTE: this is not a full xml parser. A full
 * xml parser would be a bit better to use */
unsigned long GetBundleVersion(const char *bundle)
{
#ifdef xMAC
    CFBundleRef bundle;
    CURLRef	url;
    unsigned long version;

    url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, bundle, 
					kCFURLPOSIXPathStyle, true );
    if (!url) {
	return 0;
    }

    bundle = CFBundleCreate(kCFAllocatorDefault, url);
    CFRelease(url);
    if (!bundle) {
	return 0;
    }

    version = (unsigned long) CFBundleGetVersionNumber(bundle);
    CFRelease(bundle);

    return version;
#else
    FILE *infoFile;
    char *bundleFile;
    char *str;
    char buf[256];
    int versions[MAX_VERSION_TYPES];
    int i, currentType;
    unsigned long version;

    bundleFile = (char *)malloc(strlen(bundle) + strlen(INFO_FILE)+1);

    if (bundleFile == NULL) {
	return 0;
    }
    
    sprintf(bundleFile,"%s"INFO_FILE,bundle);
    infoFile = fopen(bundleFile,"r");
    free(bundleFile);
    if (infoFile == NULL) {
	return 0;
    }

    while ((str=fgets(buf, sizeof(buf),infoFile)) != NULL) {
	if (HasString(str,"CFBundleVersion")) {
    	    str=fgets(buf, sizeof(buf),infoFile);
	    break;
	}
    }
    fclose(infoFile);
    if (str == NULL) {
	return 0;
    }
    while (*str && !isdigit(*str)) {
	str++;
    }
    if (*str == 0) {
	return 0;
    }
    for (i=0; i < MAX_VERSION_TYPES; i++) {
    	versions[i] = 0;
    }
    currentType = 0;
    for (; currentType < MAX_VERSION_TYPES &&
		*str && (isdigit(*str) || *str == '.'); str++) {
	if (*str == '.') {
	   currentType++;
	   if (currentType >= MAX_VERSION_TYPES) {
		break;
	   }
	   continue;
	} 
	/* only record up to 2 digits for minor versions */
        if ((currentType != 0) && (versions[currentType] >= 10)) {
	    versions[currentType] = 99;
	    continue;
	}
	
	versions[currentType] =
	   versions[currentType] * 10 + (*str) - '0';
    }

    /* now assemble the decoded version number */
    version = 0;
    for (i=0; i < MAX_VERSION_TYPES; i++) {
	version = version * 100 + versions[i];
    }

    return version;
#endif
}

#define BUFSIZE 32*1024
int Copy(const char *src, const char *target, int mode)
{
    int fdsrc,fdtarget;
    int bytes,wbytes,rc = 0;
    char buf[BUFSIZE];

    fdsrc = open(src,O_RDONLY);
    if (fdsrc < 0) {
	return fdsrc;
    }
    fdtarget = open(target, O_WRONLY|O_CREAT|O_TRUNC, mode);
    if (fdtarget < 0) {
	close(fdsrc);
	return fdtarget;
    }

    while ((bytes = read(fdsrc,buf,sizeof(buf))) > 0) {
	wbytes = write(fdtarget,buf, bytes);
	if (wbytes != bytes) {
	    rc = -1;
	    break;
	}
    }
    if (bytes < 0) {
	rc = bytes;
    }

    close(fdtarget);
    close(fdsrc);
    return rc;
}

    

int Cpdir(const char *source,const char *target)
{
    FTS *dir;
    FTSENT *entry;
    int rc = 0;
    char buf[MAXPATHLEN];
    char *files[2];
    int mode;
    int cdir;

    files[0]=".";
    files[1]= 0;

    cdir = open(".",O_RDONLY);
    rc = chdir(source);
    if (rc != 0) {
	close(cdir);
	return rc;
    }

    rc = Makedir(target, 0, DIR_MODE);
    if (rc != 0) {
	return rc;
    }

    dir = fts_open(files,FTS_NOCHDIR|FTS_LOGICAL,NULL);
    if (dir == NULL) {
	return -1;
    }

    while (entry = fts_read(dir)) {
	sprintf(buf,"%s/%s",target,entry->fts_accpath);
	mode = DIR_MODE;
        if (entry->fts_statp) {
	   mode = entry->fts_statp->st_mode;
	}
	switch (entry->fts_info) {
	case FTS_D:
	   /* need more .... */
	   rc = Makedir(buf, 0, mode);
	   break;
	case FTS_F:
	   rc = Copy(entry->fts_path, buf, mode);
	   break;
	}
	if (rc != 0) break;
    }
    fchdir(cdir);
    close(cdir);
    fts_close(dir);
    return rc;
}

int RmFile(const char *fileName) 
{
    int rc = unlink(fileName);
    if ((rc < 0) && (errno == EPERM)) {
	chmod(fileName,0644);
	rc = unlink(fileName);
    }
    return rc;
}

int RmDir(const char *dirName) 
{
    int rc = 0;
    int count = 0;
    FTS *dir;
    FTSENT *entry;
    char *files[2];

    files[0] = (char *) dirName;
    files[1] = 0;
    if (FileExists(dirName)) {
	if (IsDirectory(dirName)) {
	    dir = fts_open(files,FTS_NOCHDIR|FTS_PHYSICAL,NULL);
	    if (dir == NULL) {
		return -1;
	    }

	    while (entry = fts_read(dir)) {
		switch (entry->fts_info) {
		case FTS_DP:
		    count++;
		    rc = rmdir(entry->fts_path);
		    break;
		case FTS_DEFAULT:
		case FTS_SL:
		case FTS_SLNONE:
		case FTS_NS:
		case FTS_NSOK:
		case FTS_F:
		    rc = RmFile(entry->fts_path);
		    break;
	        }
		if (rc != 0) break;
	   }
	   fts_close(dir);
	   if (count == 0) {
		rc = rmdir(dirName);
	   }
	   return rc;
	} else {
	   return RmFile(dirName);
	}
     }
     return 0;
}


char *
GetFullPath(const char *prog, int includeProg) {
    char *instDir, *end;
    char *cwd = NULL;
    char *new = NULL;

    /* get the install directory */
    instDir = strdup(prog);
    if ((end = strrchr(instDir, '/')) == 0) {
	if (includeProg) {
	    cwd = getcwd(NULL, 0);
	    new = (char *)malloc(strlen(cwd)+strlen(instDir)+2);
	    sprintf(new,"%s/%s",cwd,instDir);
	} else {
	    new = getcwd(NULL,0);
	}
    } else {
	if (!includeProg) {
	    *end = 0;
	}
	if (*instDir != '/') {
	    cwd = getcwd(NULL,0);
	    new = (char *)malloc(strlen(cwd)+strlen(instDir)+2);
	    char *instPtr = instDir;

	    /* handle . and .. prefixes */
	    if (*instDir == '.') {
		if ((instDir[1] = 0)  ||  /* . only */
		    ((instDir[1] == '.')  &&  /* .. & ../ */
			((instDir[2] == '/') || (instDir[2] == 0))) || 
		    (instDir[1] == '/') ) { /* ./ */

		    instPtr++;
		    if (*instPtr == '.') {
		        /* back up one element */
		        if ((end = strrchr(cwd,'/')) == 0) {
			    *end = 0;
		        } else {
			    *cwd = 0;
		        }
		        instPtr++;
		    }
		    if (*instPtr == '/') {
		        instPtr ++;
		    }
	        }
	    }
	    sprintf(new,"%s/%s",cwd,instPtr);
	}
    }
    if (cwd) {
	free(cwd);
    }
    if (new) {
	free(instDir);
	instDir = new;
    }
    return instDir;
}


#ifdef MAC
typedef struct kinfo_proc kinfo_proc;
static const int    listProc[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
static const int    listProcLen=(sizeof(listProc)/sizeof(int)) -1;
#endif

/*
 * find the PCSCD process
 */
#define MAX_RETRIES 100

int FindProcessByName(const char *procName)
{
#ifdef MAC
    int                 ret;
    kinfo_proc *        pList;
    size_t              length;
    int 		processCount;
    int			proc;
    int			i;
    int 		pid = -1;
    /*
     * the process table is always changing. we may need to loop several times
     * before we actually get the process list. We start with a large static
     * buffer hoping that we don't have to actually allocate anything in the
     * normal case 
     */ 
    pList = NULL; 
    length =  0;
    /* don't hang forever */
    for (i=0; i< MAX_RETRIES; i++) {
        length = 0;
        ret = sysctl( (int *) listProc, listProcLen, NULL, &length, NULL, 0);
        if (ret < 0) {
	    break;
	}
	pList = malloc(length);
	if (pList == NULL) {
	    break;
	}

	ret = sysctl( (int *) listProc, listProcLen, pList, &length, NULL, 0);
	if (ret < 0) {
	    if (errno == ENOMEM) {
		free(pList);
		pList = NULL;
		continue;
	    }
	}

	break;
    }

    /* just couldn't get our process list */
    if (pList == NULL) {
	perror("process list failed:");
	return -1;
    }

    /* now loop through lookin for our process */
    processCount = length / sizeof(kinfo_proc);
    for (proc=0; proc < processCount; proc++) {
	if (strcmp(pList[proc].kp_proc.p_comm,procName) == 0) {
	    pid = pList[proc].kp_proc.p_pid;
	    break;
	}
    }

    free(pList);
    return pid;
#else
    return -1;
#endif
}

int
WaitForProcessDeath(int pid, int retries)
{
    int rc;
    int i;

    /* loop for our retries until we can't send a signal to the process */
    for (i=0; i < retries; i++) {
	rc = kill(pid, 0);
	if ( rc!= 0 ) {
	    break;
	}
	sleep(1);
    }
    if (rc == 0) {
	/* process is still around past the retries */
	return PROCESS_ALIVE;
    }
    if (errno == EPERM) {
        /* we don't even have permission to kill the process */
	return PROCESS_IMPERVIOUS;
    }
    /* process has been killed */
    return PROCESS_DEAD;
}

#ifndef O_EXLOCK
#define O_EXLOCK 0
#endif

int
Setuid(const char *path) {
    /* NULL for now */
    struct stat statbuf;
    int fd;
    int rc, mode; 
    int ret = 0;

    fd = open(path, O_NONBLOCK|O_RDONLY|O_EXLOCK, 0);
    if (fd < 0) {
	return errno;
    }

    /* Get info about the file */
    rc = fstat(fd, &statbuf);
    if (rc < 0) {
	close(fd);
  	return errno;
    }

    /* make sure the file is owned by root */
    if (statbuf.st_uid != 0) {
 	rc = fchown(fd, 0, statbuf.st_gid); 
	if (rc < 0)  {
	    close(fd);
  	    return errno;
	}
    }

    /* turn off group and other write permission so the 
     * file can't be replaced */
    mode = statbuf.st_mode & ~(S_IWGRP|S_IWOTH);
    rc = fchmod(fd, mode | S_ISUID); /* set the uid bit */
    if (rc < 0) ret = errno;

    close(fd);
    return ret;
}

const char smartCardServices[] = {
"#!/bin/sh\n"
"\n"
"##\n"
"# Start PC/SC\n"
"##\n"
"\n"
". /etc/rc.common\n"
"\n"
"	ConsoleMessage \"Starting SmartCard Services\"\n"
"	/usr/sbin/pcscd\n"
"\n" };

/* SmartcardServices */
/* StartupParameters.plist */
const char startupParametersPList[] = {
"{\n"
" Description     = \"PC/SC Daemon\";\n"
" Provides        = (\"SmartCardServices\");\n"
" Requires        = ();\n"
" OrderPreference = \"None\";\n"
" Messages =\n"
" {\n"
"   start = \"Starting SmartCard Services\";\n"
"   stop  = \"Stopping SmartCard Services\";\n"
" };\n"
"}\n"
"\n" };


#define STARTUP_DIR "/System/Library/StartupItems"

int 
RemoveSystemBoot()
{

    int rc;

    if (IsDirectory(STARTUP_DIR"/SmartCardServices")) {

        /*Blow it away **/
        rc = RmDir(STARTUP_DIR"/SmartCardServices");
        if (rc < 0) {
            return -1;
        }
    }

    return rc;
}

int
SetupSystemBoot()
{
    int rc,fd; 

    if (!IsDirectory(STARTUP_DIR"/SmartCardServices")) {

	/*check for errors and clean up so we don't have any partial installs*/
	rc = Makedir(STARTUP_DIR"/SmartCardServices", 0, DIR_MODE);
	if (rc < 0) {
	    return -1;
	}
    }
    if (!FileExists(STARTUP_DIR"/SmartCardServices/SmartcardServices")) {
	fd = open(STARTUP_DIR"/SmartCardServices/_SmartcardServices", 
						O_CREAT|O_TRUNC|O_WRONLY);
	if (fd < 0) {
	    return -1;
	}
  	rc = write(fd,smartCardServices,sizeof(smartCardServices)-1);
	if (rc < 0) {
	    return -1;
	}
	if (rc < sizeof(smartCardServices)-1) {
	    return -1;
	    errno = ENOSPC;
	    return -1;
	}
	close(fd);
	rc = rename(STARTUP_DIR"/SmartCardServices/_SmartcardServices", 
		    STARTUP_DIR"/SmartCardServices/SmartcardServices");
	if (rc < 0) {
	    return -1;
	}
    }
    if (!FileExists(STARTUP_DIR"/SmartCardServices/StartupParameters.plist")) {
	fd = open(STARTUP_DIR"/SmartCardServices/_StartupParameters.plist", 
						O_CREAT|O_TRUNC|O_WRONLY);
	if (fd < 0) {
	    return -1;
	}
  	rc = write(fd, startupParametersPList, sizeof(startupParametersPList)-1);
	if (rc < 0) {
	    return -1;
	}
	if (rc < sizeof(startupParametersPList)-1) {
	    errno = ENOSPC;
	    return -1;
	}
	close(fd);
	rc = rename(STARTUP_DIR"/SmartCardServices/_StartupParameters.plist", 
		    STARTUP_DIR"/SmartCardServices/StartupParameters.plist"); 
	if (rc < 0) {
	    return -1;
	}
   }
   return 0;
}

#endif


--- NEW FILE instlib.h ---
/* ***** BEGIN COPYRIGHT BLOCK *****
 *** * Copyright (C) 2005 Red Hat, Inc.
 *** * All rights reserved.
 ***
 *** This library is free software; you can redistribute it and/or
 *** modify it under the terms of the GNU Lesser General Public
 *** License as published by the Free Software Foundation version
 *** 2.1 of the License.
 ***
 *** This library 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
 *** Lesser General Public License for more details.
 ***
 *** You should have received a copy of the GNU Lesser General Public
 *** License along with this library; if not, write to the Free Software
 *** Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *** ***** END COPYRIGHT BLOCK *****/

#ifndef _INSTLILB_H_
#define _INSTLILB_H_ 1

/* macros for encoding function return codes to pass to the calling
 * process so it can present reasonable UI for when things go wrong */
#define MK_ERR(type,val)   (((type)<<16)|((val)&0xffff))
#define _ABS(x)		((x) < 0 ? (x)*-1:(x))
#define _NORMALIZE(x,base,op) ((x) op (base) ? (x -(base)) : (x))

#define ARG_ERR(x)	MK_ERR(0, x) /* 1, 2, 3 for x */
#define PID_ERR(x)	MK_ERR(1, x) /* returned status */
#define AUTH_ERR(x)	MK_ERR(2, _ABS(_NORMALIZE(x,-6000,<))) /* Mac auth */
#define RDRCNF_ERR(x)	MK_ERR(3, x) /* errno */
#define EXEC_ERR(x)	MK_ERR(4, x) /* errno */
#define RESTART_ERR(x)	MK_ERR(5, x) /* errno */
#define CLEANUP_ERR(x)	MK_ERR(6, x) /* errno */


#define BUFSIZE 32*1024
/* does the target string exist in search string. Case insensitive compare */
int HasString(const char *target,const char *search);

/* is the given file a directory */
int IsDirectory(const char *dir);

/* does the given file exist */
int FileExists(const char *file);

/* Make a directory path. removes regular files found along the path, 
 * recursively builds all the directories needed along the path 
 * (like mkdir -p) */
int Makedir(const char *directory, int level, int mode);

/* find the version number of a bundle */
unsigned long GetBundleVersion(const char *bundle);

/* copy file src to file specified by target */
int Copy(const char *src, const char *target, int mode);

/* copy a directory and all it's contents from source to target.
 * symbolic links are followed */
int Cpdir(const char *source,const char *target);

/* Remove a File... force the removal with chown if necessary */
int RmFile(const char *file);

/* Remove a directory and all it's contents */
int RmDir(const char *directory);

/* expand the path name of a program name. if includeProg is true, the
 * path includes the program name, otherwise it's just the directory path
 * of the program */
char * GetFullPath(const char *prog, int includeProg);

/* find a process id from it's name. if more than on, only the first one is
 * returned */
int FindProcessByName(const char *procName);

#define PROCESS_ALIVE 1
#define PROCESS_IMPERVIOUS 2
#define PROCESS_DEAD 3
/* wait for a process to die */
int WaitForProcessDeath(int pid, int retries);

/* set the permissions and UID bits on a file */
int Setuid(const char *path);

/* setup pcscd to restart on system boot */
int SetupSystemBoot(void);

#endif /* !_INSTLIB_H_ */




More information about the Fedora-directory-commits mailing list