⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 4 页
字号:
    } else {	while (waitpid(pid, &status, 0) < 0) {	    if (errno == EINTR)		continue;	    fatal("error waiting for (dis)connection process: %m");	}	--conn_running;    }    return (status == 0 ? 0 : -1);}/* * run-program - execute a program with given arguments, * but don't wait for it. * If the program can't be executed, logs an error unless * must_exist is 0 and the program file doesn't exist. * Returns -1 if it couldn't fork, 0 if the file doesn't exist * or isn't an executable plain file, or the process ID of the child. * If done != NULL, (*done)(arg) will be called later (within * reap_kids) iff the return value is > 0. */pid_trun_program(prog, args, must_exist, done, arg)    char *prog;    char **args;    int must_exist;    void (*done) __P((void *));    void *arg;{    int pid;    struct stat sbuf;    /*     * First check if the file exists and is executable.     * We don't use access() because that would use the     * real user-id, which might not be root, and the script     * might be accessible only to root.     */    errno = EINVAL;    if (stat(prog, &sbuf) < 0 || !S_ISREG(sbuf.st_mode)	|| (sbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) {	if (must_exist || errno != ENOENT)	    warn("Can't execute %s: %m", prog);	return 0;    }    pid = fork();    if (pid == -1) {	error("Failed to create child process for %s: %m", prog);	return -1;    }    if (pid == 0) {	int new_fd;	/* Leave the current location */	(void) setsid();	/* No controlling tty. */	(void) umask (S_IRWXG|S_IRWXO);	(void) chdir ("/");	/* no current directory. */	setuid(0);		/* set real UID = root */	setgid(getegid());	/* Ensure that nothing of our device environment is inherited. */	sys_close();	closelog();	close (0);	close (1);	close (2);	close (ttyfd);  /* tty interface to the ppp device */	if (real_ttyfd >= 0)	    close(real_ttyfd);        /* Don't pass handles to the PPP device, even by accident. */	new_fd = open (_PATH_DEVNULL, O_RDWR);	if (new_fd >= 0) {	    if (new_fd != 0) {	        dup2  (new_fd, 0); /* stdin <- /dev/null */		close (new_fd);	    }	    dup2 (0, 1); /* stdout -> /dev/null */	    dup2 (0, 2); /* stderr -> /dev/null */	}#ifdef BSD	/* Force the priority back to zero if pppd is running higher. */	if (setpriority (PRIO_PROCESS, 0, 0) < 0)	    warn("can't reset priority to 0: %m"); #endif	/* SysV recommends a second fork at this point. */	/* run the program */	execve(prog, args, script_env);	if (must_exist || errno != ENOENT) {	    /* have to reopen the log, there's nowhere else	       for the message to go. */	    reopen_log();	    syslog(LOG_ERR, "Can't execute %s: %m", prog);	    closelog();	}	_exit(-1);    }    if (debug)	dbglog("Script %s started (pid %d)", prog, pid);    record_child(pid, prog, done, arg);    return pid;}/* * record_child - add a child process to the list for reap_kids * to use. */static voidrecord_child(pid, prog, done, arg)    int pid;    char *prog;    void (*done) __P((void *));    void *arg;{    struct subprocess *chp;    ++n_children;    chp = (struct subprocess *) malloc(sizeof(struct subprocess));    if (chp == NULL) {	warn("losing track of %s process", prog);    } else {	chp->pid = pid;	chp->prog = prog;	chp->done = done;	chp->arg = arg;	chp->next = children;	children = chp;    }}/* * reap_kids - get status from any dead child processes, * and log a message for abnormal terminations. */static intreap_kids(waitfor)    int waitfor;{    int pid, status;    struct subprocess *chp, **prevp;    got_sigchld = 0;    if (n_children == 0)	return 0;    while ((pid = waitpid(-1, &status, (waitfor? 0: WNOHANG))) != -1	   && pid != 0) {	--n_children;	for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) {	    if (chp->pid == pid) {		*prevp = chp->next;		break;	    }	}	if (WIFSIGNALED(status)) {	    warn("Child process %s (pid %d) terminated with signal %d",		 (chp? chp->prog: "??"), pid, WTERMSIG(status));	} else if (debug)	    dbglog("Script %s finished (pid %d), status = 0x%x",		   (chp? chp->prog: "??"), pid, status);	if (chp && chp->done)	    (*chp->done)(chp->arg);	if (chp)	    free(chp);    }    if (pid == -1) {	if (errno == ECHILD)	    return -1;	if (errno != EINTR)	    error("Error waiting for child process: %m");    }    return 0;}/* * novm - log an error message saying we ran out of memory, and die. */voidnovm(msg)    char *msg;{    fatal("Virtual memory exhausted allocating %s\n", msg);}/* * script_setenv - set an environment variable value to be used * for scripts that we run (e.g. ip-up, auth-up, etc.) */voidscript_setenv(var, value)    char *var, *value;{    size_t vl = strlen(var) + strlen(value) + 2;    int i;    char *p, *newstring;    newstring = (char *) malloc(vl);    if (newstring == 0)	return;    slprintf(newstring, vl, "%s=%s", var, value);    /* check if this variable is already set */    if (script_env != 0) {	for (i = 0; (p = script_env[i]) != 0; ++i) {	    if (strncmp(p, var, vl) == 0 && p[vl] == '=') {		free(p);		script_env[i] = newstring;		return;	    }	}    } else {	/* no space allocated for script env. ptrs. yet */	i = 0;	script_env = (char **) malloc(16 * sizeof(char *));	if (script_env == 0)	    return;	s_env_nalloc = 16;    }    /* reallocate script_env with more space if needed */    if (i + 1 >= s_env_nalloc) {	int new_n = i + 17;	char **newenv = (char **) realloc((void *)script_env,					  new_n * sizeof(char *));	if (newenv == 0)	    return;	script_env = newenv;	s_env_nalloc = new_n;    }    script_env[i] = newstring;    script_env[i+1] = 0;}/* * script_unsetenv - remove a variable from the environment * for scripts. */voidscript_unsetenv(var)    char *var;{    int vl = strlen(var);    int i;    char *p;    if (script_env == 0)	return;    for (i = 0; (p = script_env[i]) != 0; ++i) {	if (strncmp(p, var, vl) == 0 && p[vl] == '=') {	    free(p);	    while ((script_env[i] = script_env[i+1]) != 0)		++i;	    break;	}    }}/* * start_charshunt - create a child process to run the character shunt. */static intstart_charshunt(ifd, ofd)    int ifd, ofd;{    int cpid;    cpid = fork();    if (cpid == -1) {	error("Can't fork process for character shunt: %m");	return 0;    }    if (cpid == 0) {	/* child */	close(pty_slave);	setuid(uid);	if (getuid() != uid)	    fatal("setuid failed");	setgid(getgid());	if (!nodetach)	    log_to_fd = -1;	charshunt(ifd, ofd, record_file);	exit(0);    }    charshunt_pid = cpid;    close(pty_master);    pty_master = -1;    ttyfd = pty_slave;    record_child(cpid, "pppd (charshunt)", charshunt_done, NULL);    return 1;}static voidcharshunt_done(arg)    void *arg;{    charshunt_pid = 0;}/* * charshunt - the character shunt, which passes characters between * the pty master side and the serial port (or stdin/stdout). * This runs as the user (not as root). * (We assume ofd >= ifd which is true the way this gets called. :-). */static voidcharshunt(ifd, ofd, record_file)    int ifd, ofd;    char *record_file;{    int n, nfds;    fd_set ready, writey;    u_char *ibufp, *obufp;    int nibuf, nobuf;    int flags;    int pty_readable, stdin_readable;    struct timeval lasttime;    FILE *recordf = NULL;    /*     * Reset signal handlers.     */    signal(SIGHUP, SIG_IGN);		/* Hangup */    signal(SIGINT, SIG_DFL);		/* Interrupt */    signal(SIGTERM, SIG_DFL);		/* Terminate */    signal(SIGCHLD, SIG_DFL);    signal(SIGUSR1, SIG_DFL);    signal(SIGUSR2, SIG_DFL);    signal(SIGABRT, SIG_DFL);    signal(SIGALRM, SIG_DFL);    signal(SIGFPE, SIG_DFL);    signal(SIGILL, SIG_DFL);    signal(SIGPIPE, SIG_DFL);    signal(SIGQUIT, SIG_DFL);    signal(SIGSEGV, SIG_DFL);#ifdef SIGBUS    signal(SIGBUS, SIG_DFL);#endif#ifdef SIGEMT    signal(SIGEMT, SIG_DFL);#endif#ifdef SIGPOLL    signal(SIGPOLL, SIG_DFL);#endif#ifdef SIGPROF    signal(SIGPROF, SIG_DFL);#endif#ifdef SIGSYS    signal(SIGSYS, SIG_DFL);#endif#ifdef SIGTRAP    signal(SIGTRAP, SIG_DFL);#endif#ifdef SIGVTALRM    signal(SIGVTALRM, SIG_DFL);#endif#ifdef SIGXCPU    signal(SIGXCPU, SIG_DFL);#endif#ifdef SIGXFSZ    signal(SIGXFSZ, SIG_DFL);#endif    /*     * Open the record file if required.     */    if (record_file != NULL) {	recordf = fopen(record_file, "a");	if (recordf == NULL)	    error("Couldn't create record file %s: %m", record_file);    }    /* set all the fds to non-blocking mode */    flags = fcntl(pty_master, F_GETFL);    if (flags == -1	|| fcntl(pty_master, F_SETFL, flags | O_NONBLOCK) == -1)	warn("couldn't set pty master to nonblock: %m");    flags = fcntl(ifd, F_GETFL);    if (flags == -1	|| fcntl(ifd, F_SETFL, flags | O_NONBLOCK) == -1)	warn("couldn't set %s to nonblock: %m", (ifd==0? "stdin": "tty"));    if (ofd != ifd) {	flags = fcntl(ofd, F_GETFL);	if (flags == -1	    || fcntl(ofd, F_SETFL, flags | O_NONBLOCK) == -1)	    warn("couldn't set stdout to nonblock: %m");    }    nibuf = nobuf = 0;    ibufp = obufp = NULL;    pty_readable = stdin_readable = 1;    nfds = (ofd > pty_master? ofd: pty_master) + 1;    if (recordf != NULL) {	gettimeofday(&lasttime, NULL);	putc(7, recordf);	/* put start marker */	putc(lasttime.tv_sec >> 24, recordf);	putc(lasttime.tv_sec >> 16, recordf);	putc(lasttime.tv_sec >> 8, recordf);	putc(lasttime.tv_sec, recordf);	lasttime.tv_usec = 0;    }    while (nibuf != 0 || nobuf != 0 || pty_readable || stdin_readable) {	FD_ZERO(&ready);	FD_ZERO(&writey);	if (nibuf != 0)	    FD_SET(pty_master, &writey);	else if (stdin_readable)	    FD_SET(ifd, &ready);	if (nobuf != 0)	    FD_SET(ofd, &writey);	else if (pty_readable)	    FD_SET(pty_master, &ready);	if (select(nfds, &ready, &writey, NULL, NULL) < 0) {	    if (errno != EINTR)		fatal("select");	    continue;	}	if (FD_ISSET(ifd, &ready)) {	    ibufp = inpacket_buf;	    nibuf = read(ifd, ibufp, sizeof(inpacket_buf));	    if (nibuf < 0 && errno == EIO)		nibuf = 0;	    if (nibuf < 0) {		if (!(errno == EINTR || errno == EAGAIN)) {		    error("Error reading standard input: %m");		    break;		}		nibuf = 0;	    } else if (nibuf == 0) {		/* end of file from stdin */		stdin_readable = 0;		/* do a 0-length write, hopefully this will generate		   an EOF (hangup) on the slave side. */		write(pty_master, inpacket_buf, 0);		if (recordf)		    if (!record_write(recordf, 4, NULL, 0, &lasttime))			recordf = NULL;	    } else {		FD_SET(pty_master, &writey);		if (recordf)		    if (!record_write(recordf, 2, ibufp, nibuf, &lasttime))			recordf = NULL;	    }	}	if (FD_ISSET(pty_master, &ready)) {	    obufp = outpacket_buf;	    nobuf = read(pty_master, obufp, sizeof(outpacket_buf));	    if (nobuf < 0 && errno == EIO)		nobuf = 0;	    if (nobuf < 0) {		if (!(errno == EINTR || errno == EAGAIN)) {		    error("Error reading pseudo-tty master: %m");		    break;		}		nobuf = 0;	    } else if (nobuf == 0) {		/* end of file from the pty - slave side has closed */		pty_readable = 0;		stdin_readable = 0;	/* pty is not writable now */		nibuf = 0;		close(ofd);		if (recordf)		    if (!record_write(recordf, 3, NULL, 0, &lasttime))			recordf = NULL;	    } else {		FD_SET(ofd, &writey);		if (recordf)		    if (!record_write(recordf, 1, obufp, nobuf, &lasttime))			recordf = NULL;	    }	}	if (FD_ISSET(ofd, &writey)) {	    n = write(ofd, obufp, nobuf);	    if (n < 0) {		if (errno != EIO) {		    error("Error writing standard output: %m");		    break;		}		pty_readable = 0;		nobuf = 0;	    } else {		obufp += n;		nobuf -= n;	    }	}	if (FD_ISSET(pty_master, &writey)) {	    n = write(pty_master, ibufp, nibuf);	    if (n < 0) {		if (errno != EIO) {		    error("Error writing pseudo-tty master: %m");		    break;		}		stdin_readable = 0;		nibuf = 0;	    } else {		ibufp += n;		nibuf -= n;	    }	}    }    exit(0);}static intrecord_write(f, code, buf, nb, tp)    FILE *f;    int code;    u_char *buf;    int nb;    struct timeval *tp;{    struct timeval now;    int diff;    gettimeofday(&now, NULL);    now.tv_usec /= 100000;	/* actually 1/10 s, not usec now */    diff = (now.tv_sec - tp->tv_sec) * 10 + (now.tv_usec - tp->tv_usec);    if (diff > 0) {	if (diff > 255) {	    putc(5, f);	    putc(diff >> 24, f);	    putc(diff >> 16, f);	    putc(diff >> 8, f);	    putc(diff, f);	} else {	    putc(6, f);	    putc(diff, f);	}	*tp = now;    }    putc(code, f);    if (buf != NULL) {	putc(nb >> 8, f);	putc(nb, f);	fwrite(buf, nb, 1, f);    }    fflush(f);    if (ferror(f)) {	error("Error writing record file: %m");	return 0;    }    return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -