/* * PortsHelper.c * PortsNotifier * * Created by eddyxu@gmail.com on 07-5-25. * Copyright 2007 portsnotifier.sf.net All rights reserved. * * PortsNotifier is released under BSD License */ #include #include #include #include #include #include "PNDefines.h" /** * @brief store property list to file * * @param propertyList a reference to property list * @param fileURL url of file location * */ void WritePropertyListToFile( CFPropertyListRef propertyList, CFURLRef fileURL ) { CFDataRef xmlData; Boolean status; SInt32 errorCode; // Convert the property list into XML data. xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList ); // Write the XML data to the file. status = CFURLWriteDataAndPropertiesToResource ( fileURL, // URL to use xmlData, // data to write NULL, &errorCode); CFRelease(xmlData); } /// load property list form file that named from fileURL CFPropertyListRef CreatePropertyListFromFile( CFURLRef fileURL ) { CFPropertyListRef propertyList; CFStringRef errorString; CFDataRef resourceData; Boolean status; SInt32 errorCode; // Read the XML file. status = CFURLCreateDataAndPropertiesFromResource( kCFAllocatorDefault, fileURL, &resourceData, // place to put file data NULL, NULL, &errorCode); // Reconstitute the dictionary using the XML data. propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault, resourceData, kCFPropertyListImmutable, &errorString); CFRelease( resourceData ); return propertyList; } /// check if the ports in installed int pn_is_ports_installed(void) { return access(PN_PORT_PATH, F_OK) < 0 ? 0 : 1; } /// sync the ports int pn_sync_ports(void) { if(!pn_is_ports_installed()) return 1; syslog(LOG_INFO ,"Run port selfupdate"); return system("/opt/local/bin/port selfupdate"); } /// create the property list for launchd CFDictionaryRef pn_create_launchd_plist(int interval){ CFMutableDictionaryRef dict; CFNumberRef num; int seconds = interval * 60; // translate to seconds // Create a dictionary that will hold the data. dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); CFDictionarySetValue(dict, CFSTR("Label"), CFSTR(PN_APP_ID)); CFDictionarySetValue(dict, CFSTR("Program"), CFSTR(PN_HELPER_PATH)); CFDictionarySetValue(dict, CFSTR("ServiceDescription"), CFSTR("Automatic update macports")); CFDictionarySetValue(dict, CFSTR("StandardErrorPath"), CFSTR("/var/log/portsnotifier.log")); num = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &seconds ); CFDictionarySetValue( dict, CFSTR("StartInterval"), num ); CFRelease( num ); int timeout = 125; num = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &timeout ); CFDictionarySetValue( dict, CFSTR("TimeOut"), num ); CFRelease( num ); CFDictionarySetValue( dict, CFSTR("UserName"), CFSTR("root")); return dict; } /// write launchd plist with new startInterval int pn_write_plist(int interval) { if(interval < 0) return -1; syslog(LOG_INFO, "Modified interval to: %d", interval); CFPropertyListRef propertyList; CFURLRef fileURL; fileURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, CFSTR(PN_LAUNCHD_PLIST), // file path name kCFURLPOSIXPathStyle, // interpret as POSIX path false ); propertyList = pn_create_launchd_plist(interval); WritePropertyListToFile( propertyList, fileURL ); CFRelease(propertyList); return 0; } void pn_usage(void) { printf("macports-sync-agent -- Helper for MacPorts Notifier\n"); printf("Usage: macports-sync-agent [OPTIONS]\n"); printf("Options:\n"); printf("-i \t\tsetting the interval of calling helper by launchd\n"); printf("-h\t\t\tdisplay this help\n"); printf("\nIf no options be provided, macports-sync-agent will do \"port sync\"\n"); } int main(int argc, char * const argv[]) { openlog("macports-sync-agent", (LOG_CONS|LOG_PERROR|LOG_PID), LOG_DAEMON); int ch, ret; while((ch = getopt(argc, argv, "hi:")) != -1){ switch (ch) { case 'h': pn_usage(); exit(0); break; case 'i': ret = pn_write_plist(atoi(optarg)); return ret; break; case '?': default: pn_usage(); exit(0); break; } } argc -= optind; argv += optind; ret = pn_sync_ports(); closelog(); return ret; }