int do_gzip(const char* strGZ, const char* strInput) { // take an input file (strInput) and turn it into a compressed file (strGZ) // get rid of the input file after FILE* fIn = boinc_fopen(strInput, "rb"); if (!fIn) return 1; //error gzFile fOut = gzopen(strGZ, "wb"); if (!fOut) return 1; //error fseek(fIn, 0, SEEK_SET); // go to the top of the files gzseek(fOut, 0, SEEK_SET); unsigned char buf[1024]; long lRead = 0, lWrite = 0; while (!feof(fIn)) { // read 1KB at a time until end of file memset(buf, 0x00, 1024); lRead = 0; lRead = fread(buf, 1, 1024, fIn); lWrite = gzwrite(fOut, buf, lRead); if (lRead != lWrite) break; } gzclose(fOut); fclose(fIn); if (lRead != lWrite) return 1; //error -- read bytes != written bytes // if we made it here, it compressed OK, can erase strInput and leave boinc_delete_file(strInput); return 0; }
// check a running benchmark thread/process. // void check_benchmark(BENCHMARK_DESC& desc) { #ifdef _WIN32 DWORD exit_code = 0; GetExitCodeThread(desc.handle, &exit_code); if (exit_code != STILL_ACTIVE) { CloseHandle(desc.handle); desc.done = true; } #else int retval; int exit_code = 0; retval = waitpid(desc.pid, &exit_code, WNOHANG); if (retval) { desc.done = true; FILE* f = fopen(desc.filename, "r"); if (!f) { desc.error = true; return; } retval = desc.host_info.parse_cpu_benchmarks(f); fclose(f); boinc_delete_file(desc.filename); if (retval) { desc.error = true; } } #endif }
// exit handler: really only meant to handle exits() called by GLUT... // void restart() { // don't do anything except when exit is called from the graphics-thread if (!pthread_equal(pthread_self(), graphics_thread)) { if (debug) fprintf(stderr, "exit() was called from worker-thread\n"); return; } if (debug) fprintf(stderr, "restart: exit() called from graphics-thread.\n"); // if we are standalone and glut was initialized, // we assume user pressed 'close', and we exit the app // // if (glut_is_initialized ) { if (boinc_is_standalone()) { if (debug) fprintf(stderr, "Assuming user pressed 'close'... means we're exiting now.\n" ); if (boinc_delete_file(LOCKFILE) != 0) { perror ("Failed to remove lockfile..\n"); } return; } } // re-install the exit-handler to catch glut's notorious exits()... // atexit(restart); // jump back to entry-point in xwin_graphics_event_loop(); // if (debug) fprintf(stderr, "restart: Jumping back to event_loop.\n"); longjmp(jbuf, JUMP_EXIT); }
int GUI_HTTP::do_rpc_post(GUI_HTTP_OP* op, std::string url, std::string input_file, std::string output_file) { int retval; if (state != GUI_HTTP_STATE_IDLE) { return ERR_RETRY; } http_op.set_proxy(&gstate.proxy_info); boinc_delete_file(output_file.c_str()); retval = http_op.init_post(url.c_str(), input_file.c_str(), output_file.c_str()); if (!retval) retval = gstate.http_ops->insert(&http_op); if (!retval) { gui_http_op = op; state = GUI_HTTP_STATE_BUSY; } return retval; }
int GUI_HTTP::do_rpc_post( GUI_HTTP_OP* op, char* url, const char* input_file, const char* output_file, bool is_bkgd ) { int retval; if (gui_http_state != GUI_HTTP_STATE_IDLE) { return ERR_RETRY; } boinc_delete_file(output_file); retval = http_op.init_post(0, url, input_file, output_file); if (retval) return retval; gstate.http_ops->insert(&http_op); gui_http_op = op; gui_http_state = GUI_HTTP_STATE_BUSY; http_op.is_background = is_bkgd; return 0; }
int GUI_HTTP::do_rpc( GUI_HTTP_OP* op, const char* url, const char* output_file, bool is_bkgd ) { int retval; // this check should be done at a higher level. // Do it here too just in case // if (gui_http_state != GUI_HTTP_STATE_IDLE) { return ERR_RETRY; } boinc_delete_file(output_file); retval = http_op.init_get(0, url, output_file, true); if (retval) return retval; gstate.http_ops->insert(&http_op); gui_http_op = op; gui_http_state = GUI_HTTP_STATE_BUSY; http_op.is_background = is_bkgd; return 0; }
int PROJECT_INIT::remove() { clear(); return boinc_delete_file(PROJECT_INIT_FILENAME); }
static void remove_benchmark_file(int which) { boinc_delete_file(file_names[which]); }
// Write the client_state.xml file // int CLIENT_STATE::write_state_file() { MFILE mf; int retval, ret1, ret2, attempt; #ifdef _WIN32 char win_error_msg[4096]; #endif for (attempt=1; attempt<=MAX_STATE_FILE_WRITE_ATTEMPTS; attempt++) { if (attempt > 1) boinc_sleep(1.0); if (log_flags.statefile_debug) { msg_printf(0, MSG_INFO, "[statefile] Writing state file" ); } #ifdef _WIN32 retval = mf.open(STATE_FILE_NEXT, "wc"); #else retval = mf.open(STATE_FILE_NEXT, "w"); #endif if (retval) { if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) { msg_printf(0, MSG_INTERNAL_ERROR, "Can't open %s: %s", STATE_FILE_NEXT, boincerror(retval) ); } if (attempt < MAX_STATE_FILE_WRITE_ATTEMPTS) continue; return ERR_FOPEN; } MIOFILE miof; miof.init_mfile(&mf); ret1 = write_state(miof); ret2 = mf.close(); if (ret1) { if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) { msg_printf(NULL, MSG_INTERNAL_ERROR, "Couldn't write state file: %s", boincerror(retval) ); } if (attempt < MAX_STATE_FILE_WRITE_ATTEMPTS) continue; return ret1; } if (ret2) { if (attempt < MAX_STATE_FILE_WRITE_ATTEMPTS) continue; return ret2; } // only attempt to rename the current state file if it exists. // if (boinc_file_exists(STATE_FILE_NAME)) { if (boinc_file_exists(STATE_FILE_PREV)) { retval = boinc_delete_file(STATE_FILE_PREV); if (retval) { if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) { #ifdef _WIN32 msg_printf(0, MSG_INFO, "Can't delete previous state file; %s", windows_format_error_string(GetLastError(), win_error_msg, sizeof(win_error_msg)) ); #else msg_printf(0, MSG_INFO, "Can't delete previous state file: %s", strerror(errno) ); #endif } if (attempt < MAX_STATE_FILE_WRITE_ATTEMPTS) continue; } } retval = boinc_rename(STATE_FILE_NAME, STATE_FILE_PREV); if (retval) { if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) { #ifdef _WIN32 msg_printf(0, MSG_INFO, "Can't rename current state file to previous state file; %s", windows_format_error_string(GetLastError(), win_error_msg, sizeof(win_error_msg)) ); #else msg_printf(0, MSG_INFO, "Can't rename current state file to previous state file: %s", strerror(errno) ); #endif } if (attempt < MAX_STATE_FILE_WRITE_ATTEMPTS) continue; } } retval = boinc_rename(STATE_FILE_NEXT, STATE_FILE_NAME); if (log_flags.statefile_debug) { msg_printf(0, MSG_INFO, "[statefile] Done writing state file" ); } if (!retval) break; // Success! if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) { #ifdef _WIN32 msg_printf(0, MSG_INFO, "rename error: %s", windows_format_error_string(GetLastError(), win_error_msg, sizeof(win_error_msg)) ); #elif defined (__APPLE__) if (log_flags.statefile_debug) { system("ls -al /Library/Application\\ Support/BOINC\\ Data/client*.*"); } #endif } if (attempt < MAX_STATE_FILE_WRITE_ATTEMPTS) continue; return ERR_RENAME; } return 0; }
// do an account manager RPC; // if URL is null, detach from current account manager // int ACCT_MGR_OP::do_rpc( std::string _url, std::string name, std::string password_hash, bool _via_gui ) { int retval; unsigned int i; char url[256], password[256], buf[256]; FILE *pwdf; strlcpy(url, _url.c_str(), sizeof(url)); error_num = ERR_IN_PROGRESS; via_gui = _via_gui; if (global_prefs_xml) { free(global_prefs_xml); global_prefs_xml = 0; } // if null URL, detach from current AMS // if (!strlen(url) && strlen(gstate.acct_mgr_info.acct_mgr_url)) { msg_printf(NULL, MSG_INFO, "Removing account manager info"); gstate.acct_mgr_info.clear(); boinc_delete_file(ACCT_MGR_URL_FILENAME); boinc_delete_file(ACCT_MGR_LOGIN_FILENAME); error_num = 0; for (i=0; i<gstate.projects.size(); i++) { PROJECT* p = gstate.projects[i]; p->attached_via_acct_mgr = false; p->ams_resource_share = -1; } return 0; } canonicalize_master_url(url); if (!valid_master_url(url)) { error_num = ERR_INVALID_URL; return 0; } strlcpy(ami.acct_mgr_url, url, sizeof(ami.acct_mgr_url)); strlcpy(ami.acct_mgr_name, "", sizeof(ami.acct_mgr_name)); strlcpy(ami.login_name, name.c_str(), sizeof(ami.login_name)); strlcpy(ami.password_hash, password_hash.c_str(), sizeof(ami.password_hash)); FILE* f = boinc_fopen(ACCT_MGR_REQUEST_FILENAME, "w"); if (!f) return ERR_FOPEN; fprintf(f, "<acct_mgr_request>\n" " <name>%s</name>\n" " <password_hash>%s</password_hash>\n" " <host_cpid>%s</host_cpid>\n" " <domain_name>%s</domain_name>\n" " <client_version>%d.%d.%d</client_version>\n" " <run_mode>%s</run_mode>\n", name.c_str(), password_hash.c_str(), gstate.host_info.host_cpid, gstate.host_info.domain_name, gstate.core_client_version.major, gstate.core_client_version.minor, gstate.core_client_version.release, run_mode_name[gstate.run_mode.get_perm()] ); if (strlen(gstate.acct_mgr_info.previous_host_cpid)) { fprintf(f, " <previous_host_cpid>%s</previous_host_cpid>\n", gstate.acct_mgr_info.previous_host_cpid ); } // If the AMS requested it, send GUI RPC port and password hash. // This is for the "farm" account manager so it // can know where to send GUI RPC requests to // without having to configure each host // if (gstate.acct_mgr_info.send_gui_rpc_info) { if (gstate.cmdline_gui_rpc_port) { fprintf(f," <gui_rpc_port>%d</gui_rpc_port>\n", gstate.cmdline_gui_rpc_port); } else { fprintf(f," <gui_rpc_port>%d</gui_rpc_port>\n", GUI_RPC_PORT); } if (boinc_file_exists(GUI_RPC_PASSWD_FILE)) { strcpy(password, ""); pwdf = fopen(GUI_RPC_PASSWD_FILE, "r"); if (pwdf) { if (fgets(password, 256, pwdf)) { strip_whitespace(password); } fclose(pwdf); } fprintf(f," <gui_rpc_password>%s</gui_rpc_password>\n", password); } } for (i=0; i<gstate.projects.size(); i++) { PROJECT* p = gstate.projects[i]; fprintf(f, " <project>\n" " <url>%s</url>\n" " <project_name>%s</project_name>\n" " <suspended_via_gui>%d</suspended_via_gui>\n" " <account_key>%s</account_key>\n" " <hostid>%d</hostid>\n" "%s" " </project>\n", p->master_url, p->project_name, p->suspended_via_gui, p->authenticator, p->hostid, p->attached_via_acct_mgr?" <attached_via_acct_mgr/>\n":"" ); } if (boinc_file_exists(GLOBAL_PREFS_FILE_NAME)) { FILE* fprefs = fopen(GLOBAL_PREFS_FILE_NAME, "r"); if (fprefs) { copy_stream(fprefs, f); fclose(fprefs); } } if (strlen(gstate.acct_mgr_info.opaque)) { fprintf(f, " <opaque>\n%s\n" " </opaque>\n", gstate.acct_mgr_info.opaque ); } fprintf(f, "</acct_mgr_request>\n"); fclose(f); sprintf(buf, "%srpc.php", url); retval = gstate.gui_http.do_rpc_post( this, buf, ACCT_MGR_REQUEST_FILENAME, ACCT_MGR_REPLY_FILENAME ); if (retval) { error_num = retval; return retval; } msg_printf(NULL, MSG_INFO, "Contacting account manager at %s", url); return 0; }
// do an account manager RPC; // if URL is null, detach from current account manager // int ACCT_MGR_OP::do_rpc(ACCT_MGR_INFO& _ami, bool _via_gui) { int retval; unsigned int i; char buf[256]; ami = _ami; error_num = ERR_IN_PROGRESS; error_str = ""; via_gui = _via_gui; global_prefs_xml = ""; // if null URL, detach from current AMS // if (!strlen(ami.master_url) && strlen(gstate.acct_mgr_info.master_url)) { msg_printf(NULL, MSG_INFO, "Removing account manager info"); gstate.acct_mgr_info.clear(); boinc_delete_file(ACCT_MGR_URL_FILENAME); boinc_delete_file(ACCT_MGR_LOGIN_FILENAME); error_num = 0; for (i=0; i<gstate.projects.size(); i++) { gstate.projects[i]->detach_ams(); } ::rss_feeds.update_feed_list(); gstate.set_client_state_dirty("detach from AMS"); return 0; } canonicalize_master_url(ami.master_url, sizeof(ami.master_url)); if (!valid_master_url(ami.master_url)) { error_num = ERR_INVALID_URL; return 0; } FILE* f = boinc_fopen(ACCT_MGR_REQUEST_FILENAME, "w"); if (!f) return ERR_FOPEN; fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" "<acct_mgr_request>\n" ); if (strlen(ami.authenticator)) { fprintf(f, " <authenticator>%s</authenticator>\n", ami.authenticator ); } else { fprintf(f, " <name>%s</name>\n" " <password_hash>%s</password_hash>\n", ami.login_name, ami.password_hash ); } fprintf(f, " <host_cpid>%s</host_cpid>\n" " <domain_name>%s</domain_name>\n" " <client_version>%d.%d.%d</client_version>\n" " <run_mode>%s</run_mode>\n", gstate.host_info.host_cpid, gstate.host_info.domain_name, gstate.core_client_version.major, gstate.core_client_version.minor, gstate.core_client_version.release, run_mode_name[gstate.cpu_run_mode.get_perm()] ); gstate.write_platforms(NULL, f); if (strlen(gstate.acct_mgr_info.previous_host_cpid)) { fprintf(f, " <previous_host_cpid>%s</previous_host_cpid>\n", gstate.acct_mgr_info.previous_host_cpid ); } // If the AMS requested it, send GUI RPC port and password. // This is for the "farm" account manager so it // can know where to send GUI RPC requests to // without having to configure each host // if (gstate.acct_mgr_info.send_gui_rpc_info) { if (gstate.cmdline_gui_rpc_port) { fprintf(f," <gui_rpc_port>%d</gui_rpc_port>\n", gstate.cmdline_gui_rpc_port); } else { fprintf(f," <gui_rpc_port>%d</gui_rpc_port>\n", GUI_RPC_PORT); } if (boinc_file_exists(GUI_RPC_PASSWD_FILE)) { char gui_rpc_password[256]; safe_strcpy(gui_rpc_password, ""); FILE* pwdf = fopen(GUI_RPC_PASSWD_FILE, "r"); if (pwdf) { if (fgets(gui_rpc_password, 256, pwdf)) { strip_whitespace(gui_rpc_password); } fclose(pwdf); } fprintf(f, " <gui_rpc_password>%s</gui_rpc_password>\n", gui_rpc_password ); } } for (i=0; i<gstate.projects.size(); i++) { PROJECT* p = gstate.projects[i]; double not_started_dur, in_progress_dur; p->get_task_durs(not_started_dur, in_progress_dur); fprintf(f, " <project>\n" " <url>%s</url>\n" " <project_name>%s</project_name>\n" " <suspended_via_gui>%d</suspended_via_gui>\n" " <hostid>%d</hostid>\n" " <not_started_dur>%f</not_started_dur>\n" " <in_progress_dur>%f</in_progress_dur>\n" " <attached_via_acct_mgr>%d</attached_via_acct_mgr>\n" " <dont_request_more_work>%d</dont_request_more_work>\n" " <detach_when_done>%d</detach_when_done>\n" " <ended>%d</ended>\n" " <resource_share>%f</resource_share>\n" " <disk_usage>%f</disk_usage>\n" " <disk_share>%f</disk_share>\n", p->master_url, p->project_name, p->suspended_via_gui?1:0, p->hostid, not_started_dur, in_progress_dur, p->attached_via_acct_mgr?1:0, p->dont_request_more_work?1:0, p->detach_when_done?1:0, p->ended?1:0, p->resource_share, p->disk_usage, p->disk_share ); // send work and starvation-related info // if (ami.dynamic) { fprintf(f, " <nrpc_failures>%d</nrpc_failures>\n" " <cpu_ec>%f</cpu_ec>\n" " <cpu_time>%f</cpu_time>\n" " <gpu_ec>%f</gpu_ec>\n" " <gpu_time>%f</gpu_time>\n" " <njobs_success>%d</njobs_success>\n" " <njobs_error>%d</njobs_error>\n", p->nrpc_failures, p->cpu_ec, p->cpu_time, p->gpu_ec, p->gpu_time, p->njobs_success, p->njobs_error ); for (int j=0; j<coprocs.n_rsc; j++) { if (p->sched_req_no_work[j]) { fprintf(f, " <sched_req_no_work>%s</sched_req_no_work>\n", coprocs.coprocs[j].type ); } } } if (p->attached_via_acct_mgr) { fprintf(f, " <account_key>%s</account_key>\n", p->authenticator ); } fprintf(f, " </project>\n" ); } MIOFILE mf; mf.init_file(f); // send working prefs // fprintf(f, "<working_global_preferences>\n"); gstate.global_prefs.write(mf); fprintf(f, "</working_global_preferences>\n"); if (boinc_file_exists(GLOBAL_PREFS_FILE_NAME)) { FILE* fprefs = fopen(GLOBAL_PREFS_FILE_NAME, "r"); if (fprefs) { copy_stream(fprefs, f); fclose(fprefs); } } gstate.host_info.write(mf, !cc_config.suppress_net_info, true); if (strlen(gstate.acct_mgr_info.opaque)) { fprintf(f, " <opaque>\n%s\n" " </opaque>\n", gstate.acct_mgr_info.opaque ); } gstate.time_stats.write(mf, true); gstate.net_stats.write(mf); fprintf(f, "</acct_mgr_request>\n"); fclose(f); snprintf(buf, sizeof(buf), "%srpc.php", ami.master_url); retval = gui_http->do_rpc_post( this, buf, ACCT_MGR_REQUEST_FILENAME, ACCT_MGR_REPLY_FILENAME, true ); if (retval) { error_num = retval; return retval; } msg_printf(NULL, MSG_INFO, "Contacting account manager at %s", ami.master_url); return 0; }
int main(int argc, char *argv[]) { long brandID = 0; Boolean AddUsers = false; Boolean SetSavers = false; Boolean isBMGroupMember, isBPGroupMember; Boolean saverIsSet = false; passwd *pw; uid_t saved_uid; group grpBOINC_master, *grpBOINC_masterPtr; group grpBOINC_project, *grpBOINC_projectPtr; char bmBuf[32768]; char bpBuf[32768]; char loginName[256]; short index, i; FILE *f; int flag; char *p; char s[1024], buf[1024]; OSStatus err; brandID = GetBrandID(); #ifndef _DEBUG if (getuid() != 0) { printf("This program must be run as root\n"); printUsage(brandID); return 0; } #endif saved_uid = geteuid(); if (argc < 3) { printUsage(brandID); return 0; } if (strcmp(argv[1], "-a") == 0) { AddUsers = true; } else if (strcmp(argv[1], "-s") == 0) { AddUsers = true; SetSavers = true; } else if (strcmp(argv[1], "-r") != 0) { printUsage(brandID); return 0; } printf("\n"); if (!check_branding_arrays(s, sizeof(s))) { printf("Branding array has too few entries: %s\n", s); return -1; } loginName[0] = '\0'; strncpy(loginName, getenv("USER"), sizeof(loginName)-1); err = getgrnam_r("boinc_master", &grpBOINC_master, bmBuf, sizeof(bmBuf), &grpBOINC_masterPtr); if (err) { // Should never happen unless buffer too small puts("getgrnam(\"boinc_master\") failed\n"); return -1; } err = getgrnam_r("boinc_project", &grpBOINC_project, bpBuf, sizeof(bpBuf), &grpBOINC_projectPtr); if (err) { // Should never happen unless buffer too small puts("getgrnam(\"boinc_project\") failed\n"); return -1; } for (index=2; index<argc; index++) { // getpwnam works with either the full / login name (pw->pw_gecos) // or the short / Posix name (pw->pw_name) pw = getpwnam(argv[index]); if ((pw == NULL) || (pw->pw_uid < 501)) { printf("User %s not found.\n\n", argv[index]); continue; } flag = 0; sprintf(s, "dscl . -read \"/Users/%s\" NFSHomeDirectory", pw->pw_name); f = popen(s, "r"); if (!f) { flag = 1; } else { while (PersistentFGets(buf, sizeof(buf), f)) { p = strrchr(buf, ' '); if (p) { if (strstr(p, "/var/empty") != NULL) { flag = 1; break; } } } pclose(f); } if (flag) { sprintf(s, "dscl . -read \"/Users/%s\" UserShell", pw->pw_name); f = popen(s, "r"); if (!f) { flag |= 2; } else { while (PersistentFGets(buf, sizeof(buf), f)) { p = strrchr(buf, ' '); if (p) { if (strstr(p, "/usr/bin/false") != NULL) { flag |= 2; break; } } } pclose(f); } } if (flag == 3) { // if (Home Directory == "/var/empty") && (UserShell == "/usr/bin/false") printf("%s is not a valid user name.\n\n", argv[index]); continue; } printf("%s user %s (/Users/%s)\n", AddUsers? "Adding" : "Removing", pw->pw_gecos, pw->pw_name); isBMGroupMember = false; i = 0; while ((p = grpBOINC_master.gr_mem[i]) != NULL) { // Step through all users in group boinc_master if (strcmp(p, pw->pw_name) == 0) { // Only the short / Posix names are in the list // User is a member of group boinc_master isBMGroupMember = true; break; } ++i; } isBPGroupMember = false; i = 0; while ((p = grpBOINC_project.gr_mem[i]) != NULL) { // Step through all users in group boinc_project if (strcmp(p, pw->pw_name) == 0) { // Only the short / Posix names are in the list // User is a member of group boinc_master isBPGroupMember = true; break; } ++i; } if ((!isBMGroupMember) && AddUsers) { sprintf(s, "dscl . -merge /groups/boinc_master GroupMembership %s", pw->pw_name); callPosixSpawn(s); } if ((!isBPGroupMember) && AddUsers) { sprintf(s, "dscl . -merge /groups/boinc_project GroupMembership %s", pw->pw_name); callPosixSpawn(s); } if (isBMGroupMember && (!AddUsers)) { sprintf(s, "dscl . -delete /Groups/boinc_master GroupMembership %s", pw->pw_name); callPosixSpawn(s); } if (isBPGroupMember && (!AddUsers)) { sprintf(s, "dscl . -delete /Groups/boinc_project GroupMembership %s", pw->pw_name); callPosixSpawn(s); } if (!AddUsers) { // Delete per-user BOINC Manager and screensaver files sprintf(s, "rm -fR \"/Users/%s/Library/Application Support/BOINC\"", pw->pw_name); callPosixSpawn (s); } // Set or remove login item for this user bool useOSASript = false; if ((compareOSVersionTo(10, 13) < 0) || (strcmp(loginName, pw->pw_name) == 0) || (strcmp(loginName, pw->pw_gecos) == 0)) { useOSASript = true; } #if USE_OSASCRIPT_FOR_ALL_LOGGED_IN_USERS if (! useOSASript) { useOSASript = IsUserLoggedIn(pw->pw_name); } #endif if (useOSASript) { snprintf(s, sizeof(s), "/Users/%s/Library/LaunchAgents/edu.berkeley.boinc.plist", pw->pw_name); boinc_delete_file(s); SetLoginItemOSAScript(brandID, !AddUsers, pw->pw_name); } else { SetLoginItemLaunchAgent(brandID, !AddUsers, pw); } saverIsSet = false; err = GetCurrentScreenSaverSelection(pw, s, sizeof(s) -1); #if VERBOSE fprintf(stderr, "Current Screensaver Selection for user %s is: \"%s\"\n", pw->pw_name, s); #endif if (err == noErr) { if (!strcmp(s, saverName[brandID])) { saverIsSet = true; } } if (SetSavers) { if (saverIsSet) { printf("Screensaver already set to %s for user %s (/Users/%s)\n", saverName[brandID], pw->pw_gecos, pw->pw_name); } else { printf("Setting screensaver to %s for user %s (/Users/%s)\n", saverName[brandID], pw->pw_gecos, pw->pw_name); } } if ((!saverIsSet) && SetSavers) { seteuid(pw->pw_uid); // Temporarily set effective uid to this user sprintf(s, "/Library/Screen Savers/%s.saver", saverName[brandID]); err = SetScreenSaverSelection(pw, saverName[brandID], s, 0); #if VERBOSE fprintf(stderr, "SetScreenSaverSelection for user %s (uid %d) to \"%s\" returned error %d\n", pw->pw_name, geteuid(), saverName[brandID], err); #endif seteuid(saved_uid); // Set effective uid back to privileged user // This seems to work also: // sprintf(buf, "su -l \"%s\" -c 'defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName \"%s\" path \"%s\ type 0'", pw->pw_name, saverName[brandID], s); // callPosixSpawn(s); } if (saverIsSet && (!AddUsers)) { printf("Setting screensaver to Flurry for user %s (/Users/%s)\n", pw->pw_gecos, pw->pw_name); seteuid(pw->pw_uid); // Temporarily set effective uid to this user err = SetScreenSaverSelection(pw, "Flurry", "/System/Library/Screen Savers/Flurry.saver", 0); #if VERBOSE fprintf(stderr, "SetScreenSaverSelection for user %s (%d) to Flurry returned error %d\n", pw->pw_name, geteuid(), err); #endif seteuid(saved_uid); // Set effective uid back to privileged user } seteuid(saved_uid); // Set effective uid back to privileged user printf("\n"); } printf("WARNING: Changes may require a system restart to take effect.\n"); return 0; }