示例#1
0
文件: main.c 项目: EmisFR/burp
static int init_listen_socket(const char *address, const char *port, int *fds)
{
	int i;
	int gai_ret;
	struct addrinfo hints;
	struct addrinfo *rp=NULL;
	struct addrinfo *info=NULL;

	close_fds(fds);

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family=AF_UNSPEC;
	hints.ai_socktype=SOCK_STREAM;
	hints.ai_protocol=IPPROTO_TCP;
	hints.ai_flags=AI_NUMERICHOST;
	hints.ai_flags|=AI_PASSIVE;

	if((gai_ret=getaddrinfo(address, port, &hints, &info)))
	{
		logp("unable to getaddrinfo on port %s: %s\n",
			port, gai_strerror(gai_ret));
		return -1;
	}

	i=0;
	for(rp=info; rp && i<LISTEN_SOCKETS; rp=rp->ai_next)
	{
		fds[i]=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
		if(fds[i]<0)
		{
			logp("unable to create socket on port %s: %s\n",
				port, strerror(errno));
			continue;
		}
		set_keepalive(fds[i], 1);
#ifdef HAVE_IPV6
		if(rp->ai_family==AF_INET6)
		{
			// Attempt to say that it should not listen on IPv6
			// only.
			int optval=0;
			setsockopt(fds[i], IPPROTO_IPV6, IPV6_V6ONLY,
				&optval, sizeof(optval));
		}
#endif
		reuseaddr(fds[i]);
		if(bind(fds[i], rp->ai_addr, rp->ai_addrlen))
		{
			logp("unable to bind socket on port %s: %s\n",
				port, strerror(errno));
			close(fds[i]);
			fds[i]=-1;
			continue;
		}

		// Say that we are happy to accept connections.
		if(listen(fds[i], 5)<0)
		{
			close_fd(&(fds[i]));
			logp("could not listen on main socket %s\n", port);
			return -1;
		}

#ifdef HAVE_WIN32
		{
			u_long ioctlArg=0;
			ioctlsocket(fds[i], FIONBIO, &ioctlArg);
		}
#endif
		i++;
	}

	freeaddrinfo(info);

	if(!i)
	{
		logp("could not listen on address: %s\n", address);
#ifdef HAVE_IPV6
		if(strchr(address, ':'))
			logp("maybe check whether your OS has IPv6 enabled.\n");
#endif
		return -1;
	}

	return 0;
}
示例#2
0
文件: ttymsg.c 项目: 0xAX/util-linux
/*
 * Display the contents of a uio structure on a terminal.  Used by wall(1),
 * syslogd(8), and talkd(8).  Forks and finishes in child if write would block,
 * waiting up to tmout seconds.  Returns pointer to error string on unexpected
 * error; string is not newline-terminated.  Various "normal" errors are
 * ignored (exclusive-use, lack of permission, etc.).
 */
char *
ttymsg(struct iovec *iov, size_t iovcnt, char *line, int tmout) {
	static char device[MAXNAMLEN];
	static char errbuf[ERR_BUFLEN];
	size_t cnt, left;
	ssize_t wret;
	struct iovec localiov[6];
	int fd, forked = 0;
	ssize_t	len = 0;

	if (iovcnt > ARRAY_SIZE(localiov)) {
		snprintf(errbuf, sizeof(errbuf), _("internal error: too many iov's"));
		return errbuf;
	}

	/* The old code here rejected the line argument when it contained a '/',
	   saying: "A slash may be an attempt to break security...".
	   However, if a user can control the line argument here
	   then he can make this routine write to /dev/hda or /dev/sda
	   already. So, this test was worthless, and these days it is
	   also wrong since people use /dev/pts/xxx. */

	len = snprintf(device, sizeof(device), "%s%s", _PATH_DEV, line);
	if (len < 0 || (size_t)len >= sizeof(device)) {
		snprintf(errbuf, sizeof(errbuf), _("excessively long line arg"));
		return errbuf;
	}

	/*
	 * open will fail on slip lines or exclusive-use lines
	 * if not running as root; not an error.
	 */
	if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
		if (errno == EBUSY || errno == EACCES)
			return NULL;

		len = snprintf(errbuf, sizeof(errbuf), "%s: %m", device);
		if (len < 0 || (size_t)len >= sizeof(errbuf))
			snprintf(errbuf, sizeof(errbuf), _("open failed"));
		return errbuf;
	}

	for (cnt = left = 0; cnt < iovcnt; ++cnt)
		left += iov[cnt].iov_len;

	for (;;) {
		wret = writev(fd, iov, iovcnt);
		if (wret >= (ssize_t) left)
			break;
		if (wret >= 0) {
			left -= wret;
			if (iov != localiov) {
				memmove(localiov, iov,
				    iovcnt * sizeof(struct iovec));
				iov = localiov;
			}
			for (cnt = 0; wret >= (ssize_t) iov->iov_len; ++cnt) {
				wret -= iov->iov_len;
				++iov;
				--iovcnt;
			}
			if (wret) {
				iov->iov_base = (char *) iov->iov_base + wret;
				iov->iov_len -= wret;
			}
			continue;
		}
		if (errno == EWOULDBLOCK) {
			int cpid, flags;
			sigset_t sigmask;

			if (forked) {
				close(fd);
				_exit(EXIT_FAILURE);
			}
			cpid = fork();
			if (cpid < 0) {
				len = snprintf(errbuf, sizeof(errbuf), _("fork: %m"));
				if (len < 0 || (size_t)len >= sizeof(errbuf))
					snprintf(errbuf, sizeof(errbuf), _("cannot fork"));
				close(fd);
				return errbuf;
			}
			if (cpid) {	/* parent */
				close(fd);
				return NULL;
			}
			forked++;
			/* wait at most tmout seconds */
			signal(SIGALRM, SIG_DFL);
			signal(SIGTERM, SIG_DFL); /* XXX */
			sigemptyset(&sigmask);
			sigprocmask (SIG_SETMASK, &sigmask, NULL);
			alarm((u_int)tmout);
			flags = fcntl(fd, F_GETFL);
			fcntl(flags, F_SETFL, (long) (flags & ~O_NONBLOCK));
			continue;
		}
		/*
		 * We get ENODEV on a slip line if we're running as root,
		 * and EIO if the line just went away.
		 */
		if (errno == ENODEV || errno == EIO)
			break;
		if (close_fd(fd) != 0)
			warn(_("write failed: %s"), device);
		if (forked)
			_exit(EXIT_FAILURE);

		len = snprintf(errbuf, sizeof(errbuf), "%s: %m", device);
		if (len < 0 || (size_t)len >= sizeof(errbuf))
			snprintf(errbuf, sizeof(errbuf),
					_("%s: BAD ERROR, message is "
					  "far too long"), device);
		return errbuf;
	}

	if (forked)
		_exit(EXIT_SUCCESS);
	return NULL;
}
示例#3
0
文件: w32pipe.c 项目: jrmiddle/vile
static int
tmp_inout_popen(FILE **fr, FILE **fw, char *cmd)
{
    char  buf[NFILEN + 128];
    DWORD dummy, len;
    int   rc, term_status, tmpin_fd;

    TRACE(("tmp_inout_popen cmd=%s\n", cmd));
    proc_handle = BAD_PROC_HANDLE;
    handles[0]  = handles[1] = handles[2]  = INVALID_HANDLE_VALUE;
    tmpin_fd    = stdin_fd   = stdout_fd   = BAD_FD;
    tmpin_name  = stdin_name = stdout_name = NULL;
    set_console_title(cmd);
    do
    {
        if (fr)
        {
            *fr = NULL;
            if ((stdin_name = _tempnam(getenv("TEMP"), "vile")) == NULL)
                break;
            if ((stdin_fd = open(stdin_name,
                                 O_RDWR|O_CREAT|O_TRUNC|O_TEXT,
                                 _S_IWRITE|_S_IREAD)) == BAD_FD)
            {
                break;
            }
            handles[2] = handles[1] = (HANDLE) _get_osfhandle(stdin_fd);
            if (! fw)
            {
                /*
                 * This is a read pipe (only).  Connect child's stdin to
                 * an empty file.  Under no circumstances should the
                 * child's stdin be connected to a device (else lots of
                 * screwy things will occur).  In particular, connecting
                 * the child's stdin to the parent's stdin will cause
                 * aborts and hangs on the various Win32 hosts.  You've
                 * been warned.
                 */

                if ((tmpin_name = _tempnam(getenv("TEMP"), "vile")) == NULL)
                    break;
                if ((tmpin_fd = open(tmpin_name,
                                     O_RDONLY|O_CREAT|O_TRUNC,
                                     _S_IWRITE|_S_IREAD)) == BAD_FD)
                {
                    break;
                }
                handles[0] = (HANDLE) _get_osfhandle(tmpin_fd);
            }
            else
            {
                /*
                 * Set up descriptor for filter operation.   Note the
                 * sublteties here:  exec'd shell is passed a descriptor
                 * to the temp file that's opened "w".  The editor
                 * receives a descriptor to the file that's opened "r".
                 */

                if ((*fr = fopen(stdin_name, "r")) == NULL)
                    break;
            }
        }
        if (fw)
        {
            *fw = NULL;

            /* create a temp file to receive data from the editor */
            if ((stdout_name = _tempnam(getenv("TEMP"), "vile")) == NULL)
                break;
            if ((stdout_fd = open(stdout_name,
                                  O_RDWR|O_CREAT|O_TRUNC|O_BINARY,
                                  _S_IWRITE|_S_IREAD)) == BAD_FD)
            {
                break;
            }
            if ((*fw = fdopen(stdout_fd, "w")) == 0)
                break;

            /*
             * we're all set up, but can't exec "cmd" until the editor
             * writes data to the temp file connected to stdout.
             */
            shcmd = cmd;   /* remember this */
            return (TRUE);
        }

        /* This must be a read (only) pipe.  Appropriate to exec "cmd". */
        rc = (exec_shell(cmd,
                         handles,
                         TRUE       /* hide child wdw */
                        ) == BAD_PROC_HANDLE) ? FALSE : TRUE;

        if (! rc)
        {
            /*
             * Shell process failed, put complaint in user's buffer, which
             * is currently proxied by a temp file that the editor will
             * suck in shortly.
             */

            len = (DWORD) (lsprintf(buf, SHELL_ERR_MSG, get_shell()) - buf);
            (void) WriteFile(handles[1], buf, len, &dummy, NULL);
            FlushFileBuffers(handles[1]);
        }
        else
        {
            /* wait for exec'd process to exit */

            (void) cwait(&term_status, (CWAIT_PARAM_TYPE) proc_handle, 0);
            TRACE(("...CreateProcess finished waiting in tmp_inout_popen\n"));
            close_proc_handle();
        }

        /*
         * When closing descriptors shared between parent and child, order
         * is quite important when $shell == command.com .  In this
         * situation, the descriptors can't be closed until the exec'd
         * process exits (I kid you not).
         */
        close_fd(stdin_fd);
        (void) close(tmpin_fd);

        /* let the editor consume the output of the read pipe */
        if ((*fr = fopen(stdin_name, "r")) == NULL)
        {
            /*
             * impossible to put error in user's buffer since that file
             * descriptor is closed.
             */

            sprintf(buf,
                    "[error opening temp file \"%s\": %s]",
                    stdin_name,
                    strerror(errno));
            lastditch_msg(buf);
            break;
        }
        return (rc);
    }
    while (FALSE);

    /* If we get here -- some operation has failed.  Clean up. */
    tmp_cleanup();
    return (FALSE);
}
示例#4
0
int recv_message(const char * host_name, char * message, size_t message_size)
{
	int rv;
	
	struct addrinfo hints =
	{
		.ai_family = AF_UNSPEC,
		.ai_socktype = SOCK_STREAM
	};

	struct addrinfo * servinfo;	
	const char * port = "3490";  	
	rv = getaddrinfo(host_name, port, &hints, &servinfo);
	if (rv != 0)
	{
		fputs("getaddrinfo: ", stderr);
		fputs(gai_strerror(rv) ,stderr);
		fputc('\n', stderr);
    return EXIT_FAILURE;
	}

	// loop through all the results and connect to the first we can
	int sock_fd;
	struct addrinfo * p;
	for (p = servinfo; p; p = p->ai_next)
	{
		sock_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
		if (sock_fd == -1)
		{
			perror("socket");
			continue;
		}
		rv = connect(sock_fd, p->ai_addr, p->ai_addrlen);
		if (rv == -1)
		{
			perror("connect");
			close_fd(sock_fd);
			continue;
		}
		break;
	}
	if (!p)
	{
		fputs("client: failed to connect\n", stderr);
		close_fd(sock_fd);		
    return EXIT_FAILURE;
	}

	char address[INET6_ADDRSTRLEN];
	const char * dst = inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), address, sizeof address);
	if (dst == NULL)
	{
		perror("inet_ntop");
		close_fd(sock_fd);				
    return EXIT_FAILURE;
	}
	freeaddrinfo(servinfo); // all done with this structure

	fputs("client: connecting to ", stdout);
	fputs(address, stdout);
	fputc('\n', stdout);
	
	const int num_bytes = recv(sock_fd, message, message_size - 1, 0);
	if (num_bytes == -1)
	{
	    perror("recv");
			close_fd(sock_fd);							
	    return EXIT_FAILURE;
	}

	message[num_bytes] = '\0';

	close_fd(sock_fd);
	
	return 0;
}
示例#5
0
文件: misc.c 项目: wieck/minix
/*===========================================================================*
 *				do_vm_call				     *
 *===========================================================================*/
int do_vm_call(message *m_out)
{
/* A call that VM does to VFS.
 * We must reply with the fixed type VM_VFS_REPLY (and put our result info
 * in the rest of the message) so VM can tell the difference between a
 * request from VFS and a reply to this call.
 */
	int req = job_m_in.VFS_VMCALL_REQ;
	int req_fd = job_m_in.VFS_VMCALL_FD;
	u32_t req_id = job_m_in.VFS_VMCALL_REQID;
	endpoint_t ep = job_m_in.VFS_VMCALL_ENDPOINT;
	u64_t offset = make64(job_m_in.VFS_VMCALL_OFFSET_LO,
		job_m_in.VFS_VMCALL_OFFSET_HI);
	u32_t length = job_m_in.VFS_VMCALL_LENGTH;
	int result = OK;
	int slot;
	struct fproc *rfp, *vmf;
	struct filp *f = NULL;
	int r;

	if(job_m_in.m_source != VM_PROC_NR)
		return ENOSYS;

	if(isokendpt(ep, &slot) != OK) rfp = NULL;
	else rfp = &fproc[slot];

	vmf = &fproc[VM_PROC_NR];
	assert(fp == vmf);
	assert(rfp != vmf);

	switch(req) {
		case VMVFSREQ_FDLOOKUP:
		{
			int procfd;

			/* Lookup fd in referenced process. */

			if(!rfp) {
				printf("VFS: why isn't ep %d here?!\n", ep);
				result = ESRCH;
				goto reqdone;
			}

			if((result = dupvm(rfp, req_fd, &procfd, &f)) != OK) {
				printf("vfs: dupvm failed\n");
				goto reqdone;
			}

			if(S_ISBLK(f->filp_vno->v_mode)) {
				assert(f->filp_vno->v_sdev != NO_DEV);
				m_out->VMV_DEV = f->filp_vno->v_sdev;
				m_out->VMV_INO = VMC_NO_INODE;
				m_out->VMV_SIZE_PAGES = LONG_MAX;
			} else {
				m_out->VMV_DEV = f->filp_vno->v_dev;
				m_out->VMV_INO = f->filp_vno->v_inode_nr;
				m_out->VMV_SIZE_PAGES =
					roundup(f->filp_vno->v_size,
						PAGE_SIZE)/PAGE_SIZE;
			}

			m_out->VMV_FD = procfd;

			result = OK;

			break;
		}
		case VMVFSREQ_FDCLOSE:
		{
			result = close_fd(fp, req_fd);
			if(result != OK) {
				printf("VFS: VM fd close for fd %d, %d (%d)\n",
					req_fd, fp->fp_endpoint, result);
			}
			break;
		}
		case VMVFSREQ_FDIO:
		{
			message dummy_out;

			result = actual_llseek(fp, &dummy_out, req_fd,
				SEEK_SET, offset);

			if(result == OK) {
				result = actual_read_write_peek(fp, PEEKING,
					req_fd, NULL, length);
			}

			break;
		}
		default:
			panic("VFS: bad request code from VM\n");
			break;
	}

reqdone:
	if(f)
		unlock_filp(f);

	/* fp is VM still. */
	assert(fp == vmf);
	m_out->VMV_ENDPOINT = ep;
	m_out->VMV_RESULT = result;
	m_out->VMV_REQID = req_id;

	/* reply asynchronously as VM may not be able to receive
	 * a sendnb() message
	 */

	m_out->m_type = VM_VFS_REPLY;
	r = asynsend3(VM_PROC_NR, m_out, 0);
	if(r != OK) printf("VFS: couldn't asynsend3() to VM\n");

	/* VFS does not reply any further */
	return SUSPEND;
}
示例#6
0
文件: champ_server.c 项目: grke/burp
int champ_chooser_server(struct sdirs *sdirs, struct conf **confs,
	int resume)
{
	int s;
	int ret=-1;
	int len;
	struct asfd *asfd=NULL;
	struct sockaddr_un local;
	struct lock *lock=NULL;
	struct async *as=NULL;
	int started=0;
	struct scores *scores=NULL;
	const char *directory=get_string(confs[OPT_DIRECTORY]);

	if(!(lock=lock_alloc_and_init(sdirs->champlock))
	  || build_path_w(sdirs->champlock))
		goto end;
	lock_get(lock);
	switch(lock->status)
	{
		case GET_LOCK_GOT:
			log_fzp_set(sdirs->champlog, confs);
			logp("Got champ lock for dedup_group: %s\n",
				get_string(confs[OPT_DEDUP_GROUP]));
			break;
		case GET_LOCK_NOT_GOT:
		case GET_LOCK_ERROR:
		default:
			//logp("Did not get champ lock\n");
			goto end;
	}

	if((s=socket(AF_UNIX, SOCK_STREAM, 0))<0)
	{
		logp("socket error in %s: %s\n", __func__, strerror(errno));
		goto end;
	}

	memset(&local, 0, sizeof(struct sockaddr_un));
	local.sun_family=AF_UNIX;
	snprintf(local.sun_path, sizeof(local.sun_path),
		"%s", sdirs->champsock);
	len=strlen(local.sun_path)+sizeof(local.sun_family)+1;
	unlink(sdirs->champsock);
	if(bind(s, (struct sockaddr *)&local, len)<0)
	{
		logp("bind error in %s: %s\n", __func__, strerror(errno));
		goto end;
	}

	if(listen(s, 5)<0)
	{
		logp("listen error in %s: %s\n", __func__, strerror(errno));
		goto end;
	}

	if(!(as=async_alloc())
	  || as->init(as, 0)
	  || !(asfd=setup_asfd(as, "champ chooser main socket", &s,
		/*listen*/"")))
			goto end;
	asfd->fdtype=ASFD_FD_SERVER_LISTEN_MAIN;

	// I think that this is probably the best point at which to run a
	// cleanup job to delete unused data files, because no other process
	// can fiddle with the dedup_group at this point.
	// Cannot do it on a resume, or it will delete files that are
	// referenced in the backup we are resuming.
	if(delete_unused_data_files(sdirs, resume))
		goto end;

	// Load the sparse indexes for this dedup group.
	if(!(scores=champ_chooser_init(sdirs->data)))
		goto end;

	while(1)
	{
		for(asfd=as->asfd->next; asfd; asfd=asfd->next)
		{
			if(!asfd->blist->head
			  || asfd->blist->head->got==BLK_INCOMING) continue;
			if(results_to_fd(asfd)) goto end;
		}

		int removed;

		switch(as->read_write(as))
		{
			case 0:
				// Check the main socket last, as it might add
				// a new client to the list.
				for(asfd=as->asfd->next; asfd; asfd=asfd->next)
				{
					while(asfd->rbuf->buf)
					{
						if(deal_with_client_rbuf(asfd,
							directory, scores))
								goto end;
						// Get as much out of the
						// readbuf as possible.
						if(asfd->parse_readbuf(asfd))
							goto end;
					}
				}
				if(as->asfd->new_client)
				{
					// Incoming client.
					as->asfd->new_client=0;
					if(champ_chooser_new_client(as, confs))
						goto end;
					started=1;
				}
				break;
			default:
				removed=0;
				// Maybe one of the fds had a problem.
				// Find and remove it and carry on if possible.
				for(asfd=as->asfd->next; asfd; )
				{
					struct asfd *a;
					if(!asfd->want_to_remove)
					{
						asfd=asfd->next;
						continue;
					}
					as->asfd_remove(as, asfd);
					logp("%s: disconnected fd %d\n",
						asfd->desc, asfd->fd);
					a=asfd->next;
					asfd_free(&asfd);
					asfd=a;
					removed++;
				}
				if(removed) break;
				// If we got here, there was no fd to remove.
				// It is a fatal error.
				goto end;
		}
				
		if(started && !as->asfd->next)
		{
			logp("All clients disconnected.\n");
			ret=0;
			break;
		}
	}

end:
	logp("champ chooser exiting: %d\n", ret);
	champ_chooser_free(&scores);
	log_fzp_set(NULL, confs);
	async_free(&as);
	asfd_free(&asfd); // This closes s for us.
	close_fd(&s);
	unlink(sdirs->champsock);
// FIX THIS: free asfds.
	lock_release(lock);
	lock_free(&lock);
	return ret;
}
示例#7
0
void *workerFn(void *param)
{
    while (1) {
        struct epoll_event events[EVENT_LEN];
        int n = epoll_wait(epollfd, events, EVENT_LEN, 10000);
        if (n < 0) {
            if (errno == EINTR) {
                continue;
            }
            perror("epoll_wait error");
            exit(1);
        }
        int i;
        int reenable = 1;
        for (i = 0; i < n; ++i) {
            if (events[i].data.fd == listenfd) {
                int fd = accept(listenfd, NULL, NULL);
                if (fd > 0) {
                    add_new_fd(fd);
                } else {
                    perror("accept error");
                    exit(1);
                }
            } else {
                char buf[1024];
                while (1) {
                    ssize_t n = recv(events[i].data.fd, buf, sizeof(buf), MSG_DONTWAIT); 
                    if (n == 0) {
                        reenable = 0;
                        close_fd(events[i].data.fd);
                        break;
                    } else if (n < 0) {
                        if (errno == EINTR) {
                            continue;
                        } else if (errno == EAGAIN) {
                            break;
                        } else {
                            reenable = 0;
                            close_fd(events[i].data.fd);
                            break;
                        }
                    } else {
                        __sync_fetch_and_add(&packets, 1);
                        int pos = 0;
                        while (pos < n) {
                            int sent = send(events[i].data.fd, buf+pos, n-pos, 0);
                            if (sent <= 0) {
                                break;
                            }
                            pos += sent;
                        }
                        if (pos < n) {
                            reenable = 0;
                            close_fd(events[i].data.fd);
                        }
                    }
                    if (n < sizeof(buf)) {
                        break;
                    }
                }
            }

            if (reenable) {
                reenable_fd(events[i].data.fd);
            }
        }
    }
}
示例#8
0
文件: sysfile.c 项目: mtaufen/akaros
void fdclose(struct fd_table *fdt, int fd)
{
	close_fd(fdt, fd);
}
示例#9
0
/*
 * accepts new connections
 */
void
MakeNewConnections(void)
{
    fd_mask     readyconnections;
    int         curconn;
    int         newconn;
    long        connect_time;
    int         i;
    ClientPtr   client;
    OsCommPtr   oc;
    fd_set	tmask;

    XFD_ANDSET (&tmask, &LastSelectMask, &WellKnownConnections);
    readyconnections = tmask.fds_bits[0];
    if (!readyconnections)
	return;
    connect_time = GetTimeInMillis();

    /* kill off stragglers */
    for (i = MINCLIENT; i < currentMaxClients; i++) {
	if ((client = clients[i]) != NullClient) {
	    oc = (OsCommPtr) client->osPrivate;
	    if ((oc && (oc->conn_time != 0) &&
		    (connect_time - oc->conn_time) >= TimeOutValue) ||
		     ((client->noClientException != FSSuccess) &&
		      (client->clientGone != CLIENT_GONE)))
		CloseDownClient(client);
	}
    }

    while (readyconnections) {
	XtransConnInfo trans_conn, new_trans_conn;
	int status;

	curconn = ffs(readyconnections) - 1;
	readyconnections &= ~(1 << curconn);

	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
	    continue;

	if ((new_trans_conn = _FontTransAccept (trans_conn, &status)) == NULL)
	    continue;

	newconn = _FontTransGetConnectionNumber (new_trans_conn);

	_FontTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);

	oc = (OsCommPtr) fsalloc(sizeof(OsCommRec));
	if (!oc) {
	    fsfree(oc);
	    error_conn_max(new_trans_conn);
	    _FontTransClose(new_trans_conn);
	    continue;
	}
	FD_SET(newconn, &AllClients);
	FD_SET(newconn, &AllSockets);
	oc->fd = newconn;
	oc->trans_conn = new_trans_conn;
	oc->input = (ConnectionInputPtr) NULL;
	oc->output = (ConnectionOutputPtr) NULL;
	oc->conn_time = connect_time;

	if ((newconn < lastfdesc) &&
		(client = NextAvailableClient((pointer) oc))) {
	    ConnectionTranslation[newconn] = client->index;
	} else {
	    error_conn_max(new_trans_conn);
	    close_fd(oc);
	}
    }
}
示例#10
0
/* May return 1 to mean try again. This happens after a successful certificate
   signing request so that it connects again straight away with the new
   key/certificate.
   Returns 2 if there were restore/verify warnings.
   Returns 3 if timer conditions were not met.
*/
static int do_client(struct config *conf, enum action act, int vss_restore, int json)
{
	int ret=0;
	int rfd=-1;
	int resume=0;
	SSL *ssl=NULL;
	BIO *sbio=NULL;
	char buf[256]="";
	SSL_CTX *ctx=NULL;
	struct cntr cntr;
	struct cntr p1cntr;
	char *incexc=NULL;
	char *server_version=NULL;
	const char *phase1str="backupphase1";

	reset_filecounter(&p1cntr, time(NULL));
	reset_filecounter(&cntr, time(NULL));

	setup_signals_client();
//	settimers(0, 100);
	logp("begin client\n");

	if(act!=ACTION_ESTIMATE)
	{
		ssl_load_globals();
		if(!(ctx=ssl_initialise_ctx(conf)))
		{
			logp("error initialising ssl ctx\n");
			ret=-1;
			goto end;
		}

		SSL_CTX_set_session_id_context(ctx,
			(const unsigned char *)&s_server_session_id_context,
			sizeof(s_server_session_id_context));

		if((rfd=init_client_socket(conf->server, conf->port))<0)
		{
			ret=-1;
			goto end;
		}

		if(!(ssl=SSL_new(ctx))
		  || !(sbio=BIO_new_socket(rfd, BIO_NOCLOSE)))
		{
			ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
			logp("Problem joining SSL to the socket: %s\n", buf);
			ret=-1;
			goto end;
		}
		SSL_set_bio(ssl, sbio, sbio);
		if(SSL_connect(ssl)<=0)
		{
			ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
			logp("SSL connect error: %s\n", buf);
			ret=-1;
			goto end;
		}
	}

	if((ret=async_init(rfd, ssl, conf, act==ACTION_ESTIMATE)))
		goto end;

	// Set quality of service bits on backup packets.
	if(act==ACTION_BACKUP || act==ACTION_BACKUP_TIMED)
		set_bulk_packets();

	if(act!=ACTION_ESTIMATE)
	{
		char cmd=0;
		size_t len=0;
		char *feat=NULL;
		int ca_ret=0;
		if((ret=authorise_client(conf, &server_version, &p1cntr)))
			goto end;

		if(server_version)
		{
			logp("Server version: %s\n", server_version);
			// Servers before 1.3.2 did not tell us their versions.
			// 1.3.2 and above can do the automatic CA stuff that
			// follows.
			if((ca_ret=ca_client_setup(conf, &p1cntr))<0)
			{
				// Error
				logp("Error with certificate signing request\n");
				ret=-1;
				goto end;
			}
			else if(ca_ret>0)
			{
				// Certificate signed successfully.
				// Everything is OK, but we will reconnect now, in
				// order to use the new keys/certificates.
				ret=1;
				goto end;
			}
		}

		set_non_blocking(rfd);

		if((ret=ssl_check_cert(ssl, conf)))
		{
			logp("check cert failed\n");
			goto end;
		}

		if((ret=async_write_str(CMD_GEN, "extra_comms_begin")))
		{
			logp("Problem requesting extra_comms_begin\n");
			goto end;
		}
		// Servers greater than 1.3.0 will list the extra_comms
		// features they support.
		else if((ret=async_read(&cmd, &feat, &len)))
		{
			logp("Problem reading response to extra_comms_begin\n");
			goto end;
		}
		else if(cmd!=CMD_GEN)
		{
			logp("Unexpected command from server when reading response to extra_comms_begin: %c:%s\n", cmd, feat);
			ret=-1;
			goto end;
		}
		else if(strncmp(feat,
		  "extra_comms_begin ok", strlen("extra_comms_begin ok")))
		{
			logp("Unexpected response from server when reading response to extra_comms_begin: %c:%s\n", cmd, feat);
			ret=-1;
			goto end;
		}

		// Can add extra bits here. The first extra bit is the
		// autoupgrade stuff.

		if(server_supports_autoupgrade(feat))
		{
			if(conf->autoupgrade_dir && conf->autoupgrade_os
			  && (ret=autoupgrade_client(conf, &p1cntr)))
				goto end;
		}

		// :srestore: means that the server wants to do a restore.
		if(server_supports(feat, ":srestore:"))
		{
			if(conf->server_can_restore)
			{
				logp("Server is initiating a restore\n");
				if(incexc) { free(incexc); incexc=NULL; }
				if((ret=incexc_recv_client_restore(&incexc,
					conf, &p1cntr)))
						goto end;
				if(incexc)
				{
					if((ret=parse_incexcs_buf(conf,
						incexc))) goto end;
					act=ACTION_RESTORE;
					log_restore_settings(conf, 1);
				}
			}
			else
			{
				logp("Server wants to initiate a restore\n");
				logp("Client configuration says no\n");
				if(async_write_str(CMD_GEN, "srestore not ok"))
				{
					ret=-1;
					goto end;
				}
			}
		}

		if(conf->orig_client)
		{
			char str[512]="";
			snprintf(str, sizeof(str),
				"orig_client=%s", conf->orig_client);
			if(!server_supports(feat, ":orig_client:"))
			{
				logp("Server does not support switching client.\n");
				ret=-1;
				goto end;
			}
			if((ret=async_write_str(CMD_GEN, str))
			  || (ret=async_read_expect(CMD_GEN, "orig_client ok")))
			{
				logp("Problem requesting %s\n", str);
				ret=-1;
				goto end;
			}
			logp("Switched to client %s\n", conf->orig_client);
		}

		// :sincexc: is for the server giving the client the
		// incexc config.
		if(act==ACTION_BACKUP
		  || act==ACTION_BACKUP_TIMED)
		{
			if(!incexc && server_supports(feat, ":sincexc:"))
			{
				logp("Server is setting includes/excludes.\n");
				if(incexc) { free(incexc); incexc=NULL; }
				if((ret=incexc_recv_client(&incexc,
					conf, &p1cntr))) goto end;
				if(incexc && (ret=parse_incexcs_buf(conf,
					incexc))) goto end;
			}
		}

		if(server_supports(feat, ":counters:"))
		{
			if(async_write_str(CMD_GEN, "countersok"))
				goto end;
			conf->send_client_counters=1;
		}

		// :incexc: is for the client sending the server the
		// incexc config so that it better knows what to do on
		// resume.
		if(server_supports(feat, ":incexc:")
		  && (ret=incexc_send_client(conf, &p1cntr)))
			goto end;

		if((ret=async_write_str(CMD_GEN, "extra_comms_end"))
		  || (ret=async_read_expect(CMD_GEN, "extra_comms_end ok")))
		{
			logp("Problem requesting extra_comms_end\n");
			goto end;
		}

		if(feat) free(feat);
	}

	rfd=-1;
	switch(act)
	{
		case ACTION_BACKUP_TIMED:
			phase1str="backupphase1timed";
		case ACTION_BACKUP:
		{
			// Set bulk packets quality of service flags on backup.
			if(incexc)
			{
				logp("Server is overriding the configuration\n");
				logp("with the following settings:\n");
				if(log_incexcs_buf(incexc))
				{
					ret=-1;
					goto end;
				}
			}
			if(!conf->sdcount)
			{
				logp("Found no include paths!\n");
				ret=-1;
				goto end;
			}

			if(!(ret=maybe_check_timer(phase1str,
				conf, &resume)))
			{
				if(conf->backup_script_pre)
				{
					int a=0;
					const char *args[12];
					args[a++]=conf->backup_script_pre;
					args[a++]="pre";
					args[a++]="reserved2";
					args[a++]="reserved3";
					args[a++]="reserved4";
					args[a++]="reserved5";
					args[a++]=NULL;
					if(run_script(args,
						conf->backup_script_pre_arg,
						conf->bprecount,
						&p1cntr, 1, 1)) ret=-1;
				}

				if(!ret && do_backup_client(conf,
					resume, 0, &p1cntr, &cntr))
						ret=-1;

				if((conf->backup_script_post_run_on_fail
				  || !ret) && conf->backup_script_post)
				{
					int a=0;
					const char *args[12];
					args[a++]=conf->backup_script_post;
					args[a++]="post";
					// Tell post script whether the restore
					// failed.
					args[a++]=ret?"1":"0";
					args[a++]="reserved3";
					args[a++]="reserved4";
					args[a++]="reserved5";
					args[a++]=NULL;
					if(run_script(args,
						conf->backup_script_post_arg,
						conf->bpostcount,
						&cntr, 1, 1)) ret=-1;
				}
			}

			if(ret<0)
				logp("error in backup\n");
			else if(ret>0)
			{
				// Timer script said no.
				// Have a distinct return value to
				// differentiate between other cases
				// (ssl reconnection and restore/verify
				// warnings).
				ret=3;
			}
			else
				logp("backup finished ok\n");
			
			break;
		}
		case ACTION_RESTORE:
		case ACTION_VERIFY:
		{
			if(conf->restore_script_pre)
			{
				int a=0;
				const char *args[12];
				args[a++]=conf->restore_script_pre;
				args[a++]="pre";
				args[a++]="reserved2";
				args[a++]="reserved3";
				args[a++]="reserved4";
				args[a++]="reserved5";
				args[a++]=NULL;
				if(run_script(args,
					conf->restore_script_pre_arg,
					conf->rprecount, &cntr, 1, 1)) ret=-1;
			}
			if(!ret && do_restore_client(conf,
				act, vss_restore, &p1cntr, &cntr)) ret=-1;
			if((conf->restore_script_post_run_on_fail
			  || !ret) && conf->restore_script_post)
			{
				int a=0;
				const char *args[12];
				args[a++]=conf->restore_script_pre;
				args[a++]="post";
				// Tell post script whether the restore
				// failed.
				args[a++]=ret?"1":"0";
				args[a++]="reserved3";
				args[a++]="reserved4";
				args[a++]="reserved5";
				args[a++]=NULL;
				if(run_script(args,
					conf->restore_script_post_arg,
					conf->rpostcount, &cntr, 1, 1)) ret=-1;
			}

			// Return non-zero if there were warnings,
			// so that the test script can easily check.
			if(p1cntr.warning+cntr.warning)
				ret=2;

			break;
		}
		case ACTION_ESTIMATE:
			if(!ret) ret=do_backup_client(conf, 0, 1,
					&p1cntr, &cntr);
			break;
		case ACTION_DELETE:
			if(!ret) ret=do_delete_client(conf);
			break;
		case ACTION_LIST:
		case ACTION_LONG_LIST:
		default:
			ret=do_list_client(conf, act, json);
			break;
	}

end:
	close_fd(&rfd);
	async_free();
	if(act!=ACTION_ESTIMATE) ssl_destroy_ctx(ctx);

	if(incexc) free(incexc);
	if(server_version) free(server_version);

        //logp("end client\n");
	return ret;
}
示例#11
0
gboolean
egg_spawn_sync_with_callbacks  (const gchar *working_directory, gchar **argv,
                                gchar **envp, GSpawnFlags flags, GPid *child_pid,
                                EggSpawnCallbacks *cbs, gpointer user_data,
                                gint *exit_status, GError **error)
{
	gint in_fd, out_fd, err_fd, max_fd;
	fd_set read_fds, write_fds;
	gboolean failed = FALSE;
	gint status;
	GPid pid;
	gint ret;

	g_return_val_if_fail (argv != NULL, FALSE);
	g_return_val_if_fail ((cbs && cbs->standard_input == NULL) ||
	                      !(flags & G_SPAWN_CHILD_INHERITS_STDIN), 0);
	g_return_val_if_fail ((cbs && cbs->standard_output == NULL) ||
	                      !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), 0);
	g_return_val_if_fail ((cbs && cbs->standard_error == NULL) ||
	                      !(flags & G_SPAWN_STDERR_TO_DEV_NULL), 0);

	in_fd = out_fd = err_fd = -1;

	if (exit_status)
		flags |= G_SPAWN_DO_NOT_REAP_CHILD;

	if (!g_spawn_async_with_pipes (working_directory, argv, envp, flags,
	                               cbs ? cbs->child_setup : NULL,
	                               user_data, &pid,
	                               cbs && cbs->standard_input ? &in_fd : NULL,
	                               cbs && cbs->standard_output ? &out_fd : NULL,
	                               cbs && cbs->standard_error ? &err_fd : NULL,
	                               error))
		return FALSE;

	if (child_pid)
		*child_pid = pid;

	max_fd = MAX (in_fd, MAX (out_fd, err_fd)) + 1;

	while (in_fd >= 0 || out_fd >= 0 || err_fd >= 0) {

		FD_ZERO (&write_fds);
		if (in_fd >= 0)
			FD_SET (in_fd, &write_fds);
		FD_ZERO (&read_fds);
		if (out_fd >= 0)
			FD_SET (out_fd, &read_fds);
		if (err_fd >= 0)
			FD_SET (err_fd, &read_fds);

		ret = select (max_fd, &read_fds, &write_fds, NULL, NULL);
		if (ret < 0 && errno != EINTR) {
			failed = TRUE;
			g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
			             _("Unexpected error in select() reading data from a child process (%s)"),
			             g_strerror (errno));
			break;
		}

		if (in_fd >= 0 && FD_ISSET (in_fd, &write_fds)) {
			g_assert (cbs && cbs->standard_input);
			if (!(cbs->standard_input) (in_fd, user_data))
				close_fd (&in_fd);
		}
		if (out_fd >= 0 && FD_ISSET (out_fd, &read_fds)) {
			g_assert (cbs && cbs->standard_output);
			if (!(cbs->standard_output) (out_fd, user_data))
				close_fd (&out_fd);
		}
		if (err_fd >= 0 && FD_ISSET (err_fd, &read_fds)) {
			g_assert (cbs && cbs->standard_error);
			if (!(cbs->standard_error) (err_fd, user_data))
				close_fd (&err_fd);
		}
	}

	if (in_fd >= 0)
		close_fd (&in_fd);
	if (out_fd >= 0)
		close_fd (&out_fd);
	if (err_fd >= 0)
		close_fd (&err_fd);

	if (!failed) {
		if (cbs && cbs->completed)
			(cbs->completed) (user_data);
	}

again:
	ret = waitpid (pid, &status, 0);
	if (ret < 0) {
		if (errno == EINTR)
			goto again;
		else if (errno == ECHILD) {
			if (exit_status)
				g_warning ("In call to g_spawn_sync(), exit status of a child process was requested but SIGCHLD action was set to SIG_IGN and ECHILD was received by waitpid(), so exit status can't be returned. This is a bug in the program calling g_spawn_sync(); either don't request the exit status, or don't set the SIGCHLD action.");
			else
				; /* We don't need the exit status. */
		} else if (!failed) { /* avoid error pileups */
			failed = TRUE;
			g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
			             _("Unexpected error in waitpid() (%s)"),
			             g_strerror (errno));
		}
	} else {
		if (exit_status)
			*exit_status = status;
	}

	if (!child_pid)
		g_spawn_close_pid (pid);

	if (cbs && cbs->finalize_func)
		(cbs->finalize_func) (user_data);

	return !failed;
}
示例#12
0
/**
 * _gcr_gnupg_process_run_async:
 * @self: The process
 * @argv: (array zero-terminated=1): The arguments for the process, not including executable, terminated with %NULL.
 * @envp: (allow-none) (array zero-terminated=1): The environment for new process, terminated with %NULL.
 * @flags: Flags for starting the process.
 * @cancellable: (allow-none): Cancellation object
 * @callback: Will be called when operation completes.
 * @user_data: (closure): Data passed to callback.
 *
 * Run the gpg process. Only one 'run' operation can run per GcrGnupgProcess
 * object. The GcrGnupgProcess:output_data and GcrGnupgProcess:error_line
 * signals will be emitted when data is received from the gpg process.
 *
 * Unless the %GCR_GNUPG_PROCESS_RESPECT_LOCALE flag is specified, the process
 * will be run in the 'C' locale. If the %GCR_GNUPG_PROCESS_WITH_STATUS or
 * %GCR_GNUPG_PROCESS_WITH_ATTRIBUTES flags are set, then the gpg process
 * will be status and attribute output respectively. The
 * GcrGnupgProcess:status_record and GcrGnupgProcess:attribute_data signals
 * will provide this data.
 */
void
_gcr_gnupg_process_run_async (GcrGnupgProcess *self, const gchar **argv, const gchar **envp,
                              GcrGnupgProcessFlags flags, GCancellable *cancellable,
                              GAsyncReadyCallback callback, gpointer user_data)
{
	GError *error = NULL;
	GPtrArray *args;
	GPtrArray *envs;
	int child_fds[NUM_FDS];
	int status_fds[2] = { -1, -1 };
	int attribute_fds[2] = { -1, -1 };
	int output_fd = -1;
	int error_fd = -1;
	int input_fd = -1;
	GnupgSource *gnupg_source;
	GSource *source;
	GPid pid;
	guint i;

	g_return_if_fail (GCR_IS_GNUPG_PROCESS (self));
	g_return_if_fail (argv);
	g_return_if_fail (callback);
	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));

	g_return_if_fail (self->pv->running == FALSE);
	g_return_if_fail (self->pv->complete == FALSE);
	g_return_if_fail (self->pv->executable);

	self->pv->async_callback = callback;
	self->pv->user_data = user_data;

	for (i = 0; i < NUM_FDS; i++)
		child_fds[i] = -1;

	/* The command needs to be updated with these status and attribute fds */
	args = g_ptr_array_new_with_free_func (g_free);
	g_ptr_array_add (args, g_strdup (self->pv->executable));

	/* Spawn/child will close all other attributes, besides thesthose in child_fds */
	child_fds[FD_INPUT] = 0;
	child_fds[FD_OUTPUT] = 1;
	child_fds[FD_ERROR] = 2;

	if (flags & GCR_GNUPG_PROCESS_WITH_STATUS) {
		if (pipe (status_fds) < 0)
			g_return_if_reached ();
		child_fds[FD_STATUS] = status_fds[1];
		g_ptr_array_add (args, g_strdup ("--status-fd"));
		g_ptr_array_add (args, g_strdup_printf ("%d", child_fds[FD_STATUS]));
	}
	if (flags & GCR_GNUPG_PROCESS_WITH_ATTRIBUTES) {
		if (pipe (attribute_fds) < 0)
			g_return_if_reached ();
		child_fds[FD_ATTRIBUTE] = attribute_fds[1];
		g_ptr_array_add (args, g_strdup ("--attribute-fd"));
		g_ptr_array_add (args, g_strdup_printf ("%d", child_fds[FD_ATTRIBUTE]));
	}

	if (self->pv->directory) {
		g_ptr_array_add (args, g_strdup ("--homedir"));
		g_ptr_array_add (args, g_strdup (self->pv->directory));
	}

	/* All the remaining arguments */
	for (i = 0; argv[i] != NULL; i++)
		g_ptr_array_add (args, g_strdup (argv[i]));
	g_ptr_array_add (args, NULL);

	envs = g_ptr_array_new ();
	for (i = 0; envp && envp[i] != NULL; i++) {
		if (flags & GCR_GNUPG_PROCESS_RESPECT_LOCALE ||
		    !g_str_has_prefix (envp[i], "LOCALE="))
			g_ptr_array_add (envs, (gpointer)envp[i]);
	}
	if (!(flags & GCR_GNUPG_PROCESS_RESPECT_LOCALE))
		g_ptr_array_add (envs, (gpointer)"LOCALE=C");
	g_ptr_array_add (envs, NULL);

	gchar *command = g_strjoinv (" ", (gchar**)args->pdata);
	gchar *environ = g_strjoinv (", ", (gchar**)envs->pdata);
	g_debug ("running command: %s", command);
	g_debug ("process environment: %s", environ);
	g_free (command);
	g_free (environ);

	g_spawn_async_with_pipes (self->pv->directory, (gchar**)args->pdata,
	                          (gchar**)envs->pdata, G_SPAWN_DO_NOT_REAP_CHILD,
	                          on_gnupg_process_child_setup, child_fds,
	                          &pid, &input_fd, &output_fd, &error_fd, &error);

	g_ptr_array_free (args, TRUE);
	g_ptr_array_free (envs, TRUE);

	/* Close 'wrong' ends of extra file descriptors */
	close_fd (&(status_fds[1]));
	close_fd (&(attribute_fds[1]));

	self->pv->complete = FALSE;
	self->pv->running = TRUE;

	if (error) {
		close_fd (&(status_fds[0]));
		close_fd (&(attribute_fds[0]));
		g_assert (!self->pv->error);
		self->pv->error = error;
		complete_run_process (self);
		run_async_ready_callback_later (self);
		return;
	}

	g_debug ("process started: %d", (int)pid);

	source = g_source_new (&gnupg_source_funcs, sizeof (GnupgSource));

	/* Initialize the source */
	gnupg_source = (GnupgSource*)source;
	for (i = 0; i < NUM_FDS; i++)
		gnupg_source->polls[i].fd = -1;
	gnupg_source->error_buf = g_string_sized_new (128);
	gnupg_source->status_buf = g_string_sized_new (128);
	gnupg_source->process = g_object_ref (self);
	gnupg_source->child_pid = pid;

	gnupg_source->polls[FD_INPUT].fd = input_fd;
	if (input_fd >= 0) {
		gnupg_source->polls[FD_INPUT].events = G_IO_HUP | G_IO_OUT;
		g_source_add_poll (source, &gnupg_source->polls[FD_INPUT]);
	}
	gnupg_source->polls[FD_OUTPUT].fd = output_fd;
	if (output_fd >= 0) {
		gnupg_source->polls[FD_OUTPUT].events = G_IO_HUP | G_IO_IN;
		g_source_add_poll (source, &gnupg_source->polls[FD_OUTPUT]);
	}
	gnupg_source->polls[FD_ERROR].fd = error_fd;
	if (error_fd >= 0) {
		gnupg_source->polls[FD_ERROR].events = G_IO_HUP | G_IO_IN;
		g_source_add_poll (source, &gnupg_source->polls[FD_ERROR]);
	}
	gnupg_source->polls[FD_STATUS].fd = status_fds[0];
	if (status_fds[0] >= 0) {
		gnupg_source->polls[FD_STATUS].events = G_IO_HUP | G_IO_IN;
		g_source_add_poll (source, &gnupg_source->polls[FD_STATUS]);
	}
	gnupg_source->polls[FD_ATTRIBUTE].fd = attribute_fds[0];
	if (attribute_fds[0] >= 0) {
		gnupg_source->polls[FD_ATTRIBUTE].events = G_IO_HUP | G_IO_IN;
		g_source_add_poll (source, &gnupg_source->polls[FD_ATTRIBUTE]);
	}

	if (cancellable) {
		gnupg_source->cancellable = g_object_ref (cancellable);
		gnupg_source->cancel_sig = g_cancellable_connect (cancellable,
		                                                  G_CALLBACK (on_cancellable_cancelled),
		                                                  g_source_ref (source),
		                                                  (GDestroyNotify)g_source_unref);
	}

	g_assert (self->pv->source_sig == 0);
	g_source_set_callback (source, unused_callback, NULL, NULL);
	self->pv->source_sig = g_source_attach (source, g_main_context_default ());

	/* This assumes the outstanding reference to source */
	g_assert (gnupg_source->child_sig == 0);
	gnupg_source->child_sig = g_child_watch_add_full (G_PRIORITY_DEFAULT, pid,
	                                                  on_gnupg_process_child_exited,
	                                                  g_source_ref (source),
	                                                  (GDestroyNotify)g_source_unref);

	/* source is unreffed in complete_if_source_is_done() */
}
示例#13
0
/*===========================================================================*
 *				do_close				     *
 *===========================================================================*/
int do_close(message *UNUSED(m_out))
{
/* Perform the close(fd) system call. */
  int thefd = job_m_in.fd;
  return close_fd(fp, thefd);
}
示例#14
0
/*===========================================================================*
 *				do_close				     *
 *===========================================================================*/
int do_close()
{
/* Perform the close(fd) system call. */
  return close_fd(fp, m_in.fd);
}
示例#15
0
bool run_matlab_command(::std::string const& cmd,
						ArgsT const& args,
						ConsumerT& consumer)
{
	int pipefd[2];

	// Create a pipe to let to communicate with MATLAB.
	// Specifically, we want to read the output from MATLAB.
	// So, the parent process read from the pipe, while the child process
	// write on it.
	if (::pipe(pipefd) == -1)
	{
		char const* err_str = ::strerror(errno);
		::std::ostringstream oss;
		oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] pipe(2) failed: "
			<< ::std::string(err_str);
		throw ::std::runtime_error(oss.str());
	}

//	// Install signal handlers
//	struct ::sigaction sig_act;
//	struct ::sigaction old_sigterm_act;
//	struct ::sigaction old_sigint_act;
//	//::memset(&sig_act, 0, sizeof(sig_act));
//	::sigemptyset(&sig_act.sa_mask);
//	sig_act.sa_flags = 0;
//	sig_act.sa_handler = self_type::process_signals;
//	::sigaction(SIGTERM, &sig_act, &old_sigterm_act);
//	::sigaction(SIGINT, &sig_act, &old_sigint_act);

	// Spawn a new process

	// Between fork() and execve() only async-signal-safe functions
	// must be called if multithreaded applications should be supported.
	// That's why the following code is executed before fork() is called.

	::pid_t pid = ::fork();

	// check: pid == -1 --> error
	if (pid == -1)
	{
		char const* err_str = ::strerror(errno);
		::std::ostringstream oss;
		oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] fork(2) failed: "
			<< ::std::string(err_str);
		throw ::std::runtime_error(oss.str());
	}

	if (pid == 0)
	{
		// The child

//		// Cancel signal handler set for parent
//		sig_act.sa_handler = SIG_DFL;
//		::sigaction(SIGTERM, &sig_act, 0);
//		::sigaction(SIGINT, &sig_act, 0);

		// Get the maximum number of files this process is allowed to open
#if defined(F_MAXFD)
		int maxdescs = ::fcntl(-1, F_MAXFD, 0);
		if (maxdescs == -1)
		{
#if defined(_SC_OPEN_MAX)
			maxdescs = ::sysconf(_SC_OPEN_MAX);
#else
			::rlimit limit;
			if (::getrlimit(RLIMIT_NOFILE, &limit) < 0)
			{
				char const* err_str = ::strerror(errno);
				::std::ostringstream oss;
				oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] getrlimit(2) failed: "
					<< ::std::string(err_str);
				throw ::std::runtime_error(oss.str());
			}
			maxdescs = limit.rlim_cur;
#endif // _SC_OPEN_MAX
		}
#else // F_MAXFD
#if defined(_SC_OPEN_MAX)
		int maxdescs = ::sysconf(_SC_OPEN_MAX);
#else // _SC_OPEN_MAX
		::rlimit limit;
		if (::getrlimit(RLIMIT_NOFILE, &limit) < 0)
		{
			char const* err_str = ::strerror(errno);
			::std::ostringstream oss;
			oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] getrlimit(2) failed: "
				<< ::std::string(err_str);
			throw ::std::runtime_error(oss.str());
		}
		maxdescs = limit.rlim_cur;
#endif // _SC_OPEN_MAX
#endif // F_MAXFD
		if (maxdescs == -1)
		{
			maxdescs = 1024;
		}

		::std::vector<bool> close_fd(maxdescs, true);

		// Associate the child's stdout to the pipe write fd.
		close_fd[STDOUT_FILENO] = false;
		if (pipefd[1] != STDOUT_FILENO)
		{
			if (::dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO)
			{
				char const* err_str = ::strerror(errno);
				::std::ostringstream oss;
				oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] dup2(2) failed: "
					<< ::std::string(err_str);
				throw ::std::runtime_error(oss.str());
			}
		}
		else
		{
			close_fd[pipefd[1]] = false;
		}
//			::close(STDOUT_FILENO);
//			::dup(pipefd[1]);

		// Check if the command already has path information
		::std::string cmd_path;
		::std::string cmd_name;
		typename ::std::string::size_type pos;
		pos = cmd.find_last_of('/');
		if (pos != ::std::string::npos)
		{
			cmd_path = cmd.substr(0, pos);
			cmd_name = cmd.substr(pos+1);
		}

		//FIXME: use scoped_ptr in place of "new"

		::std::size_t nargs = args.size()+1;
		char** argv = new char*[nargs + 2];
		argv[0] = new char[cmd_name.size()+1];
		::std::strncpy(argv[0], cmd_name.c_str(), cmd_name.size()+1); // by convention, the first argument is always the command name
		typename ArgsT::size_type i(1);
		typename ArgsT::const_iterator end_it(args.end());
		for (typename ArgsT::const_iterator it = args.begin(); it != end_it; ++it)
		{
			argv[i] = new char[it->size()+1];
			::std::strncpy(argv[i], it->c_str(), it->size()+1);
			++i;
		}
		argv[nargs] = 0;

		//char** envp(0);

		// Close unused file descriptors
#ifdef DCS_DEBUG
		// Keep standard error open for debug
		close_fd[STDERR_FILENO] = false;
#endif // DCS_DEBUG
		for (int fd = 0; fd < maxdescs; ++fd)
		{
			if (close_fd[fd])
			{
				::close(fd);
			}
		}

//[XXX]
#ifdef DCS_DEBUG
::std::cerr << "Executing MATLAB: " << cmd;//XXX
for (::std::size_t i=0; i < args.size(); ++i)//XXX
{//XXX
::std::cerr << " " << args[i] << ::std::flush;//XXX
}//XXX
::std::cerr << ::std::endl;//XXX
#endif // DCS_DEBUG
//[/XXX]
//DCS_DEBUG_TRACE("Executing: " << cmd << " " << args[0] << " " << args[1] << " " << args[2] << " - " << args[3]);

		//::execve(cmd.c_str(), argv, envp);
		::execvp(cmd.c_str(), argv);

		// Actually we should delete argv and envp data. As we must not
		// call any non-async-signal-safe functions though we simply exit.
		::write(STDERR_FILENO, "execvp() failed\n", 17);
		//_exit(EXIT_FAILURE);
		_exit(127);
	}

	// The parent

//		// Associate the parent's stdin to the pipe read fd.
	::close(pipefd[1]);
//		::close(STDIN_FILENO);
//		::dup(pipefd[0]);
	if (pipefd[0] != STDIN_FILENO)
	{
		if (::dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO)
		{
			char const* err_str = ::strerror(errno);
			::std::ostringstream oss;
			oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] dup2(2) failed: "
				<< ::std::string(err_str);
			throw ::std::runtime_error(oss.str());
		}
		::close(pipefd[0]);
	}

	typedef ::boost::iostreams::file_descriptor_source fd_device_type;
	typedef ::boost::iostreams::stream_buffer<fd_device_type> fd_streambuf_type;
	//fd_device_type fd_src(pipefd[0], ::boost::iostreams::close_handle);
	fd_device_type fd_src(STDIN_FILENO, ::boost::iostreams::close_handle);
	fd_streambuf_type fd_buf(fd_src);
	::std::istream is(&fd_buf);

	consumer(is);

DCS_DEBUG_TRACE("END parsing MATLAB output");//XXX
DCS_DEBUG_TRACE("IS state: " << is.good() << " - " << is.eof() << " - " << is.fail() << " - " << is.bad());//XXX

	// Wait the child termination (in order to prevent zombies)
	int status;
//		::pid_t wait_pid;
//		wait_pid = ::wait(&status);
//		if (wait_pid != pid)
//		{
//			throw ::std::runtime_error("[dcs::des::cloud::detail::rls_miso_matlab_app_proxy::run_matlab] Unexpected child process.");
//		}
	if (::waitpid(pid, &status, 0) == -1)
	{
		char const* err_str = ::strerror(errno);
		::std::ostringstream oss;
		oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] waitpid(2) failed: "
			<< ::std::string(err_str);
		throw ::std::runtime_error(oss.str());
	}
DCS_DEBUG_TRACE("MATLAB exited");//XXX
	bool ok(true);
	if (WIFEXITED(status))
	{
DCS_DEBUG_TRACE("MATLAB exited with a call to 'exit(" << WEXITSTATUS(status) << ")'");//XXX
		if (WEXITSTATUS(status))
		{
			// status != 0 --> error in the execution
			::std::clog << "[Warning] MATLAB command exited with status " << WEXITSTATUS(status) << ::std::endl;
			ok = false;
		}
	}
	else if (WIFSIGNALED(status))
	{
DCS_DEBUG_TRACE("MATLAB exited with a call to 'kill(" << WTERMSIG(status) << ")'");//XXX
	   ::std::clog << "[Warning] MATLAB command received signal " << WTERMSIG(status) << ::std::endl;
		ok = false;
	}
	else
	{
DCS_DEBUG_TRACE("MATLAB exited with an unexpected way");//XXX
		ok = false;
	}

//	// Restore signal handler
//	::sigaction(SIGTERM, &old_sigterm_act, 0);
//	::sigaction(SIGINT, &old_sigint_act, 0);
	return ok;
}
示例#16
0
int status_client_ncurses(struct config *conf, enum action act, const char *sclient)
{
	int fd=0;
        int ret=0;
	int sel=0;
	char *rbuf=NULL;
	char buf[512]="";
	int count=0;
	int details=0;
	char *last_rbuf=NULL;
	int srbr=0;
	char *client=NULL;
	int enterpressed=0;
//	int loop=0;
	int reqdone=0;

#ifdef HAVE_NCURSES_H
	int stdinfd=fileno(stdin);
	actg=act; // So that the sighandler can call endwin().
#else
	if(act==ACTION_STATUS)
	{
		printf("To use the live status monitor, you need to recompile with ncurses support.\n");
		return -1;
	}
#endif

	setup_signals();

	/* NULL == ::1 or 127.0.0.1 */
	if((fd=init_client_socket(NULL, conf->status_port))<0)
		return -1;
	set_non_blocking(fd);

#ifdef HAVE_NCURSES_H
	if(actg==ACTION_STATUS)
	{
		initscr();
		start_color();
		init_pair(1, COLOR_WHITE, COLOR_BLACK);
		init_pair(2, COLOR_WHITE, COLOR_BLACK);
		init_pair(3, COLOR_WHITE, COLOR_BLACK);
		raw();
		keypad(stdscr, TRUE);
		noecho();
		curs_set(0);
		halfdelay(3);
		//nodelay(stdscr, TRUE);
	}
#endif
#ifdef DBFP
	dbfp=fopen("/tmp/dbfp", "w");
#endif

	while(!ret)
	{
		int l;
		int mfd=-1;
		fd_set fsr;
		fd_set fse;
		struct timeval tval;

		// Failsafe to prevent the snapshot ever getting permanently
		// stuck.
		//if(act==ACTION_STATUS_SNAPSHOT && loop++>10000)
		//	break;

		if(sclient && !client)
		{
			client=strdup(sclient);
			details=1;
		}

		if((enterpressed || need_status()) && !reqdone)
		{
			char *req=NULL;
			if(details && client) req=client;
			if(request_status(fd, req, conf))
			{
				ret=-1;
				break;
			}
			enterpressed=0;
			if(act==ACTION_STATUS_SNAPSHOT)
				reqdone++;
		}

		FD_ZERO(&fsr);
		FD_ZERO(&fse);

		tval.tv_sec=1;
		tval.tv_usec=0;

		add_fd_to_sets(fd, &fsr, NULL, &fse, &mfd);
#ifdef HAVE_NCURSES_H
		if(actg==ACTION_STATUS)
			add_fd_to_sets(stdinfd, &fsr, NULL, &fse, &mfd);
#endif

		if(select(mfd+1, &fsr, NULL, &fse, &tval)<0)
		{
			if(errno!=EAGAIN && errno!=EINTR)
			{
				logp("select error: %s\n",
					strerror(errno));
				ret=-1;
				break;
			}
			continue;
		}

		if(FD_ISSET(fd, &fse))
		{
			ret=-1;
			break;
		}

#ifdef HAVE_NCURSES_H
		if(actg==ACTION_STATUS)
		{
			if(FD_ISSET(stdinfd, &fse))
			{
				ret=-1;
				break;
			}
			if(FD_ISSET(stdinfd, &fsr))
			{
				int quit=0;
				
				switch(getch())
				{
					case 'q':
					case 'Q':
						quit++;
						break;
					case KEY_UP:
					case 'k':
					case 'K':
						if(details) break;
						sel--;
						break;
					case KEY_DOWN:
					case 'j':
					case 'J':
						if(details) break;
						sel++;
						break;
					case KEY_ENTER:
					case '\n':
					case ' ':
						if(details) details=0;
						else details++;
						enterpressed++;
						break;
					case KEY_LEFT:
					case 'h':
					case 'H':
						details=0;
						break;
					case KEY_RIGHT:
					case 'l':
					case 'L':
						details++;
						break;
					case KEY_NPAGE:
					{
						int row=0, col=0;
						getmaxyx(stdscr, row, col);
						sel+=row-TOP_SPACE;
						break;
					}
					case KEY_PPAGE:
					{
						int row=0, col=0;
						getmaxyx(stdscr, row, col);
						sel-=row-TOP_SPACE;
						break;
					}
				}
				if(quit) break;

				if(sel<0) sel=0;
				if(sel>=count) sel=count-1;

				// Attempt to print stuff to the screen right
				// now, to give the impression of key strokes
				// being responsive.
				if(!details && !sclient)
				{
				  if((srbr=show_rbuf(last_rbuf,
					conf, sel, &client,
					&count, details, sclient))<0)
				  {
					ret=-1;
					break;
				  }
				  if(!details) print_star(sel);
				
				  refresh();
				}
			}
		}
#endif

		if(FD_ISSET(fd, &fsr))
		{
			// ready to read.
			if((l=read(fd, buf, sizeof(buf)-1))>0)
			{
				size_t r=0;
				buf[l]='\0';
				if(rbuf) r=strlen(rbuf);
				rbuf=(char *)realloc(rbuf, r+l+1);
				if(!r) *rbuf='\0';
				strcat(rbuf+r, buf);
			}
			else
				break;

			if(act==ACTION_STATUS_SNAPSHOT)
			{
				if(rbuf)
				{
					if(!strcmp(rbuf, "\n"))
					{
						// This happens when there are
						// no backup clients.
						break;
					}
					if(strstr(rbuf, "\n-list end-\n"))
					{
						printf("%s", rbuf);
						break;
					}
				}
				continue;
			}

			//if(rbuf) printf("rbuf: %s\n", rbuf);
/*
			if(l<0)
			{
				ret=-1;
				break;
			}
*/
		}

		if((srbr=show_rbuf(rbuf, conf,
			sel, &client, &count, details, sclient))<0)
		{
			ret=-1;
			break;
		}
		else if(srbr)
		{
			// Remember it, so that we can present the detailed
			// screen without delay, above.
			if(last_rbuf) free(last_rbuf);
			last_rbuf=rbuf;
			rbuf=NULL;
		}

		if(sclient) details++;

		usleep(20000);
#ifdef HAVE_NCURSES_H
		if(actg==ACTION_STATUS)
		{
			flushinp();
			continue;
		}
#endif
		if(count)
		{
			printf("\n");
			break;
		}
	}
#ifdef HAVE_NCURSES_H
	if(actg==ACTION_STATUS) endwin();
#endif
	close_fd(&fd);
	if(last_rbuf) free(last_rbuf);
	if(rbuf) free(rbuf);
#ifdef DBFP
	if(dbfp) fclose(dbfp);
#endif
	return ret;
}
示例#17
0
/*===========================================================================*
 *				pm_exec					     *
 *===========================================================================*/
int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
		   vir_bytes frame, size_t frame_len, vir_bytes *pc,
		   vir_bytes *newsp, int user_exec_flags)
{
/* Perform the execve(name, argv, envp) call.  The user library builds a
 * complete stack image, including pointers, args, environ, etc.  The stack
 * is copied to a buffer inside VFS, and then to the new core image.
 */
  int r, slot;
  vir_bytes vsp;
  struct fproc *rfp;
  int extrabase = 0;
  static char mbuf[ARG_MAX];	/* buffer for stack and zeroes */
  struct vfs_exec_info execi;
  int i;
  static char fullpath[PATH_MAX],
  	elf_interpreter[PATH_MAX],
	firstexec[PATH_MAX],
	finalexec[PATH_MAX];
  struct lookup resolve;
  struct fproc *vmfp = &fproc[VM_PROC_NR];
  stackhook_t makestack = NULL;
  static int n;
  n++;
  struct filp *newfilp = NULL;

  lock_exec();
  lock_proc(vmfp, 0);

  /* unset execi values are 0. */
  memset(&execi, 0, sizeof(execi));
  execi.vmfd = -1;

  /* passed from exec() libc code */
  execi.userflags = user_exec_flags;
  execi.args.stack_high = kinfo.user_sp;
  execi.args.stack_size = DEFAULT_STACK_LIMIT;

  okendpt(proc_e, &slot);
  rfp = fp = &fproc[slot];

  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &execi.vmp, &execi.vp);

  resolve.l_vmnt_lock = VMNT_READ;
  resolve.l_vnode_lock = VNODE_READ;

  /* Fetch the stack from the user before destroying the old core image. */
  if (frame_len > ARG_MAX)
	FAILCHECK(ENOMEM); /* stack too big */

  r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
		   (size_t) frame_len);
  if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */
        printf("VFS: pm_exec: sys_datacopy failed\n");
	FAILCHECK(r);
  }

  /* The default is to keep the original user and group IDs */
  execi.args.new_uid = rfp->fp_effuid;
  execi.args.new_gid = rfp->fp_effgid;

  /* Get the exec file name. */
  FAILCHECK(fetch_name(path, path_len, fullpath));
  strlcpy(finalexec, fullpath, PATH_MAX);
  strlcpy(firstexec, fullpath, PATH_MAX);

  /* Get_read_vp will return an opened vn in execi.
   * if necessary it releases the existing vp so we can
   * switch after we find out what's inside the file.
   * It reads the start of the file.
   */
  Get_read_vp(execi, fullpath, 1, 1, &resolve, fp);

  /* If this is a script (i.e. has a #!/interpreter line),
   * retrieve the name of the interpreter and open that
   * executable instead.
   */
  if(is_script(&execi)) {
  	/* patch_stack will add interpreter name and
	 * args to stack and retrieve the new binary
	 * name into fullpath.
	 */
	FAILCHECK(fetch_name(path, path_len, fullpath));
	FAILCHECK(patch_stack(execi.vp, mbuf, &frame_len, fullpath));
	strlcpy(finalexec, fullpath, PATH_MAX);
  	strlcpy(firstexec, fullpath, PATH_MAX);
	Get_read_vp(execi, fullpath, 1, 0, &resolve, fp);
  }

  /* If this is a dynamically linked executable, retrieve
   * the name of that interpreter in elf_interpreter and open that
   * executable instead. But open the current executable in an
   * fd for the current process.
   */
  if(elf_has_interpreter(execi.args.hdr, execi.args.hdr_len,
	elf_interpreter, sizeof(elf_interpreter))) {
	/* Switch the executable vnode to the interpreter */
	execi.is_dyn = 1;

	/* The interpreter (loader) needs an fd to the main program,
	 * which is currently in finalexec
	 */
	if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0)) < 0) {
		printf("VFS: exec: dynamic: open main exec failed %s (%d)\n",
			fullpath, r);
		FAILCHECK(r);
	}

	/* ld.so is linked at 0, but it can relocate itself; we
	 * want it higher to trap NULL pointer dereferences. 
	 */
	execi.args.load_offset = 0x10000;

	/* Remember it */
	strlcpy(execi.execname, finalexec, PATH_MAX);

	/* The executable we need to execute first (loader)
	 * is in elf_interpreter, and has to be in fullpath to
	 * be looked up
	 */
	strlcpy(fullpath, elf_interpreter, PATH_MAX);
	strlcpy(firstexec, elf_interpreter, PATH_MAX);
	Get_read_vp(execi, fullpath, 0, 0, &resolve, fp);
  }

  /* We also want an FD for VM to mmap() the process in if possible. */
  {
	struct vnode *vp = execi.vp;
	assert(vp);
	if(vp->v_vmnt->m_haspeek && major(vp->v_dev) != MEMORY_MAJOR) {
		int newfd = -1;
		if(get_fd(vmfp, 0, R_BIT, &newfd, &newfilp) == OK) {
			assert(newfd >= 0 && newfd < OPEN_MAX);
			assert(!vmfp->fp_filp[newfd]);
			newfilp->filp_count = 1;
			newfilp->filp_vno = vp;
			newfilp->filp_flags = O_RDONLY;
			FD_SET(newfd, &vmfp->fp_filp_inuse);
			vmfp->fp_filp[newfd] = newfilp;
			/* dup_vnode(vp); */
			execi.vmfd = newfd;
			execi.args.memmap = vfs_memmap;
		}
	}
  }

  /* callback functions and data */
  execi.args.copymem = read_seg;
  execi.args.clearproc = libexec_clearproc_vm_procctl;
  execi.args.clearmem = libexec_clear_sys_memset;
  execi.args.allocmem_prealloc_cleared = libexec_alloc_mmap_prealloc_cleared;
  execi.args.allocmem_prealloc_junk = libexec_alloc_mmap_prealloc_junk;
  execi.args.allocmem_ondemand = libexec_alloc_mmap_ondemand;
  execi.args.opaque = &execi;

  execi.args.proc_e = proc_e;
  execi.args.frame_len = frame_len;
  execi.args.filesize = execi.vp->v_size;

  for (i = 0; exec_loaders[i].load_object != NULL; i++) {
      r = (*exec_loaders[i].load_object)(&execi.args);
      /* Loaded successfully, so no need to try other loaders */
      if (r == OK) { makestack = exec_loaders[i].setup_stack; break; }
  }

  FAILCHECK(r);

  /* Inform PM */
  FAILCHECK(libexec_pm_newexec(proc_e, &execi.args));

  /* Save off PC */
  *pc = execi.args.pc;

  /* call a stack-setup function if this executable type wants it */
  vsp = execi.args.stack_high - frame_len;
  if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp, &extrabase));

  /* Patch up stack and copy it from VFS to new core image. */
  libexec_patch_ptr(mbuf, vsp + extrabase);
  FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
		   (phys_bytes)frame_len));

  /* Return new stack pointer to caller */
  *newsp = vsp;

  clo_exec(rfp);

  if (execi.args.allow_setuid) {
	/* If after loading the image we're still allowed to run with
	 * setuid or setgid, change credentials now */
	rfp->fp_effuid = execi.args.new_uid;
	rfp->fp_effgid = execi.args.new_gid;
  }

  /* Remember the new name of the process */
  strlcpy(rfp->fp_name, execi.args.progname, PROC_NAME_LEN);

pm_execfinal:
  if(newfilp) unlock_filp(newfilp);
  else if (execi.vp != NULL) {
	unlock_vnode(execi.vp);
	put_vnode(execi.vp);
  }

  if(execi.vmfd >= 0 && !execi.vmfd_used) {
  	if(OK != close_fd(vmfp, execi.vmfd)) {
		printf("VFS: unexpected close fail of vm fd\n");
	}
  }

  unlock_proc(vmfp);
  unlock_exec();

  return(r);
}
示例#18
0
文件: vdialog.c 项目: timburrow/ovj3
static void
dialog_sync_func(int cmd, int argc, char **argv)
{
	int	r, this_expnum, cpid;
	int	gfd;
	double  dval;
	char	*retStr;
	DLIST   *dlist;
	vInfo   info;
	int	ret, tree;
        char    dstr[256];

	if (debug > 1)
	  fprintf(stderr, " dialog_sync_func: cmd= %d  argc= %d\n", cmd, argc);
	cpid = atoi(argv[3]);
	if (debug > 1)
	  fprintf(stderr, " dialog command: %d, pid %d\n", cmd, cpid);
	dlist = dialog_list;
	gfd = -1;
	while (dlist != NULL)
	{
	    if (dlist->pid == cpid)
	    {
		gfd = dlist->fout;
		break;
	    }
	    dlist = dlist->next;
	}
	if (dlist == NULL || gfd < 0)
	{
	    if (debug > 1)
	       fprintf(stderr, " dialog_sync_func: could not find process\n");
	    return;
	}
	if (debug > 1)
	  fprintf(stderr, " execute command: %d, pid %d\n", cmd, cpid);
	switch (cmd) {
	  case  PWD:
		retStr = get_cwd();
             	write(gfd, retStr, strlen(retStr));
		break;
	  case  EXPDIR:
             	write(gfd, curexpdir, strlen(curexpdir));
		break;
	  case  GEXIT:
		dlist->used = 0;
		close_fd(dlist);
		dlist->pid = -1;
		break;
	  case  GOK: /* verify console is available */
		this_expnum = expdir_to_expnum( curexpdir );
  		r = is_exp_active( this_expnum );
		sprintf(data, "%d  \n", r);
             	write(gfd, data, strlen(data));
		break;
	  case  GQUERY:
		if (argc < 5)
		{
		    strcpy(data, "0  \n");
                    write(gfd, data, strlen(data));
		    return;
		}
		retStr = NULL;
                if (strstr(argv[4], "macro_value") != NULL)
                {
                    retStr = modify_show_str(argv[4], dstr);
                }
                if (retStr == NULL)
                    retStr = argv[4];

		queryFlag = 0;
		sprintf(data, "if (%s) then dialog('SYNCFUNC', %d, %d, '1') else dialog('SYNCFUNC', %d, %d, '0') endif\n", retStr, GTEST,cpid, GTEST, cpid);
		execString(data);
		if (queryFlag == 0)
                {
                    strcpy(data, "0  \n");
                    write(gfd, data, strlen(data));
                }
		break;
	  case  GTEST:
		if (argc < 5)
		    return;
		queryFlag = 1;
		if (debug > 1)
	  	    fprintf(stderr, " write to dialog: '%s'\n", argv[4]);
		sprintf(data, "%s   \n", argv[4]);
             	write(gfd, data, strlen(data));
		break;
	  case  VEXEC:
		if (argc < 5)
		    return;
		execString(argv[4]);
		break;
	  case  VGET:
		sprintf(data, "    \n");
		if (argc < 5)
		{
             	    write(gfd, data, strlen(data));
		    return;
		}
		tree = CURRENT;
		if ( (ret = P_getVarInfo(tree, argv[4], &info)) )
		{
		    tree = GLOBAL;
		    ret = P_getVarInfo(tree, argv[4], &info);
		}
		if (ret != 0)
		{
             	    write(gfd, data, strlen(data));
		    return;
		}
		if (info.basicType == T_STRING)
		{
		    P_getstring(tree,argv[4],data,1,1023);
		    if (strlen(data) < 4)
			strcat (data, "    \n");
		}
		else
		{
		    dval = 0.0;
		    P_getreal(tree,argv[4],&dval,1);
		    sprintf(data, "%g\n", dval);
		}
             	write(gfd, data, strlen(data));
		break;
	}
}
示例#19
0
文件: fd.cpp 项目: mmanley/Antares
status_t
select_fd(int32 fd, struct select_info* info, bool kernel)
{
	TRACE(("select_fd(fd = %ld, info = %p (%p), 0x%x)\n", fd, info,
		info->sync, info->selected_events));

	FDGetter fdGetter;
		// define before the context locker, so it will be destroyed after it

	io_context* context = get_current_io_context(kernel);
	MutexLocker locker(context->io_mutex);

	struct file_descriptor* descriptor = fdGetter.SetTo(context, fd, true);
	if (descriptor == NULL)
		return B_FILE_ERROR;

	uint16 eventsToSelect = info->selected_events & ~B_EVENT_INVALID;

	if (descriptor->ops->fd_select == NULL && eventsToSelect != 0) {
		// if the I/O subsystem doesn't support select(), we will
		// immediately notify the select call
		return notify_select_events(info, eventsToSelect);
	}

	// We need the FD to stay open while we're doing this, so no select()/
	// deselect() will be called on it after it is closed.
	atomic_add(&descriptor->open_count, 1);

	locker.Unlock();

	// select any events asked for
	uint32 selectedEvents = 0;

	for (uint16 event = 1; event < 16; event++) {
		if ((eventsToSelect & SELECT_FLAG(event)) != 0
			&& descriptor->ops->fd_select(descriptor, event,
				(selectsync*)info) == B_OK) {
			selectedEvents |= SELECT_FLAG(event);
		}
	}
	info->selected_events = selectedEvents
		| (info->selected_events & B_EVENT_INVALID);

	// Add the info to the IO context. Even if nothing has been selected -- we
	// always support B_EVENT_INVALID.
	locker.Lock();
	if (context->fds[fd] != descriptor) {
		// Someone close()d the index in the meantime. deselect() all
		// events.
		info->next = NULL;
		deselect_select_infos(descriptor, info);

		// Release our open reference of the descriptor.
		close_fd(descriptor);
		return B_FILE_ERROR;
	}

	// The FD index hasn't changed, so we add the select info to the table.

	info->next = context->select_infos[fd];
	context->select_infos[fd] = info;

	// As long as the info is in the list, we keep a reference to the sync
	// object.
	atomic_add(&info->sync->ref_count, 1);

	// Finally release our open reference. It is safe just to decrement,
	// since as long as the descriptor is associated with the slot,
	// someone else still has it open.
	atomic_add(&descriptor->open_count, -1);

	return B_OK;
}
示例#20
0
文件: exec_wrapper.c 项目: 63n/ardour
int main(int argc, char *argv[]) {
	if (argc < 10) {
		// TODO: if argv > 3, assume pok[] is given, notifify parent.
		// usage() and a man-page (help2man) would not be bad, either :)
		return -1;
	}

	int pok[2];
	int pin[2];
	int pout[2];

	pok[0]  = atoi(argv[1]);
	pok[1]  = atoi(argv[2]);
	pin[0]  = atoi(argv[3]);
	pin[1]  = atoi(argv[4]);
	pout[0] = atoi(argv[5]);
	pout[1] = atoi(argv[6]);

	int stderr_mode = atoi(argv[7]);
	int nicelevel = atoi(argv[8]);

	/* vfork()ed child process - exec external process */
	close_fd(&pok[0]);
	fcntl(pok[1], F_SETFD, FD_CLOEXEC);

	close_fd(&pin[1]);
	if (pin[0] != STDIN_FILENO) {
		dup2(pin[0], STDIN_FILENO);
	}
	close_fd(&pin[0]);
	close_fd(&pout[0]);
	if (pout[1] != STDOUT_FILENO) {
		dup2(pout[1], STDOUT_FILENO);
	}

	if (stderr_mode == 2) {
		/* merge STDERR into output */
		if (pout[1] != STDERR_FILENO) {
			dup2(pout[1], STDERR_FILENO);
		}
	} else if (stderr_mode == 1) {
		/* ignore STDERR */
		close(STDERR_FILENO);
	} else {
		/* keep STDERR */
	}

	if (pout[1] != STDOUT_FILENO && pout[1] != STDERR_FILENO) {
		close_fd(&pout[1]);
	}

	if (nicelevel !=0) {
		nice(nicelevel);
	}

	/* copy current environment */
	char **envp = NULL;
	int i=0;
	envp = (char **) calloc(1, sizeof(char*));
	for (i=0;environ[i];++i) {
		envp[i] = strdup(environ[i]);
		envp = (char **) realloc(envp, (i+2) * sizeof(char*));
	}
	envp[i] = 0;

#ifdef HAVE_SIGSET
	sigset(SIGPIPE, SIG_DFL);
#else
	signal(SIGPIPE, SIG_DFL);
#endif

	/* all systems go */
	execve(argv[9], &argv[9], envp);

	/* if we reach here something went wrong.. */
	char buf = 0;
	(void) write(pok[1], &buf, 1 );
	close_fd(&pok[1]);

#ifdef __clang_analyzer__
	// the clang static analyzer warns about a memleak here,
	// but we don't care. The OS will clean up after us in a jiffy.
	for (i=0; envp && envp[i]; ++i) {
		free (envp[i]);
	}
	free (envp);
#endif
	return -1;
}
示例#21
0
	void TcpListener::_close_sock(){
		if(m_sock != INVALID_FD){
			close_fd(m_sock);
			m_sock =INVALID_FD;
		}
	}
示例#22
0
int main(int argc, char **argv)
{
	int	c;
	int	fd;
	int	mode = 0;
	int	dig = 0;
	int posix = 0;
	loff_t	length = -2LL;
	loff_t	offset = 0;

	static const struct option longopts[] = {
	    { "help",           no_argument,       NULL, 'h' },
	    { "version",        no_argument,       NULL, 'V' },
	    { "keep-size",      no_argument,       NULL, 'n' },
	    { "punch-hole",     no_argument,       NULL, 'p' },
	    { "collapse-range", no_argument,       NULL, 'c' },
	    { "dig-holes",      no_argument,       NULL, 'd' },
	    { "insert-range",   no_argument,       NULL, 'i' },
	    { "zero-range",     no_argument,       NULL, 'z' },
	    { "offset",         required_argument, NULL, 'o' },
	    { "length",         required_argument, NULL, 'l' },
	    { "posix",          no_argument,       NULL, 'x' },
	    { "verbose",        no_argument,       NULL, 'v' },
	    { NULL, 0, NULL, 0 }
	};

	static const ul_excl_t excl[] = {	/* rows and cols in ASCII order */
		{ 'c', 'd', 'p', 'z' },
		{ 'c', 'n' },
		{ 'x', 'c', 'd', 'i', 'n', 'p', 'z'},
		{ 0 }
	};
	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	close_stdout_atexit();

	while ((c = getopt_long(argc, argv, "hvVncpdizxl:o:", longopts, NULL))
			!= -1) {

		err_exclusive_options(c, longopts, excl, excl_st);

		switch(c) {
		case 'c':
			mode |= FALLOC_FL_COLLAPSE_RANGE;
			break;
		case 'd':
			dig = 1;
			break;
		case 'i':
			mode |= FALLOC_FL_INSERT_RANGE;
			break;
		case 'l':
			length = cvtnum(optarg);
			break;
		case 'n':
			mode |= FALLOC_FL_KEEP_SIZE;
			break;
		case 'o':
			offset = cvtnum(optarg);
			break;
		case 'p':
			mode |= FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
			break;
		case 'z':
			mode |= FALLOC_FL_ZERO_RANGE;
			break;
		case 'x':
#ifdef HAVE_POSIX_FALLOCATE
			posix = 1;
			break;
#else
			errx(EXIT_FAILURE, _("posix_fallocate support is not compiled"));
#endif
		case 'v':
			verbose++;
			break;

		case 'h':
			usage();
		case 'V':
			print_version(EXIT_SUCCESS);
		default:
			errtryhelp(EXIT_FAILURE);
		}
	}

	if (optind == argc)
		errx(EXIT_FAILURE, _("no filename specified"));

	filename = argv[optind++];

	if (optind != argc)
		errx(EXIT_FAILURE, _("unexpected number of arguments"));

	if (dig) {
		/* for --dig-holes the default is analyze all file */
		if (length == -2LL)
			length = 0;
		if (length < 0)
			errx(EXIT_FAILURE, _("invalid length value specified"));
	} else {
		/* it's safer to require the range specification (--length --offset) */
		if (length == -2LL)
			errx(EXIT_FAILURE, _("no length argument specified"));
		if (length <= 0)
			errx(EXIT_FAILURE, _("invalid length value specified"));
	}
	if (offset < 0)
		errx(EXIT_FAILURE, _("invalid offset value specified"));

	/* O_CREAT makes sense only for the default fallocate(2) behavior
	 * when mode is no specified and new space is allocated */
	fd = open(filename, O_RDWR | (!dig && !mode ? O_CREAT : 0),
		  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
	if (fd < 0)
		err(EXIT_FAILURE, _("cannot open %s"), filename);

	if (dig)
		dig_holes(fd, offset, length);
#ifdef HAVE_POSIX_FALLOCATE
	else if (posix)
		xposix_fallocate(fd, offset, length);
#endif
	else
		xfallocate(fd, mode, offset, length);

	if (close_fd(fd) != 0)
		err(EXIT_FAILURE, _("write failed: %s"), filename);

	return EXIT_SUCCESS;
}
示例#23
0
int send_message(const char * message, size_t message_size)
{	
	int rv;
	
  struct addrinfo hints =
	{
		.ai_family = AF_UNSPEC,
		.ai_socktype = SOCK_STREAM,
		.ai_flags = AI_PASSIVE // use my IP
	};

	const char * port = "3490"; 
	struct addrinfo * serv_info;
	rv = getaddrinfo(NULL, port, &hints, &serv_info);
	if (rv != 0)
	{
		fputs("getaddrinfo: ", stderr);
		fputs(gai_strerror(rv), stderr);
		fputc('\n', stderr);
    return EXIT_FAILURE;
	}

	// loop through all the results and bind to the first we can
	int sock_fd;
	struct addrinfo * p;
	for (p = serv_info; p; p = p->ai_next)
	{
		sock_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
		if (sock_fd == -1)
		{
			perror("socket");
			continue;
		}
		const int yes = 1;	
		rv = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes); 	
		if (rv == -1)
		{
			perror("setsockopt");
			close_fd(sock_fd);			
			continue;
		}
		rv = bind(sock_fd, p->ai_addr, p->ai_addrlen); 
		if (rv == -1)
		{
			perror("bind");
			close_fd(sock_fd);
			continue;
		}
		break;
	}
	freeaddrinfo(serv_info); // all done with this structure
	if (!p)
	{
		fputs("server: failed to bind\n", stderr);
    return EXIT_FAILURE;
	}

  const int backlog = 0; // no pending connections
	rv = listen(sock_fd, backlog); 
	if (rv == -1)
	{
		perror("listen");
		close_fd(sock_fd);		
    return EXIT_FAILURE;
	}

	fputs("server: waiting for connections...\n", stdout);
	
	struct sockaddr_storage client_addr;		
	socklen_t sin_size = sizeof client_addr;
	const int new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
	if (new_fd == -1)
	{
		perror("accept");
		close_fd(sock_fd);		
    return EXIT_FAILURE;
	}

	char address[INET6_ADDRSTRLEN];
	const char * dst = inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), address, sizeof address);
	if (dst == NULL)
	{
		perror("inet_ntop");
		close_fd(new_fd);				
		close_fd(sock_fd);		
    return EXIT_FAILURE;
	}
		
	fputs("server: got connection from ", stdout);
	fputs(address, stdout);
	fputc('\n', stdout);
	
	const ssize_t num_bytes = send(new_fd, message, message_size, 0);
	if (num_bytes == -1)
	{
		perror("send");
		close_fd(new_fd);		
		close_fd(sock_fd);		
    return EXIT_FAILURE;
	}
	
	close_fd(new_fd);
	close_fd(sock_fd);
	
	return 0;
}
示例#24
0
void * do_crawler(void *item)
{
	char *url_ptr;
	int clientfd ;
	static int pages = 0;
	static int error = 0;
	char *buf = NULL;
	urlq_t *url_list_head = NULL, *p, *p_pre;
	char cur_dir[256];
	hash_table *hash_in, *hash_out;
/*	int tid = pthread_self();*/
	int j = 0;
	int i= 0;
	int pos_found = 0;
	char temp[256];
	int status = 0;
	static int a = 0;
	static int b = 0;
	static int c = 0;
	static int d = 0;
	static int e = 0;
	static int f = 0;
	static int g = 0;
	while(1){	
		pthread_mutex_lock(&mutex);
		while (urlqueue.head_ptr->next == NULL){
			pthread_cond_wait(&ready, &mutex);
		}

		pthread_mutex_lock(&((threadpool_item *)item)->waitlock);
		((threadpool_item *)item)->idle = 0;
		pthread_mutex_unlock(&((threadpool_item *)item)->waitlock);	
		url_ptr = queue_pop(&urlqueue);
		g++;
		pthread_mutex_unlock(&mutex);
		

		pthread_mutex_lock(&mutex);
		/*if not visited, set flag = 1*/
		if(has_visited(hash, url_ptr) == 1){
			pthread_mutex_unlock(&mutex);
			free(url_ptr); 
			pthread_mutex_lock(&((threadpool_item *)item)->waitlock);	
			((threadpool_item *)item)->idle =1;
			pthread_mutex_unlock(&((threadpool_item *)item)->waitlock);
			d++;	
			continue;	
		}
		hash_out = has_url(hash, url_ptr);
		e++;
		pthread_mutex_unlock(&mutex);
		if (hash_out == NULL){
			printf("error\n");
			getchar();
		}
		*temp = '\0';
		cur_dir[0] = '\0';
		strcpy(cur_dir, url_ptr);
		j = strlen(cur_dir);
		for (;cur_dir[j] != '/' && j != 0; j--) ;
		if(j == 0)
			cur_dir[j] = '\0';
		else
			cur_dir[j+1] = '\0';

		for (i = 0; i < 3; i++){
			if((clientfd = open_tcp("127.0.0.1", 80)) < 0){
				close_fd(clientfd);
				continue;
			}

			if( http_do_get(clientfd, rootdir, "127.0.0.1", url_ptr) < 0){
				close_fd(clientfd);
				continue;
			}

			if(recv_line(clientfd, temp) <= 0){
				close_fd(clientfd);
				continue;
			}
			if((status = http_response_status(temp))  == 4){
				printf("%s error %d\n",url_ptr, error++);
				pthread_mutex_lock(&mutex);
				set_status(hash, url_ptr, 4);
				set_webg_status(webg, hash_out, 4);
				pthread_mutex_unlock(&mutex);
			
				pthread_mutex_lock(&((threadpool_item *)item)->waitlock);	
				((threadpool_item *)item)->idle =1;
				pthread_mutex_unlock(&((threadpool_item *)item)->waitlock);	
				close_fd(clientfd);
				break;	
			}
			buf = http_response_body(clientfd);
			close_fd(clientfd);
			break;
		}
		if (status == 4)
			continue;
		if(i == 3){
			pthread_mutex_lock(&((threadpool_item *)item)->waitlock);	
			((threadpool_item *)item)->idle =1;
			pthread_mutex_unlock(&((threadpool_item *)item)->waitlock);	
			close_fd(clientfd);
			continue;	
		}
		if (buf == NULL){
			pthread_mutex_lock(&((threadpool_item *)item)->waitlock);	
			((threadpool_item *)item)->idle =1;
			pthread_mutex_unlock(&((threadpool_item *)item)->waitlock);	
			continue;
		}
		printf("%s pages %d\n", url_ptr,pages++);
		extract_link(buf, cur_dir, &url_list_head);
		free(buf);
		buf = NULL;	
		p = url_list_head->next;
		p_pre = url_list_head;
		while (p != NULL){
			
			if(strcmp(url_ptr, p->url_ptr) == 0){
				p_pre->next = p->next;
				free(p->url_ptr);
				free(p);
				a++;
				p = p_pre->next;
				printf("a= %d, b= %d, c= %d, d= %d, e= %d, f= %d, g= %d\n", a,b,c,d,e,f,g);
				continue;	
			}			
			pthread_mutex_lock(&mutex);
			hash_in = has_url(hash, p->url_ptr);	
			if (hash_in != NULL ){
				insert_edge(webg, hash_in, hash_out);
				pthread_mutex_unlock(&mutex);
				p_pre->next = p->next;
				free(p->url_ptr);
				free(p);
				p = p_pre->next;
				b++;
				printf("a= %d, b= %d, c= %d, d= %d, e= %d, f= %d, g= %d\n", a,b,c,d,e,f,g);
				continue;
			}
			else{
				pos_found = insert_vertex(webg, hash_out, p->url_ptr);
				insert_hash_item(hash, p->url_ptr, pos_found, 0);	
				pthread_mutex_unlock(&mutex);
				c++;
				p_pre = p;
				p = p->next;
				printf("a= %d, b= %d, c= %d, d= %d, e= %d, f= %d, g= %d\n", a,b,c,d,e,f,g);
			}
		}
		
		if(p_pre != url_list_head){
			pthread_mutex_lock(&mutex);
			queue_push(&urlqueue, url_list_head->next, p_pre);
			f++;
			pthread_mutex_unlock(&mutex);
		}
		free(url_list_head);
		p = p_pre = url_list_head = NULL;
	
		pthread_mutex_lock(&((threadpool_item *)item)->waitlock);	
		((threadpool_item *)item)->idle = 1;
		pthread_mutex_unlock(&((threadpool_item *)item)->waitlock);	
/*printf("next time!\n");*/
	}
/*printf("over!\n");*/
	return NULL;	
}
示例#25
0
文件: misc.c 项目: wieck/minix
/*===========================================================================*
 *				free_proc				     *
 *===========================================================================*/
static void free_proc(struct fproc *exiter, int flags)
{
  int i;
  register struct fproc *rfp;
  register struct filp *rfilp;
  register struct vnode *vp;
  dev_t dev;

  if (exiter->fp_endpoint == NONE)
	panic("free_proc: already free");

  if (fp_is_blocked(exiter))
	unpause(exiter->fp_endpoint);

  /* Loop on file descriptors, closing any that are open. */
  for (i = 0; i < OPEN_MAX; i++) {
	(void) close_fd(exiter, i);
  }

  /* Release root and working directories. */
  if (exiter->fp_rd) { put_vnode(exiter->fp_rd); exiter->fp_rd = NULL; }
  if (exiter->fp_wd) { put_vnode(exiter->fp_wd); exiter->fp_wd = NULL; }

  /* The rest of these actions is only done when processes actually exit. */
  if (!(flags & FP_EXITING)) return;

  exiter->fp_flags |= FP_EXITING;

  /* Check if any process is SUSPENDed on this driver.
   * If a driver exits, unmap its entries in the dmap table.
   * (unmapping has to be done after the first step, because the
   * dmap table is used in the first step.)
   */
  unsuspend_by_endpt(exiter->fp_endpoint);
  dmap_unmap_by_endpt(exiter->fp_endpoint);

  worker_stop_by_endpt(exiter->fp_endpoint); /* Unblock waiting threads */
  vmnt_unmap_by_endpt(exiter->fp_endpoint); /* Invalidate open files if this
					     * was an active FS */

  /* Invalidate endpoint number for error and sanity checks. */
  exiter->fp_endpoint = NONE;

  /* If a session leader exits and it has a controlling tty, then revoke
   * access to its controlling tty from all other processes using it.
   */
  if ((exiter->fp_flags & FP_SESLDR) && exiter->fp_tty != 0) {
      dev = exiter->fp_tty;
      for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
	  if(rfp->fp_pid == PID_FREE) continue;
          if (rfp->fp_tty == dev) rfp->fp_tty = 0;

          for (i = 0; i < OPEN_MAX; i++) {
		if ((rfilp = rfp->fp_filp[i]) == NULL) continue;
		if (rfilp->filp_mode == FILP_CLOSED) continue;
		vp = rfilp->filp_vno;
		if (!S_ISCHR(vp->v_mode)) continue;
		if ((dev_t) vp->v_sdev != dev) continue;
		lock_filp(rfilp, VNODE_READ);
		(void) dev_close(dev, rfilp-filp); /* Ignore any errors, even
						    * SUSPEND. */

		rfilp->filp_mode = FILP_CLOSED;
		unlock_filp(rfilp);
          }
      }
  }

  /* Exit done. Mark slot as free. */
  exiter->fp_pid = PID_FREE;
  if (exiter->fp_flags & FP_PENDING)
	pending--;	/* No longer pending job, not going to do it */
  exiter->fp_flags = FP_NOFLAGS;
}
示例#26
0
// This function is called in order to setup the file descriptors in the
// processes. This will deal with stdin, stdout, stderr as well as any
// of the extra files defined in the Cmd structure. Once all the file
// descriptors have been duplicated into place all other open file descriptors
// will be closed.
static void setup_files(goclone_cmd *cmd)
{
    DIR *d;
    char buffer[sizeof(struct dirent) + FILENAMESIZE];
    int closed;
    int fd;
    int i;
    struct dirent *results;

    // Walk through all of the file descriptors to see if any of the
    // descriptors are actually within the range that will be duped. If so
    // we need to copy the file descriptor out of the way.
    for (i = 0; i < cmd->files_len; i++) {
        if (cmd->files[i] == -1) {
            continue;
        } else if (cmd->files[i] >= cmd->files_len) {
            continue;
        } else if (cmd->files[i] == i) {
            continue;
        }

        // Its possible for a duped descriptor to land in the range we are
        // managing. If this happens then we need to dupe again until the
        // resulting descriptor is greater than the list.
        do {
            fd = dup(cmd->files[i]);
            if (fd == -1) {
                // FIXME: Log?
                _exit(EX_OSERR);
            }
        } while (fd < cmd->files_len);
        cmd->files[i] = fd;
    }

    // Now walk through duping all of the file descriptors.
    for (i = 0; i < cmd->files_len; i++) {
        if (cmd->files[i] == -1) {
            close_fd(i);
        } else {
            if (dup2(cmd->files[i], i) == -1) {
                // FIXME
                _exit(EX_OSERR);
            }
        }
    }

    // Now walk through closing all files larger than the list of descriptors
    // passed in. This ensures that all descriptors that are not desired are
    // closed, regardless of the "close on exec" status of the descriptor.
    do {
        closed = 0;

        // Open the /proc directory. This can only real fail if /proc is not
        // mounted.
        d = opendir("/proc/self/fdinfo");
        if (d == NULL) {
            _exit(EX_OSERR);
        }

        while (1) {
            // Read each element from the directory listing one at a time.
            if (readdir_r(d, (struct dirent *) &buffer, &results) != 0) {
                // FIXME: logging?
                _exit(EX_OSERR);
            }

            // NULL here is the end of the directory list.
            if (results == NULL) {
                break;
            }

            // Parse the file name into an integer.
            i = atoi(results->d_name);

            // Make sure that no descriptor less than the list given above
            // is not closed, and that the descriptor with the directory
            // listing is left open as well.
            if (i < cmd->files_len || i == dirfd(d)) {
                continue;
            }

            // Close the file descriptor.
            close_fd(i);
            closed++;
        }

        // Close the open directory file descriptor.
        if (closedir(d) == -1) {
            _exit(EX_OSERR);
        }

        // Keep looping while descriptors are being closed.
    } while (closed != 0);
}
示例#27
0
文件: w32pipe.c 项目: jrmiddle/vile
static int
native_inout_popen(FILE **fr, FILE **fw, char *cmd)
{
    char   buf[NFILEN + 128];
    HANDLE handles[3];
    int    i, rc, rp[3], tmpin_fd, wp[3];

    TRACE((T_CALLED "native_inout_popen cmd=%s\n", cmd));
    proc_handle   = BAD_PROC_HANDLE;
    rp[0] = rp[1] = rp[2] = wp[0] = wp[1] = wp[2] = BAD_FD;
    handles[0]    = handles[1] = handles[2] = INVALID_HANDLE_VALUE;
    tmpin_fd      = BAD_FD;
    tmpin_name    = NULL;
    set_console_title(cmd);
    if (is_win95())
    {
        char *cmdp;

        /*
         * If w32pipes is set on a win95 host, you don't ever want slowreadf()
         * to periodically update the display while an intrinisic, high
         * bandwidth DOS command is in progress.  Reason:  the win95 shell,
         * command.com, will simply hang in the following scenario:
         *
         *    ^X!<high_bandwidth_cmd>
         *
         *         and
         *
         *    PIPESIZ < output of <high_bandwidth_cmd>
         *
         * I'm assuming that what's going on here is that command.com is
         * written in ASM and is using very low level BIOS/DOS calls to
         * effect output and, furthermore, that these low level calls don't
         * block when the input consumer is busy.
         */

        cmdp = skip_blanks(cmd);
        nowait_pipe_cmd = (strnicmp(cmdp, "dir", 3) == 0)  ||
                          (strnicmp(cmdp, "type", 4) == 0);
    }
    do
    {
        if (fr)
        {
            *fr = NULL;

            /*
             * Open (parent's) input pipe in TEXT mode, which will force
             * translation of the child's CR/LF record delimiters to NL
             * and keep the dreaded ^M chars from temporarily appearing
             * in a vile buffer (ugly).
             */
            if (_pipe(rp, PIPESIZ, O_TEXT|O_NOINHERIT) == -1)
                break;
            if ((rp[2] = _dup(rp[1])) == -1)
                break;
            handles[2] = handles[1] = (HANDLE) _get_osfhandle(rp[2]);
            (void) close(rp[1]);
            rp[1] = BAD_FD;
            if (! fw)
            {
                /*
                 * This is a read pipe (only).  Connect child's stdin to
                 * an empty file.  Under no circumstances should the
                 * child's stdin be connected to a device (else lots of
                 * screwy things will occur).  In particular, connecting
                 * the child's stdin to the parent's stdin will cause
                 * aborts and hangs on the various Win32 hosts.  You've
                 * been warned.
                 */

                if ((tmpin_name = _tempnam(getenv("TEMP"), "vile")) == NULL)
                    break;
                if ((tmpin_fd = open(tmpin_name,
                                     O_RDONLY|O_CREAT|O_TRUNC,
                                     _S_IWRITE|_S_IREAD)) == BAD_FD)
                {
                    break;
                }
                handles[0] = (HANDLE) _get_osfhandle(tmpin_fd);
            }
            if ((*fr = fdopen(rp[0], "r")) == 0)
                break;
        }
        if (fw)
        {
            *fw = NULL;

            /*
             * Open (child's) output pipe in binary mode, which will
             * prevent translation of the parent's CR/LF record delimiters
             * to NL.  Apparently, many apps want those delimiters :-) .
             */
            if (_pipe(wp, PIPESIZ, O_BINARY|O_NOINHERIT) == -1)
                break;
            if ((wp[2] = _dup(wp[0])) == -1)
                break;
            handles[0] = (HANDLE)_get_osfhandle(wp[2]);
            (void) close(wp[0]);
            wp[0] = BAD_FD;
            if (! fr)
                handles[1] = handles[2] = GetStdHandle(STD_OUTPUT_HANDLE);
            if ((*fw = fdopen(wp[1], "w")) == 0)
                break;
        }
        rc = (exec_shell(cmd,
                         handles,
                         fr != NULL  /* Child wdw hidden unless write pipe. */
                        ) == BAD_PROC_HANDLE) ? FALSE : TRUE;
        if (fw)
        {
            if (! rc)
            {
                /* Shell process failed, put complaint in user's face. */

                sprintf(buf, SHELL_ERR_MSG, get_shell());
                lastditch_msg(buf);
            }
            w32_close_handle(handles[0]);
        }
        if (fr)
        {
            if (! rc)
            {
                unsigned len;

                /*
                 * Shell process failed, put complaint in user's buffer.
                 * Can't write to handles[1] on a win2k host because the
                 * previously failed CreateProcess() call damaged the
                 * handle.
                 */
                len = (unsigned) (lsprintf(buf, SHELL_ERR_MSG, get_shell()) - buf);
                (void) write(rp[2], buf, len);
                (void) close(rp[2]);   /* in weird state; why not? */
            }
            w32_close_handle(handles[1]);
            close_fd(tmpin_fd);
        }
        returnCode(rc);
    }
    while (FALSE);

    /* If we get here -- some operation has failed.  Clean up. */

    close_fd(wp[0]);
    close_fd(wp[1]);
    close_fd(wp[2]);
    close_fd(rp[0]);
    close_fd(rp[1]);
    close_fd(rp[2]);
    close_fd(tmpin_fd);
    for (i = 0; i < 3; i++)
    {
        if (handles[i] != INVALID_HANDLE_VALUE)
            w32_close_handle(handles[i]);
    }
    common_cleanup();
    returnCode(FALSE);
}
示例#28
0
int main(int argc, char **argv)
{
	struct mkswap_control ctl = { .fd = -1 };
	int c;
	uint64_t sz;
	int version = SWAP_VERSION;
	char *block_count = NULL, *strsz = NULL;
#ifdef HAVE_LIBUUID
	const char *opt_uuid = NULL;
	uuid_t uuid_dat;
#endif
	static const struct option longopts[] = {
		{ "check",       no_argument,       0, 'c' },
		{ "force",       no_argument,       0, 'f' },
		{ "pagesize",    required_argument, 0, 'p' },
		{ "label",       required_argument, 0, 'L' },
		{ "swapversion", required_argument, 0, 'v' },
		{ "uuid",        required_argument, 0, 'U' },
		{ "version",     no_argument,       0, 'V' },
		{ "help",        no_argument,       0, 'h' },
		{ NULL,          0, 0, 0 }
	};

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	atexit(close_stdout);

	while((c = getopt_long(argc, argv, "cfp:L:v:U:Vh", longopts, NULL)) != -1) {
		switch (c) {
		case 'c':
			ctl.check = 1;
			break;
		case 'f':
			ctl.force = 1;
			break;
		case 'p':
			ctl.user_pagesize = strtou32_or_err(optarg, _("parsing page size failed"));
			break;
		case 'L':
			ctl.opt_label = optarg;
			break;
		case 'v':
			version = strtos32_or_err(optarg, _("parsing version number failed"));
			if (version != SWAP_VERSION)
				errx(EXIT_FAILURE,
					_("swapspace version %d is not supported"), version);
			break;
		case 'U':
#ifdef HAVE_LIBUUID
			opt_uuid = optarg;
#else
			warnx(_("warning: ignoring -U (UUIDs are unsupported by %s)"),
				program_invocation_short_name);
#endif
			break;
		case 'V':
			printf(UTIL_LINUX_VERSION);
			exit(EXIT_SUCCESS);
		case 'h':
			usage(stdout);
		default:
			usage(stderr);
		}
	}

	if (optind < argc)
		ctl.devname = argv[optind++];
	if (optind < argc)
		block_count = argv[optind++];
	if (optind != argc) {
		warnx(_("only one device argument is currently supported"));
		usage(stderr);
	}

#ifdef HAVE_LIBUUID
	if(opt_uuid) {
		if (uuid_parse(opt_uuid, uuid_dat) != 0)
			errx(EXIT_FAILURE, _("error: parsing UUID failed"));
	} else
		uuid_generate(uuid_dat);
	ctl.uuid = uuid_dat;
#endif

	init_signature_page(&ctl);	/* get pagesize and allocate signature page */

	if (!ctl.devname) {
		warnx(_("error: Nowhere to set up swap on?"));
		usage(stderr);
	}
	if (block_count) {
		/* this silly user specified the number of blocks explicitly */
		uint64_t blks = strtou64_or_err(block_count,
					_("invalid block count argument"));
		ctl.npages = blks / (ctl.pagesize / 1024);
	}

	sz = get_size(&ctl);
	if (!ctl.npages)
		ctl.npages = sz;
	else if (ctl.npages > sz && !ctl.force)
		errx(EXIT_FAILURE,
			_("error: "
			  "size %llu KiB is larger than device size %ju KiB"),
			ctl.npages * (ctl.pagesize / 1024), sz * (ctl.pagesize / 1024));

	if (ctl.npages < MIN_GOODPAGES)
		errx(EXIT_FAILURE,
		     _("error: swap area needs to be at least %ld KiB"),
		     (long)(MIN_GOODPAGES * ctl.pagesize / 1024));
	if (ctl.npages > UINT32_MAX) {
		/* true when swap is bigger than 17.59 terabytes */
		ctl.npages = UINT32_MAX;
		warnx(_("warning: truncating swap area to %llu KiB"),
			ctl.npages * ctl.pagesize / 1024);
	}

	if (is_mounted(ctl.devname))
		errx(EXIT_FAILURE, _("error: "
			"%s is mounted; will not make swapspace"),
			ctl.devname);

	open_device(&ctl);

	if (ctl.check)
		check_blocks(&ctl);

	wipe_device(&ctl);

	assert(ctl.hdr);
	ctl.hdr->version = version;
	ctl.hdr->last_page = ctl.npages - 1;
	ctl.hdr->nr_badpages = ctl.nbadpages;

	if ((ctl.npages - MIN_GOODPAGES) < ctl.nbadpages)
		errx(EXIT_FAILURE, _("Unable to set up swap-space: unreadable"));

	sz = (ctl.npages - ctl.nbadpages - 1) * ctl.pagesize;
	strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER, sz);

	printf(_("Setting up swapspace version %d, size = %s (%ju bytes)\n"),
		version, strsz, sz);
	free(strsz);

	set_signature(&ctl);
	set_uuid_and_label(&ctl);

	write_header_to_device(&ctl);

	deinit_signature_page(&ctl);

#ifdef HAVE_LIBSELINUX
	if (S_ISREG(ctl.devstat.st_mode) && is_selinux_enabled() > 0) {
		security_context_t context_string;
		security_context_t oldcontext;
		context_t newcontext;

		if (fgetfilecon(ctl.fd, &oldcontext) < 0) {
			if (errno != ENODATA)
				err(EXIT_FAILURE,
					_("%s: unable to obtain selinux file label"),
					ctl.devname);
			if (matchpathcon(ctl.devname, ctl.devstat.st_mode, &oldcontext))
				errx(EXIT_FAILURE, _("unable to matchpathcon()"));
		}
		if (!(newcontext = context_new(oldcontext)))
			errx(EXIT_FAILURE, _("unable to create new selinux context"));
		if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE))
			errx(EXIT_FAILURE, _("couldn't compute selinux context"));

		context_string = context_str(newcontext);

		if (strcmp(context_string, oldcontext)!=0) {
			if (fsetfilecon(ctl.fd, context_string))
				err(EXIT_FAILURE, _("unable to relabel %s to %s"),
						ctl.devname, context_string);
		}
		context_free(newcontext);
		freecon(oldcontext);
	}
#endif
	/*
	 * A subsequent swapon() will fail if the signature
	 * is not actually on disk. (This is a kernel bug.)
	 * The fsync() in close_fd() will take care of writing.
	 */
	if (close_fd(ctl.fd) != 0)
		err(EXIT_FAILURE, _("write failed"));
	return EXIT_SUCCESS;
}
示例#29
0
文件: w32pipe.c 项目: jrmiddle/vile
static void
tmp_npclose(FILE *fp)
{
    char buf[NFILEN + 128];
    int  rc, term_status;

    (void) fflush(fp);
    (void) fclose(fp);

    if (stdout_fd != BAD_FD)
    {
        /*
         * write pipe, but not a filter.  Editor has written data to temp
         * file, time now to exec "cmd" and hook its stdin to the file.
         *
         * It should be noted that exec'ing a process in the npclose()
         * phase of a write pipe is not exactly keeping in spirit with
         * the control flow in file.c :-) .  However, the strategy used
         * here ensures that the launched process reads a temp file that
         * is completey flushed to disk.  The only direct drawback with
         * this approach is that when the exec'd process exits, the user
         * does not receive a "[press return to continue]" prompt from
         * file.c .  But, cough, we can work around that problem :-) .
         */

        if ((stdout_fd = open(stdout_name, O_RDONLY|O_BINARY)) == BAD_FD)
        {
            /* oh my, put complaint in user's face. */

            sprintf(buf, "[unable to open temp file \"%s\": %s]",
                    stdout_name,
                    strerror(errno));
            lastditch_msg(buf);
        }
        else
        {
            handles[0] = (HANDLE) _get_osfhandle(stdout_fd);
            handles[1] = handles[2] = GetStdHandle(STD_OUTPUT_HANDLE);
            rc = (exec_shell(shcmd,
                             handles,
                             FALSE    /* don't hide child window */
                            ) == BAD_PROC_HANDLE) ? FALSE : TRUE;
            if (! rc)
            {
                /* Shell process failed, put complaint in user's face. */

                sprintf(buf, SHELL_ERR_MSG, get_shell());
                lastditch_msg(buf);
            }
            else
            {
                /* now wait for app to exit */

                (void) cwait(&term_status, (CWAIT_PARAM_TYPE) proc_handle, 0);
                TRACE(("...CreateProcess finished waiting in tmp_npclose\n"));
                close_proc_handle();
            }

            /*
             * When closing descriptors shared between parent and child,
             * order is quite important when $shell == command.com .  In
             * this situation, the descriptors can't be closed until the
             * exec'd process exits.
             */
            close_fd(stdout_fd);
        }
        pressreturn();  /* cough */
        sgarbf = TRUE;
    }
    tmp_cleanup();
}
示例#30
0
文件: main.c 项目: EmisFR/burp
static void close_fds(int *fds)
{
	for(int i=0; i<LISTEN_SOCKETS; i++) close_fd(&(fds[i]));
}