示例#1
0
文件: unix.c 项目: NTmatter/Netatalk
/*!
 * Daemonize
 *
 * Fork, exit parent, setsid(), optionally chdir("/"), optionally close all fds
 *
 * returns -1 on failure, but you can't do much except exit in that case
 * since we may already have forked
 */
int daemonize(int nochdir, int noclose)
{
    switch (fork()) {
    case 0:
        break;
    case -1:
        return -1;
    default:
        _exit(0);
    }

    if (setsid() < 0)
        return -1;

    switch (fork()) {
    case 0: 
        break;
    case -1:
        return -1;
    default:
        _exit(0);
    }

    if (!nochdir)
        chdir("/");

    if (!noclose) {
        closeall(0);
        open("/dev/null",O_RDWR);
        dup(0);
        dup(0);
    }

    return 0;
}
示例#2
0
文件: tunemu.c 项目: HannesHofer/hans
static int ppp_load_kext(void)
{
    int pid = fork();
    if (pid < 0)
    {
        tun_error("fork for ppp kext: %s", strerror(errno));
        return -1;
    }

    if (pid == 0)
    {
        closeall();
        execle("/sbin/kextload", "kextload", PPP_KEXT_PATH, NULL, NULL);
        exit(1);
    }

    int status;
    while (waitpid(pid, &status, 0) < 0)
    {
        if (errno == EINTR)
            continue;

        tun_error("waitpid for ppp kext: %s", strerror(errno));
        return -1;
    }

    if (WEXITSTATUS(status) != 0)
    {
        tun_error("could not load ppp kext \"%s\"", PPP_KEXT_PATH);
        return -1;
    }

    tun_noerror();
    return 0;
}
示例#3
0
main()
{
	register got;
	request(KBD|MOUSE|RCV|SEND);
	newlnsz=defont.height;
	init();
	strzero(&snarfbuf);
	waitunix(&diagdone);	/* when menu is loaded */
	for(got=0; ; got=wait(MOUSE|KBD|RCV)){
		if(P->state&RESHAPED){
			rectf(&display, Drect, F_CLR);
			closeall();
			init();
			P->state&=~RESHAPED;
		}
		/* NOTE: cursor is OFF at all times... */
		if((got&RCV) && rcv()){
			curse(current->frame);
			(void)message();
			curse(current->frame);
		}
		if((got&MOUSE) && bttn123() && ptinrect(mouse.xy, display.rect)){
			curse(current->frame);
			buttonhit(mouse.xy, mouse.buttons);
			curse(current->frame);
		}
		if((got&KBD) && current)	/* ...except in type */
			type(current);	/* manages cursor itself */
	}
}
示例#4
0
文件: boot.c 项目: andreiw/polaris
/*ARGSUSED*/
int
bootprog(char *bpath, char *bargs, boolean_t user_specified_filename)
{
	boolean_t	once = B_FALSE;

	systype = set_fstype(v2path, bpath);

loop:
	/*
	 * Beware: the following code may be executed twice, with different
	 * bpath's if we discover a redirection file.
	 */

	if (verbosemode) {
		printf("device path '%s'\n", bpath);
		if (strcmp(bpath, v2path) != 0)
			printf("client path '%s'\n", v2path);
	}

	if (mountroot(bpath) != SUCCESS)
		prom_panic("Could not mount filesystem.");

	/*
	 * kernname (default-name) might have changed if mountroot() called
	 * boot_nfs_mountroot(), and it called set_default_filename().
	 */
	if (!user_specified_filename)
		(void) strcpy(filename, kernname);

	if (verbosemode)
		printf("standalone = `%s', args = `%s'\n", filename, bargs);

	set_client_bootargs(filename, bargs);

	if (!once &&
	    (strcmp(systype, "ufs") == 0 || strcmp(systype, "hsfs") == 0)) {
		char redirect[OBP_MAXPATHLEN];

		post_mountroot(filename, redirect);

		/*
		 * If we return at all, it's because we discovered
		 * a redirection file - the 'redirect' string now contains
		 * the name of the disk slice we should be looking at.
		 *
		 * Unmount the filesystem, tweak the boot path and retry
		 * the whole operation one more time.
		 */
		closeall(1);
		once = B_TRUE;
		redirect_boot_path(bpath, redirect);
		if (verbosemode)
			printf("%sboot: using '%s'\n", systype, bpath);

		goto loop;
		/*NOTREACHED*/
	}

	return (0);
}
示例#5
0
文件: notify.c 项目: Sir168/dsnat
/* Execute external script/program */
int
notify_exec(char *cmd)
{
	pid_t pid;
	int ret;

	pid = fork();

	/* In case of fork is error. */
	if (pid < 0) {
		log_message(LOG_INFO, "Failed fork process");
		return -1;
	}

	/* In case of this is parent process */
	if (pid)
		return 0;

	signal_handler_destroy();
	closeall(0);

	open("/dev/null", O_RDWR);
	ret = dup(0);
	ret = dup(0);

	system_call(cmd);

	exit(0);
}
示例#6
0
void run(Node *a)	/* execution of parse tree starts here */
{
	extern void stdinit(void);

	stdinit();
	execute(a);
	closeall();
}
示例#7
0
static int
elf_exec(struct loaded_module *mp)
{
    static struct bootinfo_v1	bootinfo_v1;
    struct module_metadata	*md;
    Elf_Ehdr			*hdr;
    int				err;
    int				flen;

    if ((md = mod_findmetadata(mp, MODINFOMD_ELFHDR)) == NULL)
	return(EFTYPE);			/* XXX actually EFUCKUP */
    hdr = (Elf_Ehdr *)&(md->md_data);

    /* XXX ffp_save does not appear to be used in the kernel.. */
    bzero(&bootinfo_v1, sizeof(bootinfo_v1));
    err = bi_load(&bootinfo_v1, &ffp_save, mp);
    if (err)
	return(err);

    /*
     * Fill in the bootinfo for the kernel.
     */
    strncpy(bootinfo_v1.booted_kernel, mp->m_name,
	    sizeof(bootinfo_v1.booted_kernel));
    flen = prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo_v1.boot_flags,
		sizeof(bootinfo_v1.boot_flags));
    bootinfo_v1.hwrpb = (void *)HWRPB_ADDR;
    bootinfo_v1.hwrpbsize = ((struct rpb *)HWRPB_ADDR)->rpb_size;
    bootinfo_v1.cngetc = NULL;
    bootinfo_v1.cnputc = NULL;
    bootinfo_v1.cnpollc = NULL;

    /*
     * Append the boot command flags.
     */
    if (mp->m_args != NULL && *mp->m_args != '\0') {
	const char *p = mp->m_args;

	do {
	    if (*p == '-') {
		while (*++p != ' ' && *p != '\0')
		    if (flen < sizeof(bootinfo_v1.boot_flags) - 1)
			bootinfo_v1.boot_flags[flen++] = *p;
	    } else
		while (*p != ' ' && *p != '\0')
		    p++;
	    while (*p == ' ')
		p++;
	} while (*p != '\0');
	bootinfo_v1.boot_flags[flen] = '\0';
    }

    printf("Entering %s at 0x%lx...\n", mp->m_name, hdr->e_entry);
    closeall();
    alpha_pal_imb();
    (*(void (*)())hdr->e_entry)(ffp_save, ptbr_save,
			       BOOTINFO_MAGIC, &bootinfo_v1, 1, 0);
}
示例#8
0
文件: popen2.c 项目: IFCA/slurm
/**
 * popen2  -  Open a bidirectional pipe to a process
 * @path:	full path of executable to run
 * @to_child:	return file descriptor for child stdin
 * @from_child:	return file descriptor for child stdout
 *
 * Return -1 on error, pid of child process on success.
 */
pid_t popen2(const char *path, int *to_child, int *from_child, bool no_stderr)
{
	int child_in[2], child_out[2];
	pid_t pid;

	if (access(path, X_OK) < 0)
		return -1;

	if (pipe(child_in) < 0 || pipe(child_out) < 0)
		return -1;

	pid = fork();
	if (pid < 0)
		return -1;

	if (pid == 0) {
		/*
		 * child
		 */
		close(child_in[1]);
		close(child_out[0]);

		/*
		 * Rationale: by making sure that fd > 2, dup(fd) <= 2,
		 * a new copy is created, allowing to close the pipe end,
		 * and with FD_CLOEXEC to off (on linux).
		 */
		if (fd_no_clobber_stdio(&child_in[0]) < 0		||
		    dup2(child_in[0], STDIN_FILENO) != STDIN_FILENO	||
		    close(child_in[0]) < 0)
			_exit(127);

		if (fd_no_clobber_stdio(&child_out[1]) < 0		||
		    dup2(child_out[1], STDOUT_FILENO) != STDOUT_FILENO	||
		    close(child_out[1]) < 0)
			_exit(127);

		if (no_stderr && dup_devnull(STDERR_FILENO) < 0)
			_exit(127);

		closeall(STDERR_FILENO + 1);

		if (execl(path, path, NULL) < 0)
			_exit(1);
	}

	/*
	 * parent
	 */
	close(child_in[0]);
	close(child_out[1]);

	*to_child   = child_in[1];
	*from_child = child_out[0];

	return pid;
}
示例#9
0
static void
mydaemon(int nochdir, int noclose)
{
	int pid, status, tempfd;

	if (pipe(pipefds) < 0) {
		printerr(1, "mydaemon: pipe() failed: errno %d (%s)\n",
			errno, strerror(errno));
		exit(1);
	}
	if ((pid = fork ()) < 0) {
		printerr(1, "mydaemon: fork() failed: errno %d (%s)\n",
			errno, strerror(errno));
		exit(1);
	}

	if (pid != 0) {
		/*
		 * Parent. Wait for status from child.
		 */
		close(pipefds[1]);
		if (read(pipefds[0], &status, 1) != 1)
			exit(1);
		exit (0);
	}
	/* Child.	*/
	close(pipefds[0]);
	setsid ();
	if (nochdir == 0) {
		if (chdir ("/") == -1) {
			printerr(1, "mydaemon: chdir() failed: errno %d (%s)\n",
				errno, strerror(errno));
			exit(1);
		}
	}

	while (pipefds[1] <= 2) {
		pipefds[1] = dup(pipefds[1]);
		if (pipefds[1] < 0) {
			printerr(1, "mydaemon: dup() failed: errno %d (%s)\n",
				errno, strerror(errno));
			exit(1);
		}
	}

	if (noclose == 0) {
		tempfd = open("/dev/null", O_RDWR);
		dup2(tempfd, 0);
		dup2(tempfd, 1);
		dup2(tempfd, 2);
		closeall(3);
	}

	return;
}
示例#10
0
文件: main.c 项目: sunank200/ATOM-OS
int main(int argc, char  **argv)
{
	char s[10000];
	int k,sum=0;
	int fd0;
	FILE *fd1;

	initialize();

	if (argc < 3)
	{
		printf("Usage:\n\ncpfile -o fimage-source host-target\ncpfile host-source fimage-target\n");
		exit(0);
	}
	if (strcmp(argv[1], "-o") == 0)
	{
		fd0 = syscall_open(argv[2],O_RDONLY,0);
		fd1 = fopen(argv[3],"wb");

		if (fd0 < 0 || fd1 < 0)
		{
			printf("Error opening input/output files\n");
			exit(0);
		}
		while ((k=syscall_read(fd0, s, 10000))>0)
		{
			fwrite(s,k,1,fd1);
			sum += k;
		}
		syscall_close(fd0);
		fclose(fd1);
	}
	else
	{
		fd0 = syscall_open(argv[2],O_WRONLY,0);
		fd1 = fopen(argv[1],"rb");
		if (fd0 < 0 || fd1 < 0)
		{
			printf("Error opening input/output files\n");
			exit(0);
		}
		
		while ((k=fread(s, 1, 10000, fd1))>0)
		{
			syscall_write(fd0,s,k);
			sum += k;
		}
		syscall_close(fd0);
		fclose(fd1);
	}
	closeall();
	//printf("Image copied\n");
	return 0;
}
示例#11
0
文件: daemonize.c 项目: IFCA/slurm
/* detach and go into background.
 * caller is responsible for umasks
 *
 * if nochdir == 0, will do a chdir to /
 * if noclose == 0, will close all FDs
 */
int
daemon(int nochdir, int noclose)
{
	switch (fork()) {
		case  0 : break;        /* child */
		case -1 : return -1;
		default : _exit(0);     /* exit parent */
	}

	if (setsid() < 0)
		return -1;

	switch (fork()) {
		case 0 : break;         /* child */
		case -1: return -1;
		default: _exit(0);      /* exit parent */
	}

	if (!nochdir && chdir("/") < 0) {
		error("chdir(/): %m");
		return -1;
	}

	/* Close all file descriptors if requested
	 */
	if (!noclose) {
		closeall(0);
		if (open("/dev/null", O_RDWR) != 0)
			error("Unable to open /dev/null on stdin: %m");
		dup2(0, STDOUT_FILENO);
		dup2(0, STDERR_FILENO);
	} else {
		/*
		 * Otherwise, dup stdin, stdout, and stderr onto /dev/null
		 */
		int devnull = open("/dev/null", O_RDWR);
		if (devnull < 0)
			error("Unable to open /dev/null: %m");
		if (dup2(devnull, STDIN_FILENO) < 0)
			error("Unable to dup /dev/null onto stdin: %m");
		if (dup2(devnull, STDOUT_FILENO) < 0)
			error("Unable to dup /dev/null onto stdout: %m");
		if (dup2(devnull, STDERR_FILENO) < 0)
			error("Unable to dup /dev/null onto stderr: %m");
		if (close(devnull) < 0)
			error("Unable to close /dev/null: %m");
	}

	return 0;

}
示例#12
0
void CleanUpMex(void)
{
    if(closeall()) /* close all still open connections...*/
    {
	/* ....if not all alread closed put out a matlab warning*/
        /* should an breaking error message be better ??? */
	mexWarnMsgTxt("Unloading mex file!\n"
		      "Unclosed tcpip connections will be lost!!!!\n");
    }
#ifdef WIN32
  WSACleanup();
#else
  signal(SIGPIPE,SIG_DFL);  /*reset SIGPIPE to default. Is this good ??? */
#endif
}
示例#13
0
/* believed to work on all Posix systems */
static pid_t init_daemon (fd_set keepfds) 
{
	pid_t pid;
	switch ((pid = fork ())) {
		case 0:  break;
		case -1: return -1;
		default: _exit (0);	/* exit the original process */
	}

	closeall (keepfds);

	if (setsid () < 0)		/* shoudn't fail */
		return -1;

	return pid;
}
示例#14
0
文件: unix.c 项目: NTmatter/Netatalk
/*!
 * Run command in a child and wait for it to finish
 */
int run_cmd(const char *cmd, char **cmd_argv)
{
    EC_INIT;
    pid_t pid, wpid;
    sigset_t sigs, oldsigs;
	int status = 0;

    sigfillset(&sigs);
    pthread_sigmask(SIG_SETMASK, &sigs, &oldsigs);

    if ((pid = fork()) < 0) {
        LOG(log_error, logtype_default, "run_cmd: fork: %s", strerror(errno));
        return -1;
    }

    if (pid == 0) {
        /* child */
        closeall(3);
        execvp("mv", cmd_argv);
    }

    /* parent */
	while ((wpid = waitpid(pid, &status, 0)) < 0) {
	    if (errno == EINTR)
            continue;
	    break;
	}
	if (wpid != pid) {
	    LOG(log_error, logtype_default, "waitpid(%d): %s", (int)pid, strerror(errno));
        EC_FAIL;
	}

    if (WIFEXITED(status))
        status = WEXITSTATUS(status);
    else if (WIFSIGNALED(status))
        status = WTERMSIG(status);

    LOG(log_note, logtype_default, "run_cmd(\"%s\"): status: %d", cmd, status);

EC_CLEANUP:
    if (status != 0)
        ret = status;
    pthread_sigmask(SIG_SETMASK, &oldsigs, NULL);
    EC_EXIT;
}
示例#15
0
文件: exit.c 项目: SylvestreG/bitrig
__dead void
panic(const char *fmt, ...)
{
	extern void closeall(void);
	va_list ap;
	static int paniced;

	if (!paniced) {
		paniced = 1;
		closeall();
	}

	va_start(ap, fmt);
	vprintf(fmt, ap);
	printf("\n");
	va_end(ap);
	_rtt();
	/*NOTREACHED*/
}
示例#16
0
/* -----------------------------------------------------------------------------
    load_kext
----------------------------------------------------------------------------- */
static u_long load_kext(char *kext)
{
    int pid;

    if ((pid = fork()) < 0)
        return 1;

    if (pid == 0) {
        closeall();
        // PPP kernel extension not loaded, try load it...
        execl("/sbin/kextload", "kextload", kext, (char *)0);
        exit(1);
    }

    while (waitpid(pid, 0, 0) < 0) {
        if (errno == EINTR)
            continue;
       return 1;
    }
    return 0;
}
示例#17
0
int daemon(int nochdir, int noclose, int asroot)
{
	switch (fork())
	{
		case 0:  break;
		case -1: return -1;
		default: _exit(0);          /* exit the original process */
	}

	if (setsid() < 0)               /* shoudn't fail */
		return -1;

	if ( !asroot && (setuid(1) < 0) )              /* shoudn't fail */
		return -1;

	/* dyke out this switch if you want to acquire a control tty in */
	/* the future -- not normally advisable for daemons */

	switch (fork())
	{
		case 0:  break;
		case -1: return -1;
		default: _exit(0);
	}

	if (!nochdir)
		chdir("/");

	if (!noclose)
	{
		closeall(0);
		dup(0); dup(0);
	}

	return 0;
}
示例#18
0
文件: bas1.c 项目: LGTMCU/f32c
int
main(int argc, char **argv)
{
	int i = 0;
	int fp;

#ifdef f32c
	setup_f32c();
	maxfiles = MAXFILES;
#else
	catchsignal();
#endif
	startfp();              /* start up the floating point hardware */

	setup_fb();		/* video framebuffer */
#ifndef f32c
	setupfiles(argc,argv);
	setupmyterm();		/* set up files after processing files */
#endif
	program = 0;
	clear();
	prints("Rabbit BASIC version 2.1.3 (built " __DATE__ ")\n");
	if(setexit() == ERR_RESET){
		drop_fns();
		execute();	/* execute the line */
	}
	drop_fns();
	docont();
	stocurlin=0;            /* say we are in immeadiate mode */
	if(cursor)              /* put cursor on a blank line */
		prints( (char *)nl);
	
	if (firstrun && (
#ifdef f32c
	    (fp = open("d:autoexec.bas",0)) > 0 ||
#endif
	    (fp = open("autoexec.bas",0)) > 0)) {
		firstrun = 0;
		readfi(fp, 0, 0);
		close(fp);
        	clear();
        	if (program) {
        		stocurlin=program;
        		point= program->lin;
        		elsecount=0;
        		execute();
		}
	}
	firstrun = 0;

	prints("Ready\n");

	for(;;){
		do{
			trapped=0;
			line[0] = '>';
			line[1] = 0;
			VOID edit( (ival)1, (ival)1, (ival)0);
		}while( trapped || ( !(i=compile(1, nline, 0)) && !linenumber));
		if(!linenumber)
			break;
		insert(i);
	}
	if(inserted){
		inserted=0;
		clear();
		closeall();
	}

#ifdef MSDOS
	lcount = 0;
#endif
	clr_stack(bstack);	/* reset the gosub stack */
	bstack = estack = 0;
	if(str_used)		/* free any spare strings */
		FREE_STR(str_used);

	trap_env.e_stolin = 0;	/* disable error traps */
	intrap=0;               /* say we are not in the error trap */
	trapped=0;              /* say we haven't got a cntrl-c */
	cursor=0;               /* cursor is at start of line */
	elsecount=0;            /* disallow elses as terminators */
	point=nline;            /* start executing at start of input line */
	stocurlin=0;            /* start of current line is null- see 'next' */
	execute();              /* execute the line */
	return(-1);             /* see note below */
}
示例#19
0
int
main(int argc, char *argv[])
{
    ni_status status;
    ni_name myname = argv[0];
    int create = 0;
    int log_pri = LOG_NOTICE;
    ni_name dbsource_name = NULL;
    ni_name dbsource_addr = NULL;
    ni_name dbsource_tag = NULL;
    struct rlimit rlim;
    char *str;
    unsigned db_checksum;
    FILE *logf;
    int nctoken;

    logf = NULL;
    forcedIsRoot = 0;

    Argv = argv;	/* Save program and argument information for setproctitle */
    Argc = argc;

    argc--;
    argv++;
    while (argc > 0 && **argv == '-')
    {
        if (strcmp(*argv, "-d") == 0)
        {
            debug = 1;
            log_pri = LOG_DEBUG;
            if (argc < 2) logf = stderr;
            else
            {
                debug = atoi(argv[1]);
                argc -= 1;
                argv += 1;
            }
        }
        else if (strcmp(*argv, "-l") == 0)
        {
            if (argc < 2) usage(myname);
            else
            {
                log_pri = atoi(argv[1]);
                argc -= 1;
                argv += 1;
            }
        }
        else if (strcmp(*argv, "-n") == 0) forcedIsRoot = 1;
        else if (strcmp(*argv, "-s") == 0) standalone = 1;
        else if (strcmp(*argv, "-m") == 0) create++;
        else if (strcmp(*argv, "-c") == 0)
        {
            if (argc < 4) usage(myname);

            create++;
            dbsource_name = argv[1];
            dbsource_addr = argv[2];
            dbsource_tag = argv[3];
            argc -= 3;
            argv += 3;
        }
        else usage(myname);

        argc--;
        argv++;
    }

    if (argc != 1) usage(myname);

    if (debug == 0)
    {
        closeall();
        if (standalone == 1) daemon(1, 1);
    }

    db_tag = malloc(strlen(argv[0]) + 1);
    strcpy(db_tag, argv[0]);

    str = malloc(strlen("netinfod ") + strlen(db_tag) + 1);
    sprintf(str, "netinfod %s", db_tag);
    system_log_open(str, (LOG_NDELAY | LOG_PID), LOG_NETINFO, logf);
    free(str);
    system_log_set_max_priority(log_pri);

    system_log(LOG_DEBUG, "version %s (pid %d) - starting",
               _PROJECT_VERSION_, getpid());

    rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
    setrlimit(RLIMIT_CORE, &rlim);

    rlim.rlim_cur = rlim.rlim_max = FD_SETSIZE;
    setrlimit(RLIMIT_NOFILE, &rlim);

    umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);

    srandom(gethostid() ^ time(NULL));

    readall_syslock = syslock_new(0);
    lockup_syslock= syslock_new(0);
    cleanupwait = CLEANUPWAIT;
    auth_count[GOOD] = 0;
    auth_count[BAD] = 0;
    auth_count[WGOOD] = 0;
    auth_count[WBAD] = 0;

    if (create)
    {
        if (dbsource_addr == NULL)
        {
            system_log(LOG_DEBUG, "creating master");
            status = dir_mastercreate(db_tag);
        }
        else
        {
            system_log(LOG_DEBUG, "creating clone");
            status = dir_clonecreate(db_tag, dbsource_name,
                                     dbsource_addr, dbsource_tag);
        }

        if (status != NI_OK)
        {
            system_log_close();
            exit(status);
        }
    }

    nctoken = -1;
    notify_register_signal(NETWORK_CHANGE_NOTIFICATION, SIGHUP, &nctoken);

    if (standalone == 0) signal(SIGTERM, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGHUP, (void *)catch_sighup);
    signal(SIGCHLD, (void *)readall_catcher);
    if (debug == 0)
    {
        signal(SIGINT, (void *)dblock_catcher);
        if (standalone == 0)
        {
            if (setsid() < 0) syslog(LOG_WARNING, "setsid failed: %m");
        }
    }

    writepid(db_tag);

    status = start_service(db_tag);
    if (status != NI_OK)
    {
        system_log(LOG_ERR, "start_service failed: %s - exiting", ni_error(status));
        system_log_close();
        exit(status);
    }

    setproctitle("netinfod %s (%s)", db_tag, i_am_clone ? "clone" : "master");

    if (i_am_clone)
    {
        system_log(LOG_DEBUG, "checking clone");
        cloneReadallResponseOK = get_clone_readall(db_ni);
        dir_clonecheck();
        if (get_sanitycheck(db_ni)) sanitycheck(db_tag);
        system_log(LOG_DEBUG, "finished clone check");
    }
    else
    {
        system_log(LOG_DEBUG, "setting up master server");
        promote_admins = get_promote_admins(db_ni);
        get_readall_info(db_ni, &max_readall_proxies, &strict_proxies);
        max_subthreads = get_max_subthreads(db_ni);
        update_latency_secs = get_update_latency(db_ni);

        /* Tracking readall proxy pids uses ObjC, so isolate it */
        initialize_readall_proxies(-1 == max_readall_proxies ?
                                   MAX_READALL_PROXIES : max_readall_proxies);

        system_log(LOG_DEBUG, "starting notify thread");
        (void) notify_start();
    }

    /* Shutdown gracefully after this point */
    if (standalone == 1) signal(SIGTERM, (void *)sig_shutdown);
    signal(SIGUSR1, (void *)sig_shutdown);

    system_log(LOG_DEBUG, "starting RPC service");

    ni_svc_run(_rpc_dtablesize() - (FD_SLOPSIZE + max_subthreads));

    system_log(LOG_DEBUG, "shutting down");

    /*
     * Tell the readall proxies to shut down
     */
    if (readall_proxies > 0)
    {
        system_log(LOG_INFO, "killing %d readall prox%s", readall_proxies,
                   1 == readall_proxies ? "y" : "ies");
        if (!kill_proxies())
            system_log(LOG_WARNING, "some readall proxies still running");
    }

    db_checksum = ni_getchecksum(db_ni);
    ni_shutdown(db_ni, db_checksum);
    system_log(LOG_INFO, "exiting; checksum %u", db_checksum);
    system_log_close();
    exit(0);
}
示例#20
0
文件: bios.c 项目: jhallen/cpm
void
warmboot(z80info *z80)
{
	int i;

	closeall(z80);

	if (silent_exit) {
		finish(z80);
	}

	/* load CCP and BDOS into memory (max 0x1600 in size) */
	for (i = 0; i < 0x1600 && i < sizeof cpm_array; i++)
		SETMEM(CCP + i, cpm_array[i]);

	/* try to load CCP/BDOS from disk, but ignore any errors */
	loadfile(z80, "bdos.hex");
	loadfile(z80, "ccp.hex");

	/* CP/M system reset via "JP 00" - entry into BIOS warm-boot */
	SETMEM(0x0000, 0xC3);		/* JP CBIOS+3 */
	SETMEM(0x0001, ((CBIOS + 3) & 0xFF));
	SETMEM(0x0002, ((CBIOS + 3) >> 8));

	/* 0x0003 is the IOBYTE, 0x0004 is the current DISK */
	SETMEM(0x0003, 0x00);
	SETMEM(0x0004, z80->drive);

	/* CP/M syscall via "CALL 05" - entry into BDOS */
	SETMEM(0x0005, 0xC3);		/* JP BDOS+6 */
	SETMEM(0x0006, ((BDOS+6) & 0xFF));
	SETMEM(0x0007, ((BDOS+6) >> 8));

	/* fake BIOS entry points */
	for (i = 0; i < NENTRY; i++)
	{
		/* JP <bios-entry> */
		SETMEM(CBIOS + 3 * i, 0xC3);
		SETMEM(CBIOS + 3 * i + 1, (CBIOS + NENTRY * 3 + i * 5) & 0xFF);
		SETMEM(CBIOS + 3 * i + 2, (CBIOS + NENTRY * 3 + i * 5) >> 8);

		/* LD A,<bios-call> - start of bios-entry */
		SETMEM(CBIOS + NENTRY * 3 + i * 5, 0x3E);
		SETMEM(CBIOS + NENTRY * 3 + i * 5 + 1, i);

		/* OUT A,0FFH - we use port 0xFF to fake the BIOS call */
		SETMEM(CBIOS + NENTRY * 3 + i * 5 + 2, 0xD3);
		SETMEM(CBIOS + NENTRY * 3 + i * 5 + 3, 0xFF);

		/* RET - end of bios-entry */
		SETMEM(CBIOS + NENTRY * 3 + i * 5 + 4, 0xC9);
	}

	/* disc parameter block - a 5Mb ST-506 hard disc */
	SETMEM(HDPBLOCK, HDSECTORSPERTRACK & 0xFF);/* SPT - sectors per track */
	SETMEM(HDPBLOCK + 1, HDSECTORSPERTRACK >> 8);
	SETMEM(HDPBLOCK + 2, 4);	/* BSH - data block shift factor */
	SETMEM(HDPBLOCK + 3, 15);		/* BLM - data block mask */
	SETMEM(HDPBLOCK + 4, 0);		/* EXM - extent mask */
	SETMEM(HDPBLOCK + 5, 2441 & 0xFF);	/* DSM - total drive capacity */
	SETMEM(HDPBLOCK + 6, 2441 >> 8);
	SETMEM(HDPBLOCK + 7, 1023 & 0xFF);	/* DRM - total dir entries */
	SETMEM(HDPBLOCK + 8, 1023 >> 8);
	SETMEM(HDPBLOCK + 9, 0xFF);	/* AL0 - blocks for directory entries */
	SETMEM(HDPBLOCK + 10, 0xFF);	/* AL1 */
	SETMEM(HDPBLOCK + 11, 0x00);	/* CKS - directory check vector */
	SETMEM(HDPBLOCK + 12, 0x00);
	SETMEM(HDPBLOCK + 13, RESERVEDTRACKS & 0xFF);/* OFF - reserved tracks */
	SETMEM(HDPBLOCK + 14, RESERVEDTRACKS >> 8);

	/* disk parameter headers for hard disc */
	for (i = 0; i < NUMHDISCS; i++)
	{
		SETMEM(HDPBASE + DPHSIZE * i, 0x00);	/* XLT */
		SETMEM(HDPBASE + DPHSIZE * i + 1, 0x00);
		SETMEM(HDPBASE + DPHSIZE * i + 2, 0x00); /* scratch 1 */
		SETMEM(HDPBASE + DPHSIZE * i + 3, 0x00);
		SETMEM(HDPBASE + DPHSIZE * i + 4, 0x00); /* scratch 2 */
		SETMEM(HDPBASE + DPHSIZE * i + 5, 0x00);
		SETMEM(HDPBASE + DPHSIZE * i + 6, 0x00); /* scratch 3 */
		SETMEM(HDPBASE + DPHSIZE * i + 7, 0x00);
		SETMEM(HDPBASE + DPHSIZE * i + 8, DIRBUF & 0xFF); /* DIRBUF */
		SETMEM(HDPBASE + DPHSIZE * i + 9, DIRBUF >> 8);
		SETMEM(HDPBASE + DPHSIZE * i + 10, HDPBLOCK & 0xFF); /* DPB */
		SETMEM(HDPBASE + DPHSIZE * i + 11, HDPBLOCK >> 8);
		SETMEM(HDPBASE + DPHSIZE * i + 12, 0x00);
		SETMEM(HDPBASE + DPHSIZE * i + 13, 0x00);
		SETMEM(HDPBASE + DPHSIZE * i + 14,
			(HALVBASE + HALVSIZE * i) & 0xFF);
		SETMEM(HDPBASE + DPHSIZE * i + 15,
			(HALVBASE + HALVSIZE * i) >> 8);
	}

	/* disc parameter block - a single-sided single-density 8" 256k disc */
	SETMEM(DPBLOCK, SECTORSPERTRACK & 0xFF); /* SPT - sectors per track */
	SETMEM(DPBLOCK + 1, SECTORSPERTRACK >> 8);
	SETMEM(DPBLOCK + 2, 3);		/* BSH - data block shift factor */
	SETMEM(DPBLOCK + 3, 7);			/* BLM - data block mask */
	SETMEM(DPBLOCK + 4, 0);			/* EXM - extent mask */
	SETMEM(DPBLOCK + 5, 242);	/* DSM - total capacity of drive */
	SETMEM(DPBLOCK + 6, 0);
	SETMEM(DPBLOCK + 7, 63);	/* DRM - total directory entries */
	SETMEM(DPBLOCK + 8, 0);
	SETMEM(DPBLOCK + 9, 0xC0);	/* AL0 - blocks for directory entries */
	SETMEM(DPBLOCK + 10, 0x00);	/* AL1 */
	SETMEM(DPBLOCK + 11, 0x00);	/* CKS - directory check vector */
	SETMEM(DPBLOCK + 12, 0x00);
	SETMEM(DPBLOCK + 13, RESERVEDTRACKS & 0xFF); /* OFF - reserved tracks */
	SETMEM(DPBLOCK + 14, RESERVEDTRACKS >> 8);

	/* disc parameter headers */
	for (i = 0; i < NUMDISCS; i++)
	{
		SETMEM(DPBASE + DPHSIZE * i, 0x00);	/* XLT */
		SETMEM(DPBASE + DPHSIZE * i + 1, 0x00);
		SETMEM(DPBASE + DPHSIZE * i + 2, 0x00); /* scratch 1 */
		SETMEM(DPBASE + DPHSIZE * i + 3, 0x00);
		SETMEM(DPBASE + DPHSIZE * i + 4, 0x00); /* scratch 2 */
		SETMEM(DPBASE + DPHSIZE * i + 5, 0x00);
		SETMEM(DPBASE + DPHSIZE * i + 6, 0x00); /* scratch 3 */
		SETMEM(DPBASE + DPHSIZE * i + 7, 0x00);
		SETMEM(DPBASE + DPHSIZE * i + 8, DIRBUF & 0xFF); /* DIRBUF */
		SETMEM(DPBASE + DPHSIZE * i + 9, DIRBUF >> 8);
		SETMEM(DPBASE + DPHSIZE * i + 10, DPBLOCK & 0xFF); /* DPB */
		SETMEM(DPBASE + DPHSIZE * i + 11, DPBLOCK >> 8);
#if (CVSIZE == 0)
		SETMEM(DPBASE + DPHSIZE * i + 12, 0x00);
		SETMEM(DPBASE + DPHSIZE * i + 13, 0x00);
#else
		SETMEM(DPBASE + DPHSIZE * i + 12,
			(CVBASE + CVSIZE * i) & 0xFF);
		SETMEM(DPBASE + DPHSIZE * i + 13,
			(CVBASE + CVSIZE * i) >> 8);
#endif
		SETMEM(DPBASE + DPHSIZE * i + 14,
			(ALVBASE + ALVSIZE * i) & 0xFF);
		SETMEM(DPBASE + DPHSIZE * i + 15,
			(ALVBASE + ALVSIZE * i) >> 8);
	}

	/* set up the stack for an 8-level RET to do a system reset */
	SP = STACK;

	for (i = 0; i < 8; i++)
	{
		/* push reboot entry (CBIOS + 3) onto stack */
		--SP;
		SETMEM(SP, (CBIOS + 3) >> 8);
		--SP;
		SETMEM(SP, (CBIOS + 3) & 0xFF);
	}

	/* set up the default disk (A:) and dma address */
	z80->dma = 0x0080;

	/* and all our default drive info */
	z80->track = 0;
	z80->sector = 1;

	/* make sure the current file/disk is open */
	B = 0;
	C = z80->drive;
	seldisc(z80);

	PC = CCP;
}
示例#21
0
int8_t RogueSD::sync(void)
{
  // procedure:
  // 1. sync (send ESC, clear prompt)
  // 2. get version ("v"), and module type
  // 3. change settings as needed
  // 4. check status
  // 5. close files (if needed - E08, or other error, not needed)

  // 0. empty any data in the serial buffer
  _comm_flush();

  // 1. sync
  _comm_write(0x1b);                    // send ESC to clear buffer on uMMC
  _read_blocked();                      // consume prompt

  // 2. get version (ignore prompt - just drop it)
  
  _get_version();

  // 3. change settings as needed
  // OLD: write timeout setting = 10 ms timeout
  // NEW: listing style = old style (0)
  if ((_moduletype == uMMC && _fwversion < UMMC_MIN_FW_VERSION_FOR_NEW_COMMANDS) ||
      (_moduletype == uMP3 && _fwversion < UMP3_MIN_FW_VERSION_FOR_NEW_COMMANDS))
  {
    // we need to set the write timeout to allow us to control when a line is finished
    // in writeln.
    changesetting('1', 1);              // 10 ms timeout
  }
  else
  {
    // we're using the new version
    // Let's make sure the Listing Style setting is set to the old style
    if (getsetting('L') != 0)
    {
      changesetting('L', 0);
    }

    // get the prompt char
    print('S');
    if (_moduletype != uMMC) { print('T'); };
    print('P'); print('\r');  // get our prompt (if possible)
    _promptchar = _getnumber(10);
    _read_blocked();                    // consume prompt
  }
  
  // 4. check status

  if (_moduletype != uMMC) { print("FC"); };
  print('Z'); print('\r');              // Get status
  
  if (_get_response())
    return -1;
  else
  {
    // good
    _read_blocked();                    // consume prompt

    // 5. close all files
    closeall();                         // ensure all handles are closed

    return 0;
  }
}
示例#22
0
void run(Node *a)	/* execution of parse tree starts here */
{
	execute(a);
	closeall();
}
示例#23
0
文件: mountd.c 项目: gygy/asuswrt
int
main(int argc, char **argv)
{
	char	*export_file = _PATH_EXPORTS;
	char    *state_dir = NFS_STATEDIR;
	int	foreground = 0;
	int	port = 0;
	int	descriptors = 0;
	int	c;
	struct sigaction sa;
	struct rlimit rlim;

	/* Parse the command line options and arguments. */
	opterr = 0;
	while ((c = getopt_long(argc, argv, "o:nFd:f:p:P:hH:N:V:vrs:t:g", longopts, NULL)) != EOF)
		switch (c) {
		case 'g':
			manage_gids = 1;
			break;
		case 'o':
			descriptors = atoi(optarg);
			if (descriptors <= 0) {
				fprintf(stderr, "%s: bad descriptors: %s\n",
					argv [0], optarg);
				usage(argv [0], 1);
			}
			break;
		case 'F':
			foreground = 1;
			break;
		case 'd':
			xlog_sconfig(optarg, 1);
			break;
		case 'f':
			export_file = optarg;
			break;
		case 'H': /* PRC: specify a high-availability callout program */
			ha_callout_prog = optarg;
			break;
		case 'h':
			usage(argv [0], 0);
			break;
		case 'P':	/* XXX for nfs-server compatibility */
		case 'p':
			port = atoi(optarg);
			if (port <= 0 || port > 65535) {
				fprintf(stderr, "%s: bad port number: %s\n",
					argv [0], optarg);
				usage(argv [0], 1);
			}
			break;
		case 'N':
			nfs_version &= ~(1 << (atoi (optarg) - 1));
			break;
		case 'n':
			_rpcfdtype = SOCK_DGRAM;
			break;
		case 'r':
			reverse_resolve = 1;
			break;
		case 's':
			if ((state_dir = xstrdup(optarg)) == NULL) {
				fprintf(stderr, "%s: xstrdup(%s) failed!\n",
					argv[0], optarg);
				exit(1);
			}
			break;
		case 't':
			num_threads = atoi (optarg);
			break;
		case 'V':
			nfs_version |= 1 << (atoi (optarg) - 1);
			break;
		case 'v':
			printf("kmountd %s\n", VERSION);
			exit(0);
		case 0:
			break;
		case '?':
		default:
			usage(argv [0], 1);
		}

	/* No more arguments allowed.
	 * Require at least one valid version (2, 3, or 4)
	 */
	if (optind != argc || !(nfs_version & 0xE))
		usage(argv [0], 1);

	if (chdir(state_dir)) {
		fprintf(stderr, "%s: chdir(%s) failed: %s\n",
			argv [0], state_dir, strerror(errno));
		exit(1);
	}

	if (getrlimit (RLIMIT_NOFILE, &rlim) != 0)
		fprintf(stderr, "%s: getrlimit (RLIMIT_NOFILE) failed: %s\n",
				argv [0], strerror(errno));
	else {
		/* glibc sunrpc code dies if getdtablesize > FD_SETSIZE */
		if ((descriptors == 0 && rlim.rlim_cur > FD_SETSIZE) ||
		    descriptors > FD_SETSIZE)
			descriptors = FD_SETSIZE;
		if (descriptors) {
			rlim.rlim_cur = descriptors;
			if (setrlimit (RLIMIT_NOFILE, &rlim) != 0) {
				fprintf(stderr, "%s: setrlimit (RLIMIT_NOFILE) failed: %s\n",
					argv [0], strerror(errno));
				exit(1);
			}
		}
	}
	/* Initialize logging. */
	if (!foreground) xlog_stderr(0);
	xlog_open("mountd");

	sa.sa_handler = SIG_IGN;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	sigaction(SIGHUP, &sa, NULL);
	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);
	/* WARNING: the following works on Linux and SysV, but not BSD! */
	sigaction(SIGCHLD, &sa, NULL);

	/* Daemons should close all extra filehandles ... *before* RPC init. */
	if (!foreground)
		closeall(3);

	new_cache = check_new_cache();
	if (new_cache)
		cache_open();

	if (nfs_version & 0x1)
		rpc_init("mountd", MOUNTPROG, MOUNTVERS,
			 mount_dispatch, port);
	if (nfs_version & (0x1 << 1))
		rpc_init("mountd", MOUNTPROG, MOUNTVERS_POSIX,
			 mount_dispatch, port);
	if (nfs_version & (0x1 << 2))
		rpc_init("mountd", MOUNTPROG, MOUNTVERS_NFSV3,
			 mount_dispatch, port);

	sa.sa_handler = killer;
	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sa.sa_handler = sig_hup;
	sigaction(SIGHUP, &sa, NULL);

	auth_init(export_file);

	if (!foreground) {
		/* We first fork off a child. */
		if ((c = fork()) > 0)
			exit(0);
		if (c < 0) {
			xlog(L_FATAL, "mountd: cannot fork: %s\n",
						strerror(errno));
		}
		/* Now we remove ourselves from the foreground.
		   Redirect stdin/stdout/stderr first. */
		{
			int fd = open("/dev/null", O_RDWR);
			(void) dup2(fd, 0);
			(void) dup2(fd, 1);
			(void) dup2(fd, 2);
			if (fd > 2) (void) close(fd);
		}
		setsid();
	}

	/* silently bounds check num_threads */
	if (foreground)
		num_threads = 1;
	else if (num_threads < 1)
		num_threads = 1;
	else if (num_threads > MAX_THREADS)
		num_threads = MAX_THREADS;

	if (num_threads > 1)
		fork_workers();

	my_svc_run();

	xlog(L_ERROR, "Ack! Gack! svc_run returned!\n");
	exit(1);
}
示例#24
0
int
kadmin(int cmd, int fcn, void *mdep, cred_t *credp)
{
	int error = 0;
	char *buf;
	size_t buflen = 0;
	boolean_t invoke_cb = B_FALSE;

	/*
	 * We might be called directly by the kernel's fault-handling code, so
	 * we can't assert that the caller is in the global zone.
	 */

	/*
	 * Make sure that cmd is one of the valid <sys/uadmin.h> command codes
	 * and that we have appropriate privileges for this action.
	 */
	switch (cmd) {
	case A_FTRACE:
	case A_SHUTDOWN:
	case A_REBOOT:
	case A_REMOUNT:
	case A_FREEZE:
	case A_DUMP:
	case A_SDTTEST:
	case A_CONFIG:
		if (secpolicy_sys_config(credp, B_FALSE) != 0)
			return (EPERM);
		break;

	default:
		return (EINVAL);
	}

	/*
	 * Serialize these operations on ualock.  If it is held, the
	 * system should shutdown, reboot, or remount shortly, unless there is
	 * an error.  We need a cv rather than just a mutex because proper
	 * functioning of A_REBOOT relies on being able to interrupt blocked
	 * userland callers.
	 *
	 * We only clear ua_shutdown_thread after A_REMOUNT or A_CONFIG.
	 * Other commands should never return.
	 */
	if (cmd == A_SHUTDOWN || cmd == A_REBOOT || cmd == A_REMOUNT ||
	    cmd == A_CONFIG) {
		mutex_enter(&ualock);
		while (ua_shutdown_thread != NULL) {
			if (cv_wait_sig(&uacond, &ualock) == 0) {
				/*
				 * If we were interrupted, leave, and handle
				 * the signal (or exit, depending on what
				 * happened)
				 */
				mutex_exit(&ualock);
				return (EINTR);
			}
		}
		ua_shutdown_thread = curthread;
		mutex_exit(&ualock);
	}

	switch (cmd) {
	case A_SHUTDOWN:
	{
		proc_t *p = ttoproc(curthread);

		/*
		 * Release (almost) all of our own resources if we are called
		 * from a user context, however if we are calling kadmin() from
		 * a kernel context then we do not release these resources.
		 */
		if (p != &p0) {
			proc_is_exiting(p);
			if ((error = exitlwps(0)) != 0) {
				/*
				 * Another thread in this process also called
				 * exitlwps().
				 */
				mutex_enter(&ualock);
				ua_shutdown_thread = NULL;
				cv_signal(&uacond);
				mutex_exit(&ualock);
				return (error);
			}
			mutex_enter(&p->p_lock);
			p->p_flag |= SNOWAIT;
			sigfillset(&p->p_ignore);
			curthread->t_lwp->lwp_cursig = 0;
			curthread->t_lwp->lwp_extsig = 0;
			if (p->p_exec) {
				vnode_t *exec_vp = p->p_exec;
				p->p_exec = NULLVP;
				mutex_exit(&p->p_lock);
				VN_RELE(exec_vp);
			} else {
				mutex_exit(&p->p_lock);
			}

			pollcleanup();
			closeall(P_FINFO(curproc));
			relvm();

		} else {
			/*
			 * Reset t_cred if not set because much of the
			 * filesystem code depends on CRED() being valid.
			 */
			if (curthread->t_cred == NULL)
				curthread->t_cred = kcred;
		}

		/* indicate shutdown in progress */
		sys_shutdown = 1;

		/*
		 * Communcate that init shouldn't be restarted.
		 */
		zone_shutdown_global();

		killall(ALL_ZONES);
		/*
		 * If we are calling kadmin() from a kernel context then we
		 * do not release these resources.
		 */
		if (ttoproc(curthread) != &p0) {
			VN_RELE(PTOU(curproc)->u_cdir);
			if (PTOU(curproc)->u_rdir)
				VN_RELE(PTOU(curproc)->u_rdir);
			if (PTOU(curproc)->u_cwd)
				refstr_rele(PTOU(curproc)->u_cwd);

			PTOU(curproc)->u_cdir = rootdir;
			PTOU(curproc)->u_rdir = NULL;
			PTOU(curproc)->u_cwd = NULL;
		}

		/*
		 * Allow the reboot/halt/poweroff code a chance to do
		 * anything it needs to whilst we still have filesystems
		 * mounted, like loading any modules necessary for later
		 * performing the actual poweroff.
		 */
		if ((mdep != NULL) && (*(char *)mdep == '/')) {
			buf = i_convert_boot_device_name(mdep, NULL, &buflen);
			mdpreboot(cmd, fcn, buf);
		} else
			mdpreboot(cmd, fcn, mdep);

		/*
		 * Allow fsflush to finish running and then prevent it
		 * from ever running again so that vfs_unmountall() and
		 * vfs_syncall() can acquire the vfs locks they need.
		 */
		sema_p(&fsflush_sema);
		(void) callb_execute_class(CB_CL_UADMIN_PRE_VFS, NULL);

		vfs_unmountall();
		(void) VFS_MOUNTROOT(rootvfs, ROOT_UNMOUNT);
		vfs_syncall();

		dump_ereports();
		dump_messages();

		invoke_cb = B_TRUE;

		/* FALLTHROUGH */
	}

	case A_REBOOT:
		if ((mdep != NULL) && (*(char *)mdep == '/')) {
			buf = i_convert_boot_device_name(mdep, NULL, &buflen);
			mdboot(cmd, fcn, buf, invoke_cb);
		} else
			mdboot(cmd, fcn, mdep, invoke_cb);
		/* no return expected */
		break;

	case A_CONFIG:
		switch (fcn) {
		case AD_UPDATE_BOOT_CONFIG:
#ifndef	__sparc
		{
			extern void fastboot_update_config(const char *);

			fastboot_update_config(mdep);
		}
#endif

			break;
		}
		/* Let other threads enter the shutdown path now */
		mutex_enter(&ualock);
		ua_shutdown_thread = NULL;
		cv_signal(&uacond);
		mutex_exit(&ualock);
		break;

	case A_REMOUNT:
		(void) VFS_MOUNTROOT(rootvfs, ROOT_REMOUNT);
		/* Let other threads enter the shutdown path now */
		mutex_enter(&ualock);
		ua_shutdown_thread = NULL;
		cv_signal(&uacond);
		mutex_exit(&ualock);
		break;

	case A_FREEZE:
	{
		/*
		 * This is the entrypoint for all suspend/resume actions.
		 */
		extern int cpr(int, void *);

		if (modload("misc", "cpr") == -1)
			return (ENOTSUP);
		/* Let the CPR module decide what to do with mdep */
		error = cpr(fcn, mdep);
		break;
	}

	case A_FTRACE:
	{
		switch (fcn) {
		case AD_FTRACE_START:
			(void) FTRACE_START();
			break;
		case AD_FTRACE_STOP:
			(void) FTRACE_STOP();
			break;
		default:
			error = EINVAL;
		}
		break;
	}

	case A_DUMP:
	{
		if (fcn == AD_NOSYNC) {
			in_sync = 1;
			break;
		}

		panic_bootfcn = fcn;
		panic_forced = 1;

		if ((mdep != NULL) && (*(char *)mdep == '/')) {
			panic_bootstr = i_convert_boot_device_name(mdep,
			    NULL, &buflen);
		} else
			panic_bootstr = mdep;

#ifndef	__sparc
		extern void fastboot_update_and_load(int, char *);

		fastboot_update_and_load(fcn, mdep);
#endif

		panic("forced crash dump initiated at user request");
		/*NOTREACHED*/
	}

	case A_SDTTEST:
	{
		DTRACE_PROBE7(test, int, 1, int, 2, int, 3, int, 4, int, 5,
		    int, 6, int, 7);
		break;
	}

	default:
		error = EINVAL;
	}

	return (error);
}
示例#25
0
void mexFunction(
    int           nlhs,           /* number of expected outputs */
    mxArray       *plhs[],        /* array of pointers to output arguments */
    int           nrhs,           /* number of inputs */
    const mxArray *prhs[]         /* array of pointers to input arguments */
)
{
  int fun;
  struct in_addr addr;

  /* Initialization on first call to the mex file */
  if(mex_call_counter==0)
  {
//      int i;
#ifdef WIN32
      {
	  WORD wVersionRequested;
	  WSADATA wsaData;
	  int wsa_err;
	  
	  wVersionRequested = MAKEWORD( 2, 0 );
	  wsa_err = WSAStartup( wVersionRequested, &wsaData );
	  if ( wsa_err )
	  {
	      mexErrMsgTxt("Error starting WINSOCK32.");
	      return;
	  }
      }
#endif
      mexAtExit(CleanUpMex);
      /* Init all to free */
      for(ipi_index=0;ipi_index<MAX_IPI;ipi_index++)
	  init_ipi(-1,STATUS_FREE);
      ipi_index=0;
  }

  mex_call_counter++;
  ret_args=0;

  debug_view_ipi_status("ENTER_MEX");

  if(nrhs<2) 
      mexErrMsgTxt("You must specify at least two arguments!");

  if(mxGetM(prhs[0])*mxGetN(prhs[0])!=1)
      mexErrMsgTxt("Error on first argument! should be a function selection number.");
  fun=(int)mxGetScalar(prhs[0]);


  /* ---CLOSE ALL----  */
  if(fun<0)
  {
    closeall();
    return;
  }

  /* Find given handel */
  {
      int idx;
      if(mxGetM(prhs[1])*mxGetN(prhs[1])!=1)
	  mexErrMsgTxt("Error on second argument. Specify handler as scalar!");
      idx=(int)mxGetScalar(prhs[1]);
      if(move_ipi(idx)==0)
	  mexErrMsgTxt("Unknown handler!");
  }
  debug_view_ipi_status("IPI_MOVED!!");  
  switch(fun)
  {


/* ---CLOSE--- */
  case 0:
      {   
	  if(ipi[ipi_index].fid<0)   /* Already closed?? */
	      mexPrintf("Cant close already closed fid.\n");
	  else
	      close_ipi();
	  break;
      }

/* ---OPEN AS CLIENT--- */
  case 1:
      {
	char hostname[NAMEBUFF_LEN+1];
	int len;
	int port;

   debug_view_ipi_status("O1");
	if(ipi[ipi_index].fid>=0)
	  mexErrMsgTxt("This handler is already open !!??");

   debug_view_ipi_status("O2");
	if(nrhs<3)
	    mexErrMsgTxt("Wrong number of arguments for OPEN!");
	if(mxIsChar(prhs[2])==0 || mxIsNumeric(prhs[3])==0)
	    mexErrMsgTxt("Wrong argument datatype for OPEN!");

	len=mxGetM(prhs[2])*mxGetN(prhs[2])+1;
	if(len>=NAMEBUFF_LEN)
	    mexErrMsgTxt("To long hostname!");

	mxGetString(prhs[2], hostname, len);

	port=(int)mxGetScalar(prhs[3]);
   debug_view_ipi_status("O3");
//	ipi[ipi_index].he=gethostbyname(hostname);
   debug_view_ipi_status("O4");

	if(ipi[ipi_index].he!=NULL)
	    addr = *((struct in_addr *)ipi[ipi_index].he->h_addr);
	else
	{
	    /* Can't lookup hostname, try IP address */
	    addr.s_addr=inet_addr(hostname);
	    if (addr.s_addr==INADDR_NONE)
	    {
		my_mexReturnValue(nlhs,plhs,-1);	
		break;
	    }
	}
   debug_view_ipi_status("O5");
	ipi[ipi_index].fid=socket(AF_INET, SOCK_STREAM, 0);
   debug_view_ipi_status("O5");

	if(ipi[ipi_index].fid== IPI_FREE)
	{
	    /* Can't make socket for connnection to remote host. */
	    my_mexReturnValue(nlhs,plhs,-1);
	    break;
	}
   debug_view_ipi_status("O6");

	ipi[ipi_index].remote_addr.sin_family=AF_INET;
	ipi[ipi_index].remote_addr.sin_port=htons(port);
	ipi[ipi_index].remote_addr.sin_addr=addr;
	ipi[ipi_index].remote_addr.sin_family=AF_INET;
	memset(&ipi[ipi_index].remote_addr.sin_zero, 0,8);
	if(connect(ipi[ipi_index].fid,(struct sockaddr *)&ipi[ipi_index].remote_addr,
		   sizeof(struct sockaddr)) == -1)
	{
	    /*Can't connect to remote host. */
	    my_mexReturnValue(nlhs,plhs,-1);
	    close_ipi();
	    break;
	}
   debug_view_ipi_status("O7");
	init_ipi(ipi[ipi_index].fid,STATUS_CLIENT);
	nonblockingsocket(ipi[ipi_index].fid); /* Non blocking read! */
   debug_view_ipi_status("O8");
	my_mexReturnValue(nlhs,plhs,ipi_index);
	break;
      }

/* ---- WRITESTRING ---- */
  case 2:
      {
	int retval=100000;
	int sentlen=0;
	char *buff;
	int len;
	
	if(nrhs<3)
	  mexErrMsgTxt("You must specify string to write as third argument!");
	if(mxIsChar(prhs[2])==0)
	  mexErrMsgTxt("Write string must be array of chars!");
	len=mxGetM(prhs[2])*mxGetN(prhs[2]);
	if(len==0)
	{
          my_mexReturnValue(nlhs,plhs,0);
	  break;
	}
	if((buff=(char *)mxMalloc(len))==NULL)
	  mexErrMsgTxt("Running out of memory! Can't send string!");
	CopymxCharArray2Buff(prhs[2],buff,len);
	sentlen=writedata(buff,len);
	my_mexReturnValue(nlhs,plhs,sentlen);
	mxFree(buff);
	break;
      }
      break;

/* ---- READSTRING ---- */
  case 3:
      {
	  int readlen;
	  if(nrhs<3)
	      mexErrMsgTxt("You must specify maximum of characteer to read!");
	  readlen=(int)mxGetScalar(prhs[2]);
	  read2buff(readlen);
	  if(readlen>ipi[ipi_index].buffdatalen)
	      readlen=ipi[ipi_index].buffdatalen;
	  my_mexReturnCharArray(nlhs,plhs,ipi[ipi_index].buff,readlen);
	  removefrombuff(readlen);
      }
      break;


/* ---- READSTRING UNTIL (READLINE) ---- */
  case 4:
      {
	int i;
	int readlen;
	int flag=0;
	int termchar1=13;  /* Two default string termination characters */
	int termchar2=10;

	if(nrhs<3)
	  mexErrMsgTxt("You must specify maximum of characters to read!");

	if(nrhs>3) 
	  termchar1=termchar2=(int)mxGetScalar(prhs[3]);
	if(nrhs>4) 
	  termchar2=(int)mxGetScalar(prhs[4]);
	readlen=(int)mxGetScalar(prhs[2]);
	read2buff(readlen);

	for(i=0; i<readlen, i<ipi[ipi_index].buffdatalen; i++)
	{
	    if(ipi[ipi_index].buff[i]==termchar1 || ipi[ipi_index].buff[i]==termchar2)
	    {
	      my_mexReturnCharArray(nlhs,plhs,ipi[ipi_index].buff,i+1);
	      removefrombuff(i+1);
	      break;
	    }
	}
	if(readlen==ipi[ipi_index].buffdatalen)                 /*Is read buffer full? */
	{
	  /* then wrap line...*/
	  my_mexReturnCharArray(nlhs,plhs,ipi[ipi_index].buff,ipi[ipi_index].buffdatalen);
	  removefrombuff(ipi[ipi_index].buffdatalen); 
        }
	else
	  /* else return empty*/ 
	  my_mexReturnCharArray(nlhs,plhs,"",0);       
      }
      break;



/* ----- "VIEW" INCOMMING DATA, (NOT DELETE FROM BUFFER)------ */
  case 5:
      {
	  int readlen;
	  readlen=(int)mxGetScalar(prhs[2]);
	  read2buff(readlen);
	  if(readlen>ipi[ipi_index].buffdatalen)
	      readlen=ipi[ipi_index].buffdatalen;
	  my_mexReturnCharArray(nlhs,plhs,ipi[ipi_index].buff,readlen);
      }
      break;


/* --- RETURN STATUS --- */
  case 6:
      my_mexReturnValue(nlhs,plhs,ipi[ipi_index].status);
      break;


/* --- SET_CALLBACK_FUNCTION --- */
  case 7:
      {
	if(nrhs<3)
	  mexErrMsgTxt("You must specify a string as callback function name!");
	if(mxIsChar(prhs[2])==0)
	  mexErrMsgTxt("You must specify a string as callback function name!");
	mxGetString(prhs[2],ipi[ipi_index].callback, CBNAMELEN);
	break;
      }
      break;



/* --- EXECUTE_CALLBACK_FUNCTION --- */
  case 9:
      {

	  /*.............

	    Type a lote here

	    ................*/

      }
      break;


/* ---- OPEN_AS_SERVER  ----*/          /* OLD!!! Remove this ???? */ 
  case 10:
      {
	  int port;
	  int idx;
	  if(ipi[ipi_index].fid>=0) 
	      mexErrMsgTxt("already open??? Always specify handler -1 when open a new!");
	  if(nrhs<3)
	      mexErrMsgTxt("Wrong number of arguments for OPEN_AS_SERVER!");
	  port=(int)mxGetScalar(prhs[2]);
	  idx=tcpipserver(port);
	  my_mexReturnValue(nlhs,plhs,idx);
      }
      break;



/* ---- OPEN_SERVER_SOCKET ---*/
  case 20:
     {
	 int fd;   /* File descriptor for socket! */
	 int port;
	 if(ipi[ipi_index].status!=STATUS_NOCONNECT) 
	     mexErrMsgTxt("already open??? Always specify handler -1 when open a new!");
	 if(nrhs<3)
	     mexErrMsgTxt("Wrong number of arguments. specify port number.");
	 port=(int)mxGetScalar(prhs[2]);
	 fd=tcpipsocket(port);
	 if(fd>=0)
	 {
	     init_ipi(fd,STATUS_SERVSOCKET);
  	     my_mexReturnValue(nlhs,plhs,ipi_index);
	 }
	 else
	 {
	     init_ipi(-1,STATUS_FREE);
  	     my_mexReturnValue(nlhs,plhs,-1);
	 }
     }
     break;
     
/* ---- OPEN_CONNECTED TO SERVER ---   Listen for calls and return */
  case 21:
     {
	 int conn_fd;
//	 int sockfd;
	 if(ipi[ipi_index].status!=STATUS_SERVSOCKET)
	     mexErrMsgTxt("Its not a open socket you tries listens to...");
	 conn_fd=tcpiplisten(ipi[ipi_index].fid);
	 if( conn_fd >=0)
	 {
             /* Find a new free ipi struct for the new connection.... */
	     move_ipi(IPI_FREE);
	     init_ipi(conn_fd,STATUS_SERVER);
  	     my_mexReturnValue(nlhs,plhs,ipi_index);
	 }
	 else
	 {
  	     my_mexReturnValue(nlhs,plhs,-1);
	 }
     }
     break;

  default:
      mexErrMsgTxt("Unknown number for called function! Not implemented in this verion?");
      break;
      
  }
  debug_view_ipi_status("EXIT");
}
示例#26
0
int
main(int argc, char *argv[])
{
	SVCXPRT *utransp, *ttransp;
	struct sockaddr_in addr;
	DIR *dp;
	struct direct *d;
	ni_name tag = NULL;
	ni_namelist nl;
	ni_index i;
	int pid, localonly, nctoken = -1;
	int log_pri = LOG_NOTICE;
	struct rlimit rlim;
	char *netinfod_argv[16]; /* XXX */
	int netinfod_argc, x;
	union wait wait_stat;
	pid_t child_pid;
	char *pri;
#ifdef _UNIX_BSD_43_
	int ttyfd;
#endif

	localonly = 1;

	netinfod_argc = 0;
	netinfod_argv[netinfod_argc++] = (char *)NETINFO_PROG;

	debug = 0;

	for (i = 1; i < argc; i++)
	{
		if (!strcmp(argv[i], "-n"))
		{
			netinfod_argv[netinfod_argc++] = argv[i];
		}

		if (!strcmp(argv[i], "-d"))
		{
			debug = 1;
			log_pri = LOG_DEBUG;
			if ((argc > (i+1)) && (argv[i+1][0] != '-'))
				debug = atoi(argv[++i]);
		}

		if (!strcmp(argv[i], "-l"))
		{
			if ((argc > (i+1)) && (argv[i+1][0] != '-'))
				log_pri = atoi(argv[++i]);
		}

		if (!strcmp(argv[i], "-D"))
		{
			netinfod_argv[netinfod_argc++] = "-d";

			if ((argc > (i+1)) && (argv[i+1][0] != '-'))
			{
				netinfod_argv[netinfod_argc++] = argv[i];
			}
		}

		if (!strcmp(argv[i], "-L"))
		{
			netinfod_argv[netinfod_argc++] = "-l";

			if ((argc > (i+1)) && (argv[i+1][0] != '-'))
			{
				netinfod_argv[netinfod_argc++] = argv[i];
			}
			else
			{
				pri = malloc(sizeof("999"));
				sprintf(pri, "%d", LOG_DEBUG);
				netinfod_argv[netinfod_argc++] = pri;
			}
		}
	}

	if (debug == 1)
	{
		system_log_open("nibindd", LOG_NDELAY | LOG_PID, LOG_NETINFO, stderr);
		system_log_set_max_priority(log_pri);
		system_log(LOG_DEBUG, "version %s - debug mode\n", _PROJECT_VERSION_);
	}
	else
	{
		closeall();
		system_log_open("nibindd", LOG_NDELAY | LOG_PID, LOG_NETINFO, NULL);
		system_log_set_max_priority(log_pri);
		system_log(LOG_DEBUG, "version %s - starting\n", _PROJECT_VERSION_);

		child_pid = fork();
		if (child_pid == -1)
		{
			system_log(LOG_ALERT, "fork() failed: %m, aborting");
			system_log_close();
			exit(1);
		}
		else if (child_pid > 0)
		{
			signal(SIGTERM, parentexit);
			system_log(LOG_DEBUG, "parent waiting for child to start");
			wait4(child_pid, (_WAIT_TYPE_ *)&wait_stat, 0, 0);

			if (WIFEXITED(wait_stat))
			{
				system_log(LOG_DEBUG,
					"unexpected child exit, status=%d",
					WEXITSTATUS(wait_stat));
			}
			else
			{
				system_log(LOG_DEBUG,
					"unexpected child exit, received signal=%d",
					WTERMSIG(wait_stat));
			}
			system_log_close();
			exit(1);
		}
	}

	restart = 0;

	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
	setrlimit(RLIMIT_CORE, &rlim);
	signal(SIGCHLD, catchchild);
	signal(SIGTERM, killchildren);
	signal(SIGHUP, catchhup);
	signal(SIGINT, SIG_IGN);

	notify_register_signal(NETWORK_CHANGE_NOTIFICATION, SIGHUP, &nctoken);

	writepid();

	/*
	 * cd to netinfo directory, find out which databases should
	 * be served and lock the directory before registering service.
	 */
	if (chdir(NETINFO_DIR) < 0)
	{
		killparent();
		system_log(LOG_ALERT, "cannot chdir to netinfo directory");
		exit(1);
	}

	dp = opendir(NETINFO_DIR);
	if (dp == NULL)
	{
		killparent();
		system_log(LOG_ALERT, "cannot open netinfo directory");
		exit(1);
	}

	MM_ZERO(&nl);
	while ((d = readdir(dp)))
	{
		if (isnidir(d->d_name, &tag))
		{
			if (ni_namelist_match(nl, tag) == NI_INDEX_NULL)
			{
				system_log(LOG_DEBUG, "found database: %s", tag);
				ni_namelist_insert(&nl, tag, NI_INDEX_NULL);
				if (strcmp(tag, "local")) localonly = 0;
			} 
			ni_name_free(&tag);
		}
	}

#ifdef _NETINFO_FLOCK_
	/*
	 * Do not close the directory: keep it locked so another nibindd
	 * won't run.
	 */
	if (flock(dp->dd_fd, LOCK_EX|LOCK_NB) < 0)
	{
		killparent();
		system_log(LOG_ALERT, "nibindd already running");
		exit(1);
	}
	fcntl(dp->dd_fd, F_SETFD, 1);
#else
	closedir(dp);
#endif

	/*
	 * Register as a SUNRPC service
	 */
	memset(&addr, 0, sizeof(struct sockaddr_in));
	addr.sin_family = AF_INET;
	if (localonly == 1) addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

	pmap_unset(NIBIND_PROG, NIBIND_VERS);
	utransp = svcudp_bind(RPC_ANYSOCK, addr);
	if (utransp == NULL)
	{
		killparent();
		system_log(LOG_ALERT, "cannot start udp service");
		exit(1);
	}

	if (!svc_register(utransp, NIBIND_PROG, NIBIND_VERS, nibind_prog_1, IPPROTO_UDP))
	{
		killparent();
		system_log(LOG_ALERT, "cannot register udp service");
		exit(1);
	}

	udp_sock = utransp->xp_sock;

	ttransp = svctcp_bind(RPC_ANYSOCK, addr, 0, 0);
	if (ttransp == NULL)
	{
		killparent();
		system_log(LOG_ALERT, "cannot start tcp service");
		exit(1);
	}

	if (!svc_register(ttransp, NIBIND_PROG, NIBIND_VERS, nibind_prog_1, IPPROTO_TCP))
	{
		killparent();
		system_log(LOG_ALERT, "cannot register tcp service");
		exit(1);
	}

	waitreg = 0;
	for (i = 0; i < nl.ninl_len; i++)
	{
		netinfod_argv[netinfod_argc] = nl.ninl_val[i];
		netinfod_argv[netinfod_argc + 1] = NULL;

		system_log(LOG_DEBUG, "starting netinfod %s", nl.ninl_val[i]);
		system_log(LOG_DEBUG, "execv debug 0: %s", NETINFO_PROG);
		for (x = 0; netinfod_argv[x] != NULL; x++)
		{
			system_log(LOG_DEBUG, "execv debug %d: %s", x, netinfod_argv[x]);
		}

		pid = fork();
		if (pid == 0)
		{
			/* child */
			execv(NETINFO_PROG, netinfod_argv);
			exit(-1);
		}

#ifdef DEBUG
		system_log(LOG_DEBUG, "netinfod %s pid = %d", nl.ninl_val[i], pid);
#endif

		if (pid > 0)
		{
			waitreg++;
			storepid(pid, nl.ninl_val[i]);
		}
		else
		{
			system_log(LOG_ERR, "server for tag %s failed to start", nl.ninl_val[i]);
		}
	}

	ni_namelist_free(&nl);
		
	/*
	 * Detach from controlling tty.
	 * Do this AFTER starting netinfod so "type c to continue..." works.
	 */
#ifdef _UNIX_BSD_43_
	ttyfd = open("/dev/tty", O_RDWR, 0);
	if (ttyfd > 0)
	{
		ioctl(ttyfd, TIOCNOTTY, NULL);
		close(ttyfd);
	}

	setpgrp(0, getpid());
#else
	if (setsid() < 0) syslog(LOG_ERR, "nibindd: setsid() failed: %m");
#endif

	system_log(LOG_DEBUG, "starting RPC service");

	nibind_svc_run();
	system_log(LOG_ALERT, "svc_run returned");
	system_log_close();
	exit(1);
}
示例#27
0
文件: nfsd.c 项目: ANFS/ANFS-utils
int
main(int argc, char **argv)
{
	int	count = 1, c, error = 0, portnum = 0, fd, found_one;
	char *p, *progname, *port;
	char *haddr = NULL;
	int	socket_up = 0;
	int minorvers4 = NFSD_MAXMINORVERS4;	/* nfsv4 minor version */
	unsigned int versbits = NFSCTL_ALLBITS;
	unsigned int protobits = NFSCTL_ALLBITS;
	unsigned int proto4 = 0;
	unsigned int proto6 = 0;

	progname = strdup(basename(argv[0]));
	if (!progname) {
		fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]);
		exit(1);
	}

	port = strdup("nfs");
	if (!port) {
		fprintf(stderr, "%s: unable to allocate memory.\n", progname);
		exit(1);
	}

	xlog_syslog(0);
	xlog_stderr(1);

	while ((c = getopt_long(argc, argv, "dH:hN:p:P:sTU", longopts, NULL)) != EOF) {
		switch(c) {
		case 'd':
			xlog_config(D_ALL, 1);
			break;
		case 'H':
			/*
			 * for now, this only handles one -H option. Use the
			 * last one specified.
			 */
			free(haddr);
			haddr = strdup(optarg);
			if (!haddr) {
				fprintf(stderr, "%s: unable to allocate "
					"memory.\n", progname);
				exit(1);
			}
			break;
		case 'P':	/* XXX for nfs-server compatibility */
		case 'p':
			/* only the last -p option has any effect */
			portnum = atoi(optarg);
			if (portnum <= 0 || portnum > 65535) {
				fprintf(stderr, "%s: bad port number: %s\n",
					progname, optarg);
				usage(progname);
			}
			free(port);
			port = strdup(optarg);
			if (!port) {
				fprintf(stderr, "%s: unable to allocate "
						"memory.\n", progname);
				exit(1);
			}
			break;
		case 'N':
			switch((c = strtol(optarg, &p, 0))) {
			case 4:
				if (*p == '.') {
					minorvers4 = -atoi(p + 1);
					break;
				}
			case 3:
			case 2:
				NFSCTL_VERUNSET(versbits, c);
				break;
			default:
				fprintf(stderr, "%s: Unsupported version\n", optarg);
				exit(1);
			}
			break;
		case 's':
			xlog_syslog(1);
			xlog_stderr(0);
			break;
		case 'T':
			NFSCTL_TCPUNSET(protobits);
			break;
		case 'U':
			NFSCTL_UDPUNSET(protobits);
			break;
		default:
			fprintf(stderr, "Invalid argument: '%c'\n", c);
		case 'h':
			usage(progname);
		}
	}

	if (optind < argc) {
		if ((count = atoi(argv[optind])) < 0) {
			/* insane # of servers */
			fprintf(stderr,
				"%s: invalid server count (%d), using 1\n",
				argv[0], count);
			count = 1;
		} else if (count == 0) {
			/*
			 * don't bother setting anything else if the threads
			 * are coming down anyway.
			 */
			socket_up = 1;
			goto set_threads;
		}
	}

	xlog_open(progname);

	nfsd_enable_protos(&proto4, &proto6);

	if (!NFSCTL_TCPISSET(protobits)) {
		NFSCTL_TCPUNSET(proto4);
		NFSCTL_TCPUNSET(proto6);
	}

	if (!NFSCTL_UDPISSET(protobits)) {
		NFSCTL_UDPUNSET(proto4);
		NFSCTL_UDPUNSET(proto6);
	}

	/* make sure that at least one version is enabled */
	found_one = 0;
	for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
		if (NFSCTL_VERISSET(versbits, c))
			found_one = 1;
	}
	if (!found_one) {
		xlog(L_ERROR, "no version specified");
		exit(1);
	}			

	if (NFSCTL_VERISSET(versbits, 4) &&
	    !NFSCTL_TCPISSET(proto4) &&
	    !NFSCTL_TCPISSET(proto6)) {
		xlog(L_ERROR, "version 4 requires the TCP protocol");
		exit(1);
	}

	if (chdir(NFS_STATEDIR)) {
		xlog(L_ERROR, "chdir(%s) failed: %m", NFS_STATEDIR);
		exit(1);
	}

	/* make sure nfsdfs is mounted if it's available */
	nfssvc_mount_nfsdfs(progname);

	/* can only change number of threads if nfsd is already up */
	if (nfssvc_inuse()) {
		socket_up = 1;
		goto set_threads;
	}

	/*
	 * must set versions before the fd's so that the right versions get
	 * registered with rpcbind. Note that on older kernels w/o the right
	 * interfaces, these are a no-op.
	 */
	nfssvc_setvers(versbits, minorvers4);
 
	error = nfssvc_set_sockets(AF_INET, proto4, haddr, port);
	if (!error)
		socket_up = 1;

#ifdef IPV6_SUPPORTED
	error = nfssvc_set_sockets(AF_INET6, proto6, haddr, port);
	if (!error)
		socket_up = 1;
#endif /* IPV6_SUPPORTED */

set_threads:
	/* don't start any threads if unable to hand off any sockets */
	if (!socket_up) {
		xlog(L_ERROR, "unable to set any sockets for nfsd");
		goto out;
	}
	error = 0;

	/*
	 * KLUDGE ALERT:
	 * Some kernels let nfsd kernel threads inherit open files
	 * from the program that spawns them (i.e. us).  So close
	 * everything before spawning kernel threads.  --Chip
	 */
	fd = open("/dev/null", O_RDWR);
	if (fd == -1)
		xlog(L_ERROR, "Unable to open /dev/null: %m");
	else {
		/* switch xlog output to syslog since stderr is being closed */
		xlog_syslog(1);
		xlog_stderr(0);
		(void) dup2(fd, 0);
		(void) dup2(fd, 1);
		(void) dup2(fd, 2);
	}
	closeall(3);

	if ((error = nfssvc_threads(portnum, count)) < 0)
		xlog(L_ERROR, "error starting threads: errno %d (%m)", errno);
out:
	free(port);
	free(haddr);
	free(progname);
	return (error != 0);
}
示例#28
0
/*
 * Called by proc_exit() when a zone's init exits, presumably because
 * it failed.  As long as the given zone is still in the "running"
 * state, we will re-exec() init, but first we need to reset things
 * which are usually inherited across exec() but will break init's
 * assumption that it is being exec()'d from a virgin process.  Most
 * importantly this includes closing all file descriptors (exec only
 * closes those marked close-on-exec) and resetting signals (exec only
 * resets handled signals, and we need to clear any signals which
 * killed init).  Anything else that exec(2) says would be inherited,
 * but would affect the execution of init, needs to be reset.
 */
static int
restart_init(int what, int why)
{
	kthread_t *t = curthread;
	klwp_t *lwp = ttolwp(t);
	proc_t *p = ttoproc(t);
	user_t *up = PTOU(p);

	vnode_t *oldcd, *oldrd;
	int i, err;
	char reason_buf[64];

	/*
	 * Let zone admin (and global zone admin if this is for a non-global
	 * zone) know that init has failed and will be restarted.
	 */
	zcmn_err(p->p_zone->zone_id, CE_WARN,
	    "init(1M) %s: restarting automatically",
	    exit_reason(reason_buf, sizeof (reason_buf), what, why));

	if (!INGLOBALZONE(p)) {
		cmn_err(CE_WARN, "init(1M) for zone %s (pid %d) %s: "
		    "restarting automatically",
		    p->p_zone->zone_name, p->p_pid, reason_buf);
	}

	/*
	 * Remove any fpollinfo_t's for this (last) thread from our file
	 * descriptors so closeall() can ASSERT() that they're all gone.
	 * Then close all open file descriptors in the process.
	 */
	pollcleanup();
	closeall(P_FINFO(p));

	/*
	 * Grab p_lock and begin clearing miscellaneous global process
	 * state that needs to be reset before we exec the new init(1M).
	 */

	mutex_enter(&p->p_lock);
	prbarrier(p);

	p->p_flag &= ~(SKILLED | SEXTKILLED | SEXITING | SDOCORE);
	up->u_cmask = CMASK;

	sigemptyset(&t->t_hold);
	sigemptyset(&t->t_sig);
	sigemptyset(&t->t_extsig);

	sigemptyset(&p->p_sig);
	sigemptyset(&p->p_extsig);

	sigdelq(p, t, 0);
	sigdelq(p, NULL, 0);

	if (p->p_killsqp) {
		siginfofree(p->p_killsqp);
		p->p_killsqp = NULL;
	}

	/*
	 * Reset any signals that are ignored back to the default disposition.
	 * Other u_signal members will be cleared when exec calls sigdefault().
	 */
	for (i = 1; i < NSIG; i++) {
		if (up->u_signal[i - 1] == SIG_IGN) {
			up->u_signal[i - 1] = SIG_DFL;
			sigemptyset(&up->u_sigmask[i - 1]);
		}
	}

	/*
	 * Clear the current signal, any signal info associated with it, and
	 * any signal information from contracts and/or contract templates.
	 */
	lwp->lwp_cursig = 0;
	lwp->lwp_extsig = 0;
	if (lwp->lwp_curinfo != NULL) {
		siginfofree(lwp->lwp_curinfo);
		lwp->lwp_curinfo = NULL;
	}
	lwp_ctmpl_clear(lwp);

	/*
	 * Reset both the process root directory and the current working
	 * directory to the root of the zone just as we do during boot.
	 */
	VN_HOLD(p->p_zone->zone_rootvp);
	oldrd = up->u_rdir;
	up->u_rdir = p->p_zone->zone_rootvp;

	VN_HOLD(p->p_zone->zone_rootvp);
	oldcd = up->u_cdir;
	up->u_cdir = p->p_zone->zone_rootvp;

	if (up->u_cwd != NULL) {
		refstr_rele(up->u_cwd);
		up->u_cwd = NULL;
	}

	mutex_exit(&p->p_lock);

	if (oldrd != NULL)
		VN_RELE(oldrd);
	if (oldcd != NULL)
		VN_RELE(oldcd);

	/* Free the controlling tty.  (freectty() always assumes curproc.) */
	ASSERT(p == curproc);
	(void) freectty(B_TRUE);

	/*
	 * Now exec() the new init(1M) on top of the current process.  If we
	 * succeed, the caller will treat this like a successful system call.
	 * If we fail, we issue messages and the caller will proceed with exit.
	 */
	err = exec_init(p->p_zone->zone_initname, NULL);

	if (err == 0)
		return (0);

	zcmn_err(p->p_zone->zone_id, CE_WARN,
	    "failed to restart init(1M) (err=%d): system reboot required", err);

	if (!INGLOBALZONE(p)) {
		cmn_err(CE_WARN, "failed to restart init(1M) for zone %s "
		    "(pid %d, err=%d): zoneadm(1M) boot required",
		    p->p_zone->zone_name, p->p_pid, err);
	}

	return (-1);
}
示例#29
0
/*
 * Return value:
 *   1 - exitlwps() failed, call (or continue) lwp_exit()
 *   0 - restarting init.  Return through system call path
 */
int
proc_exit(int why, int what)
{
	kthread_t *t = curthread;
	klwp_t *lwp = ttolwp(t);
	proc_t *p = ttoproc(t);
	zone_t *z = p->p_zone;
	timeout_id_t tmp_id;
	int rv;
	proc_t *q;
	task_t *tk;
	vnode_t *exec_vp, *execdir_vp, *cdir, *rdir;
	sigqueue_t *sqp;
	lwpdir_t *lwpdir;
	uint_t lwpdir_sz;
	tidhash_t *tidhash;
	uint_t tidhash_sz;
	ret_tidhash_t *ret_tidhash;
	refstr_t *cwd;
	hrtime_t hrutime, hrstime;
	int evaporate;

	/*
	 * Stop and discard the process's lwps except for the current one,
	 * unless some other lwp beat us to it.  If exitlwps() fails then
	 * return and the calling lwp will call (or continue in) lwp_exit().
	 */
	proc_is_exiting(p);
	if (exitlwps(0) != 0)
		return (1);

	mutex_enter(&p->p_lock);
	if (p->p_ttime > 0) {
		/*
		 * Account any remaining ticks charged to this process
		 * on its way out.
		 */
		(void) task_cpu_time_incr(p->p_task, p->p_ttime);
		p->p_ttime = 0;
	}
	mutex_exit(&p->p_lock);

	DTRACE_PROC(lwp__exit);
	DTRACE_PROC1(exit, int, why);

	/*
	 * Will perform any brand specific proc exit processing, since this
	 * is always the last lwp, will also perform lwp_exit and free brand
	 * data
	 */
	if (PROC_IS_BRANDED(p)) {
		lwp_detach_brand_hdlrs(lwp);
		brand_clearbrand(p, B_FALSE);
	}

	/*
	 * Don't let init exit unless zone_start_init() failed its exec, or
	 * we are shutting down the zone or the machine.
	 *
	 * Since we are single threaded, we don't need to lock the
	 * following accesses to zone_proc_initpid.
	 */
	if (p->p_pid == z->zone_proc_initpid) {
		if (z->zone_boot_err == 0 &&
		    zone_status_get(z) < ZONE_IS_SHUTTING_DOWN &&
		    zone_status_get(global_zone) < ZONE_IS_SHUTTING_DOWN &&
		    z->zone_restart_init == B_TRUE &&
		    restart_init(what, why) == 0)
			return (0);
		/*
		 * Since we didn't or couldn't restart init, we clear
		 * the zone's init state and proceed with exit
		 * processing.
		 */
		z->zone_proc_initpid = -1;
	}

	lwp_pcb_exit();

	/*
	 * Allocate a sigqueue now, before we grab locks.
	 * It will be given to sigcld(), below.
	 * Special case:  If we will be making the process disappear
	 * without a trace because it is either:
	 *	* an exiting SSYS process, or
	 *	* a posix_spawn() vfork child who requests it,
	 * we don't bother to allocate a useless sigqueue.
	 */
	evaporate = (p->p_flag & SSYS) || ((p->p_flag & SVFORK) &&
	    why == CLD_EXITED && what == _EVAPORATE);
	if (!evaporate)
		sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);

	/*
	 * revoke any doors created by the process.
	 */
	if (p->p_door_list)
		door_exit();

	/*
	 * Release schedctl data structures.
	 */
	if (p->p_pagep)
		schedctl_proc_cleanup();

	/*
	 * make sure all pending kaio has completed.
	 */
	if (p->p_aio)
		aio_cleanup_exit();

	/*
	 * discard the lwpchan cache.
	 */
	if (p->p_lcp != NULL)
		lwpchan_destroy_cache(0);

	/*
	 * Clean up any DTrace helper actions or probes for the process.
	 */
	if (p->p_dtrace_helpers != NULL) {
		ASSERT(dtrace_helpers_cleanup != NULL);
		(*dtrace_helpers_cleanup)();
	}

	/* untimeout the realtime timers */
	if (p->p_itimer != NULL)
		timer_exit();

	if ((tmp_id = p->p_alarmid) != 0) {
		p->p_alarmid = 0;
		(void) untimeout(tmp_id);
	}

	/*
	 * Remove any fpollinfo_t's for this (last) thread from our file
	 * descriptors so closeall() can ASSERT() that they're all gone.
	 */
	pollcleanup();

	if (p->p_rprof_cyclic != CYCLIC_NONE) {
		mutex_enter(&cpu_lock);
		cyclic_remove(p->p_rprof_cyclic);
		mutex_exit(&cpu_lock);
	}

	mutex_enter(&p->p_lock);

	/*
	 * Clean up any DTrace probes associated with this process.
	 */
	if (p->p_dtrace_probes) {
		ASSERT(dtrace_fasttrap_exit_ptr != NULL);
		dtrace_fasttrap_exit_ptr(p);
	}

	while ((tmp_id = p->p_itimerid) != 0) {
		p->p_itimerid = 0;
		mutex_exit(&p->p_lock);
		(void) untimeout(tmp_id);
		mutex_enter(&p->p_lock);
	}

	lwp_cleanup();

	/*
	 * We are about to exit; prevent our resource associations from
	 * being changed.
	 */
	pool_barrier_enter();

	/*
	 * Block the process against /proc now that we have really
	 * acquired p->p_lock (to manipulate p_tlist at least).
	 */
	prbarrier(p);

	sigfillset(&p->p_ignore);
	sigemptyset(&p->p_siginfo);
	sigemptyset(&p->p_sig);
	sigemptyset(&p->p_extsig);
	sigemptyset(&t->t_sig);
	sigemptyset(&t->t_extsig);
	sigemptyset(&p->p_sigmask);
	sigdelq(p, t, 0);
	lwp->lwp_cursig = 0;
	lwp->lwp_extsig = 0;
	p->p_flag &= ~(SKILLED | SEXTKILLED);
	if (lwp->lwp_curinfo) {
		siginfofree(lwp->lwp_curinfo);
		lwp->lwp_curinfo = NULL;
	}

	t->t_proc_flag |= TP_LWPEXIT;
	ASSERT(p->p_lwpcnt == 1 && p->p_zombcnt == 0);
	prlwpexit(t);		/* notify /proc */
	lwp_hash_out(p, t->t_tid);
	prexit(p);

	p->p_lwpcnt = 0;
	p->p_tlist = NULL;
	sigqfree(p);
	term_mstate(t);
	p->p_mterm = gethrtime();

	exec_vp = p->p_exec;
	execdir_vp = p->p_execdir;
	p->p_exec = NULLVP;
	p->p_execdir = NULLVP;
	mutex_exit(&p->p_lock);

	pr_free_watched_pages(p);

	closeall(P_FINFO(p));

	/* Free the controlling tty.  (freectty() always assumes curproc.) */
	ASSERT(p == curproc);
	(void) freectty(B_TRUE);

#if defined(__sparc)
	if (p->p_utraps != NULL)
		utrap_free(p);
#endif
	if (p->p_semacct)			/* IPC semaphore exit */
		semexit(p);
	rv = wstat(why, what);

	acct(rv & 0xff);
	exacct_commit_proc(p, rv);

	/*
	 * Release any resources associated with C2 auditing
	 */
	if (AU_AUDITING()) {
		/*
		 * audit exit system call
		 */
		audit_exit(why, what);
	}

	/*
	 * Free address space.
	 */
	relvm();

	if (exec_vp) {
		/*
		 * Close this executable which has been opened when the process
		 * was created by getproc().
		 */
		(void) VOP_CLOSE(exec_vp, FREAD, 1, (offset_t)0, CRED(), NULL);
		VN_RELE(exec_vp);
	}
	if (execdir_vp)
		VN_RELE(execdir_vp);

	/*
	 * Release held contracts.
	 */
	contract_exit(p);

	/*
	 * Depart our encapsulating process contract.
	 */
	if ((p->p_flag & SSYS) == 0) {
		ASSERT(p->p_ct_process);
		contract_process_exit(p->p_ct_process, p, rv);
	}

	/*
	 * Remove pool association, and block if requested by pool_do_bind.
	 */
	mutex_enter(&p->p_lock);
	ASSERT(p->p_pool->pool_ref > 0);
	atomic_add_32(&p->p_pool->pool_ref, -1);
	p->p_pool = pool_default;
	/*
	 * Now that our address space has been freed and all other threads
	 * in this process have exited, set the PEXITED pool flag.  This
	 * tells the pools subsystems to ignore this process if it was
	 * requested to rebind this process to a new pool.
	 */
	p->p_poolflag |= PEXITED;
	pool_barrier_exit();
	mutex_exit(&p->p_lock);

	mutex_enter(&pidlock);

	/*
	 * Delete this process from the newstate list of its parent. We
	 * will put it in the right place in the sigcld in the end.
	 */
	delete_ns(p->p_parent, p);

	/*
	 * Reassign the orphans to the next of kin.
	 * Don't rearrange init's orphanage.
	 */
	if ((q = p->p_orphan) != NULL && p != proc_init) {

		proc_t *nokp = p->p_nextofkin;

		for (;;) {
			q->p_nextofkin = nokp;
			if (q->p_nextorph == NULL)
				break;
			q = q->p_nextorph;
		}
		q->p_nextorph = nokp->p_orphan;
		nokp->p_orphan = p->p_orphan;
		p->p_orphan = NULL;
	}

	/*
	 * Reassign the children to init.
	 * Don't try to assign init's children to init.
	 */
	if ((q = p->p_child) != NULL && p != proc_init) {
		struct proc	*np;
		struct proc	*initp = proc_init;
		boolean_t	setzonetop = B_FALSE;

		if (!INGLOBALZONE(curproc))
			setzonetop = B_TRUE;

		pgdetach(p);

		do {
			np = q->p_sibling;
			/*
			 * Delete it from its current parent new state
			 * list and add it to init new state list
			 */
			delete_ns(q->p_parent, q);

			q->p_ppid = 1;
			q->p_pidflag &= ~(CLDNOSIGCHLD | CLDWAITPID);
			if (setzonetop) {
				mutex_enter(&q->p_lock);
				q->p_flag |= SZONETOP;
				mutex_exit(&q->p_lock);
			}
			q->p_parent = initp;

			/*
			 * Since q will be the first child,
			 * it will not have a previous sibling.
			 */
			q->p_psibling = NULL;
			if (initp->p_child) {
				initp->p_child->p_psibling = q;
			}
			q->p_sibling = initp->p_child;
			initp->p_child = q;
			if (q->p_proc_flag & P_PR_PTRACE) {
				mutex_enter(&q->p_lock);
				sigtoproc(q, NULL, SIGKILL);
				mutex_exit(&q->p_lock);
			}
			/*
			 * sigcld() will add the child to parents
			 * newstate list.
			 */
			if (q->p_stat == SZOMB)
				sigcld(q, NULL);
		} while ((q = np) != NULL);

		p->p_child = NULL;
		ASSERT(p->p_child_ns == NULL);
	}

	TRACE_1(TR_FAC_PROC, TR_PROC_EXIT, "proc_exit: %p", p);

	mutex_enter(&p->p_lock);
	CL_EXIT(curthread); /* tell the scheduler that curthread is exiting */

	/*
	 * Have our task accummulate our resource usage data before they
	 * become contaminated by p_cacct etc., and before we renounce
	 * membership of the task.
	 *
	 * We do this regardless of whether or not task accounting is active.
	 * This is to avoid having nonsense data reported for this task if
	 * task accounting is subsequently enabled. The overhead is minimal;
	 * by this point, this process has accounted for the usage of all its
	 * LWPs. We nonetheless do the work here, and under the protection of
	 * pidlock, so that the movement of the process's usage to the task
	 * happens at the same time as the removal of the process from the
	 * task, from the point of view of exacct_snapshot_task_usage().
	 */
	exacct_update_task_mstate(p);

	hrutime = mstate_aggr_state(p, LMS_USER);
	hrstime = mstate_aggr_state(p, LMS_SYSTEM);
	p->p_utime = (clock_t)NSEC_TO_TICK(hrutime) + p->p_cutime;
	p->p_stime = (clock_t)NSEC_TO_TICK(hrstime) + p->p_cstime;

	p->p_acct[LMS_USER]	+= p->p_cacct[LMS_USER];
	p->p_acct[LMS_SYSTEM]	+= p->p_cacct[LMS_SYSTEM];
	p->p_acct[LMS_TRAP]	+= p->p_cacct[LMS_TRAP];
	p->p_acct[LMS_TFAULT]	+= p->p_cacct[LMS_TFAULT];
	p->p_acct[LMS_DFAULT]	+= p->p_cacct[LMS_DFAULT];
	p->p_acct[LMS_KFAULT]	+= p->p_cacct[LMS_KFAULT];
	p->p_acct[LMS_USER_LOCK] += p->p_cacct[LMS_USER_LOCK];
	p->p_acct[LMS_SLEEP]	+= p->p_cacct[LMS_SLEEP];
	p->p_acct[LMS_WAIT_CPU]	+= p->p_cacct[LMS_WAIT_CPU];
	p->p_acct[LMS_STOPPED]	+= p->p_cacct[LMS_STOPPED];

	p->p_ru.minflt	+= p->p_cru.minflt;
	p->p_ru.majflt	+= p->p_cru.majflt;
	p->p_ru.nswap	+= p->p_cru.nswap;
	p->p_ru.inblock	+= p->p_cru.inblock;
	p->p_ru.oublock	+= p->p_cru.oublock;
	p->p_ru.msgsnd	+= p->p_cru.msgsnd;
	p->p_ru.msgrcv	+= p->p_cru.msgrcv;
	p->p_ru.nsignals += p->p_cru.nsignals;
	p->p_ru.nvcsw	+= p->p_cru.nvcsw;
	p->p_ru.nivcsw	+= p->p_cru.nivcsw;
	p->p_ru.sysc	+= p->p_cru.sysc;
	p->p_ru.ioch	+= p->p_cru.ioch;

	p->p_stat = SZOMB;
	p->p_proc_flag &= ~P_PR_PTRACE;
	p->p_wdata = what;
	p->p_wcode = (char)why;

	cdir = PTOU(p)->u_cdir;
	rdir = PTOU(p)->u_rdir;
	cwd = PTOU(p)->u_cwd;

	ASSERT(cdir != NULL || p->p_parent == &p0);

	/*
	 * Release resource controls, as they are no longer enforceable.
	 */
	rctl_set_free(p->p_rctls);

	/*
	 * Decrement tk_nlwps counter for our task.max-lwps resource control.
	 * An extended accounting record, if that facility is active, is
	 * scheduled to be written.  We cannot give up task and project
	 * membership at this point because that would allow zombies to escape
	 * from the max-processes resource controls.  Zombies stay in their
	 * current task and project until the process table slot is released
	 * in freeproc().
	 */
	tk = p->p_task;

	mutex_enter(&p->p_zone->zone_nlwps_lock);
	tk->tk_nlwps--;
	tk->tk_proj->kpj_nlwps--;
	p->p_zone->zone_nlwps--;
	mutex_exit(&p->p_zone->zone_nlwps_lock);

	/*
	 * Clear the lwp directory and the lwpid hash table
	 * now that /proc can't bother us any more.
	 * We free the memory below, after dropping p->p_lock.
	 */
	lwpdir = p->p_lwpdir;
	lwpdir_sz = p->p_lwpdir_sz;
	tidhash = p->p_tidhash;
	tidhash_sz = p->p_tidhash_sz;
	ret_tidhash = p->p_ret_tidhash;
	p->p_lwpdir = NULL;
	p->p_lwpfree = NULL;
	p->p_lwpdir_sz = 0;
	p->p_tidhash = NULL;
	p->p_tidhash_sz = 0;
	p->p_ret_tidhash = NULL;

	/*
	 * If the process has context ops installed, call the exit routine
	 * on behalf of this last remaining thread. Normally exitpctx() is
	 * called during thread_exit() or lwp_exit(), but because this is the
	 * last thread in the process, we must call it here. By the time
	 * thread_exit() is called (below), the association with the relevant
	 * process has been lost.
	 *
	 * We also free the context here.
	 */
	if (p->p_pctx) {
		kpreempt_disable();
		exitpctx(p);
		kpreempt_enable();

		freepctx(p, 0);
	}

	/*
	 * curthread's proc pointer is changed to point to the 'sched'
	 * process for the corresponding zone, except in the case when
	 * the exiting process is in fact a zsched instance, in which
	 * case the proc pointer is set to p0.  We do so, so that the
	 * process still points at the right zone when we call the VN_RELE()
	 * below.
	 *
	 * This is because curthread's original proc pointer can be freed as
	 * soon as the child sends a SIGCLD to its parent.  We use zsched so
	 * that for user processes, even in the final moments of death, the
	 * process is still associated with its zone.
	 */
	if (p != t->t_procp->p_zone->zone_zsched)
		t->t_procp = t->t_procp->p_zone->zone_zsched;
	else
		t->t_procp = &p0;

	mutex_exit(&p->p_lock);
	if (!evaporate) {
		p->p_pidflag &= ~CLDPEND;
		sigcld(p, sqp);
	} else {
		/*
		 * Do what sigcld() would do if the disposition
		 * of the SIGCHLD signal were set to be ignored.
		 */
		cv_broadcast(&p->p_srwchan_cv);
		freeproc(p);
	}
	mutex_exit(&pidlock);

	/*
	 * We don't release u_cdir and u_rdir until SZOMB is set.
	 * This protects us against dofusers().
	 */
	if (cdir)
		VN_RELE(cdir);
	if (rdir)
		VN_RELE(rdir);
	if (cwd)
		refstr_rele(cwd);

	/*
	 * task_rele() may ultimately cause the zone to go away (or
	 * may cause the last user process in a zone to go away, which
	 * signals zsched to go away).  So prior to this call, we must
	 * no longer point at zsched.
	 */
	t->t_procp = &p0;

	kmem_free(lwpdir, lwpdir_sz * sizeof (lwpdir_t));
	kmem_free(tidhash, tidhash_sz * sizeof (tidhash_t));
	while (ret_tidhash != NULL) {
		ret_tidhash_t *next = ret_tidhash->rth_next;
		kmem_free(ret_tidhash->rth_tidhash,
		    ret_tidhash->rth_tidhash_sz * sizeof (tidhash_t));
		kmem_free(ret_tidhash, sizeof (*ret_tidhash));
		ret_tidhash = next;
	}

	thread_exit();
	/* NOTREACHED */
}
int main ( int argc, char **argv )
{
	
	int n, m, ndx1a, ndx1b, ndx2a, ndx2b, fdin1 = 0, fdin2 = 0, fdout = 0;
	char buf1[ BUFSZ ], buf2[ BUFSZ ];
	char ch = '\n';

	if ( argc < 3 ){
		write( STDERR_FILENO, "Usage: ",7 );
		write( STDERR_FILENO, argv[0],strlen(argv[0]) );
		write( STDERR_FILENO, " <file1> <file2> [file.out]\n",28 );
		exit(-1);
	}

	if ( ( strcmp(argv[1], "-") == 0 ) && ( strcmp(argv[2], "-") == 0) ){
		write( STDERR_FILENO, "Error: file1 and file2 cannot both be -\n", 40);
		exit(-1);
	}

	if ( strcmp(argv[1], "-") == 0 ){
		fdin1 = STDIN_FILENO;
	}else if( ( fdin1 = open( argv[1], O_RDONLY ) ) < 0 ){
			perror( argv[1] );
			closeall( fdin1,fdin2,fdout );
			exit( -1 );
	}

	if ( strcmp(argv[2],"-") == 0){
		fdin2 = STDIN_FILENO;
	}else if( ( fdin2 = open(argv[2], O_RDONLY ) ) < 0 ){
			perror( argv[2] );
			closeall( fdin1, fdin2, fdout );
			exit( -1 );
	}

	if ( argc == 4 ){
		if ( ( fdout = open( argv[3],O_WRONLY | O_APPEND | O_TRUNC | O_CREAT, 0666 ) ) < 0){
			perror( argv[3] );
			closeall( fdin1, fdin2, fdout );
			exit( -1 );
		}
	}else{
		fdout = STDOUT_FILENO;
	}

	while ( ( n = read( fdin1, buf1, BUFSZ ) ) > 0 && ( m = read( fdin2, buf2, BUFSZ ) ) > 0 ){
		ndx1a = 0, ndx1b = 0, ndx2a = 0, ndx2b = 0;
		/* If the buf1's or buf2's forward ndx (ndx1a and ndx2a respectively) are less than
		 * the location of the data read in for each buffer (n and m respectively), then 
		 * the loop is entered.  Inside the loop, must still test to see which buffer has
		 * data in it, hence the if statements. 
		 */
		while ( ndx1a < n || ndx2a < m ){
			if ( ndx1a < n ){
				/* Previous index ( last char to be read in ) is stored by ndx1b and
				 * ndx2b.  Before write anything, the forward index gets passed to the
				 * back index.
				 */
				ndx1b = ndx1a;
				for( ; ndx1a < n ; ndx1a++ ){
					if( buf1[ ndx1a ] == ch ){
						ndx1a++;
						break;
					}
				}
				if ( write( fdout, &buf1[ ndx1b ], ( &buf1[ ndx1a ] - &buf1[ ndx1b ] ) ) != ( &buf1[ ndx1a ] - &buf1[ ndx1b ] ) ){
					perror( argv[3] );
					closeall( fdin1, fdin2, fdout );
					exit( -1 );
				}
			}
			
			if ( ndx2a < m ){
				ndx2b = ndx2a;
				for ( ; ndx2a < m ; ndx2a++ ){
					if ( buf2[ ndx2a ] == ch ){;
						ndx2a++;
						break;
					}
				}
				if ( write( fdout, &buf2[ ndx2b ], ( &buf2[ ndx2a ] - &buf2[ ndx2b ] ) ) != ( &buf2[ ndx2a ] - &buf2[ ndx2b ] ) ){
					perror( argv[3] );
					closeall( fdin1, fdin2, fdout );
					exit( -1 );
				}
			}
		}
	}
	if ( n < 0 || m < 0 ){
		perror ( "read error" );
		closeall( fdin1, fdin2, fdout );
		exit( -1 );
	}

	if ( n > 0 ){
		if ( write( fdout, buf1, n ) != n ){
			perror( argv[ 3 ] );
			closeall( fdin1, fdin2, fdout );
			exit( -1 );
		}
		while ( (n = read( fdin1, buf1, BUFSZ ) ) > 0 ){
			if ( write( fdout, buf1, n ) != n ){
				perror ( argv[ 3 ] );
				closeall( fdin1, fdin2, fdout );
				exit( -1 );
			}
		}
		if ( n < 0 ){
			perror ( "read error" );
			closeall( fdin1, fdin2, fdout );
			exit( -1 );
		}
	}
	
	if ( m > 0 ){
		if ( write( fdout, buf2, m ) != m ){
			perror ( argv[ 3 ] );
			closeall( fdin1, fdin2, fdout );
			exit( -1 );
		}
		while ( ( m = read( fdin2, buf2, BUFSZ ) ) > 0 ){
			if ( write( fdout, buf2, m ) != m ){
				perror( argv[ 3 ] );
				closeall( fdin1, fdin2, fdout );
				exit( -1 );
			}
		}
		if ( m < 0 ){
			perror ( "read error" );
			closeall( fdin1, fdin2, fdout );
			exit( -1 );
		}
	}


	closeall( fdin1, fdin2, fdout );
	exit( 0 );
}