Example #1
0
/* used to spawn a monitord either on startup of a daemon container, or when
 * lxc-monitor starts
 */
int lxc_monitord_spawn(const char *lxcpath)
{
    pid_t pid1,pid2;
    int pipefd[2];
    char pipefd_str[11];

    char * const args[] = {
        "/usr/bin/lxc-monitord",
        (char *)lxcpath,
        pipefd_str,
        NULL,
    };

    /* double fork to avoid zombies when monitord exits */
    pid1 = fork();
    if (pid1 < 0) {
        SYSERROR("failed to fork");
        return -1;
    }

    if (pid1) {
        if (waitpid(pid1, NULL, 0) != pid1)
            return -1;
        return 0;
    }

    if (pipe(pipefd) < 0) {
        SYSERROR("failed to create pipe");
        exit(EXIT_FAILURE);
    }

    pid2 = fork();
    if (pid2 < 0) {
        SYSERROR("failed to fork");
        exit(EXIT_FAILURE);
    }
    if (pid2) {
        char c;
        /* wait for daemon to create socket */
        close(pipefd[1]);
        /* sync with child, we're ignoring the return from read
         * because regardless if it works or not, either way we've
         * synced with the child process. the if-empty-statement
         * construct is to quiet the warn-unused-result warning.
         */
        if (read(pipefd[0], &c, 1)) ;
        close(pipefd[0]);
        exit(EXIT_SUCCESS);
    }

    umask(0);
    if (setsid() < 0) {
        SYSERROR("failed to setsid");
        exit(EXIT_FAILURE);
    }
    close(0);
    close(1);
    close(2);
    open("/dev/null", O_RDONLY);
    open("/dev/null", O_RDWR);
    open("/dev/null", O_RDWR);
    close(pipefd[0]);
    sprintf(pipefd_str, "%d", pipefd[1]);
    execvp(args[0], args);
    exit(EXIT_FAILURE);
}
int main(int argc, char **argv) {
	// Recovery needs to install world-readable files, so clear umask
	// set by init
	umask(0);

	Log_Offset = 0;

	// Set up temporary log file (/tmp/recovery.log)
	freopen(TMP_LOG_FILE, "a", stdout);
	setbuf(stdout, NULL);
	freopen(TMP_LOG_FILE, "a", stderr);
	setbuf(stderr, NULL);

	signal(SIGPIPE, SIG_IGN);

	// Handle ADB sideload
	if (argc == 3 && strcmp(argv[1], "--adbd") == 0) {
		property_set("ctl.stop", "adbd");
		adb_main(argv[2]);
		return 0;
	}

#ifdef RECOVERY_SDCARD_ON_DATA
	datamedia = true;
#endif

	char crash_prop_val[PROPERTY_VALUE_MAX];
	int crash_counter;
	property_get("twrp.crash_counter", crash_prop_val, "-1");
	crash_counter = atoi(crash_prop_val) + 1;
	snprintf(crash_prop_val, sizeof(crash_prop_val), "%d", crash_counter);
	property_set("twrp.crash_counter", crash_prop_val);
	property_set("ro.twrp.boot", "1");
	property_set("ro.twrp.version", TW_VERSION_STR);

	time_t StartupTime = time(NULL);
	printf("Starting TWRP %s on %s (pid %d)\n", TW_VERSION_STR, ctime(&StartupTime), getpid());

#ifdef HAVE_SELINUX
	printf("Setting SELinux to permissive\n");
	TWFunc::write_file("/sys/fs/selinux/enforce", "0");

	TWFunc::write_file("/file_contexts",
        "\n\n# MultiROM folders\n"
        "/data/media/multirom(/.*)?          <<none>>\n"
        "/data/media/0/multirom(/.*)?        <<none>>\n"
        "/realdata/media/multirom(/.*)?      <<none>>\n"
        "/realdata/media/0/multirom(/.*)?    <<none>>\n"
        "/sdcard/multirom(/.*)?              <<none>>\n"
        "/mnt/mrom(/.*)?                     <<none>>\n",
        "ae");
#endif

	// MultiROM _might_ have crashed the recovery while the boot device was redirected.
	// It would be bad to let that as is.
	MultiROM::failsafeCheckPartition("/tmp/mrom_fakebootpart");
	MultiROM::failsafeCheckPartition("/tmp/mrom_fakesyspart");

	// Load default values to set DataManager constants and handle ifdefs
	DataManager::SetDefaultValues();
	printf("Starting the UI...");
	gui_init();
	printf("=> Linking mtab\n");
	symlink("/proc/mounts", "/etc/mtab");
	if (TWFunc::Path_Exists("/etc/twrp.fstab")) {
		if (TWFunc::Path_Exists("/etc/recovery.fstab")) {
			printf("Renaming regular /etc/recovery.fstab -> /etc/recovery.fstab.bak\n");
			rename("/etc/recovery.fstab", "/etc/recovery.fstab.bak");
		}
		printf("Moving /etc/twrp.fstab -> /etc/recovery.fstab\n");
		rename("/etc/twrp.fstab", "/etc/recovery.fstab");
	}
	printf("=> Processing recovery.fstab\n");
	if (!PartitionManager.Process_Fstab("/etc/recovery.fstab", 1)) {
		LOGERR("Failing out of recovery due to problem with recovery.fstab.\n");
		return -1;
	}
	PartitionManager.Output_Partition_Logging();

	DataManager::SetValue(TW_MROM_REC_VERSION_VAR, MultiROM::getRecoveryVersion());
	printf("MultiROM Recovery version: %s\n", DataManager::GetStrValue(TW_MROM_REC_VERSION_VAR).c_str());

	// Load up all the resources
	gui_loadResources();

#ifdef HAVE_SELINUX
	if (TWFunc::Path_Exists("/prebuilt_file_contexts")) {
		if (TWFunc::Path_Exists("/file_contexts")) {
			printf("Renaming regular /file_contexts -> /file_contexts.bak\n");
			rename("/file_contexts", "/file_contexts.bak");
		}
		printf("Moving /prebuilt_file_contexts -> /file_contexts\n");
		rename("/prebuilt_file_contexts", "/file_contexts");
	}
	struct selinux_opt selinux_options[] = {
		{ SELABEL_OPT_PATH, "/file_contexts" }
	};
	selinux_handle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1);
	if (!selinux_handle)
		printf("No file contexts for SELinux\n");
	else
		printf("SELinux contexts loaded from /file_contexts\n");
	{ // Check to ensure SELinux can be supported by the kernel
		char *contexts = NULL;

		if (PartitionManager.Mount_By_Path("/cache", true) && TWFunc::Path_Exists("/cache/recovery")) {
			lgetfilecon("/cache/recovery", &contexts);
			if (!contexts) {
				lsetfilecon("/cache/recovery", "test");
				lgetfilecon("/cache/recovery", &contexts);
			}
		} else {
			LOGINFO("Could not check /cache/recovery SELinux contexts, using /sbin/teamwin instead which may be inaccurate.\n");
			lgetfilecon("/sbin/teamwin", &contexts);
		}
		if (!contexts) {
			gui_print_color("warning", "Kernel does not have support for reading SELinux contexts.\n");
		} else {
			free(contexts);
			gui_print("Full SELinux support is present.\n");
		}
	}
#else
	gui_print_color("warning", "No SELinux support (no libselinux).\n");
#endif

	PartitionManager.Mount_By_Path("/cache", true);

	string Zip_File, Reboot_Value;
	bool Cache_Wipe = false, Factory_Reset = false, Perform_Backup = false, Shutdown = false;

	{
		TWPartition* misc = PartitionManager.Find_Partition_By_Path("/misc");
		if (misc != NULL) {
			if (misc->Current_File_System == "emmc") {
				set_device_type('e');
				set_device_name(misc->Actual_Block_Device.c_str());
			} else if (misc->Current_File_System == "mtd") {
				set_device_type('m');
				set_device_name(misc->MTD_Name.c_str());
			} else {
				LOGERR("Unknown file system for /misc\n");
			}
		}
		get_args(&argc, &argv);

		int index, index2, len;
		char* argptr;
		char* ptr;
		printf("Startup Commands: ");
		for (index = 1; index < argc; index++) {
			argptr = argv[index];
			printf(" '%s'", argv[index]);
			len = strlen(argv[index]);
			if (*argptr == '-') {argptr++; len--;}
			if (*argptr == '-') {argptr++; len--;}
			if (*argptr == 'u') {
				ptr = argptr;
				index2 = 0;
				while (*ptr != '=' && *ptr != '\n')
					ptr++;
				// skip the = before grabbing Zip_File
				while (*ptr == '=')
					ptr++;
				if (*ptr) {
					Zip_File = ptr;
				} else
					LOGERR("argument error specifying zip file\n");
			} else if (*argptr == 'w') {
				if (len == 9)
					Factory_Reset = true;
				else if (len == 10)
					Cache_Wipe = true;
			} else if (*argptr == 'n') {
				Perform_Backup = true;
			} else if (*argptr == 'p') {
				Shutdown = true;
			} else if (*argptr == 's') {
				ptr = argptr;
				index2 = 0;
				while (*ptr != '=' && *ptr != '\n')
					ptr++;
				if (*ptr) {
					Reboot_Value = *ptr;
				}
			}
		}
		printf("\n");
	}

	if(crash_counter == 0) {
		property_list(Print_Prop, NULL);
		printf("\n");
	} else {
		printf("twrp.crash_counter=%d\n", crash_counter);
	}

	// Check for and run startup script if script exists
	TWFunc::check_and_run_script("/sbin/runatboot.sh", "boot");
	TWFunc::check_and_run_script("/sbin/postrecoveryboot.sh", "boot");

#ifdef TW_INCLUDE_INJECTTWRP
	// Back up TWRP Ramdisk if needed:
	TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot");
	LOGINFO("Backing up TWRP ramdisk...\n");
	if (Boot == NULL || Boot->Current_File_System != "emmc")
		TWFunc::Exec_Cmd("injecttwrp --backup /tmp/backup_recovery_ramdisk.img");
	else {
		string injectcmd = "injecttwrp --backup /tmp/backup_recovery_ramdisk.img bd=" + Boot->Actual_Block_Device;
		TWFunc::Exec_Cmd(injectcmd);
	}
	LOGINFO("Backup of TWRP ramdisk done.\n");
#endif

	bool Keep_Going = true;
	if (Perform_Backup) {
		DataManager::SetValue(TW_BACKUP_NAME, "(Auto Generate)");
		if (!OpenRecoveryScript::Insert_ORS_Command("backup BSDCAE\n"))
			Keep_Going = false;
	}
	if (Keep_Going && !Zip_File.empty()) {
		string ORSCommand = "install " + Zip_File;

		if (!OpenRecoveryScript::Insert_ORS_Command(ORSCommand))
			Keep_Going = false;
	}
	if (Keep_Going) {
		if (Factory_Reset) {
			if (!OpenRecoveryScript::Insert_ORS_Command("wipe data\n"))
				Keep_Going = false;
		} else if (Cache_Wipe) {
			if (!OpenRecoveryScript::Insert_ORS_Command("wipe cache\n"))
				Keep_Going = false;
		}
	}

	TWFunc::Update_Log_File();
	// Offer to decrypt if the device is encrypted
	if (DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0) {
		LOGINFO("Is encrypted, do decrypt page first\n");
		if (gui_startPage("decrypt", 1, 1) != 0) {
			LOGERR("Failed to start decrypt GUI page.\n");
		} else {
			// Check for and load custom theme if present
			gui_loadCustomResources();
		}
	} else if (datamedia) {
		if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) {
			LOGINFO("Failed to get default contexts and file mode for storage files.\n");
		} else {
			LOGINFO("Got default contexts and file mode for storage files.\n");
		}
	}

	// Read the settings file
#ifdef TW_HAS_MTP
	// We unmount partitions sometimes during early boot which may override
	// the default of MTP being enabled by auto toggling MTP off. This
	// will force it back to enabled then get overridden by the settings
	// file, assuming that an entry for tw_mtp_enabled is set.
	DataManager::SetValue("tw_mtp_enabled", 1);
#endif
	DataManager::ReadSettingsFile();

	gui_rotate(DataManager::GetIntValue(TW_ROTATION));

	// Fixup the RTC clock on devices which require it
	if(crash_counter == 0)
		TWFunc::Fixup_Time_On_Boot();

	// Run any outstanding OpenRecoveryScript
	if(DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0)
	{
		if ((TWFunc::Path_Exists(SCRIPT_FILE_TMP) || TWFunc::Path_Exists(SCRIPT_FILE_CACHE)))
			OpenRecoveryScript::Run_OpenRecoveryScript();
		else
			MultiROM::executeCacheScripts();
	}

#if 0
#ifdef TW_HAS_MTP
	// Enable MTP?
	char mtp_crash_check[PROPERTY_VALUE_MAX];
	property_get("mtp.crash_check", mtp_crash_check, "0");
	if (strcmp(mtp_crash_check, "0") == 0) {
		property_set("mtp.crash_check", "1");
		if (DataManager::GetIntValue("tw_mtp_enabled") == 1 && ((DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0 && DataManager::GetIntValue(TW_IS_DECRYPTED) != 0) || DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0)) {
			LOGINFO("Enabling MTP during startup\n");
			if (!PartitionManager.Enable_MTP())
				PartitionManager.Disable_MTP();
			else
				gui_print("MTP Enabled\n");
		} else {
			PartitionManager.Disable_MTP();
		}
		property_set("mtp.crash_check", "0");
	} else {
		gui_print_color("warning", "MTP Crashed, not starting MTP on boot.\n");
		DataManager::SetValue("tw_mtp_enabled", 0);
		PartitionManager.Disable_MTP();
	}
#else
	PartitionManager.Disable_MTP();
#endif
#endif

	// Launch the main GUI
	gui_start();

	// Disable flashing of stock recovery
	TWFunc::Disable_Stock_Recovery_Replace();
	// Check for su to see if the device is rooted or not
	if (PartitionManager.Mount_By_Path("/system", false)) {
		if (TWFunc::Path_Exists("/supersu/su") && !TWFunc::Path_Exists("/system/bin/su") && !TWFunc::Path_Exists("/system/xbin/su") && !TWFunc::Path_Exists("/system/bin/.ext/.su")) {
			// Device doesn't have su installed
			DataManager::SetValue("tw_busy", 1);
			if (gui_startPage("installsu", 1, 1) != 0) {
				LOGERR("Failed to start SuperSU install page.\n");
			}
		}
		sync();
		PartitionManager.UnMount_By_Path("/system", false);
	}

	// Reboot
	TWFunc::Update_Intent_File(Reboot_Value);
	TWFunc::Update_Log_File();
	gui_print("Rebooting...\n");
	string Reboot_Arg;
	DataManager::GetValue("tw_reboot_arg", Reboot_Arg);
	if (Reboot_Arg == "recovery")
		TWFunc::tw_reboot(rb_recovery);
	else if (Reboot_Arg == "poweroff")
		TWFunc::tw_reboot(rb_poweroff);
	else if (Reboot_Arg == "bootloader")
		TWFunc::tw_reboot(rb_bootloader);
	else if (Reboot_Arg == "download")
		TWFunc::tw_reboot(rb_download);
	else
		TWFunc::tw_reboot(rb_system);

	return 0;
}
void
Rename_INIT ( int * _rep, void * _lockfile, int _port, void * _bufsavefile )
{
  static int          init_done = 0;
  int                 on = 1;
  struct sockaddr_in  s_server;
  int                 lf;              /* file descriptor for pid/lock file */
  char                pid_buf [ 10 ];  /* buffer for pid                    */
  pid_t               f;               /* for fork                          */

  /***
  check not already initialised
  ***/
  if ( init_done ) {
    printf ( "\n  Rename_INIT: already initialised\n" );
    * _rep = FALSE;
    return;
  }

  init_done = 1;

  /***
  create master_sock
  ***/
  if ( ( master_sock = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == -1 ) {
    printf ( "\n  Rename_INIT: socket failed - errno %d\n", errno );
    * _rep = FALSE;
    return;
  }

  /***
  setsocketopt
  ***/
  if ( ( setsockopt ( master_sock, SOL_SOCKET, SO_REUSEADDR,
		      ( char * ) &on, sizeof ( on ) ) ) == -1 ) {
    printf ( "\n  Rename_INIT: setsocketopt failed - errno %d\n", errno );
    * _rep = FALSE;
    return;
  }

  /***
  bind to port
  ***/
  memset ( ( char * ) &s_server, 0, sizeof ( s_server ) );
  s_server.sin_family = AF_INET;
  s_server.sin_addr.s_addr = htonl ( INADDR_ANY );
  s_server.sin_port = htons ( _port );
  if ( bind ( master_sock, ( struct sockaddr * ) &s_server,
                                           sizeof ( s_server ) ) == -1 ) {
    printf ( "\n  Rename_INIT: can't bind to port %d - errno %d\n", _port, errno );  
    * _rep = FALSE;
    return;
  }

  /***
  listen, with maximum backlog
  ***/
  if ( listen ( master_sock, SOMAXCONN ) == -1 ) {
    printf ( "\n  Rename_INIT: listen failed - errno %d\n", errno );
    * _rep = FALSE;
    return;
  }

  /***
  operate in background
  ***/

#ifndef TEST_FLAG

  f = fork ();
  if ( f < 0 ) {        /* error */
    printf ( "\n  Rename_INIT: fork failed - errno %d\n", errno );
    * _rep = FALSE;
    return;
  }
  else if ( f ) {       /* parent */
    exit ( 0 );
  }
                        /* child continues */
  /***
  detach from controlling tty
  ***/
/*  TIOCNOTT not in the Solaris 7 operating environment
  fd = open ( "/dev/tty", O_RDWR );
  ioctl ( fd, TIOCNOTTY, 0 );
  close ( fd );
*/
  
#else

 printf ( "\n  Rename_SharedSocketServer: TEST_FLAG set - fork/detach suppressed ...\n" );

#endif


  /***
  change directory to /
  ***/
  /*
  chdir ( "/" );
  */
  /*
  printf ( "Rename_SharedSocketServer: chdir / suppressed ...\n" );
  */

  /***
  set umask
  ***/
  umask ( 027 );
  

  /***
  set parent process group
  ***/
  setpgid ( 0, getpid () );


  /***
  acquire exclusive lock
  ***/
  lf = open ( ( char * ) _lockfile, O_RDWR | O_CREAT, 0640 );
  if ( lf < 0 ) {                              /* error */
    printf ( "\n  Rename_INIT: unable to open %s O_RDWR | O_CREAT - errno %d\n",
                                                  ( char * ) _lockfile, errno );
    * _rep = FALSE;
    return;
  }

/*
  if ( flock ( lf, LOCK_EX | LOCK_NB ) ) {     /? can't obtain exclusive lock ?/
    printf ( "\n  Rename_INIT: unable to obtain lock on %s - errno %d\n",
                                                 ( char * ) _lockfile, errno  );
    * _rep = FALSE;
    return;
  }
*/

  /***
  perform malloc for _out_buf & _in_buf
  ***/
#ifdef TEST_FLAG
    printf ( "Rename_INIT: _in_buf malloc (%d)\n", _in_buf_size );
#endif
  _in_buf = ( char * ) malloc ( _in_buf_size * sizeof ( char ) );
  if ( _in_buf == NULL ) {
    printf ( "\n  Rename_INIT: in_buf malloc (%d) failure\n", _in_buf_size );
    * _rep = FALSE;
    return;    
  }
#ifdef TEST_FLAG
    printf ( "Rename_INIT: _out_buf malloc (%d)\n", _out_buf_size );
#endif
  _out_buf = ( char * ) malloc ( _out_buf_size * sizeof ( char ) );
  if ( _out_buf == NULL ) {
    printf ( "\n  Rename_INIT: in_buf malloc (%d) failure\n", _out_buf_size );
    * _rep = FALSE;
    return;    
  }

  /***
  set _sav_buf;
  zero _num_sav, reset malloc_done
  ***/
  if ( strlen ( ( char * ) _bufsavefile ) < 256 ) {
    sprintf ( _sav_buf, ( char * ) _bufsavefile );
  }
  else {
    printf ( "\n  Rename_INIT: _bufsavefile too long (%d >= 256)\n",
                                             strlen ( ( char * ) _bufsavefile ) );
    * _rep = FALSE;
    return;    
  }
  _num_sav = 0;
  malloc_done = 0;

  /***
  write pid to file & close
  ***/
  sprintf ( pid_buf, "%d", getpid () );
  write ( lf, pid_buf, strlen ( pid_buf ) );
  close ( lf );

  /***
  report server started via syslog
  ***/
  openlog ( "Rename_SharedSocketServer", LOG_PID, LOG_DAEMON );
  setlogmask ( LOG_UPTO (  LOG_WARNING ) );
  syslog ( LOG_ERR, "Listening at port %d\n", _port );
  closelog ();

  printf ( "\n  Rename_SharedSocketServer: listening at port %d\n\n", _port );

#ifdef SERVER_STATS_FLAG
  Rename_statsArrPtr = 0;
  Rename_statsArr [ 5 ] [ 0 ] = 0; /* avge wait */
  Rename_statsArr [ 6 ] [ 0 ] = 0; /* avge cycle tot */
  Rename_statsArr [ 7 ] [ 0 ] = 0; /* avge Kb * 1000  */
  Rename_statsArr [ 8 ] [ 0 ] = 0; /* cycles */
  Rename_clock_h = times ( &Rename_tms_buf_h );
  gettimeofday ( &Rename_timeval_buf_h, ( void * ) &Rename_tz );
#endif

  * _rep = TRUE;
}
Example #4
0
/* Handle the creation of a keybox if it does not yet exist.  Take
   into acount that other processes might have the keybox already
   locked.  This lock check does not work if the directory itself is
   not yet available.  If R_CREATED is not NULL it will be set to true
   if the function created a new keybox.  */
static int
maybe_create_keybox (char *filename, int force, int *r_created)
{
  dotlock_t lockhd = NULL;
  FILE *fp;
  int rc;
  mode_t oldmask;
  char *last_slash_in_filename;
  int save_slash;

  if (r_created)
    *r_created = 0;

  /* A quick test whether the filename already exists. */
  if (!access (filename, F_OK))
    return 0;

  /* If we don't want to create a new file at all, there is no need to
     go any further - bail out right here.  */
  if (!force)
    return gpg_error (GPG_ERR_ENOENT);

  /* First of all we try to create the home directory.  Note, that we
     don't do any locking here because any sane application of gpg
     would create the home directory by itself and not rely on gpg's
     tricky auto-creation which is anyway only done for some home
     directory name patterns. */
  last_slash_in_filename = strrchr (filename, DIRSEP_C);
#if HAVE_W32_SYSTEM
  {
    /* Windows may either have a slash or a backslash.  Take care of it.  */
    char *p = strrchr (filename, '/');
    if (!last_slash_in_filename || p > last_slash_in_filename)
      last_slash_in_filename = p;
  }
#endif /*HAVE_W32_SYSTEM*/
  if (!last_slash_in_filename)
    return gpg_error (GPG_ERR_ENOENT);  /* No slash at all - should
                                           not happen though.  */
  save_slash = *last_slash_in_filename;
  *last_slash_in_filename = 0;
  if (access(filename, F_OK))
    {
      static int tried;

      if (!tried)
        {
          tried = 1;
          try_make_homedir (filename);
        }
      if (access (filename, F_OK))
        {
          rc = gpg_error_from_syserror ();
          *last_slash_in_filename = save_slash;
          goto leave;
        }
    }
  *last_slash_in_filename = save_slash;

  /* To avoid races with other instances of gpg trying to create or
     update the keybox (it is removed during an update for a short
     time), we do the next stuff in a locked state. */
  lockhd = dotlock_create (filename, 0);
  if (!lockhd)
    {
      /* A reason for this to fail is that the directory is not
         writable. However, this whole locking stuff does not make
         sense if this is the case. An empty non-writable directory
         with no keyring is not really useful at all. */
      if (opt.verbose)
        log_info ("can't allocate lock for '%s'\n", filename );

      if (!force)
        return gpg_error (GPG_ERR_ENOENT);
      else
        return gpg_error (GPG_ERR_GENERAL);
    }

  if ( dotlock_take (lockhd, -1) )
    {
      /* This is something bad.  Probably a stale lockfile.  */
      log_info ("can't lock '%s'\n", filename);
      rc = gpg_error (GPG_ERR_GENERAL);
      goto leave;
    }

  /* Now the real test while we are locked. */
  if (!access(filename, F_OK))
    {
      rc = 0;  /* Okay, we may access the file now.  */
      goto leave;
    }

  /* The file does not yet exist, create it now. */
  oldmask = umask (077);
  fp = fopen (filename, "w");
  if (!fp)
    {
      rc = gpg_error_from_syserror ();
      umask (oldmask);
      log_error (_("error creating keybox '%s': %s\n"),
                 filename, gpg_strerror (rc));
      goto leave;
    }
  umask (oldmask);

  if (!opt.quiet)
    log_info (_("keybox '%s' created\n"), filename);
  if (r_created)
    *r_created = 1;

  fclose (fp);
  rc = 0;

 leave:
  if (lockhd)
    {
      dotlock_release (lockhd);
      dotlock_destroy (lockhd);
    }
  return rc;
}
Example #5
0
void *thread_func(void *arg)
{
	char localpath[PATH_MAX] = {'\0'};
	message_t *pids = (message_t *)arg;
	char mqRd[PATH_MAX] = {'\0'};
	char mqWr[PATH_MAX] = {'\0'};
	pid_t pid = (int)strtol(pids->command, NULL, 10);
	int s = 0;

	pthread_detach(pthread_self());
	
	clients++;

	//	printf("%d client connected\n", pid);

	CREATE_CLIENT_READER_NAME(mqRd, (int)pid);
	CREATE_CLIENT_WRITER_NAME(mqWr, (int)pid);

	free(pids);
	
	umask(0);
	
	s = pthread_mutex_lock(&mtx);
	if (s != 0)
		printf("Lock failed\n");

	getcwd(localpath, sizeof(localpath));

	s = pthread_mutex_unlock(&mtx);
	if (s != 0)
		printf("Unlock failed\n");

	while (1) {
		mqd_t cwr, crd;
		message_t data;
		
		memset(&data, '\0', sizeof(data));

		if ((cwr = mq_open(mqWr, O_RDONLY)) == -1) {
			printf("Open write queue failed!\n");
			clients--;
			pthread_exit(EXIT_SUCCESS);
		}
		mq_receive(cwr, (char *)&data, sizeof(data), NULL);
		mq_close(cwr);

		if (strcmp(data.command, CMD_EXIT) == 0) {
			clients--;
			//		printf("%d client exit\n", pid);
			pthread_exit(EXIT_SUCCESS);
		}
		else if (strcmp(data.command, CMD_REMOTE_CHDIR) == 0) {
			int ts;
			char local[PATH_MAX] = {'\0'};
			char res[PATH_MAX] = {'\0'};

			ts = pthread_mutex_lock(&mtx);
			if (ts != 0)
				printf("Lock failed\n");			
			
			getcwd(local, sizeof(local));
			
			if (chdir(localpath) == -1) {
				printf("Cannot change directory\n");
				continue;
			}

			if (chdir(data.payload) == -1)
				memcpy(res, "ERROR\n", strlen("ERROR\n"));
			else 
				getcwd(res, sizeof(res));
			
			memset(&data, '\0', sizeof(data));
			memcpy(data.payload, res, strlen(res));
			if (strcmp(res, "ERROR\n") != 0) {
				memset(localpath, '\0', sizeof(localpath));	
				memcpy(localpath, res, strlen(res));
			}
			if ((crd = mq_open(mqRd, O_WRONLY)) == -1) {
				printf("Cannot open read queue\n");
				continue;
			}
			mq_send(crd, (char *)&data, sizeof(data), 0);
			mq_close(crd);

			if (chdir(local) == -1) {
				printf("Cannot restore directory\n");
				continue;
			}

			ts = pthread_mutex_unlock(&mtx);
			if (ts != 0)
				printf("Unlock failed\n");
		}//cd
		else if (strcmp(data.command, CMD_REMOTE_DIR) == 0) {
			char cmd[PATH_MAX] = {'\0'};
			FILE *fp;
			
			memcpy(cmd, CMD_LS_POPEN, strlen(CMD_LS_POPEN));
			strcat(cmd, " ");
			strcat(cmd, localpath);

			if ((fp = popen(cmd, "r")) == NULL) {
				if ((crd = mq_open(mqRd, O_WRONLY)) == -1) {
					printf("Cannot open read queue\n");
					continue;
				}			
				memcpy(data.command, "ERROR\n", strlen("ERROR\n"));
				mq_send(crd, (char *)&data, sizeof(data), 0);
				mq_close(crd);
			}
			while (fgets(data.payload, sizeof(data.payload), fp) != NULL) {
				if ((crd = mq_open(mqRd, O_WRONLY)) == -1) {
					printf("Cannot open read queue\n");
					continue;
				}
				data.message_type = MESSAGE_TYPE_DIR;
				mq_send(crd, (char *)&data, sizeof(data), 0);
				mq_close(crd);
				memset(&data, '\0', sizeof(data));
			}
			memset(&data, '\0', sizeof(data));
			data.message_type = MESSAGE_TYPE_DIR_END;
			if ((crd = mq_open(mqRd, O_WRONLY)) == -1) {
				printf("Cannot open read queue\n");
				continue;
			}
			mq_send(crd, (char *)&data, sizeof(data), 0);
			mq_close(crd);
		}//dir
		else if (strcmp(data.command, CMD_REMOTE_PWD) == 0) {
			memset(&data, '\0', sizeof(data));
			memcpy(data.payload, localpath, strlen(localpath));
			if ((crd = mq_open(mqRd, O_WRONLY)) == -1) {
				printf("Cannot open read queue\n");
				continue;
			}
			mq_send(crd, (char *)&data, sizeof(data), 0);
			mq_close(crd);
		}//pwd
		else if (strcmp(data.command, CMD_REMOTE_HOME) == 0) {
			memset(&data, '\0', sizeof(data));
			memset(localpath, '\0', sizeof(localpath));
			memcpy(localpath, getenv("HOME"), strlen(getenv("HOME")));
			memcpy(data.payload, localpath, strlen(localpath));
			if ((crd = mq_open(mqRd, O_WRONLY)) == -1) {
				printf("Cannot open read queue\n");
				continue;
			}
			mq_send(crd, (char *)&data, sizeof(data), 0);
			mq_close(crd);
		}//home
		else if (strcmp(data.command, CMD_PUT) == 0) {
			int fd = 0;
			int ts = 0;
			char local[PATH_MAX] = {'\0'};
			
			ts = pthread_mutex_lock(&mtx);
			getcwd(local, sizeof(local));
			chdir(localpath);
			fd = open(basename(data.payload), SEND_FILE_FLAGS, SEND_FILE_PERMISSIONS);
			memset(&data, '\0', sizeof(data));
			if ((cwr = mq_open(mqWr, O_RDONLY)) == -1) {
				printf("Open write queue failed!\n");
				continue;
			}
			while((mq_receive(cwr, (char *)&data, sizeof(data), NULL)) && (data.message_type != MESSAGE_TYPE_SEND_END)) {
				write(fd, data.payload, data.num_bytes);
				memset(&data, '\0', sizeof(data));
			}
			close(fd);
			chdir(local);
			ts = pthread_mutex_unlock(&mtx);
		}//put
		else if (strcmp(data.command, CMD_GET) == 0) {
			int fd;
			int len;
			int ts;
			char local[PATH_MAX] = {'\0'};
			
			ts = pthread_mutex_lock(&mtx);
			getcwd(local, sizeof(local));
			chdir(localpath);
			fd = open(data.payload, O_RDONLY);
			memset(&data, '\0', sizeof(data));
			while ((len = read(fd, data.payload, sizeof(data.payload))) != 0) {
				data.num_bytes = len;
				if ((crd = mq_open(mqRd, O_WRONLY)) == -1) {
					printf("Cannot open read queue\n");
					continue;
				}
				data.message_type = MESSAGE_TYPE_SEND;
				mq_send(crd, (char *)&data, sizeof(data), 0);
				mq_close(crd);
				memset(&data, '\0', sizeof(data));
			}
			close(fd);
			memset(&data, '\0', sizeof(data));
			data.message_type = MESSAGE_TYPE_SEND_END;
			if ((crd = mq_open(mqRd, O_WRONLY)) == -1) {
				printf("Cannot open read queue\n");
				continue;
			}
			mq_send(crd, (char *)&data, sizeof(data), 0);
			mq_close(crd);
			chdir(local);
			ts = pthread_mutex_unlock(&mtx);
		}//get
	}
}
Example #6
0
SHMem *
SHMem::initSegment(const char *name, int size, bool &init)
{
    bool needInit = true;
    /* big enough to hold a uid_t value in decimal */
    /* decimal digits = ceiling(log10(uid_t_max)); */
    /* log10(uid_t_max) = log256(uid_t_max)/log256(10); */
    /* log256(uid_t_max) = sizeof(uid_t); */
    /* log10(256) just greater than .41 */
    /* so decimal_digits = (sizeof(uid_t)*100 +40)/41 */
#define UID_DIGITS (((sizeof(uid_t)*100)+40)/41)
    char uid_str[UID_DIGITS+2]; /* 1 for '-', 1 for null */
   
    init = 0;
    SHMemData *shmemData = new SHMemData;
    if (!shmemData ) {
	// applications know we failed because they will get a NULL address
	// from getSHMemAddr.
	return NULL;
    }
    int mask = umask(0);
    int ret = mkdir (MEMSEGPATH, 01777);
    umask(mask);
    if ((ret == -1) && (errno != EEXIST)) {
	delete shmemData;
	return NULL;
    }
    /* 1 for the '/', one for the '-' and one for the null */
    shmemData->path = new char [sizeof(MEMSEGPATH)+strlen(name)+UID_DIGITS+3];
    if (shmemData->path == NULL) {
	delete shmemData;
	return NULL;
    }
    memcpy(shmemData->path,MEMSEGPATH, sizeof(MEMSEGPATH));
    shmemData->path[sizeof(MEMSEGPATH)-1] = '/';
    strcpy(&shmemData->path[sizeof(MEMSEGPATH)],name);

    sprintf(uid_str, "-%u",getuid());
    strcat(shmemData->path,uid_str);
    int mode = 0600;

    shmemData->fd = open(shmemData->path, 
		O_CREAT|O_RDWR|O_EXCL|O_APPEND|O_EXLOCK, mode);
    if (shmemData->fd >= 0) {
	char *buf;
	int len = size+RESERVED_OFFSET;
        int ret;

	buf = (char *)calloc(1,len);
	if (!buf) {
	    unlink(shmemData->path);
#ifdef FULL_CLEANUP
	    flock(shmemData->fd, LOCK_UN);
#endif
	    delete shmemData;
	    return NULL;
	}
	ret = write(shmemData->fd,buf,len);
        if (ret != len) {
	    unlink(shmemData->path);
#ifdef FULL_CLEANUP
	    flock(shmemData->fd, LOCK_UN);
#endif
	    delete shmemData;
	    return NULL;
	}
	free(buf);
    } else if (errno == EEXIST) {
	needInit = false;
	shmemData->fd = safe_open(shmemData->path,O_RDWR|O_EXLOCK, mode,
				  size+RESERVED_OFFSET);
    }
    if (shmemData->fd < 0) {
	delete shmemData;
	return NULL;
    }
    shmemData->addr = (char *) mmap(0, size+RESERVED_OFFSET, 
			PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED|MAP_INHERIT, 
							shmemData->fd, 0);
    if (shmemData->addr == NULL) {
	if (needInit) {
	    unlink(shmemData->path);
	}
#ifdef FULL_CLEANUP
	flock(shmemData->fd, LOCK_UN);
#endif
	delete shmemData;
	return NULL;
    }
    shmemData->size = size;
#ifdef FULL_CLEANUP
    (*(unsigned long *)shmemData->addr)++; 
    flock(shmemData->fd, LOCK_UN);
#endif
    init = needInit;
    SHMem *memseg;

    memseg = new SHMem();
    if (!memseg) {
	delete shmemData;
	return NULL;
    }
    memseg->shmemData = shmemData;
    return memseg;
}
Example #7
0
int main(int argc,char *argv[])
{
    struct pgpmainBones *mainbPtr = &_pgp_mainBones;
    struct pgpargsBones *argsbPtr;
    struct pgpfileBones *filebPtr;
    struct pgpenvBones *envbPtr;
    PGPContextRef mainContext;
    int errorLvl = 0, status;
    PGPError err = PGPsdkInit();
    pgpAssertNoErr(err);

    err = PGPsdkNetworkLibInit();
    pgpAssertNoErr(err);

    err = PGPNewContext( kPGPsdkAPIVersion, &mainContext );
    pgpAssertNoErr(err);

    err = pgpInitSDKPrefsDir( mainContext );
    pgpAssertNoErr(err);

    initMainBones( mainbPtr, mainContext );

    signonMsg(mainbPtr);

    /* link the context and initialize what used to be the global
       variables. */
    argsbPtr = mainbPtr->argsbPtr;
    filebPtr = mainbPtr->filebPtr;
    envbPtr = mainbPtr->envbPtr;
    err = pgpParseArgs( mainbPtr, argc, argv, &errorLvl);
    /* parse the arguments */
    if(err != 0)
        goto ex;

    if (argsbPtr->keyFlag && argsbPtr->keyChar == '\0') {
        keyUsage(filebPtr,&errorLvl);
        goto ex;
    }

    if (argsbPtr->groupFlag && argsbPtr->groupChar == '\0') {
        groupUsage(filebPtr,&errorLvl);
        goto ex;
    }

    /*
     * Write to stdout if explicitly asked to, or in filter mode and
     * no explicit file name was given.
     */
    mainbPtr->outputStdout = argsbPtr->outputFileName ?
        strcmp(argsbPtr->outputFileName, "-") == 0 : envbPtr->filterMode;

#if 1
    /* At request of Peter Simons, use stderr always. Sounds reasonable. */
    /* JIS: Put this code back in... removing it broke too many things */
    if (!mainbPtr->outputStdout)
        filebPtr->pgpout = stdout;
#endif

#if defined(PGP_UNIX) || defined(VMS)
    umask(077); /* Make files default to private */
#endif

    initSignals(); /* Catch signals */

    /* get our groups...*/
    err = pgpInitializeWorkingGroupSet( mainbPtr );

    if (argsbPtr->keyFlag) {
        status = doKeyOpt( mainbPtr, argsbPtr->keyChar, &errorLvl );
        if (status < 0) {
            userError(filebPtr,&errorLvl);
            goto ex;
        }
        errorLvl=status;
        goto ex;
    }

    if(argsbPtr->groupFlag) {
        status = doGroupOpt( mainbPtr, argsbPtr->groupChar, &errorLvl );
        if( status < 0 ) {
            userError(filebPtr,&errorLvl);
            goto ex;
        }
        errorLvl=status;
        goto ex;
    }

    err = pgpProcessArgs(mainbPtr, &errorLvl);

ex:
    err = pgpFinalizeWorkingGroupSet( mainbPtr );

    pgpTearDown( mainbPtr, &errorLvl );

    exit(errorLvl);
    /*NOTREACHED*/
    return errorLvl;
}
Example #8
0
void service_start(struct service *svc, const char *dynamic_args)
{
    struct stat s;
    pid_t pid;
    int needs_console;
    char *scon = NULL;
    int rc;

        /* starting a service removes it from the disabled or reset
         * state and immediately takes it out of the restarting
         * state if it was in there
         */
    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
    svc->time_started = 0;

        /* running processes require no additional work -- if
         * they're in the process of exiting, we've ensured
         * that they will immediately restart on exit, unless
         * they are ONESHOT
         */
    if (svc->flags & SVC_RUNNING) {
        return;
    }

    needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
    if (needs_console && (!have_console)) {
        ERROR("service '%s' requires console\n", svc->name);
        svc->flags |= SVC_DISABLED;
        return;
    }

    if (stat(svc->args[0], &s) != 0) {
        ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
        svc->flags |= SVC_DISABLED;
        return;
    }

    if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
        ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
               svc->args[0]);
        svc->flags |= SVC_DISABLED;
        return;
    }

    if (is_selinux_enabled() > 0) {
        if (svc->seclabel) {
            scon = strdup(svc->seclabel);
            if (!scon) {
                ERROR("Out of memory while starting '%s'\n", svc->name);
                return;
            }
        } else {
            char *mycon = NULL, *fcon = NULL;

            INFO("computing context for service '%s'\n", svc->args[0]);
            rc = getcon(&mycon);
            if (rc < 0) {
                ERROR("could not get context while starting '%s'\n", svc->name);
                return;
            }

            rc = getfilecon(svc->args[0], &fcon);
            if (rc < 0) {
                ERROR("could not get context while starting '%s'\n", svc->name);
                freecon(mycon);
                return;
            }

            rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
            if (rc == 0 && !strcmp(scon, mycon)) {
                ERROR("Warning!  Service %s needs a SELinux domain defined; please fix!\n", svc->name);
            }
            freecon(mycon);
            freecon(fcon);
            if (rc < 0) {
                ERROR("could not get context while starting '%s'\n", svc->name);
                return;
            }
        }
    }

    NOTICE("starting '%s'\n", svc->name);

    pid = fork();

    if (pid == 0) {
        struct socketinfo *si;
        struct svcenvinfo *ei;
        char tmp[32];
        int fd, sz;

        umask(077);
        if (properties_inited()) {
            get_property_workspace(&fd, &sz);
            sprintf(tmp, "%d,%d", dup(fd), sz);
            add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
        }

        for (ei = svc->envvars; ei; ei = ei->next)
            add_environment(ei->name, ei->value);

        for (si = svc->sockets; si; si = si->next) {
            int socket_type = (
                    !strcmp(si->type, "stream") ? SOCK_STREAM :
                        (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
            int s = create_socket(si->name, socket_type,
                                  si->perm, si->uid, si->gid, si->socketcon ?: scon);
            if (s >= 0) {
                publish_socket(si->name, s);
            }
        }

        freecon(scon);
        scon = NULL;

        if (svc->ioprio_class != IoSchedClass_NONE) {
            if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
                ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
                      getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno));
            }
        }

        if (needs_console) {
            setsid();
            open_console();
        } else {
            zap_stdio();
        }

#if 0
        for (n = 0; svc->args[n]; n++) {
            INFO("args[%d] = '%s'\n", n, svc->args[n]);
        }
        for (n = 0; ENV[n]; n++) {
            INFO("env[%d] = '%s'\n", n, ENV[n]);
        }
#endif

        setpgid(0, getpid());

    /* as requested, set our gid, supplemental gids, and uid */
        if (svc->gid) {
            if (setgid(svc->gid) != 0) {
                ERROR("setgid failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (svc->nr_supp_gids) {
            if (setgroups(svc->nr_supp_gids, svc->supp_gids) != 0) {
                ERROR("setgroups failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (svc->uid) {
            if (setuid(svc->uid) != 0) {
                ERROR("setuid failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (svc->seclabel) {
            if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) {
                ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno));
                _exit(127);
            }
        }

        if (!dynamic_args) {
            if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
            }
        } else {
            char *arg_ptrs[INIT_PARSER_MAXARGS+1];
            int arg_idx = svc->nargs;
            char *tmp = strdup(dynamic_args);
            char *next = tmp;
            char *bword;

            /* Copy the static arguments */
            memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));

            while((bword = strsep(&next, " "))) {
                arg_ptrs[arg_idx++] = bword;
                if (arg_idx == INIT_PARSER_MAXARGS)
                    break;
            }
            arg_ptrs[arg_idx] = '\0';
            execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
        }
        _exit(127);
    }

    freecon(scon);

    if (pid < 0) {
        ERROR("failed to start '%s'\n", svc->name);
        svc->pid = 0;
        return;
    }

    svc->time_started = gettime();
    svc->pid = pid;
    svc->flags |= SVC_RUNNING;

    if (properties_inited())
        notify_service_state(svc->name, "running");
}
Example #9
0
int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
    bool is_charger = false;

    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    /* clear the umask */
    umask(0);

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

        /* indicate that booting is in progress to background fw loaders, etc */
    close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));

        /* We must have some place other than / to create the
         * device nodes for kmsg and null, otherwise we won't
         * be able to remount / read-only later on.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();
    klog_init();
    property_init();

    get_hardware_name(hardware, &revision);

    process_kernel_cmdline();

    union selinux_callback cb;
    cb.func_log = log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    selinux_initialize();
    /* These directories were necessarily created before initial policy load
     * and therefore need their security context restored to the proper value.
     * This must happen before /dev is populated by ueventd.
     */
    restorecon("/dev");
    restorecon("/dev/socket");
    restorecon("/dev/__properties__");
    restorecon_recursive("/sys");

    is_charger = !strcmp(bootmode, "charger");

    INFO("property init\n");
    property_load_boot_defaults();

    INFO("reading config file\n");
    init_parse_config_file("/init.rc");

    action_for_each_trigger("early-init", action_add_queue_tail);

    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    queue_builtin_action(keychord_init_action, "keychord_init");
    queue_builtin_action(console_init_action, "console_init");

    /* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);

    /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
     * wasn't ready immediately after wait_for_coldboot_done
     */
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    queue_builtin_action(property_service_init_action, "property_service_init");
    queue_builtin_action(signal_init_action, "signal_init");

    /* Don't mount filesystems or start core system services if in charger mode. */
    if (is_charger) {
        action_for_each_trigger("charger", action_add_queue_tail);
    } else {
        action_for_each_trigger("late-init", action_add_queue_tail);
    }

    /* run all property triggers based on current state of the properties */
    queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");


#if BOOTCHART
    queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif

    for(;;) {
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init && get_signal_fd() > 0) {
            ufds[fd_count].fd = get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
        if (!keychord_fd_init && get_keychord_fd() > 0) {
            ufds[fd_count].fd = get_keychord_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            keychord_fd_init = 1;
        }

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action)
            timeout = 0;

#if BOOTCHART
        if (bootchart_count > 0) {
            long long current_time;
            int elapsed_time, remaining_time;

            current_time = bootchart_gettime();
            elapsed_time = current_time - bootchart_time;

            if (elapsed_time >= BOOTCHART_POLLING_MS) {
                /* count missed samples */
                while (elapsed_time >= BOOTCHART_POLLING_MS) {
                    elapsed_time -= BOOTCHART_POLLING_MS;
                    bootchart_count--;
                }
                /* count may be negative, take a sample anyway */
                bootchart_time = current_time;
                if (bootchart_step() < 0 || bootchart_count <= 0) {
                    bootchart_finish();
                    bootchart_count = 0;
                }
            }
            if (bootchart_count > 0) {
                remaining_time = BOOTCHART_POLLING_MS - elapsed_time;
                if (timeout < 0 || timeout > remaining_time)
                    timeout = remaining_time;
            }
        }
#endif

        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents & POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }

    return 0;
}
Example #10
0
static int init(char *argv[]) {
  struct stat fstatus;
  struct group *group;
  cp_string filename;
  const char *uri=cupsBackendDeviceURI(argv);

  if ((uri != NULL) && (strncmp(uri, "cups-pdf:/", 10) == 0) && strlen(uri) > 10) {
    uri = uri + 10;
    sprintf(filename, "%s/cups-pdf-%s.conf", CP_CONFIG_PATH, uri);
  } 
  else {
    sprintf(filename, "%s/cups-pdf.conf", CP_CONFIG_PATH);
  }
  read_config_file(filename);
  cwwdebug(filename);

  read_config_ppd();

  read_config_options(argv[5]);

  (void) umask(0077);

  group=getgrnam(Conf_Grp);
  if (group)
    (void) setgid(group->gr_gid);
  cwwdebug(Conf_Log);
  if (strlen(Conf_Log)) {
    if (stat(Conf_Log, &fstatus) || !S_ISDIR(fstatus.st_mode)) {
      if (create_dir(Conf_Log, 1)) 
        return 1;
      if (chmod(Conf_Log, 0700))
        return 1;
    }
    snprintf(filename, BUFSIZE, "%s/%s%s%s", Conf_Log, "cups-pdf-", getenv("PRINTER"), "_log");
    logfp=fopen(filename, "a");
  }
  char tmpstr[100];
  *tmpstr = '\0';
  sprintf(tmpstr, "uid = %d, euid = %d", getuid(), geteuid());
  cwwdebug(tmpstr);
  if (logfp == NULL) {
	cwwdebug(strerror(errno));
	cwwdebug("logfp == NULL");
  }
  cwwdebug(filename);
  dump_configuration();

  if (!group) {
    log_event(CPERROR, "Grp not found: %s", Conf_Grp);
    return 1;
  }
  else 
    log_event(CPDEBUG, "switching to new gid: %s", Conf_Grp);
  cwwdebug("group");
  (void) umask(0022);
  cwwdebug("umask");
  cwwdebug(Conf_Spool);
  if (stat(Conf_Spool, &fstatus) || !S_ISDIR(fstatus.st_mode)) {
    if (create_dir(Conf_Spool, 0)) {
      log_event(CPERROR, "failed to create spool directory: %s", Conf_Spool);
      return 1;
    }
	cwwdebug("create_dir(Conf_Spool, 0) success!");
    if (chmod(Conf_Spool, 0751)) {
      log_event(CPERROR, "failed to set mode on spool directory: %s", Conf_Spool);
      return 1;
    }
	cwwdebug("chmod(Conf_Spool, 0751) success!");
    if (chown(Conf_Spool, -1, group->gr_gid)) 
      log_event(CPERROR, "failed to set group id %s on spool directory: %s (non fatal)", Conf_Grp, Conf_Spool);
    log_event(CPSTATUS, "spool directory created: %s", Conf_Spool);
  }
  cwwdebug("stat");
  (void) umask(0077);
  return 0;
}
Example #11
0
int main(int argc, char *argv[]) {
  char *user, *dirname, *spoolfile, *outfile, *gscall, *ppcall;
  cp_string title;
  int size;
  mode_t mode;
  struct passwd *passwd;
  gid_t *groups;
  int ngroups;
  pid_t pid;
/*
  puts("s0");
  int ff = open("/home/cww/t3", O_CREAT | O_RDWR, 0777);
  if (ff == -1) {
	  perror("13");
  }*/
  //close(ff);
  //printf("uid = %d, euid = %d\n", getuid(), geteuid());
//	puts("s1");
  if (freopen("/tmp/cups-pdf.stderr", "w", stderr) == NULL) {
	  printf("%d %s\n", errno, strerror(errno));
	return 5;
  }
  int f1 = open("/var/log/cups/cups-test", O_CREAT | O_RDWR, 0777);
  if (f1 == -1) {
	cwwdebug(strerror(errno));
	cwwdebug("open /var/log/cups/cups-test fail!");
  }
  close(f1);
  cwwdebug("freopen success!");
  int ff = open("/tmp/tt", O_CREAT | O_RDWR, 0777);
  close(ff);
  if (setuid(0)) {
    (void) fputs("CUPS-PDF cannot be called without root privileges!\n", stderr);
    return 0;
  }
  cwwdebug("setuid success!");
  if (argc==1) {
	  cwwdebug("argc = 1");
    announce_printers();
    return 0;
  }
  cwwdebug("argc != 1");
  if (argc<6 || argc>7) {
    (void) fputs("Usage: cups-pdf job-id user title copies options [file]\n", stderr);
    return 0;
  }

  if (init(argv)) {          
	  cwwdebug("init failed!");
    return 5;
  }
  cwwdebug("init success!");
  log_event(CPDEBUG, "initialization finished: %s", CPVERSION);

  size=strlen(Conf_UserPrefix)+strlen(argv[2])+1;
  user=calloc(size, sizeof(char));
  if (user == NULL) {
    (void) fputs("CUPS-PDF: failed to allocate memory\n", stderr);
    return 5;
  }  
  snprintf(user, size, "%s%s", Conf_UserPrefix, argv[2]);
  cwwdebug(user);
  passwd=getpwnam(user);
  if (passwd == NULL && Conf_LowerCase) {
    log_event(CPDEBUG, "unknown user: %s", user);
    for (size=0;size<(int) strlen(argv[2]);size++) 
      argv[2][size]=tolower(argv[2][size]);
    log_event(CPDEBUG, "trying lower case user name: %s", argv[2]);
    size=strlen(Conf_UserPrefix)+strlen(argv[2])+1;
    snprintf(user, size, "%s%s", Conf_UserPrefix, argv[2]);
    passwd=getpwnam(user);
  }  
  if (passwd == NULL) {
    if (strlen(Conf_AnonUser)) {
      passwd=getpwnam(Conf_AnonUser);
      if (passwd == NULL) {
        log_event(CPERROR, "username for anonymous access unknown: %s", Conf_AnonUser);
        free(user);
        if (logfp!=NULL)
          (void) fclose(logfp);
        return 5;
      }
      log_event(CPDEBUG, "unknown user: %s", user);
      size=strlen(Conf_AnonDirName)+4;
      dirname=calloc(size, sizeof(char));
      if (dirname == NULL) {
        (void) fputs("CUPS-PDF: failed to allocate memory\n", stderr);
        free(user);
        if (logfp!=NULL)
          (void) fclose(logfp);
        return 5;
      }  
      snprintf(dirname, size, "%s", Conf_AnonDirName);
      while (strlen(dirname) && ((dirname[strlen(dirname)-1] == '\n') ||
             (dirname[strlen(dirname)-1] == '\r')))
        dirname[strlen(dirname)-1]='\0';
      log_event(CPDEBUG, "output directory name generated: %s", dirname);
    }
    else {
      log_event(CPSTATUS, "anonymous access denied: %s", user);
      free(user);
      if (logfp!=NULL)
        (void) fclose(logfp);
      return 0;
    }
    mode=(mode_t)(0666&~Conf_AnonUMask);
  } 
  else {
    log_event(CPDEBUG, "user identified: %s", passwd->pw_name);
    if ((dirname=preparedirname(passwd, argv[2])) == NULL) {
      (void) fputs("CUPS-PDF: failed to allocate memory\n", stderr);
      free(user);
      if (logfp!=NULL)
        (void) fclose(logfp);
      return 5;
    }  
    while (strlen(dirname) && ((dirname[strlen(dirname)-1] == '\n') ||
           (dirname[strlen(dirname)-1] == '\r')))
      dirname[strlen(dirname)-1]='\0';
    log_event(CPDEBUG, "output directory name generated: %s", dirname);
    mode=(mode_t)(0666&~Conf_UserUMask);
  }
  ngroups=32;
  groups=calloc(ngroups, sizeof(gid_t));
  if (groups == NULL) {
    (void) fputs("CUPS-PDF: failed to allocate memory\n", stderr);
    free(user);
    if (logfp!=NULL)
      (void) fclose(logfp);
    return 5;
  }
  size=getgrouplist(user, passwd->pw_gid, groups, &ngroups);
  if (size == -1) {
    free(groups);
    groups=calloc(ngroups, sizeof(gid_t));
    size=getgrouplist(user, passwd->pw_gid, groups, &ngroups);
  }
  if (size < 0) {
    log_event(CPERROR, "getgrouplist failed");
    free(user);
    free(groups);
    if (logfp!=NULL)
      (void) fclose(logfp);
    return 5;
  }
  free(user);
  if (prepareuser(passwd, dirname)) {
    free(groups);
    free(dirname);
    if (logfp!=NULL)
      (void) fclose(logfp);
    return 5;
  }
  log_event(CPDEBUG, "user information prepared");

  size=strlen(Conf_Spool)+22;
  spoolfile=calloc(size, sizeof(char));
  if (spoolfile == NULL) {
    (void) fputs("CUPS-PDF: failed to allocate memory\n", stderr);
    free(groups);
    free(dirname);
    if (logfp!=NULL)
      (void) fclose(logfp);
    return 5;
  }
  snprintf(spoolfile, size, "%s/cups2pdf-%i", Conf_Spool, (int) getpid());
  log_event(CPDEBUG, "spoolfile name created: %s", spoolfile);

  if (argc == 6) {
    if (preparespoolfile(stdin, spoolfile, title, argv[3], atoi(argv[1]), passwd)) {
      free(groups);
      free(dirname);
      free(spoolfile);
      if (logfp!=NULL)
        (void) fclose(logfp);
      return 5;
    }
    log_event(CPDEBUG, "input data read from stdin");
  }
  else {
    if (preparespoolfile(fopen(argv[6], "r"), spoolfile, title, argv[3], atoi(argv[1]), passwd)) {
      free(groups);
      free(dirname);
      free(spoolfile);
      if (logfp!=NULL)
        (void) fclose(logfp);
      return 5;
    }
    log_event(CPDEBUG, "input data read from file: %s", argv[6]);
  }  

  size=strlen(dirname)+strlen(title)+strlen(Conf_OutExtension)+3;
  outfile=calloc(size, sizeof(char));
  if (outfile == NULL) {
    (void) fputs("CUPS-PDF: failed to allocate memory\n", stderr);
    if (unlink(spoolfile))
      log_event(CPERROR, "failed to unlink spoolfile during clean-up: %s", spoolfile);
    free(groups);
    free(dirname);
    free(spoolfile);
    if (logfp!=NULL)
      (void) fclose(logfp);
    return 5;
  }
  if (strlen(Conf_OutExtension))
    snprintf(outfile, size, "%s/%s.%s", dirname, title, Conf_OutExtension);
  else
    snprintf(outfile, size, "%s/%s", dirname, title);
  log_event(CPDEBUG, "output filename created: %s", outfile);

  size=strlen(Conf_GSCall)+strlen(Conf_GhostScript)+strlen(Conf_PDFVer)+strlen(outfile)+strlen(spoolfile)+6;
  gscall=calloc(size, sizeof(char));
  if (gscall == NULL) {
    (void) fputs("CUPS-PDF: failed to allocate memory\n", stderr);
    if (unlink(spoolfile))
      log_event(CPERROR, "failed to unlink spoolfile during clean-up: %s", spoolfile);
    free(groups);
    free(dirname);
    free(spoolfile);
    free(outfile);
    if (logfp!=NULL)
      (void) fclose(logfp);
    return 5;
  }
  snprintf(gscall, size, Conf_GSCall, Conf_GhostScript, Conf_PDFVer, outfile, spoolfile);
  log_event(CPDEBUG, "ghostscript commandline built: %s", gscall);

  (void) unlink(outfile);
  log_event(CPDEBUG, "output file unlinked: %s", outfile);

  if (putenv(Conf_GSTmp)) {
    log_event(CPERROR, "insufficient space in environment to set TMPDIR: %s", Conf_GSTmp);
    if (unlink(spoolfile))
      log_event(CPERROR, "failed to unlink spoolfile during clean-up: %s", spoolfile);
    free(groups);
    free(dirname);
    free(spoolfile);
    free(outfile);
    free(gscall);
    if (logfp!=NULL)
      (void) fclose(logfp);
    return 5;
  }
  log_event(CPDEBUG, "TMPDIR set for GhostScript: %s", getenv("TMPDIR"));

  pid=fork();

  if (!pid) {
    log_event(CPDEBUG, "entering child process");

    if (setgid(passwd->pw_gid))
      log_event(CPERROR, "failed to set GID for current user");
    else
      log_event(CPDEBUG, "GID set for current user");
    if (setgroups(ngroups, groups))
      log_event(CPERROR, "failed to set supplementary groups for current user");
    else 
      log_event(CPDEBUG, "supplementary groups set for current user");
    if (setuid(passwd->pw_uid))
      log_event(CPERROR, "failed to set UID for current user: %s", passwd->pw_name);
    else
      log_event(CPDEBUG, "UID set for current user: %s", passwd->pw_name);
     
    (void) umask(0077);
    size=system(gscall);
    log_event(CPDEBUG, "ghostscript has finished: %d", size);
    if (chmod(outfile, mode))
      log_event(CPERROR, "failed to set file mode for PDF file: %s (non fatal)", outfile);
    else
      log_event(CPDEBUG, "file mode set for user output: %s", outfile);
    
    if (strlen(Conf_PostProcessing)) {
      size=strlen(Conf_PostProcessing)+strlen(outfile)+strlen(passwd->pw_name)+strlen(argv[2])+4;
      ppcall=calloc(size, sizeof(char));
      if (ppcall == NULL) 
        log_event(CPERROR, "failed to allocate memory for postprocessing (non fatal)");
      else {
        snprintf(ppcall, size, "%s %s %s %s", Conf_PostProcessing, outfile, passwd->pw_name, argv[2]);
        log_event(CPDEBUG, "postprocessing commandline built: %s", ppcall);
        size=system(ppcall);
        snprintf(title,BUFSIZE,"%d",size);
        log_event(CPDEBUG, "postprocessing has finished: %s", title);
        free(ppcall);
      }
    }
    else
     log_event(CPDEBUG, "no postprocessing");

    return 0;
  }
  log_event(CPDEBUG, "waiting for child to exit");
  (void) waitpid(pid,NULL,0);

  if (unlink(spoolfile)) 
    log_event(CPERROR, "failed to unlink spoolfile: %s (non fatal)", spoolfile);
  else 
    log_event(CPDEBUG, "spoolfile unlinked: %s", spoolfile);

  free(groups);
  free(dirname);
  free(spoolfile);
  free(outfile);
  free(gscall);
  
  log_event(CPDEBUG, "all memory has been freed");

  log_event(CPSTATUS, "PDF creation successfully finished for %s", passwd->pw_name);

  if (logfp!=NULL)
    (void) fclose(logfp);
  return 0;
} 
Example #12
0
int
main(int argc, char **argv)
{
  int i;
  sigset_t set;
#if ENABLE_MPEGTS
  uint32_t adapter_mask = 0;
#endif
  int  log_level   = LOG_INFO;
  int  log_options = TVHLOG_OPT_MILLIS | TVHLOG_OPT_STDERR | TVHLOG_OPT_SYSLOG;
  const char *log_debug = NULL, *log_trace = NULL;
  gid_t gid = -1;
  uid_t uid = -1;
  char buf[512];
  FILE *pidfile = NULL;
  extern int dvb_bouquets_parse;

  main_tid = pthread_self();

  /* Setup global mutexes */
  pthread_mutex_init(&fork_lock, NULL);
  pthread_mutex_init(&global_lock, NULL);
  pthread_mutex_init(&tasklet_lock, NULL);
  pthread_mutex_init(&atomic_lock, NULL);
  pthread_cond_init(&gtimer_cond, NULL);
  pthread_cond_init(&tasklet_cond, NULL);
  TAILQ_INIT(&tasklets);

  /* Defaults */
  tvheadend_webui_port      = 9981;
  tvheadend_webroot         = NULL;
  tvheadend_htsp_port       = 9982;
  tvheadend_htsp_port_extra = 0;
  time(&dispatch_clock);

  /* Command line options */
  int         opt_help         = 0,
              opt_version      = 0,
              opt_fork         = 0,
              opt_firstrun     = 0,
              opt_stderr       = 0,
              opt_syslog       = 0,
              opt_nosyslog     = 0,
              opt_uidebug      = 0,
              opt_abort        = 0,
              opt_noacl        = 0,
              opt_fileline     = 0,
              opt_threadid     = 0,
              opt_libav        = 0,
              opt_ipv6         = 0,
              opt_satip_rtsp   = 0,
#if ENABLE_TSFILE
              opt_tsfile_tuner = 0,
#endif
              opt_dump         = 0,
              opt_xspf         = 0,
              opt_dbus         = 0,
              opt_dbus_session = 0,
              opt_nobackup     = 0,
              opt_nobat        = 0;
  const char *opt_config       = NULL,
             *opt_user         = NULL,
             *opt_group        = NULL,
             *opt_logpath      = NULL,
             *opt_log_debug    = NULL,
             *opt_log_trace    = NULL,
             *opt_pidpath      = "/var/run/tvheadend.pid",
#if ENABLE_LINUXDVB
             *opt_dvb_adapters = NULL,
#endif
             *opt_bindaddr     = NULL,
             *opt_subscribe    = NULL,
             *opt_user_agent   = NULL;
  str_list_t  opt_satip_xml    = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  str_list_t  opt_tsfile       = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  cmdline_opt_t cmdline_opts[] = {
    {   0, NULL,        N_("Generic Options"),         OPT_BOOL, NULL         },
    { 'h', "help",      N_("Show this page"),          OPT_BOOL, &opt_help    },
    { 'v', "version",   N_("Show version information"),OPT_BOOL, &opt_version },

    {   0, NULL,        N_("Service Configuration"),   OPT_BOOL, NULL         },
    { 'c', "config",    N_("Alternate config path"),   OPT_STR,  &opt_config  },
    { 'B', "nobackup",  N_("Don't backup config tree at upgrade"), OPT_BOOL, &opt_nobackup },
    { 'f', "fork",      N_("Fork and run as daemon"),  OPT_BOOL, &opt_fork    },
    { 'u', "user",      N_("Run as user"),             OPT_STR,  &opt_user    },
    { 'g', "group",     N_("Run as group"),            OPT_STR,  &opt_group   },
    { 'p', "pid",       N_("Alternate pid path"),      OPT_STR,  &opt_pidpath },
    { 'C', "firstrun",  N_("If no user account exists then create one with\n"
	                   "no username and no password. Use with care as\n"
	                   "it will allow world-wide administrative access\n"
	                   "to your Tvheadend installation until you edit/create\n"
	                   "access-control from within the Tvheadend UI"),
      OPT_BOOL, &opt_firstrun },
#if ENABLE_DBUS_1
    { 'U', "dbus",      N_("Enable DBus"),
      OPT_BOOL, &opt_dbus },
    { 'e', "dbus_session", N_("DBus - use the session message bus instead system one"),
      OPT_BOOL, &opt_dbus_session },
#endif
#if ENABLE_LINUXDVB
    { 'a', "adapters",  N_("Only use specified DVB adapters (comma separated)"),
      OPT_STR, &opt_dvb_adapters },
#endif
#if ENABLE_SATIP_SERVER
    {   0, "satip_rtsp", N_("SAT>IP RTSP port number for server\n"
                            "(default: -1 = disable, 0 = webconfig, standard port is 554)"),
      OPT_INT, &opt_satip_rtsp },
#endif
#if ENABLE_SATIP_CLIENT
    {   0, "satip_xml", N_("URL with the SAT>IP server XML location"),
      OPT_STR_LIST, &opt_satip_xml },
#endif
    {   0, NULL,         N_("Server Connectivity"),    OPT_BOOL, NULL         },
    { '6', "ipv6",       N_("Listen on IPv6"),         OPT_BOOL, &opt_ipv6    },
    { 'b', "bindaddr",   N_("Specify bind address"),   OPT_STR,  &opt_bindaddr},
    {   0, "http_port",  N_("Specify alternative http port"),
      OPT_INT, &tvheadend_webui_port },
    {   0, "http_root",  N_("Specify alternative http webroot"),
      OPT_STR, &tvheadend_webroot },
    {   0, "htsp_port",  N_("Specify alternative htsp port"),
      OPT_INT, &tvheadend_htsp_port },
    {   0, "htsp_port2", N_("Specify extra htsp port"),
      OPT_INT, &tvheadend_htsp_port_extra },
    {   0, "useragent",  N_("Specify User-Agent header for the http client"),
      OPT_STR, &opt_user_agent },
    {   0, "xspf",       N_("Use XSPF playlist instead of M3U"),
      OPT_BOOL, &opt_xspf },

    {   0, NULL,        N_("Debug Options"),           OPT_BOOL, NULL         },
    { 'd', "stderr",    N_("Enable debug on stderr"),  OPT_BOOL, &opt_stderr  },
    { 's', "syslog",    N_("Enable debug to syslog"),  OPT_BOOL, &opt_syslog  },
    { 'S', "nosyslog",  N_("Disable syslog (all msgs)"), OPT_BOOL, &opt_nosyslog },
    { 'l', "logfile",   N_("Enable debug to file"),    OPT_STR,  &opt_logpath },
    {   0, "debug",     N_("Enable debug subsystems"),  OPT_STR,  &opt_log_debug },
#if ENABLE_TRACE
    {   0, "trace",     N_("Enable trace subsystems"), OPT_STR,  &opt_log_trace },
#endif
    {   0, "fileline",  N_("Add file and line numbers to debug"), OPT_BOOL, &opt_fileline },
    {   0, "threadid",  N_("Add the thread ID to debug"), OPT_BOOL, &opt_threadid },
#if ENABLE_LIBAV
    {   0, "libav",     N_("More verbose libav log"),  OPT_BOOL, &opt_libav },
#endif
    {   0, "uidebug",   N_("Enable webUI debug (non-minified JS)"), OPT_BOOL, &opt_uidebug },
    { 'A', "abort",     N_("Immediately abort"),       OPT_BOOL, &opt_abort   },
    { 'D', "dump",      N_("Enable coredumps for daemon"), OPT_BOOL, &opt_dump },
    {   0, "noacl",     N_("Disable all access control checks"),
      OPT_BOOL, &opt_noacl },
    {   0, "nobat",     N_("Disable DVB bouquets"),
      OPT_BOOL, &opt_nobat },
    { 'j', "join",      N_("Subscribe to a service permanently"),
      OPT_STR, &opt_subscribe },


#if ENABLE_TSFILE || ENABLE_TSDEBUG
    { 0, NULL, N_("Testing options"), OPT_BOOL, NULL },
    { 0, "tsfile_tuners", N_("Number of tsfile tuners"), OPT_INT, &opt_tsfile_tuner },
    { 0, "tsfile", N_("tsfile input (mux file)"), OPT_STR_LIST, &opt_tsfile },
#endif
#if ENABLE_TSDEBUG
    { 0, "tsdebug", N_("Output directory for tsdebug"), OPT_STR, &tvheadend_tsdebug },
#endif

  };

  /* Get current directory */
  tvheadend_cwd0 = dirname(tvh_strdupa(argv[0]));
  tvheadend_cwd = dirname(tvh_strdupa(tvheadend_cwd0));

  /* Set locale */
  setlocale(LC_ALL, "");
  setlocale(LC_NUMERIC, "C");
  tvh_gettext_init();

  /* make sure the timezone is set */
  tzset();

  /* Process command line */
  for (i = 1; i < argc; i++) {

    /* Find option */
    cmdline_opt_t *opt
      = cmdline_opt_find(cmdline_opts, ARRAY_SIZE(cmdline_opts), argv[i]);
    if (!opt)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 _("invalid option specified [%s]"), argv[i]);

    /* Process */
    if (opt->type == OPT_BOOL)
      *((int*)opt->param) = 1;
    else if (++i == argc)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 _("option %s requires a value"), opt->lopt);
    else if (opt->type == OPT_INT)
      *((int*)opt->param) = atoi(argv[i]);
    else if (opt->type == OPT_STR_LIST) {
      str_list_t *strl = opt->param;
      if (strl->num < strl->max)
        strl->str[strl->num++] = argv[i];
    }
    else
      *((char**)opt->param) = argv[i];

    /* Stop processing */
    if (opt_help)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), NULL);
    if (opt_version)
      show_version(argv[0]);
  }

  /* Additional cmdline processing */
  if (opt_nobat)
    dvb_bouquets_parse = 0;
#if ENABLE_LINUXDVB
  if (!opt_dvb_adapters) {
    adapter_mask = ~0;
  } else {
    char *p, *e;
    char *r = NULL;
    char *dvb_adapters = strdup(opt_dvb_adapters);
    adapter_mask = 0x0;
    p = strtok_r(dvb_adapters, ",", &r);
    while (p) {
      int a = strtol(p, &e, 10);
      if (*e != 0 || a < 0 || a > 31) {
        fprintf(stderr, _("Invalid adapter number '%s'\n"), p);
        free(dvb_adapters);
        return 1;
      }
      adapter_mask |= (1 << a);
      p = strtok_r(NULL, ",", &r);
    }
    free(dvb_adapters);
    if (!adapter_mask) {
      fprintf(stderr, "%s", _("No adapters specified!\n"));
      return 1;
    }
  }
#endif
  if (tvheadend_webroot) {
    char *tmp;
    if (*tvheadend_webroot == '/')
      tmp = strdup(tvheadend_webroot);
    else {
      tmp = malloc(strlen(tvheadend_webroot)+2);
      *tmp = '/';
      strcpy(tmp+1, tvheadend_webroot);
    }
    if (tmp[strlen(tmp)-1] == '/')
      tmp[strlen(tmp)-1] = '\0';
    tvheadend_webroot = tmp;
  }
  tvheadend_webui_debug = opt_uidebug;

  /* Setup logging */
  if (isatty(2))
    log_options |= TVHLOG_OPT_DECORATE;
  if (opt_stderr || opt_syslog || opt_logpath) {
    if (!opt_log_trace && !opt_log_debug)
      log_debug      = "all";
    log_level      = LOG_DEBUG;
    if (opt_stderr)
      log_options   |= TVHLOG_OPT_DBG_STDERR;
    if (opt_syslog)
      log_options   |= TVHLOG_OPT_DBG_SYSLOG;
    if (opt_logpath)
      log_options   |= TVHLOG_OPT_DBG_FILE;
  }
  if (opt_nosyslog)
    log_options &= ~(TVHLOG_OPT_SYSLOG|TVHLOG_OPT_DBG_SYSLOG);
  if (opt_fileline)
    log_options |= TVHLOG_OPT_FILELINE;
  if (opt_threadid)
    log_options |= TVHLOG_OPT_THREAD;
  if (opt_libav)
    log_options |= TVHLOG_OPT_LIBAV;
  if (opt_log_trace) {
    log_level  = LOG_TRACE;
    log_trace  = opt_log_trace;
  }
  if (opt_log_debug)
    log_debug  = opt_log_debug;
    
  tvhlog_init(log_level, log_options, opt_logpath);
  tvhlog_set_debug(log_debug);
  tvhlog_set_trace(log_trace);
  tvhinfo("main", "Log started");
 
  signal(SIGPIPE, handle_sigpipe); // will be redundant later
  signal(SIGILL, handle_sigill);   // see handler..

  /* Set priviledges */
  if(opt_fork || opt_group || opt_user) {
    const char *homedir;
    struct group  *grp = getgrnam(opt_group ?: "video");
    struct passwd *pw  = opt_user ? getpwnam(opt_user) : NULL;

    if(grp != NULL) {
      gid = grp->gr_gid;
    } else {
      gid = 1;
    }

    if (pw != NULL) {
      if (getuid() != pw->pw_uid) {
        gid_t glist[16];
        int gnum;
        gnum = get_user_groups(pw, glist, ARRAY_SIZE(glist));
        if (gnum > 0 && setgroups(gnum, glist)) {
          char buf[256] = "";
          int i;
          for (i = 0; i < gnum; i++)
            snprintf(buf + strlen(buf), sizeof(buf) - 1 - strlen(buf),
                     ",%d", glist[i]);
          tvhlog(LOG_ALERT, "START",
                 "setgroups(%s) failed, do you have permission?", buf+1);
          return 1;
        }
      }
      uid     = pw->pw_uid;
      homedir = pw->pw_dir;
      setenv("HOME", homedir, 1);
    } else {
      uid = 1;
    }
  }

  uuid_init();
  config_boot(opt_config, gid, uid);
  tcp_server_preinit(opt_ipv6);
  http_server_init(opt_bindaddr);    // bind to ports only
  htsp_init(opt_bindaddr);	     // bind to ports only
  satip_server_init(opt_satip_rtsp); // bind to ports only

  if (opt_fork)
    pidfile = tvh_fopen(opt_pidpath, "w+");

  if (gid != -1 && (getgid() != gid) && setgid(gid)) {
    tvhlog(LOG_ALERT, "START",
           "setgid(%d) failed, do you have permission?", gid);
    return 1;
  }
  if (uid != -1 && (getuid() != uid) && setuid(uid)) {
    tvhlog(LOG_ALERT, "START",
           "setuid(%d) failed, do you have permission?", uid);
    return 1;
  }

  /* Daemonise */
  if(opt_fork) {
    if(daemon(0, 0)) {
      exit(2);
    }
    if(pidfile != NULL) {
      fprintf(pidfile, "%d\n", getpid());
      fclose(pidfile);
    }

    /* Make dumpable */
    if (opt_dump) {
#ifdef PLATFORM_LINUX
      if (chdir("/tmp"))
        tvhwarn("START", "failed to change cwd to /tmp");
      prctl(PR_SET_DUMPABLE, 1);
#else
      tvhwarn("START", "Coredumps not implemented on your platform");
#endif
    }

    umask(0);
  }

  tvheadend_running = 1;

  /* Start log thread (must be done post fork) */
  tvhlog_start();

  /* Alter logging */
  if (opt_fork)
    tvhlog_options &= ~TVHLOG_OPT_STDERR;
  if (!isatty(2))
    tvhlog_options &= ~TVHLOG_OPT_DECORATE;
  
  /* Initialise clock */
  pthread_mutex_lock(&global_lock);
  time(&dispatch_clock);

  /* Signal handling */
  sigfillset(&set);
  sigprocmask(SIG_BLOCK, &set, NULL);
  trap_init(argv[0]);

  /* SSL library init */
  OPENSSL_config(NULL);
  SSL_load_error_strings();
  SSL_library_init();

  /* Initialise configuration */
  notify_init();
  idnode_init();
  spawn_init();
  config_init(opt_nobackup == 0);

  /**
   * Initialize subsystems
   */

  epg_in_load = 1;

  tvhthread_create(&tasklet_tid, NULL, tasklet_thread, NULL);

  dbus_server_init(opt_dbus, opt_dbus_session);

  intlconv_init();
  
  api_init();

  fsmonitor_init();

  libav_init();

  tvhtime_init();

  profile_init();

  imagecache_init();

  http_client_init(opt_user_agent);
  esfilter_init();

  bouquet_init();

  service_init();

  dvb_init();

#if ENABLE_MPEGTS
  mpegts_init(adapter_mask, &opt_satip_xml, &opt_tsfile, opt_tsfile_tuner);
#endif

  channel_init();

  bouquet_service_resolve();

  subscription_init();

  dvr_config_init();

  access_init(opt_firstrun, opt_noacl);

#if ENABLE_TIMESHIFT
  timeshift_init();
#endif

  tcp_server_init();
  webui_init(opt_xspf);
#if ENABLE_UPNP
  upnp_server_init(opt_bindaddr);
#endif

  service_mapper_init();

  descrambler_init();

  epggrab_init();
  epg_init();

  dvr_init();

  dbus_server_start();

  http_server_register();
  satip_server_register();
  htsp_register();

  if(opt_subscribe != NULL)
    subscription_dummy_join(opt_subscribe, 1);

  avahi_init();
  bonjour_init();

  epg_updated(); // cleanup now all prev ref's should have been created
  epg_in_load = 0;

  pthread_mutex_unlock(&global_lock);

  /**
   * Wait for SIGTERM / SIGINT, but only in this thread
   */

  sigemptyset(&set);
  sigaddset(&set, SIGTERM);
  sigaddset(&set, SIGINT);

  signal(SIGTERM, doexit);
  signal(SIGINT, doexit);

  pthread_sigmask(SIG_UNBLOCK, &set, NULL);

  tvhlog(LOG_NOTICE, "START", "HTS Tvheadend version %s started, "
         "running as PID:%d UID:%d GID:%d, CWD:%s CNF:%s",
         tvheadend_version,
         getpid(), getuid(), getgid(), getcwd(buf, sizeof(buf)),
         hts_settings_get_root());

  if(opt_abort)
    abort();

  mainloop();

#if ENABLE_DBUS_1
  tvhftrace("main", dbus_server_done);
#endif
#if ENABLE_UPNP
  tvhftrace("main", upnp_server_done);
#endif
  tvhftrace("main", satip_server_done);
  tvhftrace("main", htsp_done);
  tvhftrace("main", http_server_done);
  tvhftrace("main", webui_done);
  tvhftrace("main", fsmonitor_done);
  tvhftrace("main", http_client_done);
  tvhftrace("main", tcp_server_done);

  // Note: the locking is obviously a bit redundant, but without
  //       we need to disable the gtimer_arm call in epg_save()
  pthread_mutex_lock(&global_lock);
  tvhftrace("main", epg_save);

#if ENABLE_TIMESHIFT
  tvhftrace("main", timeshift_term);
#endif
  pthread_mutex_unlock(&global_lock);

  tvhftrace("main", epggrab_done);
#if ENABLE_MPEGTS
  tvhftrace("main", mpegts_done);
#endif
  tvhftrace("main", descrambler_done);
  tvhftrace("main", service_mapper_done);
  tvhftrace("main", service_done);
  tvhftrace("main", channel_done);
  tvhftrace("main", bouquet_done);
  tvhftrace("main", dvr_done);
  tvhftrace("main", subscription_done);
  tvhftrace("main", access_done);
  tvhftrace("main", epg_done);
  tvhftrace("main", avahi_done);
  tvhftrace("main", bonjour_done);
  tvhftrace("main", imagecache_done);
  tvhftrace("main", lang_code_done);
  tvhftrace("main", api_done);

  tvhtrace("main", "tasklet enter");
  pthread_cond_signal(&tasklet_cond);
  pthread_join(tasklet_tid, NULL);
  tvhtrace("main", "tasklet thread end");
  tasklet_flush();
  tvhtrace("main", "tasklet leave");

  tvhftrace("main", hts_settings_done);
  tvhftrace("main", dvb_done);
  tvhftrace("main", lang_str_done);
  tvhftrace("main", esfilter_done);
  tvhftrace("main", profile_done);
  tvhftrace("main", intlconv_done);
  tvhftrace("main", urlparse_done);
  tvhftrace("main", idnode_done);
  tvhftrace("main", notify_done);
  tvhftrace("main", spawn_done);

  tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend");
  tvhlog_end();

  tvhftrace("main", config_done);

  if(opt_fork)
    unlink(opt_pidpath);
    
#if ENABLE_TSFILE
  free(opt_tsfile.str);
#endif
  free(opt_satip_xml.str);

  /* OpenSSL - welcome to the "cleanup" hell */
  ENGINE_cleanup();
  RAND_cleanup();
  CRYPTO_cleanup_all_ex_data();
  EVP_cleanup();
  CONF_modules_free();
#ifndef OPENSSL_NO_COMP
  COMP_zlib_cleanup();
#endif
  ERR_remove_state(0);
  ERR_free_strings();
#ifndef OPENSSL_NO_COMP
  sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
#endif
  /* end of OpenSSL cleanup code */

#if ENABLE_DBUS_1
  extern void dbus_shutdown(void);
  if (opt_dbus) dbus_shutdown();
#endif
  tvh_gettext_done();
  return 0;
}

/**
 *
 */
void
tvh_str_set(char **strp, const char *src)
{
  free(*strp);
  *strp = src ? strdup(src) : NULL;
}


/**
 *
 */
int
tvh_str_update(char **strp, const char *src)
{
  if(src == NULL)
    return 0;
  free(*strp);
  *strp = strdup(src);
  return 1;
}


/**
 *
 */
void
scopedunlock(pthread_mutex_t **mtxp)
{
  pthread_mutex_unlock(*mtxp);
}
Example #13
0
/** Opens the asynchronous request store.  */
static std::shared_ptr<folly::File> asynclog_open(proxy_t *proxy) {
  char path[PATH_MAX + 1];
  time_t now = time(nullptr);
  pid_t tid = syscall(SYS_gettid);
  struct tm date;
  struct stat st;
  int success = 0;
  int fd = -1;

  if (proxy->async_fd &&
      now - proxy->async_spool_time <= DEFAULT_ASYNCLOG_LIFETIME) {
    return proxy->async_fd;
  }

  if (proxy->async_fd) {
    proxy->async_fd = nullptr;
  }

  localtime_r(&now, &date);
  char hour_path[PATH_MAX+1];
  time_t hour_time = now - (now % 3600);
  if (snprintf(hour_path, PATH_MAX, "%s/%04d%02d%02dT%02d-%lld",
               proxy->router().opts().async_spool.c_str(),
               date.tm_year + 1900,
               date.tm_mon + 1,
               date.tm_mday,
               date.tm_hour,
               (long long) hour_time) > PATH_MAX) {
    hour_path[PATH_MAX] = '\0';
    LOG(ERROR) << "async log hourly spool path is too long: " << hour_path;
    goto epilogue;
  }

  if (stat(hour_path, &st) != 0) {
    mode_t old_umask = umask(0);
    int ret = mkdir(hour_path, 0777);
    int mkdir_errno = 0;
    if (ret != 0) {
      mkdir_errno = errno;
    }
    if (old_umask != 0) {
      umask(old_umask);
    }
    /* EEXIST is possible due to a race. We don't care. */
    if (ret != 0 && mkdir_errno != EEXIST) {
      LOG(ERROR) << "couldn't create async log hour spool path: " <<
                    hour_path << ". reason: " << strerror(mkdir_errno);
      goto epilogue;
    }
  }

  if (snprintf(path, PATH_MAX, "%s/%04d%02d%02dT%02d%02d%02d-%lld-%s-%s-t%d-%p",
               hour_path,
               date.tm_year + 1900,
               date.tm_mon + 1,
               date.tm_mday,
               date.tm_hour,
               date.tm_min,
               date.tm_sec,
               (long long) now,
               proxy->router().opts().service_name.c_str(),
               proxy->router().opts().router_name.c_str(),
               tid,
               proxy) > PATH_MAX) {
    path[PATH_MAX] = '\0';
    LOG(ERROR) << "async log path is too long: " << path;
    goto epilogue;
  }

  /*
   * Just in case, append to the log if it exists
   */
  if (stat(path, &st) != 0) {
    fd = open(path, O_WRONLY | O_CREAT, 0666);
    if (fd < 0) {
      LOG(ERROR) << "Can't create and open async store " << path << ": " <<
                    strerror(errno);
      goto epilogue;
    }
  } else {
    fd = open(path, O_WRONLY | O_APPEND, 0666);
    if (fd < 0) {
      LOG(ERROR) << "Can't re-open async store " << path << ": " <<
                    strerror(errno);
      goto epilogue;
    }
  }

  if (fstat(fd, &st)) {
    LOG(ERROR) << "Can't stat async store " << path << ": " << strerror(errno);
    goto epilogue;
  }
  if (!S_ISREG(st.st_mode)) {
    LOG(ERROR) << "Async store exists but is not a file: " << path << ": " <<
                  strerror(errno);
    goto epilogue;
  }

  proxy->async_fd = countedfd_new(fd);
  if (!proxy->async_fd) {
    LOG(ERROR) << "Unable to allocate memory for async_fd: " << strerror(errno);
    goto epilogue;
  }

  /* Ownership of the descriptor has been passed to prox->async_fd. */
  fd = -1;

  proxy->async_spool_time = now;

  success = 1;

  VLOG(1) << "Opened async store for " << path;

epilogue:
  if (!success) {
    if (fd != -1) {
      close(fd);
    }
    if (proxy->async_fd) {
      proxy->async_fd = nullptr;
    }
  }
  return proxy->async_fd;
}
Example #14
0
int shm_common_new(int key, int *size, int instance, void **shmptr, int create)
{
    struct shm_status sm;
    int retval;
    int is_new = 0;

    if (shmdrv_loaded) {
	// use shmdrv kernel driver
	sm.driver_fd = shmdrv_driver_fd();
	sm.key = key;
	sm.size = (size == NULL? 0: *size);
	sm.flags = 0;
	retval = shmdrv_status(&sm); // check if exists
	if (retval && !create) {
	    // didnt exist, but just attach requested, so fail
	    close(sm.driver_fd);
	    return -ENOENT;
	}
	if (retval) { // didnt exist, so create
	    retval = shmdrv_create(&sm); 
	    if (retval < 0) {
		return retval;
	    }
	    is_new = 1;
	}
	// now attach
	retval = shmdrv_attach(&sm, shmptr);
	if (retval < 0) {
	    close(sm.driver_fd);
	    return retval;
	}
	// if size was passed in as 0 (attach), fill in actual size
	if (size && (*size == 0)) 
	    *size = sm.size;
	close(sm.driver_fd);
	return is_new;

    } else {
	// use POSIX shared memory

	int shmfd, mmap_size;
	mode_t old_umask;
	char segment_name[LINELEN];
	if ((size == 0) || (*size == 0))
	    mmap_size = 0;
	else
	    mmap_size = *size;
	sprintf(segment_name, SHM_FMT, instance, key);
	old_umask = umask(0); //S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
	if (create && ((shmfd = shm_open(segment_name, 
					 (O_CREAT | O_EXCL | O_RDWR),
 				(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))) > 0)) {
	    // initial creation
	    if (fchown(shmfd, getuid(),getgid()))
		perror("fchown");
	    if (ftruncate(shmfd, mmap_size))
		perror("ftruncate");
	    is_new = 1;
	} else if((shmfd = shm_open(segment_name, O_RDWR,
				    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))) < 0) {
	    // just attach, and that failed:
	    umask(old_umask);
	    return -errno;
	} else {  // shmfd open
	    if (mmap_size == 0) {
		struct stat st;
		if (fstat(shmfd, &st)) {
		    perror("fstat");
		    return -errno;
		}
		mmap_size = st.st_size;
	    }
	}
	if((*shmptr = mmap(0, mmap_size, (PROT_READ | PROT_WRITE),
			   MAP_SHARED, shmfd, 0)) == MAP_FAILED) {
	    perror("shm_common_new:mmap");
	    close(shmfd);
	    umask(old_umask);
	    return -errno;
	}
	if (size)  // return actual shm size as determined in attach
	    *size = mmap_size;
	umask(old_umask);
	close(shmfd);
	return is_new;
    }
}
// If the package contains an update binary, extract it and run it.
// @param path
//      待安装的 ota_pkg 的路径字串. 
// @param zip
//      关联到 'path' 目标文件的 ZipArchive 实例的指针. 
// @param wipe_cache
//      传入 install 流程的 log file 的路径. 
// 
static int
try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {
    const ZipEntry* binary_entry =
            mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
    if (binary_entry == NULL) {
        mzCloseZipArchive(zip);
        return INSTALL_CORRUPT;
    }

    const char* binary = "/tmp/update_binary";
    unlink(binary);
    int fd = creat(binary, 0755);
    if (fd < 0) {
        mzCloseZipArchive(zip);
        LOGE("Can't make %s\n", binary);
        return INSTALL_ERROR;
    }
    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
    close(fd);
    mzCloseZipArchive(zip);

    if (!ok) {
        LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);
        return INSTALL_ERROR;
    }

    int pipefd[2];
    pipe(pipefd);

    // When executing the update binary contained in the package, the
    // arguments passed are:
    //
    //   - the version number for this interface
    //
    //   - an fd to which the program can write in order to update the
    //     progress bar.  The program can write single-line commands:
    //
    //        progress <frac> <secs>
    //            fill up the next <frac> part of of the progress bar
    //            over <secs> seconds.  If <secs> is zero, use
    //            set_progress commands to manually control the
    //            progress of this segment of the bar
    //
    //        set_progress <frac>
    //            <frac> should be between 0.0 and 1.0; sets the
    //            progress bar within the segment defined by the most
    //            recent progress command.
    //
    //        firmware <"hboot"|"radio"> <filename>
    //            arrange to install the contents of <filename> in the
    //            given partition on reboot.
    //
    //            (API v2: <filename> may start with "PACKAGE:" to
    //            indicate taking a file from the OTA package.)
    //
    //            (API v3: this command no longer exists.)
    //
    //        ui_print <string>
    //            display <string> on the screen.
    //
    //   - the name of the package zip file.
    //

    const char** args = (const char**)malloc(sizeof(char*) * 5);
    args[0] = binary;
    args[1] = EXPAND(RECOVERY_API_VERSION);   // defined in Android.mk
    char* temp = (char*)malloc(10);
    sprintf(temp, "%d", pipefd[1]);
    args[2] = temp;
    args[3] = (char*)path;
    args[4] = NULL;

    pid_t pid = fork();
    if (pid == 0) {
        umask(022);
        close(pipefd[0]);
        execv(binary, (char* const*)args);
        fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
        _exit(-1);
    }
    close(pipefd[1]);

    *wipe_cache = 0;

    char buffer[1024];
    FILE* from_child = fdopen(pipefd[0], "r");
    while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
        char* command = strtok(buffer, " \n");
        if (command == NULL) {
            continue;
        } else if (strcmp(command, "progress") == 0) {
            char* fraction_s = strtok(NULL, " \n");
            char* seconds_s = strtok(NULL, " \n");

            float fraction = strtof(fraction_s, NULL);
            int seconds = strtol(seconds_s, NULL, 10);

            ui->ShowProgress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds);
        } else if (strcmp(command, "set_progress") == 0) {
            char* fraction_s = strtok(NULL, " \n");
            float fraction = strtof(fraction_s, NULL);
            ui->SetProgress(fraction);
        } else if (strcmp(command, "ui_print") == 0) {
            char* str = strtok(NULL, "\n");
            if (str) {
                ui->Print("%s", str);
            } else {
                ui->Print("\n");
            }
            fflush(stdout);
        } else if (strcmp(command, "wipe_cache") == 0) {
            *wipe_cache = 1;
        } else if (strcmp(command, "clear_display") == 0) {
            ui->SetBackground(RecoveryUI::NONE);
        } else if (strcmp(command, "enable_reboot") == 0) {
            // packages can explicitly request that they want the user
            // to be able to reboot during installation (useful for
            // debugging packages that don't exit).
            ui->SetEnableReboot(true);
        } else {
            LOGE("unknown command [%s]\n", command);
        }
    }
    fclose(from_child);

    int status;
    waitpid(pid, &status, 0);
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));
        return INSTALL_ERROR;
    }

    return INSTALL_SUCCESS;
}
Example #16
0
int main(int argc, char **argv)
{
   pid_t pid;
   int flags;

   /* Fork off the parent process */

   pid = fork();

   if (pid < 0) { exit(EXIT_FAILURE); }

   /* If we got a good PID, then we can exit the parent process. */

   if (pid > 0) { exit(EXIT_SUCCESS); }

   /* Change the file mode mask */

   umask(0);       
   
   /* Open any logs here */

   /* NONE */
   
   /* Create a new SID for the child process */

   if (setsid() < 0) fatal("setsid failed (%m)");

   /* Change the current working directory */

   if ((chdir("/")) < 0) fatal("chdir failed (%m)");
   
   /* check command line parameters */

   initOpts(argc, argv);
   
   /* Close out the standard file descriptors */

   fclose(stdin);
   fclose(stdout);

   /* configure library */

   gpioCfgBufferSize(bufferSizeMilliseconds);

   gpioCfgClock(clockMicros, clockPeripheral, clockSource);

   gpioCfgInterfaces(ifFlags);

   gpioCfgDMAchannels(DMAprimaryChannel, DMAsecondaryChannel);

   gpioCfgSocketPort(socketPort);

   if (updateMask != -1) gpioCfgPermissions(updateMask);

   /* start library */

   if (gpioInitialise()< 0) fatal("Can't initialise pigpio library");

   /* create pipe for error reporting */

   unlink(PI_ERRFIFO);

   mkfifo(PI_ERRFIFO, 0664);

   if (chmod(PI_ERRFIFO, 0664) < 0)
      fatal("chmod %s failed (%m)", PI_ERRFIFO);

   errFifo = freopen(PI_ERRFIFO, "w+", stderr);

   if (errFifo)
   {
      /* set stderr non-blocking */

      flags = fcntl(fileno(errFifo), F_GETFL, 0);
      fcntl(fileno(errFifo), F_SETFL, flags | O_NONBLOCK);

      /* request SIGHUP/SIGTERM from libarary for termination */

      gpioSetSignalFunc(SIGHUP, terminate);
      gpioSetSignalFunc(SIGTERM, terminate);

      /* sleep forever */

      while (1)
      {
         /* cat /dev/pigerr to view daemon errors */

         sleep(5);

         fflush(errFifo);
      }
   }
   else
   {
      fprintf(stderr, "freopen failed (%m)");

      gpioTerminate();
   }

   return 0;
}
Example #17
0
/*
 * Returns 1 if a directory has been created,
 * 2 if it already existed, and 0 on failure.
 */
static int
build(char *path, mode_t omode)
{
	struct stat sb;
	mode_t numask, oumask;
	int first, last, retval;
	char *p;

	p = path;
	oumask = 0;
	retval = 1;
	if (p[0] == '/')		/* Skip leading '/'. */
		++p;
	for (first = 1, last = 0; !last ; ++p) {
		if (p[0] == '\0')
			last = 1;
		else if (p[0] != '/')
			continue;
		*p = '\0';
		if (!last && p[1] == '\0')
			last = 1;
		if (first) {
			/*
			 * POSIX 1003.2:
			 * For each dir operand that does not name an existing
			 * directory, effects equivalent to those caused by the
			 * following command shall occcur:
			 *
			 * mkdir -p -m $(umask -S),u+wx $(dirname dir) &&
			 *    mkdir [-m mode] dir
			 *
			 * We change the user's umask and then restore it,
			 * instead of doing chmod's.
			 */
			oumask = umask(0);
			numask = oumask & ~(S_IWUSR | S_IXUSR);
			(void)umask(numask);
			first = 0;
		}
		if (last)
			(void)umask(oumask);
		if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
			if (errno == EEXIST || errno == EISDIR) {
				if (stat(path, &sb) < 0) {
					warn("%s", path);
					retval = 0;
					break;
				} else if (!S_ISDIR(sb.st_mode)) {
					if (last)
						errno = EEXIST;
					else
						errno = ENOTDIR;
					warn("%s", path);
					retval = 0;
					break;
				}
				if (last)
					retval = 2;
			} else {
				warn("%s", path);
				retval = 0;
				break;
			}
		} else if (vflag)
			printf("%s\n", path);
		if (!last)
		    *p = '/';
	}
	if (!first && !last)
		(void)umask(oumask);
	return (retval);
}
Example #18
0
int bb_make_directory (char *path, long mode, int flags)
{
	mode_t mask;
	const char *fail_msg;
	char *s = path;
	char c;
	struct stat st;

	mask = umask(0);
	if (mode == -1) {
		umask(mask);
		mode = (S_IXUSR | S_IXGRP | S_IXOTH |
				S_IWUSR | S_IWGRP | S_IWOTH |
				S_IRUSR | S_IRGRP | S_IROTH) & ~mask;
	} else {
		umask(mask & ~0300);
	}

	do {
		c = 0;

		if (flags & FILEUTILS_RECUR) {	/* Get the parent. */
			/* Bypass leading non-'/'s and then subsequent '/'s. */
			while (*s) {
				if (*s == '/') {
					do {
						++s;
					} while (*s == '/');
					c = *s;		/* Save the current char */
					*s = 0;		/* and replace it with nul. */
					break;
				}
				++s;
			}
		}

		if (mkdir(path, 0777) < 0) {
			/* If we failed for any other reason than the directory
			 * already exists, output a diagnostic and return -1.*/
			if (errno != EEXIST
				|| !(flags & FILEUTILS_RECUR)
				|| (stat(path, &st) < 0 || !S_ISDIR(st.st_mode))) {
				fail_msg = "create";
				umask(mask);
				break;
			}
			/* Since the directory exists, don't attempt to change
			 * permissions if it was the full target.  Note that
			 * this is not an error conditon. */
			if (!c) {
				umask(mask);
				return 0;
			}
		}

		if (!c) {
			/* Done.  If necessary, updated perms on the newly
			 * created directory.  Failure to update here _is_
			 * an error.*/
			umask(mask);
			if ((mode != -1) && (chmod(path, mode) < 0)){
				fail_msg = "set permissions of";
				break;
			}
			return 0;
		}

		/* Remove any inserted nul from the path (recursive mode). */
		*s = c;

	} while (1);

	bb_perror_msg("cannot %s directory '%s'", fail_msg, path);
	return -1;
}
Example #19
0
int main (int argc, char** argv)
{
  UnitTest t (49);

  // Ensure environment has no influence.
  unsetenv ("TASKDATA");
  unsetenv ("TASKRC");

  Directory tmp ("tmp");
  tmp.create ();
  t.ok (tmp.exists (), "tmp dir created.");

  // Directory (const File&);
  // Directory (const Path&);
  Directory d0 (Path ("tmp"));
  Directory d1 (File ("tmp"));
  Directory d2 (File (Path ("tmp")));
  t.is (d0._data, d1._data, "Directory(std::string) == Directory (File&)");
  t.is (d0._data, d2._data, "Directory(std::string) == Directory (File (Path &))");
  t.is (d1._data, d2._data, "Directory(File&)) == Directory (File (Path &))");

  // Directory (const Directory&);
  Directory d3 (d2);
  t.is (d3._data, Directory::cwd () + "/tmp", "Directory (Directory&)");

  // Directory (const std::string&);
  Directory d4 ("tmp/test_directory");

  // Directory& operator= (const Directory&);
  Directory d5 = d4;
  t.is (d5._data, Directory::cwd () + "/tmp/test_directory", "Directory::operator=");

  // operator (std::string) const;
  t.is ((std::string) d3, Directory::cwd () + "/tmp", "Directory::operator (std::string) const");

  // virtual bool create ();
  t.ok (d5.create (), "Directory::create tmp/test_directory");
  t.ok (d5.exists (), "Directory::exists tmp/test_directory");

  Directory d6 (d5._data + "/dir");
  t.ok (d6.create (), "Directory::create tmp/test_directory/dir");

  File::create (d5._data + "/f0");
  File::create (d6._data + "/f1");

  // std::vector <std::string> list ();
  std::vector <std::string> files = d5.list ();
  std::sort (files.begin (), files.end ());
  t.is ((int)files.size (), 2, "Directory::list 1 file");
  t.is (files[0], Directory::cwd () + "/tmp/test_directory/dir", "file[0] is tmp/test_directory/dir");
  t.is (files[1], Directory::cwd () + "/tmp/test_directory/f0", "file[1] is tmp/test_directory/f0");

  // std::vector <std::string> listRecursive ();
  files = d5.listRecursive ();
  std::sort (files.begin (), files.end ());
  t.is ((int)files.size (), 2, "Directory::list 1 file");
  t.is (files[0], Directory::cwd () + "/tmp/test_directory/dir/f1", "file is tmp/test_directory/dir/f1");
  t.is (files[1], Directory::cwd () + "/tmp/test_directory/f0", "file is tmp/test_directory/f0");

  // virtual bool remove ();
  t.ok (File::remove (d5._data + "/f0"), "File::remove tmp/test_directory/f0");
  t.ok (File::remove (d6._data + "/f1"), "File::remove tmp/test_directory/dir/f1");

  t.ok (d6.remove (), "Directory::remove tmp/test_directory/dir");
  t.notok (d6.exists (), "Directory::exists tmp/test_directory/dir - no");

  t.ok (d5.remove (), "Directory::remove tmp/test_directory");
  t.notok (d5.exists (), "Directory::exists tmp/test_directory - no");

  // bool remove (const std::string&);
  Directory d7 ("tmp/to_be_removed");
  t.ok (d7.create (), "Directory::create tmp/to_be_removed");
  File::create (d7._data + "/f0");
  Directory d8 (d7._data + "/another");
  t.ok (d8.create (), "Directory::create tmp/to_be_removed/another");
  File::create (d8._data + "/f1");
  t.ok (d7.remove (), "Directory::remove tmp/to_be_removed");
  t.notok (d7.exists (), "Directory tmp/to_be_removed gone");

  // static std::string cwd ();
  std::string cwd = Directory::cwd ();
  t.ok (cwd.length () > 0, "Directory::cwd returned a value");

  // bool parent (std::string&) const;
  Directory d9 ("/one/two/three/four.txt");
  t.ok (d9.up (),                   "parent /one/two/three/four.txt --> true");
  t.is (d9._data, "/one/two/three", "parent /one/two/three/four.txt --> /one/two/three");
  t.ok (d9.up (),                   "parent /one/two/three --> true");
  t.is (d9._data, "/one/two",       "parent /one/two/three --> /one/two");
  t.ok (d9.up (),                   "parent /one/two --> true");
  t.is (d9._data, "/one",           "parent /one/two --> /one");
  t.ok (d9.up (),                   "parent /one --> true");
  t.is (d9._data, "/",              "parent /one --> /");
  t.notok (d9.up (),                "parent / --> false");

  // Test permissions.
  umask (0022);
  Directory d10 ("tmp/dir.perm");
  d10.create (0750);
  t.ok (d10.exists (),               "Directory::create perm file exists");
  mode_t m = d10.mode ();
  t.ok    (m & S_IFDIR,             "Directory::mode tmp/dir.perm S_IFDIR good");
  t.ok    (m & S_IRUSR,             "Directory::mode tmp/dir.perm r-------- good");
  t.ok    (m & S_IWUSR,             "Directory::mode tmp/dir.perm -w------- good");
  t.ok    (m & S_IXUSR,             "Directory::mode tmp/dir.perm --x------ good");
  t.ok    (m & S_IRGRP,             "Directory::mode tmp/dir.perm ---r----- good");
  t.notok (m & S_IWGRP,             "Directory::mode tmp/dir.perm ----w---- good");
  t.ok    (m & S_IXGRP,             "Directory::mode tmp/dir.perm -----x--- good");
  t.notok (m & S_IROTH,             "Directory::mode tmp/dir.perm ------r-- good");
  t.notok (m & S_IWOTH,             "Directory::mode tmp/dir.perm -------w- good");
  t.notok (m & S_IXOTH,             "Directory::mode tmp/dir.perm --------x good");
  d10.remove ();
  t.notok (d10.exists (),           "Directory::remove temp/dir.perm file no longer exists");

  tmp.remove ();
  t.notok (tmp.exists (),           "tmp dir removed.");

  return 0;
}
Example #20
0
int
main (int argc, char *argv[])
{
  static const char *options = "rv?";
  static const struct option long_options[] = {
    { "help", 0, 0, '?' },
    { "verbose", 0, 0, 'v' },
    { 0, 0, 0, 0 }
  };
  int c;
  char *cmdline;

  ignore_value (chdir ("/"));

  if (winsock_init () == -1)
    error (EXIT_FAILURE, 0, "winsock initialization failed");

#ifdef HAVE_REGISTER_PRINTF_SPECIFIER
  /* http://udrepper.livejournal.com/20948.html */
  register_printf_specifier ('Q', print_shell_quote, print_arginfo);
  register_printf_specifier ('R', print_sysroot_shell_quote, print_arginfo);
#else
#ifdef HAVE_REGISTER_PRINTF_FUNCTION
  register_printf_function ('Q', print_shell_quote, print_arginfo);
  register_printf_function ('R', print_sysroot_shell_quote, print_arginfo);
#else
#error "HAVE_REGISTER_PRINTF_{SPECIFIER|FUNCTION} not defined"
#endif
#endif

  /* XXX The appliance /init script sets LD_PRELOAD=../libSegFault.so.
   * However if we CHROOT_IN to the sysroot that file might not exist,
   * resulting in all commands failing.  What we'd really like to do
   * is to have LD_PRELOAD only set while outside the chroot.  I
   * suspect the proper way to solve this is to remove the
   * CHROOT_IN/_OUT hack and replace it properly (fork), but that is
   * for another day.
   */
  unsetenv ("LD_PRELOAD");

  struct stat statbuf;
  if (stat ("/", &statbuf) == 0)
    root_device = statbuf.st_dev;

  for (;;) {
    c = getopt_long (argc, argv, options, long_options, NULL);
    if (c == -1) break;

    switch (c) {
      /* The -r flag is used when running standalone.  It changes
       * several aspects of the daemon.
       */
    case 'r':
      sysroot = "";
      sysroot_len = 0;
      autosync_umount = 0;
      break;

    case 'v':
      verbose = 1;
      break;

    case '?':
      usage ();
      exit (EXIT_SUCCESS);

    default:
      fprintf (stderr, "guestfsd: unexpected command line option 0x%x\n", c);
      exit (EXIT_FAILURE);
    }
  }

  if (optind < argc) {
    usage ();
    exit (EXIT_FAILURE);
  }

  cmdline = read_cmdline ();

  /* Set the verbose flag. */
  verbose = verbose ||
    (cmdline && strstr (cmdline, "guestfs_verbose=1") != NULL);
  if (verbose)
    printf ("verbose daemon enabled\n");

  if (verbose) {
    if (cmdline)
      printf ("linux commmand line: %s\n", cmdline);
    else
      printf ("could not read linux command line\n");
  }

  enable_network = cmdline && strstr (cmdline, "guestfs_network=1") != NULL;

#ifndef WIN32
  /* Make sure SIGPIPE doesn't kill us. */
  struct sigaction sa;
  memset (&sa, 0, sizeof sa);
  sa.sa_handler = SIG_IGN;
  sa.sa_flags = 0;
  if (sigaction (SIGPIPE, &sa, NULL) == -1)
    perror ("sigaction SIGPIPE"); /* but try to continue anyway ... */
#endif

#ifdef WIN32
# define setenv(n,v,f) _putenv(n "=" v)
#endif
  /* Set up a basic environment.  After we are called by /init the
   * environment is essentially empty.
   * https://bugzilla.redhat.com/show_bug.cgi?id=502074#c5
   *
   * NOTE: if you change $PATH, you must also change 'prog_exists'
   * function below.
   */
  setenv ("PATH", "/sbin:/usr/sbin:/bin:/usr/bin", 1);
  setenv ("SHELL", "/bin/sh", 1);
  setenv ("LC_ALL", "C", 1);
  setenv ("TERM", "dumb", 1);

#ifndef WIN32
  /* We document that umask defaults to 022 (it should be this anyway). */
  umask (022);
#else
  /* This is the default for Windows anyway.  It's not even clear if
   * Windows ever uses this -- the MSDN documentation for the function
   * contains obvious errors.
   */
  _umask (0);
#endif

  /* Make a private copy of /etc/lvm so we can change the config (see
   * daemon/lvm-filter.c).
   */
  copy_lvm ();

  /* Connect to virtio-serial channel. */
  char *channel, *p;
  if (cmdline && (p = strstr (cmdline, "guestfs_channel=")) != NULL) {
    p += 16;
    channel = strndup (p, strcspn (p, " \n"));
  }
  else
    channel = strdup (VIRTIO_SERIAL_CHANNEL);
  if (!channel) {
    perror ("strdup");
    exit (EXIT_FAILURE);
  }

  if (verbose)
    printf ("trying to open virtio-serial channel '%s'\n", channel);

  int sock = open (channel, O_RDWR|O_CLOEXEC);
  if (sock == -1) {
    fprintf (stderr,
             "\n"
             "Failed to connect to virtio-serial channel.\n"
             "\n"
             "This is a fatal error and the appliance will now exit.\n"
             "\n"
             "Usually this error is caused by either QEMU or the appliance\n"
             "kernel not supporting the vmchannel method that the\n"
             "libguestfs library chose to use.  Please run\n"
             "'libguestfs-test-tool' and provide the complete, unedited\n"
             "output to the libguestfs developers, either in a bug report\n"
             "or on the libguestfs redhat com mailing list.\n"
             "\n");
    perror (channel);
    exit (EXIT_FAILURE);
  }

  /* If it's a serial-port like device then it probably has echoing
   * enabled.  Put it into complete raw mode.
   */
  if (STRPREFIX (channel, "/dev/ttyS"))
    makeraw (channel, sock);

  /* cmdline, channel not used after this point */
  free (cmdline);
  free (channel);

  /* Wait for udev devices to be created.  If you start libguestfs,
   * especially with disks that contain complex (eg. mdadm) data
   * already, then it is possible for the 'mdadm' and LVM commands
   * that the init script runs to have not completed by the time the
   * daemon starts executing library commands.  (This is very rare and
   * hard to test however, but we have seen it in 'brew').  Run
   * udev_settle, but do it as late as possible to minimize the chance
   * that we'll have to do any waiting here.
   */
  udev_settle ();

  /* Send the magic length message which indicates that
   * userspace is up inside the guest.
   */
  char lenbuf[4];
  XDR xdr;
  uint32_t len = GUESTFS_LAUNCH_FLAG;
  xdrmem_create (&xdr, lenbuf, sizeof lenbuf, XDR_ENCODE);
  xdr_u_int (&xdr, &len);

  if (xwrite (sock, lenbuf, sizeof lenbuf) == -1) {
    perror ("xwrite");
    exit (EXIT_FAILURE);
  }

  xdr_destroy (&xdr);

  /* Enter the main loop, reading and performing actions. */
  main_loop (sock);

  exit (EXIT_SUCCESS);
}
Example #21
0
int main(int argc, char** argv){
	fd_set writeFDs;
	fd_set readFDs;
	struct sockaddr_rc addr={0};
	char dest[] = "00:12:02:09:04:90";
	openlog("sshcounter",LOG_PID,LOG_USER);
	pid_t pid,sid;
	pid = fork();
	if(pid < 0){
		syslog(LOG_INFO,"Fork Failture");
		exit(EXIT_FAILURE);	
	}
	if(pid > 0){
		exit(EXIT_SUCCESS);	
	}
	umask(0);
	sid = setsid();
	if(sid < 0){
		syslog(LOG_INFO,"Seting Session ID Failure");
		exit(EXIT_FAILURE);	
	}
	if((chdir("/")) < 0){
		syslog(LOG_INFO,"Change Directory Failure");
		exit(EXIT_FAILURE);	
	}
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);
	int btSocket = socket(AF_BLUETOOTH, SOCK_STREAM|SOCK_NONBLOCK ,BTPROTO_RFCOMM);
	if(btSocket < 0){
		syslog(LOG_INFO,"Socket Creating Failure");
		exit(EXIT_FAILURE);	
	}
	addr.rc_family = AF_BLUETOOTH;
	addr.rc_channel = (uint8_t)1;
	str2ba(dest,&addr.rc_bdaddr);

	// Bluetooth Device Search
	int max_rsp,num_rsp,len,flags,dev_id,i;
	char buf[1024] = {0};
	int found = 0;
	inquiry_info *ii = NULL;
	len = 8;
	max_rsp = 255;
	flags = IREQ_CACHE_FLUSH;
	dev_id = hci_get_route(NULL);
	ii = (inquiry_info*)malloc(max_rsp * sizeof(inquiry_info));
	while(1){
		// Quiry bluetooth device around
		num_rsp = hci_inquiry(dev_id,len,max_rsp,NULL,&ii,flags);
		for(i = 0; i < num_rsp; i++){
			ba2str(&(ii+i)->bdaddr,buf);
			// If found, set found to true and break
			if(strcmp(dest,buf) == 0){
				found = 1;
				break;
			}
		}
		// If found, break out query loop and connect
		if(found){
			syslog(LOG_INFO,"Bluetooth Device Found");
			break;
		}
	}



	int rc;
	// Since the socket is nonblocking, using select()
	int	status = connect(btSocket,(struct sockaddr*)&addr,sizeof(addr));
	if(errno == EINPROGRESS){
		for(;;){
			FD_ZERO(&writeFDs);
			FD_ZERO(&readFDs);
			FD_SET(btSocket,&writeFDs);
			FD_SET(btSocket,&readFDs);
			rc = select(btSocket+1,&readFDs,&writeFDs,NULL,NULL);
			if(FD_ISSET(btSocket,&writeFDs)){
				if(FD_ISSET(btSocket,&readFDs)){
					sleep(5);
					status = connect(btSocket,(struct sockaddr*)&addr,sizeof(addr));
			    	continue;		
				} else{
					break;	
				}
			}
		}
	}
	syslog(LOG_INFO,"Bluetooth Device Connected");
	char numConnections;
	while(1){
		FILE* file = popen("netstat -an | grep -E '\\:22[ \\t]+' | grep ESTABLISHED | wc -l","r");
		if(file == NULL){
			syslog(LOG_INFO,"POPEN Failure");
			exit(EXIT_FAILURE);	
		}
		fscanf(file, "%c",&numConnections);
		fclose(file);
		write(btSocket, &numConnections, 1);
		sleep(1);
	}
	close(btSocket);
	exit(EXIT_SUCCESS);
}
Example #22
0
/*
 * lo_export -
 *	  exports an (inversion) large object.
 */
Datum
lo_export(PG_FUNCTION_ARGS)
{
	Oid			lobjId = PG_GETARG_OID(0);
	text	   *filename = PG_GETARG_TEXT_PP(1);
	int			fd;
	int			nbytes,
				tmp;
	char		buf[BUFSIZE];
	char		fnamebuf[MAXPGPATH];
	LargeObjectDesc *lobj;
	mode_t		oumask;

#ifndef ALLOW_DANGEROUS_LO_FUNCTIONS
	if (!superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 errmsg("must be superuser to use server-side lo_export()"),
				 errhint("Anyone can use the client-side lo_export() provided by libpq.")));
#endif

	CreateFSContext();

	/*
	 * open the inversion object (no need to test for failure)
	 */
	lobj = inv_open(lobjId, INV_READ, fscxt);

	/*
	 * open the file to be written to
	 *
	 * Note: we reduce backend's normal 077 umask to the slightly friendlier
	 * 022. This code used to drop it all the way to 0, but creating
	 * world-writable export files doesn't seem wise.
	 */
	text_to_cstring_buffer(filename, fnamebuf, sizeof(fnamebuf));
	oumask = umask(S_IWGRP | S_IWOTH);
	fd = OpenTransientFile(fnamebuf, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY,
						   S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
	umask(oumask);
	if (fd < 0)
		ereport(ERROR,
				(errcode_for_file_access(),
				 errmsg("could not create server file \"%s\": %m",
						fnamebuf)));

	/*
	 * read in from the inversion file and write to the filesystem
	 */
	while ((nbytes = inv_read(lobj, buf, BUFSIZE)) > 0)
	{
		tmp = write(fd, buf, nbytes);
		if (tmp != nbytes)
			ereport(ERROR,
					(errcode_for_file_access(),
					 errmsg("could not write server file \"%s\": %m",
							fnamebuf)));
	}

	CloseTransientFile(fd);
	inv_close(lobj);

	PG_RETURN_INT32(1);
}
Example #23
0
/**
 * The main() function of ngIRCd.
 *
 * Here all starts: this function is called by the operating system loader,
 * it is the first portion of code executed of ngIRCd.
 *
 * @param argc The number of arguments passed to ngIRCd on the command line.
 * @param argv An array containing all the arguments passed to ngIRCd.
 * @return Global exit code of ngIRCd, zero on success.
 */
GLOBAL int
main(int argc, const char *argv[])
{
	bool ok, configtest = false;
	bool NGIRCd_NoDaemon = false;
	int i;
	size_t n;

#if defined(DEBUG) && defined(HAVE_MTRACE)
	/* enable GNU libc memory tracing when running in debug mode
	 * and functionality available */
	mtrace();
#endif

	umask(0077);

	NGIRCd_SignalQuit = NGIRCd_SignalRestart = false;
	NGIRCd_Passive = false;
#ifdef DEBUG
	NGIRCd_Debug = false;
#endif
#ifdef SNIFFER
	NGIRCd_Sniffer = false;
#endif
	strlcpy(NGIRCd_ConfFile, SYSCONFDIR, sizeof(NGIRCd_ConfFile));
	strlcat(NGIRCd_ConfFile, CONFIG_FILE, sizeof(NGIRCd_ConfFile));

	Fill_Version();

	/* parse conmmand line */
	for (i = 1; i < argc; i++) {
		ok = false;
		if (argv[i][0] == '-' && argv[i][1] == '-') {
			/* long option */
			if (strcmp(argv[i], "--config") == 0) {
				if (i + 1 < argc) {
					/* Ok, there's an parameter left */
					strlcpy(NGIRCd_ConfFile, argv[i+1],
						sizeof(NGIRCd_ConfFile));
					/* next parameter */
					i++; ok = true;
				}
			}
			if (strcmp(argv[i], "--configtest") == 0) {
				configtest = true;
				ok = true;
			}
#ifdef DEBUG
			if (strcmp(argv[i], "--debug") == 0) {
				NGIRCd_Debug = true;
				ok = true;
			}
#endif
			if (strcmp(argv[i], "--help") == 0) {
				Show_Version();
				puts(""); Show_Help( ); puts( "" );
				exit(1);
			}
			if (strcmp(argv[i], "--nodaemon") == 0) {
				NGIRCd_NoDaemon = true;
				ok = true;
			}
			if (strcmp(argv[i], "--passive") == 0) {
				NGIRCd_Passive = true;
				ok = true;
			}
#ifdef SNIFFER
			if (strcmp(argv[i], "--sniffer") == 0) {
				NGIRCd_Sniffer = true;
				ok = true;
			}
#endif
			if (strcmp(argv[i], "--version") == 0) {
				Show_Version();
				exit(1);
			}
		}
		else if(argv[i][0] == '-' && argv[i][1] != '-') {
			/* short option */
			for (n = 1; n < strlen(argv[i]); n++) {
				ok = false;
#ifdef DEBUG
				if (argv[i][n] == 'd') {
					NGIRCd_Debug = true;
					ok = true;
				}
#endif
				if (argv[i][n] == 'f') {
					if (!argv[i][n+1] && i+1 < argc) {
						/* Ok, next character is a blank */
						strlcpy(NGIRCd_ConfFile, argv[i+1],
							sizeof(NGIRCd_ConfFile));

						/* go to the following parameter */
						i++;
						n = strlen(argv[i]);
						ok = true;
					}
				}

				if (argv[i][n] == 'h') {
					Show_Version();
					puts(""); Show_Help(); puts("");
					exit(1);
				}

				if (argv[i][n] == 'n') {
					NGIRCd_NoDaemon = true;
					ok = true;
				}
				if (argv[i][n] == 'p') {
					NGIRCd_Passive = true;
					ok = true;
				}
#ifdef SNIFFER
				if (argv[i][n] == 's') {
					NGIRCd_Sniffer = true;
					ok = true;
				}
#endif
				if (argv[i][n] == 't') {
					configtest = true;
					ok = true;
				}

				if (argv[i][n] == 'V') {
					Show_Version();
					exit(1);
				}

				if (!ok) {
					printf("%s: invalid option \"-%c\"!\n",
					       PACKAGE_NAME, argv[i][n]);
					printf("Try \"%s --help\" for more information.\n",
					       PACKAGE_NAME);
					exit(1);
				}
			}

		}
		if (!ok) {
			printf("%s: invalid option \"%s\"!\n",
			       PACKAGE_NAME, argv[i]);
			printf("Try \"%s --help\" for more information.\n",
			       PACKAGE_NAME);
			exit(1);
		}
	}

	/* Debug level for "VERSION" command */
	NGIRCd_DebugLevel[0] = '\0';
#ifdef DEBUG
	if (NGIRCd_Debug)
		strcpy(NGIRCd_DebugLevel, "1");
#endif
#ifdef SNIFFER
	if (NGIRCd_Sniffer) {
		NGIRCd_Debug = true;
		strcpy(NGIRCd_DebugLevel, "2");
	}
#endif

	if (configtest) {
		Show_Version(); puts("");
		exit(Conf_Test());
	}

	while (!NGIRCd_SignalQuit) {
		/* Initialize global variables */
		NGIRCd_Start = time(NULL);
		(void)strftime(NGIRCd_StartStr, 64,
			       "%a %b %d %Y at %H:%M:%S (%Z)",
			       localtime(&NGIRCd_Start));

		NGIRCd_SignalRestart = false;
		NGIRCd_SignalQuit = false;

		/* Initialize modules, part I */
		Log_Init(!NGIRCd_NoDaemon);
		Random_Init();
		Conf_Init();
		Log_ReInit();

		/* Initialize the "main program": chroot environment, user and
		 * group ID, ... */
		if (!NGIRCd_Init(NGIRCd_NoDaemon)) {
			Log(LOG_ALERT, "Fatal: Initialization failed, exiting!");
			exit(1);
		}

		/* Initialize modules, part II: these functions are eventually
		 * called with already dropped privileges ... */
		Channel_Init();
		Client_Init();
		Conn_Init();
		Class_Init();

		if (!io_library_init(CONNECTION_POOL)) {
			Log(LOG_ALERT,
			    "Fatal: Could not initialize IO routines: %s",
			    strerror(errno));
			exit(1);
		}

		if (!Signals_Init()) {
			Log(LOG_ALERT,
			    "Fatal: Could not set up signal handlers: %s",
			    strerror(errno));
			exit(1);
		}

		/* Create protocol and server identification. The syntax
		 * used by ngIRCd in PASS commands and the known "extended
		 * flags" are described in doc/Protocol.txt. */
#ifdef IRCPLUS
		snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s:%s",
			 PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION,
			 IRCPLUSFLAGS);
#ifdef ZLIB
		strlcat(NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID);
#endif
		if (Conf_OperCanMode)
			strlcat(NGIRCd_ProtoID, "o", sizeof NGIRCd_ProtoID);
#else /* IRCPLUS */
		snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s",
			 PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION);
#endif /* IRCPLUS */
		strlcat(NGIRCd_ProtoID, " P", sizeof NGIRCd_ProtoID);
#ifdef ZLIB
		strlcat(NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID);
#endif
		LogDebug("Protocol and server ID is \"%s\".", NGIRCd_ProtoID);

		Channel_InitPredefined();

		if (Conn_InitListeners() < 1) {
			Log(LOG_ALERT,
			    "Server isn't listening on a single port!" );
			Log(LOG_ALERT,
			    "%s exiting due to fatal errors!", PACKAGE_NAME);
			Pidfile_Delete();
			exit(1);
		}

		/* Main Run Loop */
		Conn_Handler();

		Conn_Exit();
		Client_Exit();
		Channel_Exit();
		Class_Exit();
		Log_Exit();
		Signals_Exit();
	}
	Pidfile_Delete();

	return 0;
} /* main */
Example #24
0
void daemonize(const char *cmd)
{
    struct rlimit rlim;
    int fd0, fd1, fd2;
    int i;
    pid_t pid;
    struct sigaction sa;

    if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
        printf("%s: getrlimit error: %s", cmd, strerror(errno));
        exit(1);
    }

    umask(0);

    if ((pid = fork()) < 0) {
        printf("%s: fork error: %s", cmd, strerror(errno));
        exit(1);
    }
    else if (pid != 0) {    /* parent */
        exit(0);
    }
    setsid();   /* child */

    sa.sa_handler = SIG_IGN;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGHUP, &sa, NULL) < 0) {
        printf("%s: sigaction SIGHUP error: %s", cmd, strerror(errno));
        exit(1);
    }

    if ((pid = fork()) < 0) {
        printf("%s: fork error: %s", cmd, strerror(errno));
        exit(1);
    }
    else if (pid != 0) {    /* parent again */
        exit(0);
    }

    if (chdir("/") < 0) {
        printf("%s: chdir to / error: %s", cmd, strerror(errno));
        exit(1);
    }

    /* child */
    if (rlim.rlim_max == RLIM_INFINITY)
        rlim.rlim_max = 1024;
    for (i = 0; i < rlim.rlim_max; ++i)
        close(i);

    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup(0);
    fd2 = dup(0);

    openlog(cmd, LOG_CONS, LOG_DAEMON);
    if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
        syslog(LOG_ERR, "unexpected file descriptors: %d, %d, %d",
                fd0, fd1, fd2);
        exit(1);
    }
}
Example #25
0
int main(int ac, char **av)
{
  int     ch, i=0;
  pid_t   pid;
  FILE    *fp;
  uid_t   uid;
#ifdef USE_THREAD
  pthread_t tid;
  pthread_attr_t attr;
  struct rlimit rl;
  rlim_t max_fd = (rlim_t)MAX_FD;
  rlim_t save_fd = 0;
#endif

#ifdef USE_THREAD
  threading = 1;
  max_thread = MAX_THREAD;
#endif

  max_child = MAX_CHILD;
  cur_child = 0;

  /* create service socket table (malloc) */
  if (serv_init(NULL) < 0) {
    msg_out(crit, "cannot malloc: %m");
    exit(-1);
  }

  proxy_tbl = NULL;
  proxy_tbl_ind = 0;

  method_num = 0;

  uid = getuid();

  openlog(ident, LOG_PID | LOG_NDELAY, SYSLOGFAC);

  while((ch = getopt(ac, av, "a:c:i:x:J:m:o:p:u:frstbwgIqvh?")) != -1)
    switch (ch) {
    case 'a':
      if (optarg != NULL) {
	for (i=0; i<sizeof method_tab; optarg++) {
	  if (*optarg == '\0')
	    break;
	  switch (*optarg) {
	  case 'p':
	    if ( uid != 0 ) {
	      /* process does not started by root */
	      msg_out(warn, "uid == %d (!=0),"
		      "user/pass auth will not work, ignored.",
		      uid);
	      break;
	    }
	    method_tab[i++] = S5AUSRPAS;
	    method_num++;
	    break;
	  case 'n':
	    method_tab[i++] = S5ANOAUTH;
	    method_num++;
	    break;
	  default:
	    break;
	  }
	}
      }
      break;

    case 'b':
      bind_restrict = 0;
      break;

    case 'c':
      if (optarg != NULL) {
        config = strdup(optarg);
      }
      break;

    case 'u':
      if (optarg != NULL) {
        pwdfile = strdup(optarg);
      }
      break;

    case 'i':
      if (optarg != NULL) {
	if (serv_init(optarg) < 0) {
	  msg_out(warn, "cannot init server socket(-i %s): %m", optarg);
	  break;
	}
      }
      break;

#ifdef SO_BINDTODEVICE
    case 'J':
      if (optarg != NULL) {
	bindtodevice = strdup(optarg);
      }
      break;
#endif

    case 'x':
      if (optarg != NULL) {
	bindout = strdup(optarg);
      }
      break;

    case 'o':
      if (optarg != NULL) {
	idle_timeout = atol(optarg);
      }
      break;

    case 'p':
      if (optarg != NULL) {
	pidfile = strdup(optarg);
      }
      break;

    case 'm':
      if (optarg != NULL) {
#ifdef USE_THREAD
	max_thread = atoi(optarg);
#endif
	max_child = atoi(optarg);
      }
      break;

    case 't':
#ifdef USE_THREAD
      threading = 0;    /* threading disabled. */
#endif
      break;

    case 'g':
      same_interface = 1;
      break;

    case 'f':
      fg = 1;
      break;

    case 'r':
      resolv_client = 1;
      break;

    case 's':
      forcesyslog = 1;
      break;

    case 'w':
#ifdef HAVE_LIBWRAP
      use_tcpwrap = 1;
#endif /* HAVE_LIBWRAP */
      break;

    case 'I':
      inetd_mode = 1;
      break;

    case 'q':
      be_quiet = 1;
      break;

    case 'v':
      show_version();
      exit(1);

    case 'h':
    case '?':
    default:
      usage();
    }

  ac -= optind;
  av += optind;

  if (fg && !forcesyslog && isatty(fileno(stderr)))
    setvbuf(stderr, NULL, _IOLBF, 0);

  if ((fp = fopen(config, "r")) != NULL) {
    if (readconf(fp) != 0) {
      /* readconf error */
      exit(1);
    }
    fclose(fp);
  }

  if (inetd_mode) {
    /* close all server socket if opened */
    close_all_serv();
    /* assuming that STDIN_FILENO handles bi-directional
     */
    exit(inetd_service(STDIN_FILENO));
    /* not reached */
  }

  if (serv_sock_ind == 0) {   /* no valid ifs yet */
    if (serv_init(":") < 0) { /* use default */
      /* fatal */
      msg_out(crit, "cannot open server socket");
      exit(1);
    }
  }

#ifdef USE_THREAD
  if ( ! threading ) {
#endif
    if (queue_init() != 0) {
      msg_out(crit, "cannot init signal queue");
      exit(1);
    }
#ifdef USE_THREAD
  }
#endif

  /* try changing working directory */
  if ( chdir(WORKDIR0) != 0 )
    if ( chdir(WORKDIR1) != 0 )
      msg_out(norm, "giving up chdir to workdir");

  if (!fg) {
    /* force stdin/out/err allocate to /dev/null */
    fclose(stdin);
    fp = fopen("/dev/null", "w+");
    if (fileno(fp) != STDIN_FILENO) {
      msg_out(crit, "fopen: %m");
      exit(1);
    }
    if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1) {
      msg_out(crit, "dup2-1: %m");
      exit(1);
    }
    if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
      msg_out(crit, "dup2-2: %m");
      exit(1);
    }

    switch(fork()) {
    case -1:
      msg_out(crit, "fork: %m");
      exit(1);
    case 0:
      /* child */
      pid = setsid();
      if (pid == -1) {
	msg_out(crit, "setsid: %m");
	exit(1);
      }
      break;
    default:
      /* parent */
      exit(0);
    }
  }

  master_pid = getpid();
  umask(S_IWGRP|S_IWOTH);
  if ((fp = fopen(pidfile, "w")) != NULL) {
    fprintf(fp, "%u\n", (unsigned)master_pid);
    fchown(fileno(fp), PROCUID, PROCGID);
    fclose(fp);
  } else {
    msg_out(warn, "cannot open pidfile %s", pidfile);
  }

  setsignal(SIGHUP, reload);
  if (fg)
    setsignal(SIGINT, cleanup);
  else
    setsignal(SIGINT, SIG_IGN);
  setsignal(SIGQUIT, SIG_IGN);
  setsignal(SIGILL, SIG_IGN);
  setsignal(SIGTRAP, SIG_IGN);
  setsignal(SIGABRT, SIG_IGN);
#ifdef SIGEMT
  setsignal(SIGEMT, SIG_IGN);
#endif
  setsignal(SIGSYS, SIG_IGN);
  setsignal(SIGPIPE, SIG_IGN);
  setsignal(SIGALRM, SIG_IGN);
  setsignal(SIGTERM, cleanup);
  setsignal(SIGUSR1, SIG_IGN);
  setsignal(SIGUSR2, SIG_IGN);
#ifdef SIGPOLL
  setsignal(SIGPOLL, SIG_IGN);
#endif
  setsignal(SIGVTALRM, SIG_IGN);
  setsignal(SIGPROF, SIG_IGN);
  setsignal(SIGXCPU, SIG_IGN);
  setsignal(SIGXFSZ, SIG_IGN);

#ifdef USE_THREAD
  if ( threading ) {
    if (max_thread <= 0 || max_thread > THREAD_LIMIT) {
      max_thread = THREAD_LIMIT;
    }
    /* resource limit is problem in threadig (e.g. Solaris:=64)*/
    memset((caddr_t)&rl, 0, sizeof rl);
    if (getrlimit(RLIMIT_NOFILE, &rl) != 0)
      msg_out(warn, "getrlimit: %m");
    else
      save_fd = rl.rlim_cur;
    if (rl.rlim_cur < (rlim_t)max_fd)
      rl.rlim_cur = max_fd;        /* willing to fix to max_fd */
    if ( rl.rlim_cur != save_fd )  /* if rlim_cur is changed   */
      if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
        msg_out(warn, "cannot set rlimit(max_fd)");

    setregid(0, PROCGID);
    setreuid(0, PROCUID);

    pthread_mutex_init(&mutex_select, NULL);
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    msg_out(norm, "Starting: MAX_TH(%d)", max_thread);
    for (i=0; i<max_thread; i++) {
      if (pthread_create(&tid, &attr,
			 (void *)&serv_loop, (void *)NULL) != 0)
        exit(1);
    }
    main_thread = pthread_self();   /* store main thread ID */
    for (;;) {
      pause();
    }
  } else {
#endif
    setsignal(SIGCHLD, reapchild);
    setregid(0, PROCGID);
    setreuid(0, PROCUID);
    msg_out(norm, "Starting: MAX_CH(%d)", max_child);
    serv_loop();
#ifdef USE_THREAD
  }
#endif
  return(0);
}
Example #26
0
int mailmbox_expunge_no_lock(struct mailmbox_folder * folder)
{
  char tmp_file[PATH_MAX];
  int r;
  int res;
  int dest_fd;
  size_t size;
  mode_t old_mask;
  
  if (folder->mb_read_only)
    return MAILMBOX_ERROR_READONLY;

  if (((folder->mb_written_uid >= folder->mb_max_uid) || folder->mb_no_uid) &&
      (!folder->mb_changed)) {
    /* no need to expunge */
    return MAILMBOX_NO_ERROR;
  }

  snprintf(tmp_file, PATH_MAX, "%sXXXXXX", folder->mb_filename);
  old_mask = umask(0077);
  dest_fd = mkstemp(tmp_file);
  umask(old_mask);
  
  if (dest_fd < 0) {
    /* fallback to tmp dir */
    
    snprintf(tmp_file, PATH_MAX, TMPDIR "/etpan-unsafe-XXXXXX");
    
    old_mask = umask(0077);
    dest_fd = mkstemp(tmp_file);
    umask(old_mask);
    
    if (dest_fd < 0) {
      res = MAILMBOX_ERROR_FILE;
      goto err;
    }
  }
  
  r = mailmbox_expunge_to_file_no_lock(tmp_file, dest_fd,
				       folder, &size);
  if (r != MAILMBOX_NO_ERROR) {
    res = r;
    goto unlink;
  }
  
  close(dest_fd);

  r = rename(tmp_file, folder->mb_filename);
  if (r < 0) {
    mailmbox_unmap(folder);
    mailmbox_close(folder);
    
    /* fallback on copy to old file */
    
    r = copy_to_old_file(tmp_file, folder->mb_filename, size);
    if (r != MAILMBOX_NO_ERROR) {
      res = r;
      goto err;
    }
    
    unlink(tmp_file);
  }
  else {
    mailmbox_unmap(folder);
    mailmbox_close(folder);
  }
  
  r = mailmbox_open(folder);
  if (r != MAILMBOX_NO_ERROR) {
    res = r;
    goto err;
  }

  r = mailmbox_map(folder);
  if (r != MAILMBOX_NO_ERROR) {
    res = r;
    goto err;
  }
      
  r = mailmbox_parse(folder);
  if (r != MAILMBOX_NO_ERROR) {
    res = r;
    goto err;
  }
  
  mailmbox_timestamp(folder);

  folder->mb_changed = FALSE;
  folder->mb_deleted_count = 0;
  
  return MAILMBOX_NO_ERROR;

 unlink:
  close(dest_fd);
  unlink(tmp_file);
 err:
  return res;
}
Example #27
0
int ds_daemon(http_conf * conf, int t)
{  
    int uid = getuid();
    int gid = getgid();
    int status = 0;


    if(conf->user && strlen(conf->user)) {
        struct passwd * pw  = getpwnam(conf->user);
        if(!pw) {
            printf(" user[%s] no found\n", conf->user);
            exit(0);
        }
        uid = pw->pw_uid;
        gid = pw->pw_gid;
        printf("\n user:%s\n", conf->user);
    }


    if(t == 0 ) {
        ds_init_daemon(conf);
    }
   

   if( t == 0 || t == 1) {
       ds_init_children(conf);

       //ds_pid = getpid();

        if(setsid() == -1) {  //setsid创建一个新会话
            printf("setsid() failed!" DS_LINEEND);
            exit(0);
        }
        
        umask(0);
        setuid(uid);
        setgid(gid);
        ds_init(conf);
   }

   /*if( t == 2) {
       conf->work_mode = FORK_PROCESS_WORK_HTTP_MODE;
   }*/
   if(t == 2) {
       //使用两个pipe 完成accept 和cgi进程的通信,pipe 0read, 1write
       int pipHttp[2], pipCgi[2];
       pipe(pipHttp);
       pipe(pipCgi);
       int forkCgiPid = fork();
       if(forkCgiPid == 0) {
            conf->child_pip.in = pipCgi[0];
            conf->child_pip.out = pipHttp[1];
            close(pipHttp[0]);
            close(pipCgi[1]);
            conf->work_mode = FORK_PROCESS_WORK_CGI_MODE;
        } else {
            conf->child_pip.in = pipHttp[0];
            conf->child_pip.out = pipCgi[1];
            close(pipHttp[1]);
            close(pipCgi[0]);
            conf->work_mode = FORK_PROCESS_WORK_HTTP_MODE;
        }
   }
 

    


    return OK;
}
Example #28
0
extern int syslogd_main(int argc, char **argv)
{
	int opt;

	int doFork = TRUE;

	char *p;

	/* do normal option parsing */
	while ((opt = getopt(argc, argv, "m:nO:s:Sb:R:LC::")) > 0) {
		switch (opt) {
		case 'm':
			MarkInterval = atoi(optarg) * 60;
			break;
		case 'n':
			doFork = FALSE;
			break;
		case 'O':
			logFilePath = optarg;
			break;
#ifdef CONFIG_FEATURE_ROTATE_LOGFILE
		case 's':
			logFileSize = atoi(optarg) * 1024;
			break;
		case 'b':
			logFileRotate = atoi(optarg);
			if( logFileRotate > 99 ) logFileRotate = 99;
			break;
#endif
#ifdef CONFIG_FEATURE_REMOTE_LOG
		case 'R':
			RemoteHost = bb_xstrdup(optarg);
			if ((p = strchr(RemoteHost, ':'))) {
				RemotePort = atoi(p + 1);
				*p = '\0';
			}
			doRemoteLog = TRUE;
			break;
		case 'L':
			local_logging = TRUE;
			break;
#endif
#ifdef CONFIG_FEATURE_IPC_SYSLOG
		case 'C':
			if (optarg) {
				int buf_size = atoi(optarg);
				if (buf_size >= 4) {
					shm_size = buf_size * 1024;
				}
			}
			circular_logging = TRUE;
			break;
#endif
		case 'S':
			small = true;
			break;
		default:
			bb_show_usage();
		}
	}

#ifdef CONFIG_FEATURE_REMOTE_LOG
	/* If they have not specified remote logging, then log locally */
	if (doRemoteLog == FALSE)
		local_logging = TRUE;
#endif


	/* Store away localhost's name before the fork */
	gethostname(LocalHostName, sizeof(LocalHostName));
	if ((p = strchr(LocalHostName, '.'))) {
		*p = '\0';
	}

	umask(0);

	if (doFork == TRUE) {
#if defined(__uClinux__)
		vfork_daemon_rexec(0, 1, argc, argv, "-n");
#else /* __uClinux__ */
		if(daemon(0, 1) < 0)
			bb_perror_msg_and_die("daemon");
#endif /* __uClinux__ */
	}
	doSyslogd();

	return EXIT_SUCCESS;
}
Example #29
0
int
main(int argc, char *argv[])
{
	/* Check to see if the user is running us as root, which is a nono */
	if(geteuid() == 0)
	{
		fprintf(stderr, "Don't run ircd as root!!!\n");
		return -1;
	}

	/*
	 * save server boot time right away, so getrusage works correctly
	 */
	set_time();
	/*
	 * Setup corefile size immediately after boot -kre
	 */
	setup_corefile();

	/*
	 * set initialVMTop before we allocate any memory
	 */
	initialVMTop = get_vm_top();

	ServerRunning = 0;
	/* It ain't random, but it ought to be a little harder to guess */
	srand(SystemTime.tv_sec ^ (SystemTime.tv_usec | (getpid() << 20)));
	memset(&me, 0, sizeof(me));
	memset(&meLocalUser, 0, sizeof(meLocalUser));
	me.localClient = &meLocalUser;

	/* Make sure all lists are zeroed */
	memset(&unknown_list, 0, sizeof(unknown_list));
	memset(&lclient_list, 0, sizeof(lclient_list));
	memset(&serv_list, 0, sizeof(serv_list));
	memset(&global_serv_list, 0, sizeof(global_serv_list));
	memset(&oper_list, 0, sizeof(oper_list));

	dlinkAddTail(&me, &me.node, &global_client_list);

	memset((void *) &Count, 0, sizeof(Count));
	memset((void *) &ServerInfo, 0, sizeof(ServerInfo));
	memset((void *) &AdminInfo, 0, sizeof(AdminInfo));

	/* Initialise the channel capability usage counts... */
	init_chcap_usage_counts();

	ConfigFileEntry.dpath = DPATH;
	ConfigFileEntry.configfile = CPATH;	/* Server configuration file */
	ConfigFileEntry.klinefile = KPATH;	/* Server kline file */
	ConfigFileEntry.dlinefile = DLPATH;	/* dline file */
	ConfigFileEntry.xlinefile = XPATH;
	ConfigFileEntry.resvfile = RESVPATH;
	ConfigFileEntry.connect_timeout = 30;	/* Default to 30 */
	myargv = argv;
	umask(077);		/* better safe than sorry --SRB */

	parseargs(&argc, &argv, myopts);

	if(printVersion)
	{
		printf("ircd: version %s\n", ircd_version);
		exit(EXIT_SUCCESS);
	}

	if(chdir(ConfigFileEntry.dpath))
	{
		fprintf(stderr, "Unable to chdir to %s: %s\n", ConfigFileEntry.dpath, strerror(errno));
		exit(EXIT_FAILURE);
	}

	setup_signals();

#ifdef __CYGWIN__
	server_state_foreground = 1;
#endif

	if (testing_conf)
		server_state_foreground = 1;

	/* We need this to initialise the fd array before anything else */
	fdlist_init();
	if(!server_state_foreground)
	{
		comm_close_all();
	}


	/* Check if there is pidfile and daemon already running */
	if(!testing_conf)
	{
		check_pidfile(pidFileName);

		if(!server_state_foreground)
			make_daemon();
		else
			print_startup(getpid());
	}

	init_netio();		/* This needs to be setup early ! -- adrian */

	/* Init the event subsystem */
	eventInit();
	init_sys();

	init_main_logfile();
	initBlockHeap();
	init_dlink_nodes();
	init_patricia();
	newconf_init();
	init_s_conf();
	init_s_newconf();
	linebuf_init();		/* set up some linebuf stuff to control paging */
	init_hash();
	clear_scache_hash_table();	/* server cache name table */
	init_host_hash();
	clear_hash_parse();
	init_client();
	initUser();
	init_channels();
	initclass();
	initwhowas();
	init_stats();
	init_hook();
	init_reject();
	init_cache();
	init_monitor();
	load_all_modules(1);
#ifndef STATIC_MODULES
	load_core_modules(1);
#endif
	init_auth();		/* Initialise the auth code */
	init_resolver();	/* Needs to be setup before the io loop */

	if (testing_conf)
		fprintf(stderr, "\nBeginning config test\n");
	read_conf_files(YES);	/* cold start init conf files */
	rehash_bans(0);
#ifndef STATIC_MODULES

	mod_add_path(MODULE_DIR); 
	mod_add_path(MODULE_DIR "/autoload"); 
#endif

	initialize_server_capabs();	/* Set up default_server_capabs */
	initialize_global_set_options();

	if(ServerInfo.name == NULL)
	{
		fprintf(stderr, "ERROR: No server name specified in serverinfo block.\n");
		ilog(L_MAIN, "No server name specified in serverinfo block.");
		exit(EXIT_FAILURE);
	}
	strlcpy(me.name, ServerInfo.name, sizeof(me.name));

	if(ServerInfo.sid[0] == '\0')
	{
		fprintf(stderr, "ERROR: No server sid specified in serverinfo block.\n");
		ilog(L_MAIN, "No server sid specified in serverinfo block.");
		exit(EXIT_FAILURE);
	}
	strcpy(me.id, ServerInfo.sid);
	init_uid();

	/* serverinfo{} description must exist.  If not, error out. */
	if(ServerInfo.description == NULL)
	{
		fprintf(stderr, "ERROR: No server description specified in serverinfo block.\n");
		ilog(L_MAIN, "ERROR: No server description specified in serverinfo block.");
		exit(EXIT_FAILURE);
	}
	strlcpy(me.info, ServerInfo.description, sizeof(me.info));

	if (testing_conf)
	{
		fprintf(stderr, "\nConfig testing complete.\n");
		fflush(stderr);
		exit(EXIT_SUCCESS);
	}

	me.from = &me;
	me.servptr = &me;
	SetMe(&me);
	make_server(&me);
	me.serv->up = me.name;
	startup_time = CurrentTime;
	add_to_client_hash(me.name, &me);
	add_to_id_hash(me.id, &me);

	dlinkAddAlloc(&me, &global_serv_list);

	check_class();
	write_pidfile(pidFileName);
	load_help();
	open_logfiles();

	ilog(L_MAIN, "Server Ready");

	eventAddIsh("cleanup_glines", cleanup_glines, NULL, CLEANUP_GLINES_TIME);

	/* We want try_connections to be called as soon as possible now! -- adrian */
	/* No, 'cause after a restart it would cause all sorts of nick collides */
	/* um.  by waiting even longer, that just means we have even *more*
	 * nick collisions.  what a stupid idea. set an event for the IO loop --fl
	 */
	eventAddIsh("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
	eventAddOnce("try_connections_startup", try_connections, NULL, 0);

	eventAddIsh("collect_zipstats", collect_zipstats, NULL, ZIPSTATS_TIME);

	/* Setup the timeout check. I'll shift it later :)  -- adrian */
	eventAddIsh("comm_checktimeouts", comm_checktimeouts, NULL, 1);

	if(ConfigServerHide.links_delay > 0)
		eventAddIsh("cache_links", cache_links, NULL,
			    ConfigServerHide.links_delay);
	else
		ConfigServerHide.links_disabled = 1;

	if(splitmode)
		eventAdd("check_splitmode", check_splitmode, NULL, 2);

	ServerRunning = 1;

	io_loop();
	return 0;
}
Example #30
0
/*
 * Initialize statics and set limits, signals & umask to try to avoid
 * interruptions, crashes etc. that might expose passord data.
 */
int
pw_init(const char *dir, const char *master)
{
#if 0
    struct rlimit rlim;
#endif

    if (dir == NULL) {
        strcpy(passwd_dir, _PATH_ETC);
    } else {
        if (strlen(dir) >= sizeof(passwd_dir)) {
            errno = ENAMETOOLONG;
            return (-1);
        }
        strcpy(passwd_dir, dir);
    }

    if (master == NULL) {
        if (dir == NULL) {
            strcpy(masterpasswd, _PATH_MASTERPASSWD);
        } else if (snprintf(masterpasswd, sizeof(masterpasswd), "%s/%s",
                            passwd_dir, _MASTERPASSWD) > (int)sizeof(masterpasswd)) {
            errno = ENAMETOOLONG;
            return (-1);
        }
    } else {
        if (strlen(master) >= sizeof(masterpasswd)) {
            errno = ENAMETOOLONG;
            return (-1);
        }
        strcpy(masterpasswd, master);
    }

    /*
     * The code that follows is extremely disruptive to the calling
     * process, and is therefore disabled until someone can conceive
     * of a realistic scenario where it would fend off a compromise.
     * Race conditions concerning the temporary files can be guarded
     * against in other ways than masking signals (by checking stat(2)
     * results after creation).
     */
#if 0
    /* Unlimited resource limits. */
    rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
    (void)setrlimit(RLIMIT_CPU, &rlim);
    (void)setrlimit(RLIMIT_FSIZE, &rlim);
    (void)setrlimit(RLIMIT_STACK, &rlim);
    (void)setrlimit(RLIMIT_DATA, &rlim);
    (void)setrlimit(RLIMIT_RSS, &rlim);

    /* Don't drop core (not really necessary, but GP's). */
    rlim.rlim_cur = rlim.rlim_max = 0;
    (void)setrlimit(RLIMIT_CORE, &rlim);

    /* Turn off signals. */
    (void)signal(SIGALRM, SIG_IGN);
    (void)signal(SIGHUP, SIG_IGN);
    (void)signal(SIGINT, SIG_IGN);
    (void)signal(SIGPIPE, SIG_IGN);
    (void)signal(SIGQUIT, SIG_IGN);
    (void)signal(SIGTERM, SIG_IGN);
    (void)signal(SIGCONT, pw_cont);

    /* Create with exact permissions. */
    (void)umask(0);
#endif
    initialized = 1;
    return (0);
}