Пример #1
0
/* Create a new PID file for the current process. */
int pa_pid_file_create(const char *procname) {
    int fd = -1;
    int ret = -1;
    char t[20];
    pid_t pid;
    size_t l;
    char *fn;

#ifdef OS_IS_WIN32
    HANDLE process;
#endif

    if (!(fn = pa_runtime_path("pid")))
        goto fail;

    if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
        goto fail;

    if ((pid = read_pid(fn, fd)) == (pid_t) -1)
        pa_log_warn("Corrupt PID file, overwriting.");
    else if (pid > 0) {
        int ours = 1;

#ifdef OS_IS_WIN32
        if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid)) != NULL) {
            CloseHandle(process);
#else
        if (kill(pid, 0) >= 0 || errno != ESRCH) {
#endif

            if (procname)
                if ((ours = proc_name_ours(pid, procname)) < 0) {
                    pa_log_warn("Could not check to see if pid %lu is a pulseaudio process. "
                                "Assuming it is and the daemon is already running.", (unsigned long) pid);
                    goto fail;
                }

            if (ours) {
                pa_log("Daemon already running.");
                ret = 1;
                goto fail;
            }
        }

        pa_log_warn("Stale PID file, overwriting.");
    }

    /* Overwrite the current PID file */
    if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, (off_t) 0) < 0) {
        pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
        goto fail;
    }

    pa_snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
    l = strlen(t);

    if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
        pa_log("Failed to write PID file.");
        goto fail;
    }

    ret = 0;

fail:
    if (fd >= 0) {
        pa_lock_fd(fd, 0);

        if (pa_close(fd) < 0) {
            pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
            ret = -1;
        }
    }

    pa_xfree(fn);

    return ret;
}

/* Remove the PID file, if it is ours */
int pa_pid_file_remove(void) {
    int fd = -1;
    char *fn;
    int ret = -1;
    pid_t pid;

    if (!(fn = pa_runtime_path("pid")))
        goto fail;

    if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
        pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
        goto fail;
    }

    if ((pid = read_pid(fn, fd)) == (pid_t) -1)
        goto fail;

    if (pid != getpid()) {
        pa_log("PID file '%s' not mine!", fn);
        goto fail;
    }

    if (ftruncate(fd, (off_t) 0) < 0) {
        pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
        goto fail;
    }

#ifdef OS_IS_WIN32
    pa_lock_fd(fd, 0);
    pa_close(fd);
    fd = -1;
#endif

    if (unlink(fn) < 0) {
        pa_log_warn("Failed to remove PID file '%s': %s", fn, pa_cstrerror(errno));
        goto fail;
    }

    ret = 0;

fail:

    if (fd >= 0) {
        pa_lock_fd(fd, 0);

        if (pa_close(fd) < 0) {
            pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
            ret = -1;
        }
    }

    pa_xfree(fn);

    return ret;
}
Пример #2
0
int main(int argc, char **argv)
{
	options_t options;
	int doversion = 0;
	int dohelp = 0;
	int userclasses = 0;
	int opt;
	int option_index = 0;
	char prefix[IF_NAMESIZE + 3];
	pid_t pid;
	int debug = 0;
	int i;
	int pidfd = -1;

	const struct option longopts[] = {
		{"arp",         no_argument,        NULL, 'a'},
		{"script",      required_argument,  NULL, 'c'},
		{"debug",       no_argument,        NULL, 'd'},
		{"hostname",    optional_argument,  NULL, 'h'},
		{"classid",     optional_argument,  NULL, 'i'},
		{"release",     no_argument,        NULL, 'k'},
		{"leasetime",   required_argument,  NULL, 'l'},
		{"metric",      required_argument,  NULL, 'm'},
		{"renew",       no_argument,        NULL, 'n'},
		{"persistent",  no_argument,        NULL, 'p'},
		{"inform",      optional_argument,  NULL, 's'},
		{"request",     optional_argument,  NULL, 'r'},
		{"timeout",     required_argument,  NULL, 't'},
		{"userclass",   required_argument,  NULL, 'u'},
		{"lastlease",   no_argument,        NULL, 'E'},
		{"fqdn",        required_argument,  NULL, 'F'},
		{"nogateway",   no_argument,        NULL, 'G'},
		{"sethostname", no_argument,        NULL, 'H'},
		{"clientid",    optional_argument,  NULL, 'I'},
		{"noipv4ll",	no_argument,		NULL, 'L'},
		{"nomtu",       no_argument,        NULL, 'M'},
		{"nontp",       no_argument,        NULL, 'N'},
		{"nodns",       no_argument,        NULL, 'R'},
		{"test",        no_argument,        NULL, 'T'},
		{"nonis",       no_argument,        NULL, 'Y'},
		{"help",        no_argument,        &dohelp, 1},
		{"version",     no_argument,        &doversion, 1},
		{NULL,          0,                  NULL, 0}
	};

	/* Close any un-needed fd's */
	for (i = getdtablesize() - 1; i >= 3; --i)
		close (i);

	openlog (PACKAGE, LOG_PID, LOG_LOCAL0);

	memset (&options, 0, sizeof (options_t));
	options.script = (char *) DEFAULT_SCRIPT;
	snprintf (options.classid, CLASS_ID_MAX_LEN, "%s %s", PACKAGE, VERSION);
	options.classid_len = strlen (options.classid);

	options.doarp = true;
	options.dodns = true;
	options.domtu = true;
	options.donis = true;
	options.dontp = true;
	options.dogateway = true;
	options.daemonise = true;
	options.doinform = false;
	options.doipv4ll = true;
	options.timeout = DEFAULT_TIMEOUT;

	gethostname (options.hostname, sizeof (options.hostname));
	if (strcmp (options.hostname, "(none)") == 0 ||
		strcmp (options.hostname, "localhost") == 0)
		memset (options.hostname, 0, sizeof (options.hostname));

	/* Don't set any optional arguments here so we retain POSIX
	 * compatibility with getopt */
	while ((opt = getopt_long(argc, argv, "c:dh:i:kl:m:npr:s:t:u:AEF:GHI:LMNRTY",
							  longopts, &option_index)) != -1)
	{
		switch (opt) {
			case 0:
				if (longopts[option_index].flag)
					break;
				logger (LOG_ERR, "option `%s' should set a flag",
						longopts[option_index].name);
				exit (EXIT_FAILURE);
				break;
			case 'c':
				options.script = optarg;
				break;
			case 'd':
				debug++;
				switch (debug) {
					case 1:
						setloglevel (LOG_DEBUG);
						break;
					case 2:
						options.daemonise = false;
						break;
				}
				break;
			case 'h':
				if (! optarg)
					memset (options.hostname, 0, sizeof (options.hostname));
				else if (strlen (optarg) > MAXHOSTNAMELEN) {
					logger (LOG_ERR, "`%s' too long for HostName string, max is %d",
							optarg, MAXHOSTNAMELEN);
					exit (EXIT_FAILURE);
				} else
					strlcpy (options.hostname, optarg, sizeof (options.hostname));
				break;
			case 'i':
				if (! optarg) {
					memset (options.classid, 0, sizeof (options.classid));
					options.classid_len = 0;
				} else if (strlen (optarg) > CLASS_ID_MAX_LEN) {
					logger (LOG_ERR, "`%s' too long for ClassID string, max is %d",
							optarg, CLASS_ID_MAX_LEN);
					exit (EXIT_FAILURE);
				} else
					options.classid_len = strlcpy (options.classid, optarg,
												   sizeof (options.classid));
				break;
			case 'k':
				options.signal = SIGHUP;
				break;
			case 'l':
				STRINGINT (optarg, options.leasetime);
				if (options.leasetime <= 0) {
					logger (LOG_ERR, "leasetime must be a positive value");
					exit (EXIT_FAILURE);
				}
				break;
			case 'm':
				STRINGINT (optarg, options.metric);
				break;
			case 'n':
				options.signal = SIGALRM;
				break;
			case 'p':
				options.persistent = true;
				break;
			case 's':
				options.doinform = true;
				if (! optarg || strlen (optarg) == 0) {
					options.request_address.s_addr = 0;
					break;
				} else {
					char *slash = strchr (optarg, '/');
					if (slash) {
						int cidr;
						/* nullify the slash, so the -r option can read the
						 * address */
						*slash++ = '\0';
						if (sscanf (slash, "%d", &cidr) != 1) {
							logger (LOG_ERR, "`%s' is not a valid CIDR", slash);
							exit (EXIT_FAILURE);
						}
						options.request_netmask = inet_cidrtoaddr (cidr);
					}
					/* fall through */
				}
			case 'r':
				if (! options.doinform)
					options.dorequest = true;
				if (strlen (optarg) > 0 &&
					! inet_aton (optarg, &options.request_address))
				{ 
					logger (LOG_ERR, "`%s' is not a valid IP address", optarg);
					exit (EXIT_FAILURE);
				}
				break;
			case 't':
				STRINGINT (optarg, options.timeout);
				if (options.timeout < 0) {
					logger (LOG_ERR, "timeout must be a positive value");
					exit (EXIT_FAILURE);
				}
				break;
			case 'u':
				{
					int offset = 0;
					for (i = 0; i < userclasses; i++)
						offset += (int) options.userclass[offset] + 1;
					if (offset + 1 + strlen (optarg) > USERCLASS_MAX_LEN) {
						logger (LOG_ERR, "userclass overrun, max is %d",
								USERCLASS_MAX_LEN);
						exit (EXIT_FAILURE);
					}
					userclasses++;
					memcpy (options.userclass + offset + 1 , optarg, strlen (optarg));
					options.userclass[offset] = strlen (optarg);
					options.userclass_len += (strlen (optarg)) + 1;
				}
				break;
			case 'A':
#ifndef ENABLE_ARP
				logger (LOG_ERR, "arp support not compiled into dhcpcd");
				exit (EXIT_FAILURE);
#endif
				options.doarp = false;
				break;
			case 'E':
#ifndef ENABLE_INFO
				logger (LOG_ERR, "info support not compiled into dhcpcd");
				exit (EXIT_FAILURE);
#endif
				options.dolastlease = true;
				break;
			case 'F':
				if (strncmp (optarg, "none", strlen (optarg)) == 0)
					options.fqdn = FQDN_NONE;
				else if (strncmp (optarg, "ptr", strlen (optarg)) == 0)
					options.fqdn = FQDN_PTR;
				else if (strncmp (optarg, "both", strlen (optarg)) == 0)
					options.fqdn = FQDN_BOTH;
				else {
					logger (LOG_ERR, "invalid value `%s' for FQDN", optarg);
					exit (EXIT_FAILURE);
				}
				break;
			case 'G':
				options.dogateway = false;
				break;
			case 'H':
				options.dohostname++;
				break;
			case 'I':
				if (optarg) {
					if (strlen (optarg) > CLIENT_ID_MAX_LEN) {
						logger (LOG_ERR, "`%s' is too long for ClientID, max is %d",
								optarg, CLIENT_ID_MAX_LEN);
						exit (EXIT_FAILURE);
					}
					options.clientid_len = strlcpy (options.clientid, optarg,
													sizeof (options.clientid));
					/* empty string disabled duid */
					if (options.clientid_len == 0)
						options.clientid_len = -1;
				} else {
					memset (options.clientid, 0, sizeof (options.clientid));
					options.clientid_len = -1;
				}
				break;
			case 'L':
				options.doipv4ll = false;
				break;
			case 'M':
				options.domtu = false;
				break;
			case 'N':
				options.dontp = false;
				break;
			case 'R':
				options.dodns = false;
				break;
			case 'T':
#ifndef ENABLE_INFO
				logger (LOG_ERR, "info support not compiled into dhcpcd");
				exit (EXIT_FAILURE);
#endif
				options.test = true;
				options.persistent = true;
				break;
			case 'Y':
				options.donis = false;
				break;
			case '?':
				usage ();
				exit (EXIT_FAILURE);
			default:
				usage ();
				exit (EXIT_FAILURE);
		}
	}
	if (doversion)
		printf (""PACKAGE" "VERSION"\n");

	if (dohelp)
		usage ();

	if (optind < argc) {
		if (strlen (argv[optind]) > IF_NAMESIZE) {
			logger (LOG_ERR, "`%s' is too long for an interface name (max=%d)",
					argv[optind], IF_NAMESIZE);
			exit (EXIT_FAILURE);
		}
		strlcpy (options.interface, argv[optind],
				 sizeof (options.interface));
	} else {
		/* If only version was requested then exit now */
		if (doversion || dohelp)
			exit (EXIT_SUCCESS);

		logger (LOG_ERR, "no interface specified");
		exit (EXIT_FAILURE);
	}

	if (strchr (options.hostname, '.')) {
		if (options.fqdn == FQDN_DISABLE)
			options.fqdn = FQDN_BOTH;
	} else
		options.fqdn = FQDN_DISABLE;

	if (options.request_address.s_addr == 0 && options.doinform) {
		if ((options.request_address.s_addr = get_address (options.interface)) != 0)
			options.keep_address = true;
	}

	if (geteuid ()) {
		logger (LOG_ERR, "you need to be root to run "PACKAGE);
		exit (EXIT_FAILURE);
	}

	snprintf (prefix, IF_NAMESIZE, "%s: ", options.interface);
	setlogprefix (prefix);
	snprintf (options.pidfile, sizeof (options.pidfile), PIDFILE,
			  options.interface);

	chdir ("/");
	umask (022);

	if (mkdir (CONFIGDIR, S_IRUSR |S_IWUSR |S_IXUSR | S_IRGRP | S_IXGRP
			   | S_IROTH | S_IXOTH) && errno != EEXIST )
	{
		logger (LOG_ERR, "mkdir(\"%s\",0): %s\n", CONFIGDIR, strerror (errno));
		exit (EXIT_FAILURE);
	}

	if (mkdir (ETCDIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP
			   | S_IROTH | S_IXOTH) && errno != EEXIST )
	{
		logger (LOG_ERR, "mkdir(\"%s\",0): %s\n", ETCDIR, strerror (errno));
		exit (EXIT_FAILURE);
	}

	if (options.test) {
		if (options.dorequest || options.doinform) {
			logger (LOG_ERR, "cannot test with --inform or --request");
			exit (EXIT_FAILURE);
		}

		if (options.dolastlease) {
			logger (LOG_ERR, "cannot test with --lastlease");
			exit (EXIT_FAILURE);
		}

		if (options.signal != 0) {
			logger (LOG_ERR, "cannot test with --release or --renew");
			exit (EXIT_FAILURE);
		}
	}

	if (options.signal != 0 ) {
		int killed = -1;
		pid = read_pid (options.pidfile);
		if (pid != 0)
			logger (LOG_INFO, "sending signal %d to pid %d", options.signal, pid);

		if (! pid || (killed = kill (pid, options.signal)))
			logger (options.signal == SIGALRM ? LOG_INFO : LOG_ERR, ""PACKAGE" not running");

		if (pid != 0 && (options.signal != SIGALRM || killed != 0))
			unlink (options.pidfile);

		if (killed == 0)
			exit (EXIT_SUCCESS);

		if (options.signal != SIGALRM)
			exit (EXIT_FAILURE);
	}

	if (! options.test) {
		if ((pid = read_pid (options.pidfile)) > 0 && kill (pid, 0) == 0) {
			logger (LOG_ERR, ""PACKAGE" already running on pid %d (%s)",
					pid, options.pidfile);
			exit (EXIT_FAILURE);
		}

		pidfd = open (options.pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0660);
		if (pidfd == -1) {
			logger (LOG_ERR, "open `%s': %s", options.pidfile, strerror (errno));
			exit (EXIT_FAILURE);
		}

		/* Lock the file so that only one instance of dhcpcd runs on an interface */
		if (flock (pidfd, LOCK_EX | LOCK_NB) == -1) {
			logger (LOG_ERR, "flock `%s': %s", options.pidfile, strerror (errno));
			exit (EXIT_FAILURE);
		}

		/* dhcpcd.sh should not interhit this fd */
		if ((i = fcntl (pidfd, F_GETFD, 0)) == -1 ||
			fcntl (pidfd, F_SETFD, i | FD_CLOEXEC) == -1)
			logger (LOG_ERR, "fcntl: %s", strerror (errno));

		logger (LOG_INFO, PACKAGE " " VERSION " starting");
	}

	/* Seed random */
	srandomdev ();

	if (dhcp_run (&options, &pidfd)) {
		if (pidfd > -1)
			close (pidfd);
		unlink (options.pidfile);
		exit (EXIT_FAILURE);
	}

	exit (EXIT_SUCCESS);
}
Пример #3
0
static ReadStatus
read_data (DBusBabysitter *sitter,
           int             fd)
{
    int what;
    int got;
    DBusError error = DBUS_ERROR_INIT;
    ReadStatus r;

    r = read_ints (fd, &what, 1, &got, &error);

    switch (r)
    {
    case READ_STATUS_ERROR:
        _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
        dbus_error_free (&error);
        return r;

    case READ_STATUS_EOF:
        return r;

    case READ_STATUS_OK:
        break;
    }

    if (got == 1)
    {
        switch (what)
        {
        case CHILD_EXITED:
        case CHILD_FORK_FAILED:
        case CHILD_EXEC_FAILED:
        {
            int arg;

            r = read_ints (fd, &arg, 1, &got, &error);

            switch (r)
            {
            case READ_STATUS_ERROR:
                _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
                dbus_error_free (&error);
                return r;
            case READ_STATUS_EOF:
                return r;
            case READ_STATUS_OK:
                break;
            }

            if (got == 1)
            {
                if (what == CHILD_EXITED)
                {
                    sitter->have_child_status = TRUE;
                    sitter->status = arg;
                    sitter->errnum = 0;
                    _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
                                   WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
                                   WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
                }
                else if (what == CHILD_FORK_FAILED)
                {
                    sitter->have_fork_errnum = TRUE;
                    sitter->errnum = arg;
                    _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
                }
                else if (what == CHILD_EXEC_FAILED)
                {
                    sitter->have_exec_errnum = TRUE;
                    sitter->errnum = arg;
                    _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
                }
            }
        }
        break;
        case CHILD_PID:
        {
            pid_t pid = -1;

            r = read_pid (fd, &pid, &error);

            switch (r)
            {
            case READ_STATUS_ERROR:
                _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
                dbus_error_free (&error);
                return r;
            case READ_STATUS_EOF:
                return r;
            case READ_STATUS_OK:
                break;
            }

            sitter->grandchild_pid = pid;

            _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
        }
        break;
        default:
            _dbus_warn ("Unknown message received from babysitter process\n");
            break;
        }
    }

    return r;
}
Пример #4
0
int ifplugd_main(int argc UNUSED_PARAM, char **argv)
{
	int iface_status;
	int delay_time;
	const char *iface_status_str;
	struct pollfd netlink_pollfd[1];
	unsigned opts;
	const char *api_mode_found;
#if ENABLE_FEATURE_PIDFILE
	char *pidfile_name;
	pid_t pid_from_pidfile;
#endif

	INIT_G();

	opts = getopt32(argv, OPTION_STR,
		&G.iface, &G.script_name, &G.poll_time, &G.delay_up,
		&G.delay_down, &G.api_mode, &G.extra_arg);
	G.poll_time *= 1000;

	applet_name = xasprintf("ifplugd(%s)", G.iface);

#if ENABLE_FEATURE_PIDFILE
	pidfile_name = xasprintf(CONFIG_PID_FILE_PATH "/ifplugd.%s.pid", G.iface);
	pid_from_pidfile = read_pid(pidfile_name);

	if (opts & FLAG_KILL) {
		if (pid_from_pidfile > 0)
			/* Upstream tool use SIGINT for -k */
			kill(pid_from_pidfile, SIGINT);
		return EXIT_SUCCESS;
	}

	if (pid_from_pidfile > 0 && kill(pid_from_pidfile, 0) == 0)
		bb_error_msg_and_die("daemon already running");
#endif

	api_mode_found = strchr(api_modes, G.api_mode[0]);
	if (!api_mode_found)
		bb_error_msg_and_die("unknown API mode '%s'", G.api_mode);
	G.api_method_num = api_mode_found - api_modes;

	if (!(opts & FLAG_NO_DAEMON))
		bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);

	xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd);
	if (opts & FLAG_MONITOR) {
		struct sockaddr_nl addr;
		int fd = xsocket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);

		memset(&addr, 0, sizeof(addr));
		addr.nl_family = AF_NETLINK;
		addr.nl_groups = RTMGRP_LINK;
		addr.nl_pid = getpid();

		xbind(fd, (struct sockaddr*)&addr, sizeof(addr));
		xmove_fd(fd, netlink_fd);
	}

	write_pidfile(pidfile_name);

	/* this can't be moved before socket creation */
	if (!(opts & FLAG_NO_SYSLOG)) {
		openlog(applet_name, 0, LOG_DAEMON);
		logmode |= LOGMODE_SYSLOG;
	}

	bb_signals(0
		| (1 << SIGINT )
		| (1 << SIGTERM)
		| (1 << SIGQUIT)
		| (1 << SIGHUP ) /* why we ignore it? */
		/* | (1 << SIGCHLD) - run_script does not use it anymore */
		, record_signo);

	bb_error_msg("started: %s", bb_banner);

	if (opts & FLAG_MONITOR) {
		struct ifreq ifrequest;
		set_ifreq_to_ifname(&ifrequest);
		G.iface_exists = (network_ioctl(SIOCGIFINDEX, &ifrequest, NULL) == 0);
	}

	if (G.iface_exists)
		maybe_up_new_iface();

	iface_status = detect_link();
	if (iface_status == IFSTATUS_ERR)
		goto exiting;
	iface_status_str = strstatus(iface_status);

	if (opts & FLAG_MONITOR) {
		bb_error_msg("interface %s",
			G.iface_exists ? "exists"
			: "doesn't exist, waiting");
	}
	/* else we assume it always exists, but don't mislead user
	 * by potentially lying that it really exists */

	if (G.iface_exists) {
		bb_error_msg("link is %s", iface_status_str);
	}

	if ((!(opts & FLAG_NO_STARTUP)
	     && iface_status == IFSTATUS_UP
	    )
	 || (opts & FLAG_INITIAL_DOWN)
	) {
		if (run_script(iface_status_str) != 0)
			goto exiting;
	}

	/* Main loop */
	netlink_pollfd[0].fd = netlink_fd;
	netlink_pollfd[0].events = POLLIN;
	delay_time = 0;
	while (1) {
		int iface_status_old;

		switch (bb_got_signal) {
		case SIGINT:
		case SIGTERM:
			bb_got_signal = 0;
			goto cleanup;
		case SIGQUIT:
			bb_got_signal = 0;
			goto exiting;
		default:
			bb_got_signal = 0;
		/* do not clear bb_got_signal if already 0, this can lose signals */
		case 0:
			break;
		}

		if (poll(netlink_pollfd,
				(opts & FLAG_MONITOR) ? 1 : 0,
				G.poll_time
			) < 0
		) {
			if (errno == EINTR)
				continue;
			bb_perror_msg("poll");
			goto exiting;
		}

		if ((opts & FLAG_MONITOR)
		 && (netlink_pollfd[0].revents & POLLIN)
		) {
			int iface_exists_old;

			iface_exists_old = G.iface_exists;
			G.iface_exists = check_existence_through_netlink();
			if (G.iface_exists < 0) /* error */
				goto exiting;
			if (iface_exists_old != G.iface_exists) {
				bb_error_msg("interface %sappeared",
						G.iface_exists ? "" : "dis");
				if (G.iface_exists)
					maybe_up_new_iface();
			}
		}

		/* note: if !G.iface_exists, returns DOWN */
		iface_status_old = iface_status;
		iface_status = detect_link();
		if (iface_status == IFSTATUS_ERR) {
			if (!(opts & FLAG_MONITOR))
				goto exiting;
			iface_status = IFSTATUS_DOWN;
		}
		iface_status_str = strstatus(iface_status);

		if (iface_status_old != iface_status) {
			bb_error_msg("link is %s", iface_status_str);

			if (delay_time) {
				/* link restored its old status before
				 * we ran script. don't run the script: */
				delay_time = 0;
			} else {
				delay_time = monotonic_sec();
				if (iface_status == IFSTATUS_UP)
					delay_time += G.delay_up;
				if (iface_status == IFSTATUS_DOWN)
					delay_time += G.delay_down;
#if 0  /* if you are back in 1970... */
				if (delay_time == 0) {
					sleep(1);
					delay_time = 1;
				}
#endif
			}
		}

		if (delay_time && (int)(monotonic_sec() - delay_time) >= 0) {
			if (run_script(iface_status_str) != 0)
				goto exiting;
			delay_time = 0;
		}
	} /* while (1) */

 cleanup:
	if (!(opts & FLAG_NO_SHUTDOWN)
	 && (iface_status == IFSTATUS_UP
	     || (iface_status == IFSTATUS_DOWN && delay_time)
	    )
	) {
		setenv(IFPLUGD_ENV_PREVIOUS, strstatus(iface_status), 1);
		setenv(IFPLUGD_ENV_CURRENT, strstatus(-1), 1);
		run_script("down\0up"); /* reusing string */
	}

 exiting:
	remove_pidfile(pidfile_name);
	bb_error_msg_and_die("exiting");
}
Пример #5
0
int main(int argc, char **argv)
{
	options_t *options;
	int userclasses = 0;
	int opt;
	int option_index = 0;
	char *prefix;
	pid_t pid;
	int debug = 0;
	int i;
	int pidfd = -1;
	int sig = 0;

	/* Close any un-needed fd's */
	for (i = getdtablesize() - 1; i >= 3; --i)
		close (i);

	openlog (PACKAGE, LOG_PID, LOG_LOCAL0);

	options = xmalloc (sizeof (options_t));
	memset (options, 0, sizeof (options_t));
	options->script = (char *) DEFAULT_SCRIPT;
	snprintf (options->classid, CLASS_ID_MAX_LEN, "%s %s", PACKAGE, VERSION);
	options->classid_len = strlen (options->classid);

	options->doarp = true;
	options->dodns = true;
	options->domtu = true;
	options->donis = true;
	options->dontp = true;
	options->dogateway = true;
	options->daemonise = true;
	options->doinform = false;
	options->doipv4ll = true;
	options->timeout = DEFAULT_TIMEOUT;

	gethostname (options->hostname, sizeof (options->hostname));
	if (strcmp (options->hostname, "(none)") == 0 ||
		strcmp (options->hostname, "localhost") == 0)
		memset (options->hostname, 0, sizeof (options->hostname));

	/* Don't set any optional arguments here so we retain POSIX
	 * compatibility with getopt */
	while ((opt = getopt_long(argc, argv, EXTRA_OPTS
							  "c:dh:i:kl:m:npr:s:t:u:xAEF:GHI:LMNRTY",
							  longopts, &option_index)) != -1)
	{
		switch (opt) {
			case 0:
				if (longopts[option_index].flag)
					break;
				logger (LOG_ERR, "option `%s' should set a flag",
						longopts[option_index].name);
				exit (EXIT_FAILURE);
				break;
			case 'c':
				options->script = optarg;
				break;
			case 'd':
				debug++;
				switch (debug) {
					case 1:
						setloglevel (LOG_DEBUG);
						break;
					case 2:
						options->daemonise = false;
						break;
				}
				break;
#ifdef THERE_IS_NO_FORK
			case 'f':
				options->daemonised = true;
				close_fds ();
				break;
			case 'g':
				dhcpcd_skiproutes = xstrdup (optarg);
				break;
#endif
			case 'h':
				if (! optarg)
					memset (options->hostname, 0, sizeof (options->hostname));
				else if (strlen (optarg) > MAXHOSTNAMELEN) {
					logger (LOG_ERR, "`%s' too long for HostName string, max is %d",
							optarg, MAXHOSTNAMELEN);
					exit (EXIT_FAILURE);
				} else
					strlcpy (options->hostname, optarg, sizeof (options->hostname));
				break;
			case 'i':
				if (! optarg) {
					memset (options->classid, 0, sizeof (options->classid));
					options->classid_len = 0;
				} else if (strlen (optarg) > CLASS_ID_MAX_LEN) {
					logger (LOG_ERR, "`%s' too long for ClassID string, max is %d",
							optarg, CLASS_ID_MAX_LEN);
					exit (EXIT_FAILURE);
				} else
					options->classid_len = strlcpy (options->classid, optarg,
												   sizeof (options->classid));
				break;
			case 'k':
				sig = SIGHUP;
				break;
			case 'l':
				STRINGINT (optarg, options->leasetime);
				if (options->leasetime <= 0) {
					logger (LOG_ERR, "leasetime must be a positive value");
					exit (EXIT_FAILURE);
				}
				break;
			case 'm':
				STRINGINT (optarg, options->metric);
				break;
			case 'n':
				sig = SIGALRM;
				break;
			case 'p':
				options->persistent = true;
				break;
			case 's':
				options->doinform = true;
				options->doarp = false;
				if (! optarg || strlen (optarg) == 0) {
					options->request_address.s_addr = 0;
					break;
				} else {
					char *slash = strchr (optarg, '/');
					if (slash) {
						int cidr;
						/* nullify the slash, so the -r option can read the
						 * address */
						*slash++ = '\0';
						if (sscanf (slash, "%d", &cidr) != 1 ||
							inet_cidrtoaddr (cidr, &options->request_netmask) != 0) {
							logger (LOG_ERR, "`%s' is not a valid CIDR", slash);
							exit (EXIT_FAILURE);
						}
					}
					/* fall through */
				}
			case 'r':
				if (! options->doinform)
					options->dorequest = true;
				if (strlen (optarg) > 0 &&
					! inet_aton (optarg, &options->request_address))
				{ 
					logger (LOG_ERR, "`%s' is not a valid IP address", optarg);
					exit (EXIT_FAILURE);
				}
				break;
			case 't':
				STRINGINT (optarg, options->timeout);
				if (options->timeout < 0) {
					logger (LOG_ERR, "timeout must be a positive value");
					exit (EXIT_FAILURE);
				}
				break;
			case 'u':
				{
					int offset = 0;
					for (i = 0; i < userclasses; i++)
						offset += (int) options->userclass[offset] + 1;
					if (offset + 1 + strlen (optarg) > USERCLASS_MAX_LEN) {
						logger (LOG_ERR, "userclass overrun, max is %d",
								USERCLASS_MAX_LEN);
						exit (EXIT_FAILURE);
					}
					userclasses++;
					memcpy (options->userclass + offset + 1 , optarg, strlen (optarg));
					options->userclass[offset] = strlen (optarg);
					options->userclass_len += (strlen (optarg)) + 1;
				}
				break;
			case 'x':
				sig = SIGTERM;
				break;
			case 'A':
#ifndef ENABLE_ARP
				logger (LOG_ERR, "arp support not compiled into dhcpcd");
				exit (EXIT_FAILURE);
#endif
				options->doarp = false;
				break;
			case 'E':
#ifndef ENABLE_INFO
				logger (LOG_ERR, "info support not compiled into dhcpcd");
				exit (EXIT_FAILURE);
#endif
				options->dolastlease = true;
				break;
			case 'F':
				if (strncmp (optarg, "none", strlen (optarg)) == 0)
					options->fqdn = FQDN_NONE;
				else if (strncmp (optarg, "ptr", strlen (optarg)) == 0)
					options->fqdn = FQDN_PTR;
				else if (strncmp (optarg, "both", strlen (optarg)) == 0)
					options->fqdn = FQDN_BOTH;
				else {
					logger (LOG_ERR, "invalid value `%s' for FQDN", optarg);
					exit (EXIT_FAILURE);
				}
				break;
			case 'G':
				options->dogateway = false;
				break;
			case 'H':
				options->dohostname++;
				break;
			case 'I':
				if (optarg) {
					if (strlen (optarg) > CLIENT_ID_MAX_LEN) {
						logger (LOG_ERR, "`%s' is too long for ClientID, max is %d",
								optarg, CLIENT_ID_MAX_LEN);
						exit (EXIT_FAILURE);
					}
					options->clientid_len = strlcpy (options->clientid, optarg,
													sizeof (options->clientid));
					/* empty string disabled duid */
					if (options->clientid_len == 0)
						options->clientid_len = -1;
				} else {
					memset (options->clientid, 0, sizeof (options->clientid));
					options->clientid_len = -1;
				}
				break;
			case 'L':
				options->doipv4ll = false;
				break;
			case 'M':
				options->domtu = false;
				break;
			case 'N':
				options->dontp = false;
				break;
			case 'R':
				options->dodns = false;
				break;
			case 'T':
#ifndef ENABLE_INFO
				logger (LOG_ERR, "info support not compiled into dhcpcd");
				exit (EXIT_FAILURE);
#endif
				options->test = true;
				options->persistent = true;
				break;
			case 'Y':
				options->donis = false;
				break;
			case '?':
				usage ();
				exit (EXIT_FAILURE);
			default:
				usage ();
				exit (EXIT_FAILURE);
		}
	}
	if (doversion) {
		printf (""PACKAGE" "VERSION"\n");
		printf ("Compile time options:"
#ifdef ENABLE_ARP
				" ARP"
#endif
#ifdef ENABLE_DUID
				" DUID"
#endif
#ifdef ENABLE_INFO
				" INFO"
#endif
#ifdef ENABLE_INFO_COMPAT
				" INFO_COMPAT"
#endif
#ifdef ENABLE_IPV4LL
				" IPV4LL"
#endif
#ifdef ENABLE_NIS
				" NIS"
#endif
#ifdef ENABLE_NTP
				" NTP"
#endif
#ifdef THERE_IS_NO_FORK
				" THERE_IS_NO_FORK"
#endif
				"\n");
	}

	if (dohelp)
		usage ();

#ifdef THERE_IS_NO_FORK
	dhcpcd_argv = argv;
	dhcpcd_argc = argc;

	/* We need the full path to the dhcpcd */
	if (*argv[0] == '/')
		strlcpy (dhcpcd, argv[0], sizeof (dhcpcd));
	else {
		char pwd[PATH_MAX];
		if (! getcwd (pwd, PATH_MAX)) {
			logger (LOG_ERR, "getcwd: %s", strerror (errno));
			exit (EXIT_FAILURE);
		}
		snprintf (dhcpcd, sizeof (dhcpcd), "%s/%s", pwd, argv[0]);
	}

#endif

	if (optind < argc) {
		if (strlen (argv[optind]) > IF_NAMESIZE) {
			logger (LOG_ERR, "`%s' is too long for an interface name (max=%d)",
					argv[optind], IF_NAMESIZE);
			exit (EXIT_FAILURE);
		}
		strlcpy (options->interface, argv[optind],
				 sizeof (options->interface));
	} else {
		/* If only version was requested then exit now */
		if (doversion || dohelp)
			exit (EXIT_SUCCESS);

		logger (LOG_ERR, "no interface specified");
		exit (EXIT_FAILURE);
	}

	if (strchr (options->hostname, '.')) {
		if (options->fqdn == FQDN_DISABLE)
			options->fqdn = FQDN_BOTH;
	} else
		options->fqdn = FQDN_DISABLE;

	if (options->request_address.s_addr == 0 && options->doinform) {
		if ((options->request_address.s_addr = get_address (options->interface)) != 0)
			options->keep_address = true;
	}

	if (IN_LINKLOCAL (options->request_address.s_addr)) {
		logger (LOG_ERR, "you are not allowed to request a link local address");
		exit (EXIT_FAILURE);
	}

	if (geteuid ()) {
		logger (LOG_ERR, "you need to be root to run "PACKAGE);
		exit (EXIT_FAILURE);
	}

	prefix = xmalloc (sizeof (char) * (IF_NAMESIZE + 3));
	snprintf (prefix, IF_NAMESIZE, "%s: ", options->interface);
	setlogprefix (prefix);
	snprintf (options->pidfile, sizeof (options->pidfile), PIDFILE,
			  options->interface);
	free (prefix);

	chdir ("/");
	umask (022);
	
	if (mkdir (CONFIGDIR, S_IRUSR |S_IWUSR |S_IXUSR | S_IRGRP | S_IXGRP
			   | S_IROTH | S_IXOTH) && errno != EEXIST )
	{
		logger (LOG_ERR, "mkdir(\"%s\",0): %s\n", CONFIGDIR, strerror (errno));
		exit (EXIT_FAILURE);
	}

	if (mkdir (ETCDIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP
			   | S_IROTH | S_IXOTH) && errno != EEXIST )
	{
		logger (LOG_ERR, "mkdir(\"%s\",0): %s\n", ETCDIR, strerror (errno));
		exit (EXIT_FAILURE);
	}

	if (options->test) {
		if (options->dorequest || options->doinform) {
			logger (LOG_ERR, "cannot test with --inform or --request");
			exit (EXIT_FAILURE);
		}

		if (options->dolastlease) {
			logger (LOG_ERR, "cannot test with --lastlease");
			exit (EXIT_FAILURE);
		}

		if (sig != 0) {
			logger (LOG_ERR, "cannot test with --release or --renew");
			exit (EXIT_FAILURE);
		}
	}

	if (sig != 0) {
		int killed = -1;
		pid = read_pid (options->pidfile);
		if (pid != 0)
			logger (LOG_INFO, "sending signal %d to pid %d", sig, pid);

		if (! pid || (killed = kill (pid, sig)))
			logger (sig == SIGALRM ? LOG_INFO : LOG_ERR, ""PACKAGE" not running");

		if (pid != 0 && (sig != SIGALRM || killed != 0))
			unlink (options->pidfile);

		if (killed == 0)
			exit (EXIT_SUCCESS);

		if (sig != SIGALRM)
			exit (EXIT_FAILURE);
	}

	if (! options->test && ! options->daemonised) {
		if ((pid = read_pid (options->pidfile)) > 0 && kill (pid, 0) == 0) {
			logger (LOG_ERR, ""PACKAGE" already running on pid %d (%s)",
					pid, options->pidfile);
			exit (EXIT_FAILURE);
		}

		pidfd = open (options->pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0660);
		if (pidfd == -1) {
			logger (LOG_ERR, "open `%s': %s", options->pidfile, strerror (errno));
			exit (EXIT_FAILURE);
		}

		/* Lock the file so that only one instance of dhcpcd runs on an interface */
		if (flock (pidfd, LOCK_EX | LOCK_NB) == -1) {
			logger (LOG_ERR, "flock `%s': %s", options->pidfile, strerror (errno));
			exit (EXIT_FAILURE);
		}

		/* dhcpcd.sh should not interhit this fd */
		if ((i = fcntl (pidfd, F_GETFD, 0)) == -1 ||
			fcntl (pidfd, F_SETFD, i | FD_CLOEXEC) == -1)
			logger (LOG_ERR, "fcntl: %s", strerror (errno));

		writepid (pidfd, getpid ());
		logger (LOG_INFO, PACKAGE " " VERSION " starting");
	}

	/* Seed random */
	srandomdev ();

	i = EXIT_FAILURE;
	if (dhcp_run (options, &pidfd) == 0)
		i = EXIT_SUCCESS;

	/* If we didn't daemonise then we need to punt the pidfile now */
	if (pidfd > -1) {
		close (pidfd);
		unlink (options->pidfile);
	}

	free (options);

#ifdef THERE_IS_NO_FORK
	/* There may have been an error before the dhcp_run function
	 * clears this, so just do it here to be safe */
	free (dhcpcd_skiproutes);
#endif

	logger (LOG_INFO, "exiting");
	
	exit (i);
}
Пример #6
0
int main(int argc, char **argv)
{
	options_t options;
	int doversion = 0;
	int dohelp = 0;
	int userclasses = 0;
	int ch;
	int option_index = 0;
	char prefix[IF_NAMESIZE + 3];
	pid_t pid;
	int debug = 0;
	int i;

	const struct option longopts[] = {
        {"arp",         no_argument,        NULL, 'a'},
        {"script",      required_argument,  NULL, 'c'},
        {"debug",       no_argument,        NULL, 'd'},
        {"hostname",    required_argument,  NULL, 'h'},
        {"classid",     required_argument,  NULL, 'i'},
        {"release",     no_argument,        NULL, 'k'},
        {"leasetime",   required_argument,  NULL, 'l'},
        {"metric",      required_argument,  NULL, 'm'},
        {"renew",       no_argument,        NULL, 'n'},
        {"persistent",  no_argument,        NULL, 'p'},
        {"request",     required_argument,  NULL, 's'},
        {"timeout",     required_argument,  NULL, 't'},
        {"userclass",   required_argument,  NULL, 'u'},
        {"fqdn",        optional_argument,  NULL, 'F'},
        {"nogateway",   no_argument,        NULL, 'G'},
        {"sethostname", no_argument,        NULL, 'H'},
        {"clientid",    required_argument,  NULL, 'I'},
        {"nomtu",       no_argument,        NULL, 'M'},
        {"nontp",       no_argument,        NULL, 'N'},
        {"nodns",       no_argument,        NULL, 'R'},
        {"nonis",       no_argument,        NULL, 'Y'},
        {"help",        no_argument,        &dohelp, 1},
        {"version",     no_argument,        &doversion, 1},
        {NULL,          0,                  NULL, 0}
	};

	/* Close any un-needed fd's */
	for (i = getdtablesize() - 1; i >= 3; --i)
		close (i);

	openlog (PACKAGE, LOG_PID, LOG_LOCAL0);

	memset (&options, 0, sizeof (options_t));
	options.script = (char *) DEFAULT_SCRIPT;
	snprintf (options.classid, CLASS_ID_MAX_LEN, "%s %s", PACKAGE, VERSION); 

	options.doarp = false;
	options.dodns = true;
	options.domtu = true;
	options.donis = true;
	options.dontp = true;
	options.dogateway = true;
	options.daemonise = true;
	options.timeout = DEFAULT_TIMEOUT;

	while ((ch = getopt_long(argc, argv, "ac:dh:i:kl:m:nps:t:u:F:GHI:MNRY", longopts,
							 &option_index)) != -1)
		switch (ch) {
			case 0:
				if (longopts[option_index].flag)
					break;
				logger (LOG_ERR, "option `%s' should set a flag",
						longopts[option_index].name);
				exit (EXIT_FAILURE);
				break;

			case 'a':
				options.doarp = true;
				break;
			case 'c':
				options.script = optarg;
				break;
			case 'd':
				debug++;
				switch (debug) {
					case 1:
						setloglevel (LOG_DEBUG);
						break;
					case 2:
						options.daemonise = false;
						break;
				}
				break;
			case 'h':
				if (strlen (optarg) > sizeof (options.hostname)) {
					logger (LOG_ERR, "`%s' too long for HostName string, max is %d",
							optarg, sizeof (options.hostname));
					exit (EXIT_FAILURE);
				} else
					strlcpy (options.hostname, optarg, sizeof (options.hostname));
				break;
			case 'i':
				if (strlen (optarg) > CLASS_ID_MAX_LEN) {
					logger (LOG_ERR, "`%s' too long for ClassID string, max is %d",
							optarg, CLASS_ID_MAX_LEN);
					exit (EXIT_FAILURE);
				} else
					strlcpy (options.classid, optarg, sizeof (options.classid));
				break;
			case 'k':
				options.signal = SIGHUP;
				break;
			case 'l':
				STRINGINT (optarg, options.leasetime);
				if (options.leasetime <= 0) {
					logger (LOG_ERR, "leasetime must be a positive value");
					exit (EXIT_FAILURE);
				}
				break;
			case 'm':
				STRINGINT (optarg, options.metric);
				break;
			case 'n':
				options.signal = SIGALRM;
				break;
			case 'p':
				options.persistent = true;
				break;
			case 's':
				if (! inet_aton (optarg, &options.requestaddress)) {
					logger (LOG_ERR, "`%s' is not a valid IP address", optarg);
					exit (EXIT_FAILURE);
				}
				break;
			case 't':
				STRINGINT (optarg, options.timeout);
				if (options.timeout < 0) {
					logger (LOG_ERR, "timeout must be a positive value");
					exit (EXIT_FAILURE);
				}
				break;
			case 'u':
				{
					int offset = 0;
					for (i = 0; i < userclasses; i++)
						offset += (int) options.userclass[offset] + 1;
					if (offset + 1 + strlen (optarg) > USERCLASS_MAX_LEN) {
						logger (LOG_ERR, "userclass overrun, max is %d",
								USERCLASS_MAX_LEN);
						exit (EXIT_FAILURE);
					}
					userclasses++;
					memcpy (options.userclass + offset + 1 , optarg, strlen (optarg));
					options.userclass[offset] = strlen (optarg);
					options.userclass_len += (strlen (optarg)) + 1;
				}
				break;
			case 'F':
				if (strncmp (optarg, "none", strlen (optarg)) == 0)
					options.fqdn = FQDN_NONE;
				else if (strncmp (optarg, "ptr", strlen (optarg)) == 0)
					options.fqdn = FQDN_PTR;
				else if (strncmp (optarg, "both", strlen (optarg)) == 0)
					options.fqdn = FQDN_BOTH;
				else {
					logger (LOG_ERR, "invalid value `%s' for FQDN", optarg);
					exit (EXIT_FAILURE);
				}
				break;
			case 'G':
				options.dogateway = false;
				break;
			case 'H':
				options.dohostname = true;
				break;
			case 'I':
				if (strlen (optarg) > CLIENT_ID_MAX_LEN) {
					logger (LOG_ERR, "`%s' is too long for ClientID, max is %d",
							optarg, CLIENT_ID_MAX_LEN);
					exit (EXIT_FAILURE);
				} else
					strlcpy (options.clientid, optarg, sizeof (options.clientid));
				break;
			case 'M':
				options.domtu = false;
				break;
			case 'N':
				options.dontp = false;
				break;
			case 'R':
				options.dodns = false;
				break;
			case 'Y':
				options.donis = false;
				break;
			case '?':
				usage ();
				exit (EXIT_FAILURE);
			default:
				usage ();
				exit (EXIT_FAILURE);
		}

	if (doversion)
		printf (""PACKAGE" "VERSION"\n");

	if (dohelp)
		usage ();

	if (optind < argc) {
		if (strlen (argv[optind]) > IF_NAMESIZE) {
			logger (LOG_ERR, "`%s' is too long for an interface name (max=%d)",
					argv[optind], IF_NAMESIZE);
			exit (EXIT_FAILURE);
		}
		strlcpy (options.interface, argv[optind],
				 sizeof (options.interface));
	} else {
		/* If only version was requested then exit now */
		if (doversion || dohelp)
			exit (EXIT_SUCCESS);

		logger (LOG_ERR, "no interface specified");
		exit (EXIT_FAILURE);
	}

	/* If we are given a hostname use it and set FQDN if it contains a . */
	if (! options.hostname[0]) {
		gethostname (options.hostname, sizeof (options.hostname));
		if (strcmp (options.hostname, "(none)") == 0 ||
			strcmp (options.hostname, "localhost") == 0)
			memset (options.hostname, 0, sizeof (options.hostname));
	}
	if (strchr (options.hostname, '.')) {
		if (options.fqdn == FQDN_DISABLE)
			options.fqdn = FQDN_BOTH;
	} else
		options.fqdn = FQDN_DISABLE;
	
	if (geteuid ()) {
		logger (LOG_ERR, "you need to be root to run "PACKAGE);
		exit (EXIT_FAILURE);
	}

	snprintf (prefix, IF_NAMESIZE, "%s: ", options.interface);
	setlogprefix (prefix);
	snprintf (options.pidfile, sizeof (options.pidfile), PIDFILE,
			  options.interface);

	if (options.signal != 0) {
		int killed = -1;
		pid = read_pid (options.pidfile);
		if (pid != 0)
			logger (LOG_INFO, "sending signal %d to pid %d", options.signal, pid);

		if (! pid || (killed = kill (pid, options.signal)))
			logger (options.signal == SIGALRM ? LOG_INFO : LOG_ERR, ""PACKAGE" not running");

		if (pid != 0 && (options.signal != SIGALRM || killed != 0))
			unlink (options.pidfile);

		if (killed == 0)
			exit (EXIT_SUCCESS);

		if (options.signal != SIGALRM)
			exit (EXIT_FAILURE);
	}

	chdir ("/");
	umask (022);

	if (mkdir (CONFIGDIR, S_IRUSR |S_IWUSR |S_IXUSR | S_IRGRP | S_IXGRP
			   | S_IROTH | S_IXOTH) && errno != EEXIST )
	{
		logger (LOG_ERR, "mkdir(\"%s\",0): %s\n", CONFIGDIR, strerror (errno));
		exit (EXIT_FAILURE);
	}

	if (mkdir (ETCDIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP
			   | S_IROTH | S_IXOTH) && errno != EEXIST )
	{
		logger (LOG_ERR, "mkdir(\"%s\",0): %s\n", ETCDIR, strerror (errno));
		exit (EXIT_FAILURE);
	}

	if ((pid = read_pid (options.pidfile)) > 0 && kill (pid, 0) == 0) {
		logger (LOG_ERR, ""PACKAGE" already running (%s)", options.pidfile);
		exit (EXIT_FAILURE);
	}

	make_pid (options.pidfile);

	logger (LOG_INFO, PACKAGE " " VERSION " starting");
	if (dhcp_run (&options)) {
		unlink (options.pidfile);
		exit (EXIT_FAILURE);
	}

	exit (EXIT_SUCCESS);
}
Пример #7
0
int
main (int argc, char **argv)
{
  const char *prev_arg;
  const char *shname;
  const char *runprog = NULL;
  int remaining_args = 0;
  int exit_with_session;
  int c_shell_syntax = FALSE;
  int bourne_shell_syntax = FALSE;
  int auto_shell_syntax = FALSE;
  int i;  
  int ret;
  int bus_pid_to_launcher_pipe[2];
  int bus_pid_to_babysitter_pipe[2];
  int bus_address_to_launcher_pipe[2];
  char *config_file;
  
  exit_with_session = FALSE;
  config_file = NULL;
  
  prev_arg = NULL;
  i = 1;
  while (i < argc)
    {
      const char *arg = argv[i];
      
      if (strcmp (arg, "--help") == 0 ||
          strcmp (arg, "-h") == 0 ||
          strcmp (arg, "-?") == 0)
        usage (0);
      else if (strcmp (arg, "--auto-syntax") == 0)
        auto_shell_syntax = TRUE;
      else if (strcmp (arg, "-c") == 0 ||
	       strcmp (arg, "--csh-syntax") == 0)
        c_shell_syntax = TRUE;
      else if (strcmp (arg, "-s") == 0 ||
	       strcmp (arg, "--sh-syntax") == 0)
        bourne_shell_syntax = TRUE;
      else if (strcmp (arg, "--version") == 0)
        version ();
      else if (strcmp (arg, "--exit-with-session") == 0)
        exit_with_session = TRUE;
      else if (strstr (arg, "--config-file=") == arg)
        {
          const char *file;

          if (config_file != NULL)
            {
              fprintf (stderr, "--config-file given twice\n");
              exit (1);
            }
          
          file = strchr (arg, '=');
          ++file;

          config_file = xstrdup (file);
        }
      else if (prev_arg &&
               strcmp (prev_arg, "--config-file") == 0)
        {
          if (config_file != NULL)
            {
              fprintf (stderr, "--config-file given twice\n");
              exit (1);
            }

          config_file = xstrdup (arg);
        }
      else if (strcmp (arg, "--config-file") == 0)
        ; /* wait for next arg */
      else
	{
	  runprog = arg;
	  remaining_args = i+1;
	  break;
	}
      
      prev_arg = arg;
      
      ++i;
    }

  if (exit_with_session)
    verbose ("--exit-with-session enabled\n");

  if (auto_shell_syntax)
    {
      if ((shname = getenv ("SHELL")) != NULL)
       {
         if (!strncmp (shname + strlen (shname) - 3, "csh", 3))
           c_shell_syntax = TRUE;
         else
           bourne_shell_syntax = TRUE;
       }
      else
       bourne_shell_syntax = TRUE;
    }  

  if (pipe (bus_pid_to_launcher_pipe) < 0 ||
      pipe (bus_address_to_launcher_pipe) < 0)
    {
      fprintf (stderr,
               "Failed to create pipe: %s\n",
               strerror (errno));
      exit (1);
    }

  bus_pid_to_babysitter_pipe[READ_END] = -1;
  bus_pid_to_babysitter_pipe[WRITE_END] = -1;
  
  ret = fork ();
  if (ret < 0)
    {
      fprintf (stderr, "Failed to fork: %s\n",
               strerror (errno));
      exit (1);
    }

  if (ret == 0)
    {
      /* Child */
#define MAX_FD_LEN 64
      char write_pid_fd_as_string[MAX_FD_LEN];
      char write_address_fd_as_string[MAX_FD_LEN];

      verbose ("=== Babysitter's intermediate parent created\n");
      
      /* Fork once more to create babysitter */
      
      if (pipe (bus_pid_to_babysitter_pipe) < 0)
        {
          fprintf (stderr,
                   "Failed to create pipe: %s\n",
                   strerror (errno));
          exit (1);              
        }
      
      ret = fork ();
      if (ret < 0)
        {
          fprintf (stderr, "Failed to fork: %s\n",
                   strerror (errno));
          exit (1);
        }
      
      if (ret > 0)
        {
          /* In babysitter */
          verbose ("=== Babysitter's intermediate parent continues\n");
          
          close (bus_pid_to_launcher_pipe[READ_END]);
          close (bus_address_to_launcher_pipe[READ_END]);
          close (bus_address_to_launcher_pipe[WRITE_END]);
          close (bus_pid_to_babysitter_pipe[WRITE_END]);
          
          /* babysit() will fork *again*
           * and will also reap the pre-forked bus
           * daemon
           */
          babysit (exit_with_session, ret,
                   bus_pid_to_babysitter_pipe[READ_END],
                   bus_pid_to_launcher_pipe[WRITE_END]);
          exit (0);
        }

      verbose ("=== Bus exec process created\n");
      
      /* Now we are the bus process (well, almost;
       * dbus-daemon itself forks again)
       */
      close (bus_pid_to_launcher_pipe[READ_END]);
      close (bus_address_to_launcher_pipe[READ_END]);
      close (bus_pid_to_babysitter_pipe[READ_END]);
      close (bus_pid_to_launcher_pipe[WRITE_END]);

      sprintf (write_pid_fd_as_string,
               "%d", bus_pid_to_babysitter_pipe[WRITE_END]);

      sprintf (write_address_fd_as_string,
               "%d", bus_address_to_launcher_pipe[WRITE_END]);

      verbose ("Calling exec()\n");
      
      execlp ("dbus-daemon",
              "dbus-daemon",
              "--fork",
              "--print-pid", write_pid_fd_as_string,
              "--print-address", write_address_fd_as_string,
              config_file ? "--config-file" : "--session",
              config_file, /* has to be last in this varargs list */
              NULL);

      fprintf (stderr,
               "Failed to execute message bus daemon: %s\n",
               strerror (errno));
      exit (1);
    }
  else
    {
      /* Parent */
#define MAX_ADDR_LEN 512
      pid_t bus_pid;  
      char bus_address[MAX_ADDR_LEN];

      verbose ("=== Parent dbus-launch continues\n");
      
      close (bus_pid_to_launcher_pipe[WRITE_END]);
      close (bus_address_to_launcher_pipe[WRITE_END]);

      verbose ("Waiting for babysitter's intermediate parent\n");
      
      /* Immediately reap parent of babysitter
       * (which was created just for us to reap)
       */
      if (do_waitpid (ret) < 0)
        {
          fprintf (stderr, "Failed to waitpid() for babysitter intermediate process: %s\n",
                   strerror (errno));
          exit (1);
        }

      verbose ("Reading address from bus\n");
      
      /* Read the pipe data, print, and exit */
      switch (read_line (bus_address_to_launcher_pipe[READ_END],
                         bus_address, MAX_ADDR_LEN))
        {
        case READ_STATUS_OK:
          break;
        case READ_STATUS_EOF:
          fprintf (stderr, "EOF in dbus-launch reading address from bus daemon\n");
          exit (1);
          break;
        case READ_STATUS_ERROR:
          fprintf (stderr, "Error in dbus-launch reading address from bus daemon: %s\n",
                   strerror (errno));
          exit (1);
          break;
        }
        
      close (bus_address_to_launcher_pipe[READ_END]);

      verbose ("Reading PID from babysitter\n");
      
      switch (read_pid (bus_pid_to_launcher_pipe[READ_END], &bus_pid))
        {
        case READ_STATUS_OK:
          break;
        case READ_STATUS_EOF:
          fprintf (stderr, "EOF in dbus-launch reading address from bus daemon\n");
          exit (1);
          break;
        case READ_STATUS_ERROR:
          fprintf (stderr, "Error in dbus-launch reading address from bus daemon: %s\n",
                   strerror (errno));
          exit (1);
          break;
        }

      close (bus_pid_to_launcher_pipe[READ_END]);
      
      if (runprog)
	{
	  char *envvar;
	  char **args;

	  envvar = malloc (strlen ("DBUS_SESSION_BUS_ADDRESS=") + strlen (bus_address) + 1);
	  args = malloc (sizeof (char *) * ((argc-remaining_args)+2));

	  if (envvar == NULL || args == NULL)
	    goto oom;

	  args[0] = xstrdup (runprog);
	  if (!args[0])
	    goto oom;
	  for (i = 1; i <= (argc-remaining_args); i++)
	    {
	      size_t len = strlen (argv[remaining_args+i-1])+1;
	      args[i] = malloc (len);
	      if (!args[i])
		goto oom;
	      strncpy (args[i], argv[remaining_args+i-1], len);
	    }
	  args[i] = NULL;

	  strcpy (envvar, "DBUS_SESSION_BUS_ADDRESS=");
	  strcat (envvar, bus_address);
	  putenv (envvar);

	  execvp (runprog, args);
	  fprintf (stderr, "Couldn't exec %s: %s\n", runprog, strerror (errno));
	  exit (1);
	}
      else
	{
	  if (c_shell_syntax)
	    printf ("setenv DBUS_SESSION_BUS_ADDRESS '%s'\n", bus_address);	
	  else
	    {
	      printf ("DBUS_SESSION_BUS_ADDRESS='%s'\n", bus_address);
	      if (bourne_shell_syntax)
		printf ("export DBUS_SESSION_BUS_ADDRESS\n");
	    }
	  if (c_shell_syntax)
	    printf ("set DBUS_SESSION_BUS_PID=%ld\n", (long) bus_pid);
	  else
	    printf ("DBUS_SESSION_BUS_PID=%ld\n", (long) bus_pid);
	}
	  
      verbose ("dbus-launch exiting\n");

      fflush (stdout);
      fflush (stderr);
      close (1);
      close (2);
      
      exit (0);
    } 
  
  return 0;
 oom:
  fprintf (stderr, "Out of memory!");
  exit (1);
}
Пример #8
0
/**
 * Daemonise the process and start a daemon
 * 
 * @param   arguments  `NULL`-terminated list of command line arguments,
 *                     the verb first, then the name of the daemon, followed
 *                     by optional additional script-dependent arguments
 * @return             The function call not return, it will
 *                     however exit the image with a return
 *                     as an unlikely fallback
 */
int start_daemon(char** arguments)
{
#define return  exit
#define t(cond)  if (cond) goto fail
  
  char* daemon_name = arguments[1];
  char buf[3 * sizeof(pid_t) + 2];
  int i, r, fd = -1, saved_errno;
  sigset_t set;
  char* pid_pathname = NULL;
  size_t n;
  pid_t pid, child;
  
  /* Get pathname of PID file. */
  pid_pathname = malloc((strlen(RUNDIR "/.pid") + strlen(daemon_name) + 1) * sizeof(char));
  t (pid_pathname == NULL);
  sprintf(pid_pathname, RUNDIR "/%s.pid", daemon_name);
  
  /* Close all file descriptors but stdin, stdout and stderr. */
  close_nonstd_fds();
  
  /* Reset all signals to SIG_DFL. */
  for (i = 1; i < _NSIG; i++)
    signal(i, SIG_DFL);
  
  /* Reset signal mask. */
  sigfillset(&set);
  sigprocmask(SIG_UNBLOCK, &set, NULL);
  
  /* Mark daemon with its name. */
  t (setenv(ENV_DAEMON_NAME_TAG, daemon_name, 1) < 0);
  
  /* Set to child subreaper and set SIGCHLD listening. */
  t (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0);
  t (signal(SIGCHLD, noop_sig_handler) == SIG_ERR);
  
  /* Fork */
  t ((pid = fork(), pid == -1));
  if (pid)
    goto wait_for_completion;
  
  /* Create session leader. */
  setsid();
  
  /* Reset some thinks. */
  prctl(PR_SET_CHILD_SUBREAPER, 0);
  
  /* Fork again, and exit first child synchronously. */
  if (pid = fork(), pid > 0)
    {
      pause();
      exit(1); /* Failure, if the grandchild dies first */
    }
  t (signal(SIGCHLD, noop_sig_handler) == SIG_ERR);
  t (prctl(PR_SET_PDEATHSIG, SIGCHLD) < 0);
  t (kill(getppid(), SIGCHLD) < 0);
  pause();
  
  /* Reset some thinks. */
  signal(SIGCHLD, SIG_DFL);
  
  /* Replace stdin and stdout, but not stderr, with /dev/null. */
  close(STDIN_FILENO);
  close(STDOUT_FILENO);
  fd = open(DEV_NULL, O_RDWR);
  if ((fd >= 0) && (fd != STDIN_FILENO))
    {
      dup2(fd, STDIN_FILENO);
      close(fd);
    }
  dup2(STDIN_FILENO, STDOUT_FILENO);
  fd = -1;
  
  /* Set umask to zero. */
  umask(0);
  
  /* Write PID file. */
  fd = open(pid_pathname, O_WRONLY | O_CREAT | O_TRUNC, 644);
  t (fd < 0);
  sprintf(buf, "%ji\n", (intmax_t)getpid());
  n = strlen(buf) * sizeof(char);
  if (write(fd, buf, n) < (ssize_t)n)
    {
      saved_errno = errno, unlink(pid_pathname), errno = saved_errno;
      goto fail;
    }
  close(fd), fd = -1;
  free(pid_pathname), pid_pathname = NULL;
  
  /* `cd` into root. */
  if (*SYSCONFDIR == '/')
    chdir("/");
  
  /* Execute into daemon. */
  arguments[1] = arguments[0];
  arguments[0] = daemon_name;
  execvp(SYSCONFDIR "/" PKGNAME ".d/daemon-base", arguments);
  
 fail:
  perror(*argv);
  if (fd >= 0)
    close(fd);
  free(pid_pathname);
  return (1);
  
 wait_for_completion:
  pause(), pause(); /* Wait for child and grandchild. */
  /* Exit like the grandchild. */
  child = read_pid(pid_pathname);
  pid = waitpid(child, &r, WNOHANG);
  if (pid == -1)
    goto fail;
  r = pid ? WIFEXITED(r) ? WEXITSTATUS(r) : WTERMSIG(r) : 0;
  free(pid_pathname);
  return (r);
  
#undef t
#undef return
}
Пример #9
0
int main(int argc, char *argv[])
{
	// Handle signals
	signal(SIGINT,shut_down);
	signal(SIGHUP,shut_down);
	signal(SIGTERM,shut_down);
	signal(SIGQUIT,shut_down);

	// HCI device number, MAC struct
	int device = 0;
	bdaddr_t bdaddr;
	bacpy(&bdaddr, BDADDR_ANY);

	// Time to scan. Scan time is roughly 1.28 seconds * scan_window
	// Originally this was always 8, now we adjust based on device:
	#ifdef OPENWRT
	int scan_window = 8;
	#elif PWNPLUG
	int scan_window = 5;
	#else
	int scan_window = 3;
	#endif

	// Maximum number of devices per scan
	int max_results = 255;
	int num_results;

	// Device cache and index
	int cache_index = 0;

	// HCI cache setting
	int flags = IREQ_CACHE_FLUSH;

	// Strings to hold MAC and name
	char addr[19] = {0};
	char addr_buff[19] = {0};

	// String for time
	char cur_time[20];

	// Process ID read from PID file
	int ext_pid;

	// Pointers to filenames
	char *infofilename = LIVE_INF;

	// Change default filename based on date
	char OUT_FILE[1000] = OUT_PATH;
	strncat(OUT_FILE, file_timestamp(),sizeof(OUT_FILE)-strlen(OUT_FILE)-1);
	char *outfilename = OUT_FILE;

	// Mode to open output file in
	char *filemode = "a+";

	// Output buffer
	char outbuffer[500];

	// Buffer for data from the second loop
	char exitbuffer[500];

	// Misc Variables
	int i, ri, opt;

	// Record numbner of BlueZ errors
	int error_count = 0;

	// Current epoch time
	long long int epoch;

	// Kernel version info
	struct utsname sysinfo;
	uname(&sysinfo);

	while ((opt=getopt_long(argc,argv,"+o:i:r:a:w:vxctghldbfenksmq", main_options, NULL)) != EOF)
	{
		switch (opt)
		{
		case 'i':
			if (!strncasecmp(optarg, "hci", 3))
				hci_devba(atoi(optarg + 3), &bdaddr);
			else
				str2ba(optarg, &bdaddr);
			break;
		case 'o':
			outfilename = strdup(optarg);
			break;
		case 'r':
			config.retry_count = atoi(optarg);
			break;
		case 'a':
			config.amnesia = atoi(optarg);
			break;
		case 'w':
			config.scan_window = round((atoi(optarg) / 1.28));
			break;
		case 'c':
			config.showclass = 1;
			break;
		case 'e':
			config.encode = 1;
			break;
		case 'f':
			config.friendlyclass = 1;
			break;
		case 'v':
			config.verbose = 1;
			break;
		case 'g':
			config.status = 1;
			break;
		case 't':
			config.showtime = 1;
			break;
		case 's':
			config.syslogonly = 1;
			break;
		case 'x':
			config.obfuscate = 1;
			break;
		case 'q':
			config.quiet = 1;
			break;
		case 'l':
			if(!LIVEMODE)
			{
				printf("Live mode has been disabled in this build. See documentation.\n");
				exit(0);
			}
			else
				config.bluelive = 1;
			break;
		case 'b':
			config.bluepropro = 1;
			break;
		case 'd':
			config.daemon = 1;
			break;
		case 'n':
			config.getname = 1;
			break;
		case 'm':
			if(!OUILOOKUP)
			{
				printf("Manufacturer lookups have been disabled in this build. See documentation.\n");
				exit(0);
			}
			else
				config.getmanufacturer = 1;
			break;
		case 'h':
			help();
			exit(0);
		case 'k':
			// Read PID from file into variable
			ext_pid = read_pid();
			if (ext_pid != 0)
			{
				printf("Killing Bluelog process with PID %i...",ext_pid);
				if(kill(ext_pid,15) != 0)
				{
					printf("ERROR!\n");
					printf("Unable to kill Bluelog process. Check permissions.\n");
					exit(1);
				}
				else
					printf("OK.\n");

				// Delete PID file
				unlink(PID_FILE);
			}
			else
				printf("No running Bluelog process found.\n");

			exit(0);
		default:
			printf("Unknown option. Use -h for help, or see README.\n");
			exit(1);
		}
	}

	// See if there is already a process running
	if (read_pid() != 0)
	{
		printf("Another instance of Bluelog is already running!\n");
		printf("Use the -k option to kill a running Bluelog process.\n");
		exit(1);
	}

	// Load config from file if no options given on command line
	if(cfg_exists() && argc == 1)
	{
		if (cfg_read() != 0)
		{
			printf("Error opening config file!\n");
			exit(1);
		}
		// Put interface into BT struct
		hci_devba(config.hci_device, &bdaddr);
	}

	// Perform sanity checks on varibles
	cfg_check();

	// Setup libmackerel
	mac_init();

	// Boilerplate
	if (!config.quiet)
	{
		printf("%s (v%s%s) by MS3FGX\n", APPNAME, VERSION, VER_MOD);
		#if defined OPENWRT || PWNPLUG
			printf("----");
		#endif
		printf("---------------------------\n");
	}

	// Show notification we loaded config from file
	if(cfg_exists() && argc == 1 && !config.quiet)
		printf("Config loaded from: %s\n", CFG_FILE);

	// Init Hardware
	ba2str(&bdaddr, config.addr);
	if (!strcmp(config.addr, "00:00:00:00:00:00"))
	{
		if (!config.quiet)
			printf("Autodetecting device...");
		device = hci_get_route(NULL);
		// Put autodetected device MAC into addr
		hci_devba(device, &bdaddr);
		ba2str(&bdaddr, config.addr);
	}
	else
	{
		if (!config.quiet)
			printf("Initializing device...");
		device = hci_devid(config.addr);
	}

	// Open device and catch errors
	config.bt_socket = hci_open_dev(device);
	if (device < 0 || config.bt_socket < 0)
	{
		// Failed to open device, that can't be good
		printf("\n");
		printf("Error initializing Bluetooth device!\n");
		exit(1);
	}

	// If we get here the device should be online.
	if (!config.quiet)
		printf("OK\n");

	// Status message for BPP
	if (!config.quiet)
		if (config.bluepropro)
			printf("Output formatted for BlueProPro.\n"
				   "More Info: www.hackfromacave.com\n");

	// Open socket
	if (config.udponly)
		open_udp_socket();

	// Open output file, unless in networking mode
	if (!config.syslogonly && !config.udponly)
	{
		if (config.bluelive)
		{
			// Change location of output file
			outfilename = LIVE_OUT;
			filemode = "w";
			if (!config.quiet)
				printf("Starting Bluelog Live...\n");
		}
		if (!config.quiet)
			printf("Opening output file: %s...", outfilename);
		if ((outfile = fopen(outfilename, filemode)) == NULL)
		{
			printf("\n");
			printf("Error opening output file!\n");
			exit(1);
		}
		if (!config.quiet)
			printf("OK\n");
	}
	else
		if (!config.quiet)
			printf("Network mode enabled, not creating log file.\n");

	// Open status file
	if (config.bluelive)
	{
		if (!config.quiet)
			printf("Opening info file: %s...", infofilename);
		if ((infofile = fopen(infofilename,"w")) == NULL)
		{
			printf("\n");
			printf("Error opening info file!\n");
			exit(1);
		}
		if (!config.quiet)
			printf("OK\n");
	}

	// Write PID file
	if (!config.daemon)
		write_pid(getpid());

	// Get and print time to console and file
	strcpy(cur_time, get_localtime());

	if (!config.daemon)
		printf("Scan started at [%s] on %s\n", cur_time, config.addr);

	if (config.showtime && (outfile != NULL))
	{
		fprintf(outfile,"[%s] Scan started on %s\n", cur_time, config.addr);
		// Make sure this gets written out
		fflush(outfile);
	}

	// Write info file for Bluelog Live
	if (config.bluelive)
	{
		fprintf(infofile,"<div class=\"sideitem\">%s Version: %s%s</div>\n", APPNAME, VERSION, VER_MOD);
		fprintf(infofile,"<div class=\"sideitem\">Device: %s</div>\n", config.addr);
		fprintf(infofile,"<div class=\"sideitem\">Started: %s</div>\n", cur_time);

		// Think we are done with you now
		fclose(infofile);
	}

	// Log success to this point
	syslog(LOG_INFO,"Init OK!");

	// Daemon switch
	if (config.daemon)
		daemonize();
	else
		if (!config.quiet)
			#if defined PWNPAD
			printf("Close this window to end scan.\n");
			#else
			printf("Hit Ctrl+C to end scan.\n");
			#endif

	// Init result struct
	results = (inquiry_info*)malloc(max_results * sizeof(inquiry_info));

	// Start scan, be careful with this infinite loop...
	for(;;)
	{
		// Flush results buffer
		memset(results, '\0', max_results * sizeof(inquiry_info));

		// Scan and return number of results
		num_results = hci_inquiry(device, scan_window, max_results, NULL, &results, flags);

		// A negative number here means an error during scan
		if(num_results < 0)
		{
			// Increment error count
			error_count++;

			// Ignore occasional errors on Pwn Plug and OpenWRT
			#if !defined PWNPLUG || OPENWRT
			// All other platforms, print error and bail out
			syslog(LOG_ERR,"Received error from BlueZ!");
			printf("Scan failed!\n");
			// Check for kernel 3.0.x
			if (!strncmp("3.0.",sysinfo.release,4))
			{
				printf("\n");
				printf("-----------------------------------------------------\n");
				printf("Device scanning failed, and you are running a 3.0.x\n");
				printf("Linux kernel. This failure is probably due to the\n");
				printf("following kernel bug:\n");
				printf("\n");
				printf("http://marc.info/?l=linux-kernel&m=131629118406044\n");
				printf("\n");
				printf("You will need to upgrade your kernel to at least the\n");
				printf("the 3.1 series to continue.\n");
				printf("-----------------------------------------------------\n");

			}
			shut_down(1);
			#else
			// Exit on back to back errors
			if (error_count > 5)
			{
				printf("Scan failed!\n");
				syslog(LOG_ERR,"BlueZ not responding, unrecoverable!");
				shut_down(1);
			}

			// Otherwise, throttle back a bit, might help
			sleep(1);
			#endif
		}
		else
		{
			// Clear error counter
			error_count = 0;
		}

		// Check if we need to reset device cache
		if ((cache_index + num_results) >= MAX_DEV)
		{
			syslog(LOG_INFO,"Resetting device cache...");
			memset(dev_cache, 0, sizeof(dev_cache));
			cache_index = 0;
		}



		// Loop through results
		for (i = 0; i < num_results; i++)
		{
			// Return current MAC from struct
			ba2str(&(results+i)->bdaddr, addr);

			// Compare to device cache
			for (ri = 0; ri <= cache_index; ri++)
			{
				// Determine if device is already logged
				if (strcmp (addr, dev_cache[ri].priv_addr) == 0)
				{
					// This device has been seen before

					// Increment seen count, update printed time
					dev_cache[ri].seen++;
					strcpy(dev_cache[ri].time, get_localtime());
					dev_cache[ri].missing_count = 0;

					// If we don't have a name, query again
					if ((dev_cache[ri].print == 3) && (dev_cache[ri].seen > config.retry_count))
					{
						syslog(LOG_INFO,"Unable to find name for %s!", addr);
						dev_cache[ri].print = 1;
					}
					else if ((dev_cache[ri].print == 3) && (dev_cache[ri].seen < config.retry_count))
					{
						// Query name
						strcpy(dev_cache[ri].name, namequery(&(results+i)->bdaddr));

						// Did we get one?
						if (strcmp (dev_cache[ri].name, "VOID") != 0)
						{
							syslog(LOG_INFO,"Name retry for %s successful!", addr);
							// Force print
							dev_cache[ri].print = 1;
						}
						else
							syslog(LOG_INFO,"Name retry %i for %s failed!",dev_cache[ri].seen, addr);
					}

					// Amnesia mode
					if (config.amnesia >= 0)
					{
						// Find current epoch time
						epoch = time(NULL);
						if ((epoch - dev_cache[ri].epoch) >= (config.amnesia * 60))
						{
							// Update epoch time
							dev_cache[ri].epoch = epoch;
							// Set device to print
							dev_cache[ri].print = 1;
						}
					}

					// This device is seen before, but has been away
					if (strcmp (dev_cache[ri].status, "gone") == 0)
					{
						dev_cache[ri].print = 1;
						strcpy(dev_cache[ri].status, "returned");
					}

					// Unless we need to get printed, move to next result
					if (dev_cache[ri].print != 1)
						break;
				}
				else if (strcmp (dev_cache[ri].addr, "") == 0)
				{
					// Write new device MAC (visible and internal use)
					strcpy(dev_cache[ri].addr, addr);
					strcpy(dev_cache[ri].priv_addr, addr);

					// Query for name
					if (config.getname)
						strcpy(dev_cache[ri].name, namequery(&(results+i)->bdaddr));
					else
						strcpy(dev_cache[ri].name, "IGNORED");

					// Get time found
					strcpy(dev_cache[ri].time, get_localtime());
					dev_cache[ri].epoch = time(NULL);

					// Class info
					dev_cache[ri].flags = (results+i)->dev_class[2];
					dev_cache[ri].major_class = (results+i)->dev_class[1];
					dev_cache[ri].minor_class = (results+i)->dev_class[0];

					// Init misc variables
					dev_cache[ri].seen = 1;
					dev_cache[ri].missing_count = 0;
					strcpy(dev_cache[ri].status, "new");

					// Increment index
					cache_index++;

					// If we have a device name, get printed
					if (strcmp (dev_cache[ri].name, "VOID") != 0)
						dev_cache[ri].print = 1;
					else
					{
						// Found with no name.
						// Print message to syslog, prevent printing, and move on
						syslog(LOG_INFO,"Device %s discovered with no name, will retry", dev_cache[ri].addr);
						dev_cache[ri].print = 3;
						break;
					}
				}

				// Ready to print?
				if (dev_cache[ri].print == 1)
				{
					// Encode MAC
					if (config.encode || config.obfuscate)
					{
						// Clear buffer
						memset(addr_buff, '\0', sizeof(addr_buff));

						if (config.obfuscate)
							strcpy(addr_buff, mac_obfuscate(dev_cache[ri].priv_addr));

						if (config.encode)
							strcpy(addr_buff, mac_encode(dev_cache[ri].priv_addr));

						// Copy to cache
						strcpy(dev_cache[ri].addr, addr_buff);
					}

					// Print everything to console if verbose is on, optionally friendly class info
					if (config.verbose)
					{
						if (config.friendlyclass)
						{
							printf("[%s] %s,%s,%s,(%s) - %s\n",\
								dev_cache[ri].time, dev_cache[ri].addr,\
								dev_cache[ri].name, device_class(dev_cache[ri].major_class,\
								dev_cache[ri].minor_class), device_capability(dev_cache[ri].flags), dev_cache[ri].status);
						}
						else
						{
							printf("[%s] %s,%s,0x%02x%02x%02x - %s\n",\
								dev_cache[ri].time, dev_cache[ri].addr,\
								dev_cache[ri].name, dev_cache[ri].flags,\
								dev_cache[ri].major_class, dev_cache[ri].minor_class, dev_cache[ri].status);
						}
					}

					if (config.bluelive)
					{
						// Write result with live function
						live_entry(ri);
					}
					else if (config.bluepropro)
					{
						// Set output format for BlueProPro
						fprintf(outfile,"%s", dev_cache[ri].addr);
						fprintf(outfile,",0x%02x%02x%02x", dev_cache[ri].flags,\
						dev_cache[ri].major_class, dev_cache[ri].minor_class);
						fprintf(outfile,",%s\n", dev_cache[ri].name);
					}
					else
					{
						// Flush buffer
						memset(outbuffer, 0, sizeof(outbuffer));

						// Print time first if enabled
						if (config.showtime)
							sprintf(outbuffer,"[%s],", dev_cache[ri].time);

						// Always output MAC
						sprintf(outbuffer+strlen(outbuffer),"%s", dev_cache[ri].addr);

						// Optionally output class
						if (config.showclass)
							sprintf(outbuffer+strlen(outbuffer),",0x%02x%02x%02x", dev_cache[ri].flags,\
							dev_cache[ri].major_class, dev_cache[ri].minor_class);

						// "Friendly" version of class info
						if (config.friendlyclass)
							sprintf(outbuffer+strlen(outbuffer),",%s,(%s)",\
							device_class(dev_cache[ri].major_class, dev_cache[ri].minor_class),\
							device_capability(dev_cache[ri].flags));

						// Get manufacturer
						if (config.getmanufacturer)
							sprintf(outbuffer+strlen(outbuffer),",%s", mac_get_vendor(dev_cache[ri].priv_addr));

						// Append the name
						if (config.getname)
							sprintf(outbuffer+strlen(outbuffer),",%s", dev_cache[ri].name);

						// Append the status
						if (config.status)
							sprintf(outbuffer+strlen(outbuffer)," - %s", dev_cache[ri].status);

						// Send buffer, else file. File needs newline
						if (config.syslogonly)
							syslog(LOG_INFO,"%s", outbuffer);
						else if (config.udponly)
						{
							// Append newline to socket, kind of hacky
							sprintf(outbuffer+strlen(outbuffer),"\n");
							send_udp_msg(outbuffer);
						}
						else
							fprintf(outfile,"%s\n",outbuffer);
					}
					dev_cache[ri].print = 0;
					break;
				}
				// If we make it this far, it means we will check next stored device
			}

			// If there's a file open, write changes
			if (outfile != NULL)
				fflush(outfile);
		}

		// Now check if any devices are missing

		// Loop through the cache
		for (ri = 0; ri < cache_index; ri++)
		{

			for (i = 0; i <= num_results; i++)
			{
				// Return current MAC from struct
				ba2str(&(results+i)->bdaddr, addr);

				// Determine if device still present
				if (strcmp (addr, dev_cache[ri].priv_addr) == 0)
				{

					break;
				}

				// Device not found.
				if (i == num_results)
				{
					// The device is missing but not marked as gone -> it has just disappeared
					if (strcmp(dev_cache[ri].status, "gone") != 0)
					{
						// Devices aren't present every time. Wait a while before marking it gone
						if (dev_cache[ri].missing_count < 10)
						{
							dev_cache[ri].missing_count++;
						}
						else
						// It's really gone :(
						{
							strcpy(dev_cache[ri].status,"gone");

							// Print to console
							if (config.verbose) {
								printf("[%s] %s,%s - %s\n",\
										dev_cache[ri].time, dev_cache[ri].addr,\
										dev_cache[ri].name, dev_cache[ri].status);

							}

							// Flush buffer
							memset(exitbuffer, 0, sizeof(exitbuffer));

							// Print time first if enabled
							if (config.showtime)
								sprintf(exitbuffer,"[%s],", dev_cache[ri].time);

							// Always output MAC
							sprintf(exitbuffer+strlen(exitbuffer),"%s", dev_cache[ri].addr);

							// Append the name
							if (config.getname)
								sprintf(exitbuffer+strlen(exitbuffer),",%s", dev_cache[ri].name);

							// Append the status
							if (config.status)
								sprintf(exitbuffer+strlen(exitbuffer)," - %s", dev_cache[ri].status);

							// Send buffer, else file. File needs newline
							if (config.syslogonly)
								syslog(LOG_INFO,"%s", exitbuffer);
							else if (config.udponly)
							{
								// Append newline to socket, kind of hacky
								sprintf(exitbuffer+strlen(exitbuffer),"\n");
								send_udp_msg(exitbuffer);
							}
							else
								fprintf(outfile,"%s\n",exitbuffer);

							// If there's a file open, write changes
							if (outfile != NULL)
								fflush(outfile);

						}
					}

				}

			}

		}



	}
	// If we get here, shut down
	shut_down(0);
	// STFU
	return (1);
}
Пример #10
0
static void
babysit (int   exit_with_session,
         pid_t child_pid,
         int   read_bus_pid_fd)  /* read pid from here */
{
  int ret;
  int dev_null_fd;
  const char *s;

  verbose ("babysitting, exit_with_session = %d, child_pid = %ld, read_bus_pid_fd = %d\n",
           exit_with_session, (long) child_pid, read_bus_pid_fd);
  
  /* We chdir ("/") since we are persistent and daemon-like, and fork
   * again so dbus-launch can reap the parent.  However, we don't
   * setsid() or close fd 0 because the idea is to remain attached
   * to the tty and the X server in order to kill the message bus
   * when the session ends.
   */

  if (chdir ("/") < 0)
    {
      fprintf (stderr, "Could not change to root directory: %s\n",
               strerror (errno));
      exit (1);
    }

  /* Close stdout/stderr so we don't block an "eval" or otherwise
   * lock up. stdout is still chaining through to dbus-launch
   * and in turn to the parent shell.
   */
  dev_null_fd = open ("/dev/null", O_RDWR);
  if (dev_null_fd >= 0)
    {
      if (!exit_with_session)
        dup2 (dev_null_fd, 0);
      dup2 (dev_null_fd, 1);
      s = getenv ("DBUS_DEBUG_OUTPUT");
      if (s == NULL || *s == '\0')
        dup2 (dev_null_fd, 2);
    }
  else
    {
      fprintf (stderr, "Failed to open /dev/null: %s\n",
               strerror (errno));
      /* continue, why not */
    }
  
  ret = fork ();

  if (ret < 0)
    {
      fprintf (stderr, "fork() failed in babysitter: %s\n",
               strerror (errno));
      exit (1);
    }

  if (ret > 0)
    {
      /* Parent reaps pre-fork part of bus daemon, then exits and is
       * reaped so the babysitter isn't a zombie
       */

      verbose ("=== Babysitter's intermediate parent continues again\n");
      
      if (do_waitpid (child_pid) < 0)
        {
          /* shouldn't happen */
          fprintf (stderr, "Failed waitpid() waiting for bus daemon's parent\n");
          exit (1);
        }

      verbose ("Babysitter's intermediate parent exiting\n");
      
      exit (0);
    }

  /* Child continues */
  verbose ("=== Babysitter process created\n");

  verbose ("Reading PID from bus\n");
      
  switch (read_pid (read_bus_pid_fd, &bus_pid_to_kill))
    {
    case READ_STATUS_OK:
      break;
    case READ_STATUS_EOF:
      fprintf (stderr, "EOF in dbus-launch reading PID from bus daemon\n");
      exit (1);
      break;
    case READ_STATUS_ERROR:
      fprintf (stderr, "Error in dbus-launch reading PID from bus daemon: %s\n",
	       strerror (errno));
      exit (1);
      break;
    }

  verbose ("Got PID %ld from daemon\n",
           (long) bus_pid_to_kill);
  
  if (exit_with_session)
    {
      /* Bus is now started and launcher has needed info;
       * we connect to X display and tty and wait to
       * kill bus if requested.
       */
      
      kill_bus_when_session_ends ();
    }

  verbose ("Babysitter exiting\n");
  
  exit (0);
}
Пример #11
0
static ReadStatus
read_data (DBusBabysitter *sitter,
           int             fd)
{
  int what;
  int got;
  DBusError error = DBUS_ERROR_INIT;
  ReadStatus r;

  r = read_ints (fd, &what, 1, &got, &error);

  switch (r)
    {
    case READ_STATUS_ERROR:
      _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
      dbus_error_free (&error);
      return r;

    case READ_STATUS_EOF:
      return r;

    case READ_STATUS_OK:
      break;
    }
  
  if (got == 1)
    {
      switch (what)
        {
        case CHILD_EXITED:
        case CHILD_FORK_FAILED:
        case CHILD_EXEC_FAILED:
          {
            int arg;
            
            r = read_ints (fd, &arg, 1, &got, &error);

            switch (r)
              {
              case READ_STATUS_ERROR:
                _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
                dbus_error_free (&error);
                return r;
              case READ_STATUS_EOF:
                return r;
              case READ_STATUS_OK:
                break;
              }
            
            if (got == 1)
              {
                if (what == CHILD_EXITED)
                  {
                    /* Do not reset sitter->errnum to 0 here. We get here if
                     * the babysitter reports that the grandchild process has
                     * exited, and there are two ways that can happen:
                     *
                     * 1. grandchild successfully exec()s the desired process,
                     * but then the desired process exits or is terminated
                     * by a signal. The babysitter observes this and reports
                     * CHILD_EXITED.
                     *
                     * 2. grandchild fails to exec() the desired process,
                     * attempts to report the exec() failure (which
                     * we will receive as CHILD_EXEC_FAILED), and then
                     * exits itself (which will prompt the babysitter to
                     * send CHILD_EXITED). We want the CHILD_EXEC_FAILED
                     * to take precedence (and have its errno logged),
                     * which _dbus_babysitter_set_child_exit_error() does.
                     */
                    sitter->have_child_status = TRUE;
                    sitter->status = arg;
                    _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
                                   WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
                                   WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
                  }
                else if (what == CHILD_FORK_FAILED)
                  {
                    sitter->have_fork_errnum = TRUE;
                    sitter->errnum = arg;
                    _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
                  }
                else if (what == CHILD_EXEC_FAILED)
                  {
                    sitter->have_exec_errnum = TRUE;
                    sitter->errnum = arg;
                    _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
                  }
              }
          }
          break;
        case CHILD_PID:
          {
            pid_t pid = -1;

            r = read_pid (fd, &pid, &error);
            
            switch (r)
              {
              case READ_STATUS_ERROR:
                _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
                dbus_error_free (&error);
                return r;
              case READ_STATUS_EOF:
                return r;
              case READ_STATUS_OK:
                break;
              }
            
            sitter->grandchild_pid = pid;
            
            _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
          }
          break;
        default:
          _dbus_warn ("Unknown message received from babysitter process\n");
          break;
        }
    }

  return r;
}
Пример #12
0
int ifplugd_main(int argc UNUSED_PARAM, char **argv)
{
    int iface_status;
    int delay_time;
    const char *iface_status_str;
    struct pollfd netlink_pollfd[1];
    unsigned opts;
#if ENABLE_FEATURE_PIDFILE
    char *pidfile_name;
    pid_t pid_from_pidfile;
#endif

    INIT_G();

    opt_complementary = "t+:u+:d+";
    opts = getopt32(argv, OPTION_STR,
                    &G.iface, &G.script_name, &G.poll_time, &G.delay_up,
                    &G.delay_down, &G.api_mode, &G.extra_arg);
    G.poll_time *= 1000;

    applet_name = xasprintf("ifplugd(%s)", G.iface);

#if ENABLE_FEATURE_PIDFILE
    pidfile_name = xasprintf(_PATH_VARRUN"ifplugd.%s.pid", G.iface);
    pid_from_pidfile = read_pid(pidfile_name);

    if (opts & FLAG_KILL) {
        if (pid_from_pidfile > 0)
            kill(pid_from_pidfile, SIGQUIT);
        return EXIT_SUCCESS;
    }

    if (pid_from_pidfile > 0 && kill(pid_from_pidfile, 0) == 0)
        bb_error_msg_and_die("daemon already running");
#endif

    switch (G.api_mode[0]) {
    case API_AUTO:
        G.detect_link_func = detect_link_auto;
        break;
    case API_ETHTOOL:
        G.detect_link_func = detect_link_ethtool;
        break;
    case API_MII:
        G.detect_link_func = detect_link_mii;
        break;
    case API_PRIVATE:
        G.detect_link_func = detect_link_priv;
        break;
    case API_WLAN:
        G.detect_link_func = detect_link_wlan;
        break;
    case API_IFF:
        G.detect_link_func = detect_link_iff;
        break;
    default:
        bb_error_msg_and_die("unknown API mode '%s'", G.api_mode);
    }

    if (!(opts & FLAG_NO_DAEMON))
        bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);

    xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd);
    if (opts & FLAG_MONITOR) {
        xmove_fd(netlink_open(), netlink_fd);
    }

    write_pidfile(pidfile_name);

    /* this can't be moved before socket creation */
    if (!(opts & FLAG_NO_SYSLOG)) {
        openlog(applet_name, 0, LOG_DAEMON);
        logmode |= LOGMODE_SYSLOG;
    }

    bb_signals(0
               | (1 << SIGINT )
               | (1 << SIGTERM)
               | (1 << SIGQUIT)
               | (1 << SIGHUP ) /* why we ignore it? */
               /* | (1 << SIGCHLD) - run_script does not use it anymore */
               , record_signo);

    bb_error_msg("started: %s", bb_banner);

    if (opts & FLAG_MONITOR) {
        struct ifreq ifrequest;
        set_ifreq_to_ifname(&ifrequest);
        G.iface_exists = (network_ioctl(SIOCGIFINDEX, &ifrequest, NULL) == 0);
    }

    if (G.iface_exists)
        maybe_up_new_iface();

    iface_status = detect_link();
    if (iface_status == IFSTATUS_ERR)
        goto exiting;
    iface_status_str = strstatus(iface_status);

    if (opts & FLAG_MONITOR) {
        bb_error_msg("interface %s",
                     G.iface_exists ? "exists"
                     : "doesn't exist, waiting");
    }
    /* else we assume it always exists, but don't mislead user
     * by potentially lying that it really exists */

    if (G.iface_exists) {
        bb_error_msg("link is %s", iface_status_str);
    }

    if ((!(opts & FLAG_NO_STARTUP)
            && iface_status == IFSTATUS_UP
        )
            || (opts & FLAG_INITIAL_DOWN)
       ) {
        if (run_script(iface_status_str) != 0)
            goto exiting;
    }

    /* Main loop */
    netlink_pollfd[0].fd = netlink_fd;
    netlink_pollfd[0].events = POLLIN;
    delay_time = 0;
    while (1) {
        int iface_status_old;
        int iface_exists_old;

        switch (bb_got_signal) {
        case SIGINT:
        case SIGTERM:
            bb_got_signal = 0;
            goto cleanup;
        case SIGQUIT:
            bb_got_signal = 0;
            goto exiting;
        default:
            bb_got_signal = 0;
            break;
        }

        if (poll(netlink_pollfd,
                 (opts & FLAG_MONITOR) ? 1 : 0,
                 G.poll_time
                ) < 0
           ) {
            if (errno == EINTR)
                continue;
            bb_perror_msg("poll");
            goto exiting;
        }

        iface_status_old = iface_status;
        iface_exists_old = G.iface_exists;

        if ((opts & FLAG_MONITOR)
                && (netlink_pollfd[0].revents & POLLIN)
           ) {
            G.iface_exists = check_existence_through_netlink();
            if (G.iface_exists < 0) /* error */
                goto exiting;
            if (iface_exists_old != G.iface_exists) {
                bb_error_msg("interface %sappeared",
                             G.iface_exists ? "" : "dis");
                if (G.iface_exists)
                    maybe_up_new_iface();
            }
        }

        /* note: if !G.iface_exists, returns DOWN */
        iface_status = detect_link();
        if (iface_status == IFSTATUS_ERR) {
            if (!(opts & FLAG_MONITOR))
                goto exiting;
            iface_status = IFSTATUS_DOWN;
        }
        iface_status_str = strstatus(iface_status);

        if (iface_status_old != iface_status) {
            bb_error_msg("link is %s", iface_status_str);

            if (delay_time) {
                /* link restored its old status before
                 * we run script. don't run the script: */
                delay_time = 0;
            } else {
                delay_time = monotonic_sec();
                if (iface_status == IFSTATUS_UP)
                    delay_time += G.delay_up;
                if (iface_status == IFSTATUS_DOWN)
                    delay_time += G.delay_down;
                if (delay_time == 0)
                    delay_time++;
            }
        }

        if (delay_time && (int)(monotonic_sec() - delay_time) >= 0) {
            delay_time = 0;
            if (run_script(iface_status_str) != 0)
                goto exiting;
        }
    } /* while (1) */

cleanup:
    if (!(opts & FLAG_NO_SHUTDOWN)
            && (iface_status == IFSTATUS_UP
                || (iface_status == IFSTATUS_DOWN && delay_time)
               )
       ) {
        setenv(IFPLUGD_ENV_PREVIOUS, strstatus(iface_status), 1);
        setenv(IFPLUGD_ENV_CURRENT, strstatus(-1), 1);
        run_script("down\0up"); /* reusing string */
    }

exiting:
    remove_pidfile(pidfile_name);
    bb_error_msg_and_die("exiting");
}
Пример #13
0
/*
 * 1) When we enter the daylight saving time, add one hour.
 * 2) When we leave the daylight saving time, subtract one hour.
 * return the flag that if we have added one hour or not.
 */
int adjust_daylight(int done,time_t start_time,time_t end_time,int time_zone)
{
	time_t cur_time;
	int i=0,check_flag=0;
	struct timeval tv;
    struct timezone tz;
    	
	gettimeofday(&tv,&tz);
	cur_time = tv.tv_sec;
	
	/*
	 * Since start_time and end_time are based on time which is not adjusted,
	 * we need to recover cur_time to be an unadjusted one.
	 */
	if(done)
		cur_time -= ONE_HOUR;
	
	
	/* Check if it is in daylight saving time now */  
    if (((start_time <= end_time) && ((cur_time >= start_time) && (cur_time < end_time))) ||
    	((start_time > end_time)  && ((cur_time >= start_time) || (cur_time < end_time))))
    {
    	/* Check if we have not add one hour*/
    	if(!done)
    	{
	        /* Check the timezone */
			for(i=0; i < EXCEPTION_ARRAY_SIZE;i++)
			{
				if(time_zone == timezone_daylight_savings_exception[i])
				{
	                check_flag = 1;
	                break;
	            }
	        }
	        if(check_flag == 0)
	        {
	        	/* Add one hour */
	        	DEBUG_MSG("Add one hour\n");
	    		tv.tv_sec += ONE_HOUR;
		    	settimeofday(&tv, &tz);
		    	
		    	/* Tell web server to get the adjusted time */
		    	kill(read_pid(HTTPD_PID), SIGUSR2);
		    	
		    	/* Record we have added one hour */
		    	done=1;
	    	}
	    }
    } 
    /* It's not in daylight saving time now */
    else
    {
    	/* We have added one hour*/
    	if(done)
    	{
	        /* Check the timezone */
			for(i=0; i < EXCEPTION_ARRAY_SIZE;i++)
			{
				if(time_zone == timezone_daylight_savings_exception[i])
				{
	                check_flag = 1;
	                break;
	            }
	        }
	        if(check_flag == 0)
	        {
	        	/* Subtract one hour */
	        	DEBUG_MSG("Subtract one hour\n");
	    		tv.tv_sec -= ONE_HOUR;
		    	settimeofday(&tv, &tz);
		    	
		    	/* Tell web server to get the adjusted time */
		    	kill(read_pid(HTTPD_PID), SIGUSR2);
		    	
		    	/* Record we have not add one hour */
		    	done=0;
	    	}
	    }
    }
   	return done;
}
Пример #14
0
int main(int argc, char *argv[])
{
	int count = argc;
	const char *file;
    file = _PATH_UTMP;
	list = (char**)malloc(SIZE*sizeof(char*));
	for(i = 0;i<SIZE;i++)
	{
		list[i] = (char*)malloc(SIZE*sizeof(char));
	}
	pid_list = (char**)malloc(SIZE*sizeof(char*));
	for(i = 0;i<SIZE;i++)
	{
		pid_list[i] = (char*)malloc(SIZE*sizeof(char));
	}
	buff = (char*)malloc(SIZE*sizeof(char));
    name = (char*)malloc(SIZE*sizeof(char));
    temp = (char*)malloc(SIZE*sizeof(char));
    ptrmsg_copy = (char*)malloc(SIZE*sizeof(char));
    sender_pid = (char*)malloc(SIZE*sizeof(char));
    bzero(sender_pid,SIZE);
	// now set up the ipc for communication
	if ((msgid = msgget(msgkey, msgflg )) < 0) 
	{
        perror("msgget");
        exit(EXIT_FAILURE);
    }
    if ((sem1 = semget(sem1key,1, msgflg )) < 0) 
    {
        perror("semget");
        exit(EXIT_FAILURE);
    }
    if ((semctl(sem1, 0, SETVAL, 1)) < 0) 
    {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
    if ((sem2 = semget(sem2key,1, msgflg )) < 0) 
    {
        perror("semget");
        exit(EXIT_FAILURE);
    }
    if ((semctl(sem2, 0, SETVAL, 0)) < 0) 
    {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
    if ((shm1 = shmget(shm1key,500, msgflg )) < 0) 
    {
        perror("shmget");
        exit(EXIT_FAILURE);
    }
    if ((shm2 = shmget(shm2key,5000, msgflg )) < 0) 
    {
        perror("shmget");
        exit(EXIT_FAILURE);
    }
    ptrpid=shmat(shm1,NULL,0);
    ptrmsg=shmat(shm2,NULL,0);
    bzero(ptrpid,500);
    bzero(ptrmsg,5000);
    printf("--- Initialization complete\n");
    // done 
    // then read all names 
    j = 0;
	while(argc>1)
	{
		strcpy(list[j],argv[--argc]);
		j++;
	}
	listsize = j;

	// open a file in excl to ensure that only one server is running
	fp = fopen("ser.txt","wx");
	if(fp == NULL)
	{
		perror("server already running");
		exit(EXIT_FAILURE);
	}
	bzero(buff,SIZE);
	sprintf(buff,"%d",getpid());
	fwrite(buff,SIZE,1,fp);

	// here comes the UTMP part
	// we need to open the file in the linux for the various terminals opened 
	if ((fputmp = fopen(file, "r")) == NULL)
    {
    	err(1, "%s", file);
    }
    while (fread(&u, sizeof(u), 1, fputmp) == 1)
	{
		if (u.ut_name != NULL) 
		{
			if(getpwnam(u.ut_name) != NULL) // means the file is not arbit 
			{
				// printf("%s\n",u.ut_line );
				for(i = 0;i<listsize;i++)
				{
					if(((strcmp(u.ut_name,list[i])) == 0) && (count > 1) && ((strcmp(u.ut_line,":0")) != 0)) 
						// means it points to real user who should be in conference
					{
						// so we need to send the commencement notification to the corresponding user
						printf("--Sending commence notification to %s\n",u.ut_line );
						sprintf(name, "./commence > /dev/%s", u.ut_line);
						system(name);
						count--;
						break;
					}
				}
			}
		}
	}
	// from here the infinite loop begins to broadcast the message to all 
	// it waits until the value of the sem2 = 2 which indicates client has written the message
	while(1)
	{
		wait_for(sem2,2);
		// now read message
		strcpy(ptrmsg_copy,ptrmsg);
		printf("%s\n",ptrmsg_copy );
		setvalue(sem2,0);
		// case 1 if the message is '.' then we need to simply ignore it
		if((strcmp(ptrmsg_copy,".")) == 0)
		{

		} 
		// case 2 if the message is '*' then we need to terminate server as there is no client 
		else if((strcmp(ptrmsg_copy,"*")) == 0)
		{
			terminate();
		}
		// case 3 now we need to broadcast the message to all the clients available except 
		// the one who send the message
		else
		{
			down(sem1);
			read_pid();
			up(sem1);
			strcpy(msg_send.mtext,ptrmsg_copy);
			int l = strlen(ptrmsg_copy)+1;
			k = 0,j = 0;
			while(ptrmsg_copy[j] != '/')
			{
				j++;
			}
			j++;
			while(ptrmsg_copy[j] != ':')
			{
				sender_pid[k] = ptrmsg_copy[j];
				j++;
				k++;
			}
			sender_pid[k] = '\0';
			for(i = 0;i<pid_list_size;i++)
			{
				if((strcmp(pid_list[i],sender_pid)) != 0)
				{
					// then send message as it is different user 
					sscanf(pid_list[i],"%d",&send_pid);
					printf("%d  %d  %d\n%s\n", msgid,l,send_pid,msg_send.mtext);
					msg_send.mtype = (long)send_pid;
					if(msgsnd(msgid,&msg_send,l,0)==-1) 		//User to Kernel memory space 
					{
						printf("error in msg_send\n");
						exit(1);
					}
					else
					{
						printf("sending message to %d\n",send_pid );
					}
				}
			}
		}
	}
	// deleting all the ipc
	
	return 0;
}