Ejemplo n.º 1
0
Archivo: handy.c Proyecto: goneri/burp
static int run_script_select(FILE **sout, FILE **serr, struct cntr *cntr, int logfunc)
{
	int mfd=-1;
	fd_set fsr;
	struct timeval tval;
	int soutfd=fileno(*sout);
	int serrfd=fileno(*serr);
	setlinebuf(*sout);
	setlinebuf(*serr);
	set_non_blocking(soutfd);
	set_non_blocking(serrfd);

	while(1)
	{
		mfd=-1;
		FD_ZERO(&fsr);
		if(*sout) add_fd_to_sets(soutfd, &fsr, NULL, NULL, &mfd);
		if(*serr) add_fd_to_sets(serrfd, &fsr, NULL, NULL, &mfd);
		tval.tv_sec=1;
		tval.tv_usec=0;
		if(select(mfd+1, &fsr, NULL, NULL, &tval)<0)
		{
			if(errno!=EAGAIN && errno!=EINTR)
			{
				logp("run_script_select error: %s\n",
					strerror(errno));
				return -1;
			}
		}
		if(FD_ISSET(soutfd, &fsr))
			log_script_output(sout, NULL, logfunc);
		if(FD_ISSET(serrfd, &fsr))
			log_script_output(serr, cntr, logfunc);

		if(!*sout && !*serr && got_sigchld)
		{
			//fclose(*sout); *sout=NULL;
			//fclose(*serr); *serr=NULL;
			got_sigchld=0;
			return 0;
		}
	}

	// Never get here.
	return -1;
}
Ejemplo n.º 2
0
int async_rw(char *rcmd, char **rdst, size_t *rlen, char wcmd, const char *wsrc, size_t *wlen)
{
        int mfd=-1;
        fd_set fsr;
        fd_set fsw;
        fd_set fse;
	int doread=0;
	int dowrite=0;
        struct timeval tval;
	static int read_blocked_on_write=0;
	static int write_blocked_on_read=0;

//printf("in async_rw\n");
	if(doing_estimate) return 0;

	if(fd<0)
	{
		logp("fd not ready in async rw: %d\n", fd);
		return -1;
	}

	if(rdst) doread++; // Given a pointer to allocate and read into.

	if(*wlen)
	{
		// More stuff to append to the write buffer.
		async_append_all_to_write_buffer(wcmd, wsrc, wlen);
	}

	if(writebuflen && !write_blocked_on_read)
		dowrite++; // The write buffer is not yet empty.

	if(doread)
	{
		if(parse_readbuf(rcmd, rdst, rlen))
		{
			logp("error in parse_readbuf\n");
			return -1;
		}
		if(*rcmd && *rdst) return 0;

		if(read_blocked_on_write) doread=0;
	}

        if(doread || dowrite)
        {
//printf("async_rw loop read %d write %d wbuflen: %d\n", doread, dowrite, writebuflen);
                mfd=-1;

                if(doread) FD_ZERO(&fsr);
                if(dowrite) FD_ZERO(&fsw);
                FD_ZERO(&fse);

                add_fd_to_sets(fd,
			doread?&fsr:NULL, dowrite?&fsw:NULL, &fse, &mfd);

                tval.tv_sec=setsec;
                tval.tv_usec=setusec;

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

		if(!FD_ISSET(fd, &fse)
		  && (!doread || !FD_ISSET(fd, &fsr))
		  && (!dowrite || !FD_ISSET(fd, &fsw)))
		{
			//logp("SELECT HIT TIMEOUT - doread: %d, dowrite: %d\n",
			//	doread, dowrite);
			// Be careful to avoid 'read quick' mode.
			if((setsec || setusec)
			  && max_network_timeout>0 && network_timeout--<=0)
			{
				logp("No activity on network for %d seconds.\n",
					max_network_timeout);
				return -1;
			}
			return 0;
		}
		network_timeout=max_network_timeout;

                if(FD_ISSET(fd, &fse))
                {
                        logp("error on socket\n");
                        return -1;
                }

                if(doread && FD_ISSET(fd, &fsr)) // able to read
                {
			int r;
			read_blocked_on_write=0;
			if(do_read(&read_blocked_on_write)) return -1;
			if((r=parse_readbuf(rcmd, rdst, rlen)))
				logp("error in second parse_readbuf\n");
			return r;
                }

                if(dowrite && FD_ISSET(fd, &fsw)) // able to write
		{
			int r=0;
			write_blocked_on_read=0;

			if((r=do_write(&write_blocked_on_read)))
				logp("error in do_write\n");
			return r;
		}
        }

        return 0;
}
Ejemplo n.º 3
0
Archivo: async.c Proyecto: jkniiv/burp
static int async_rw(struct async *as)
{
        int mfd=-1;
        fd_set fsr;
        fd_set fsw;
        fd_set fse;
	int doread=0;
	int dowrite=0;
        struct timeval tval;

	if(as->doing_estimate) return 0;

	if(as->asfd->rbuf) doread++;

	if(as->asfd->writebuflen && !as->asfd->write_blocked_on_read)
		dowrite++; // The write buffer is not yet empty.

	if(doread)
	{
		if(as->asfd->parse_readbuf(as->asfd)) return -1;
		if(as->asfd->rbuf->buf && !as->asfd->writebuflen) return 0;

		if(as->asfd->read_blocked_on_write) doread=0;
	}

        if(doread || dowrite)
        {
                mfd=-1;

                if(doread) FD_ZERO(&fsr);
                if(dowrite) FD_ZERO(&fsw);
                FD_ZERO(&fse);

                add_fd_to_sets(as->asfd->fd,
			doread?&fsr:NULL, dowrite?&fsw:NULL, &fse, &mfd);

                tval.tv_sec=as->setsec;
                tval.tv_usec=as->setusec;

                if(select(mfd+1,
			doread?&fsr:NULL, dowrite?&fsw:NULL, &fse, &tval)<0)
                {
                        if(errno!=EAGAIN && errno!=EINTR)
                        {
                                logp("select error in %s: %s\n", __func__,
					strerror(errno));
                                return -1;
                        }
                }

		if(!FD_ISSET(as->asfd->fd, &fse)
		  && (!doread || !FD_ISSET(as->asfd->fd, &fsr))
		  && (!dowrite || !FD_ISSET(as->asfd->fd, &fsw)))
		{
			// Be careful to avoid 'read quick' mode.
			if((as->setsec || as->setusec)
			  && as->asfd->max_network_timeout>0
			  && as->asfd->network_timeout--<=0)
			{
				logp("No activity on network for %d seconds.\n",
					as->asfd->max_network_timeout);
				return -1;
			}
			return 0;
		}
		as->asfd->network_timeout=as->asfd->max_network_timeout;

                if(FD_ISSET(as->asfd->fd, &fse))
                {
                        logp("error on socket\n");
                        return -1;
                }

                if(doread && FD_ISSET(as->asfd->fd, &fsr)) // able to read
                {
			if(as->asfd->ssl)
			{
				as->asfd->read_blocked_on_write=0;
				if(as->asfd->do_read_ssl(as->asfd)) return -1;
			}
			else
			{
				if(as->asfd->do_read(as->asfd)) return -1;
			}
			return as->asfd->parse_readbuf(as->asfd);
                }

                if(dowrite && FD_ISSET(as->asfd->fd, &fsw)) // able to write
		{
			if(as->asfd->ssl)
			{
				as->asfd->write_blocked_on_read=0;
				return as->asfd->do_write_ssl(as->asfd);
			}
			else
				return as->asfd->do_write(as->asfd);
		}
        }

        return 0;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
static int async_io(struct async *as, int doread)
{
	int mfd=-1;
	fd_set fsr;
	fd_set fsw;
	fd_set fse;
	int dosomething=0;
	struct timeval tval;
	struct asfd *asfd;
	static int s=0;

	as->now=time(NULL);
	if(!as->last_time) as->last_time=as->now;

	if(as->doing_estimate) goto end;

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

	tval.tv_sec=as->setsec;
	tval.tv_usec=as->setusec;

	for(asfd=as->asfd; asfd; asfd=asfd->next)
	{
		if(asfd->fdtype==ASFD_FD_SERVER_PIPE_WRITE
		 || asfd->fdtype==ASFD_FD_CHILD_PIPE_WRITE
		 || asfd->fdtype==ASFD_FD_CLIENT_MONITOR_WRITE)
			asfd->doread=0;
		else
			asfd->doread=doread;
		asfd->dowrite=0;

		if(doread)
		{
			if(asfd->parse_readbuf(asfd))
				return asfd_problem(asfd);
			if(asfd->rbuf->buf || asfd->read_blocked_on_write)
				asfd->doread=0;
		}

		if(asfd->writebuflen && !asfd->write_blocked_on_read)
			asfd->dowrite++; // The write buffer is not yet empty.

		if(!asfd->doread && !asfd->dowrite) continue;

		add_fd_to_sets(asfd->fd, asfd->doread?&fsr:NULL,
			asfd->dowrite?&fsw:NULL, &fse, &mfd);

		dosomething++;
	}
	if(!dosomething) goto end;
/*
	for(asfd=as->asfd; asfd; asfd=asfd->next)
	{
		printf("%s: %d %d %d %d\n", asfd->desc,
			asfd->doread, asfd->dowrite,
			asfd->readbuflen, asfd->writebuflen);
	}
*/

	errno=0;
	s=select(mfd+1, &fsr, &fsw, &fse, &tval);
	if(errno==EAGAIN || errno==EINTR) goto end;

	if(s<0)
	{
		logp("select error in %s: %s\n", __func__,
			strerror(errno));
		as->last_time=as->now;
		return -1;
	}

	for(asfd=as->asfd; asfd; asfd=asfd->next)
	{
		if(FD_ISSET(asfd->fd, &fse))
		{
			switch(asfd->fdtype)
			{
				case ASFD_FD_SERVER_LISTEN_MAIN:
				case ASFD_FD_SERVER_LISTEN_STATUS:
					as->last_time=as->now;
					return -1;
				default:
					logp("%s: had an exception\n",
						asfd->desc);
					return asfd_problem(asfd);
			}
		}

		if(asfd->doread && FD_ISSET(asfd->fd, &fsr)) // Able to read.
		{
			asfd->network_timeout=asfd->max_network_timeout;
			switch(asfd->fdtype)
			{
				case ASFD_FD_SERVER_LISTEN_MAIN:
				case ASFD_FD_SERVER_LISTEN_STATUS:
					// Indicate to the caller that we have
					// a new incoming client.
					asfd->new_client++;
					break;
				default:
					if(asfd->do_read(asfd)
					  || asfd->parse_readbuf(asfd))
						return asfd_problem(asfd);
					break;
			}
		}

		if(asfd->dowrite && FD_ISSET(asfd->fd, &fsw)) // Able to write.
		{
			asfd->network_timeout=asfd->max_network_timeout;
			if(asfd->do_write(asfd))
				return asfd_problem(asfd);
		}
	
		if((!asfd->doread || !FD_ISSET(asfd->fd, &fsr))
		  && (!asfd->dowrite || !FD_ISSET(asfd->fd, &fsw)))
		{
			// Be careful to avoid 'read quick' mode.
			if((as->setsec || as->setusec)
			  && asfd->fdtype!=ASFD_FD_SERVER_LISTEN_MAIN
			  && asfd->fdtype!=ASFD_FD_SERVER_LISTEN_STATUS
			  && as->now-as->last_time>0
			  && as->now-as->last_time>0
			  && asfd->max_network_timeout>0
			  && asfd->network_timeout--<=0)
			{
				logp("%s: no activity for %d seconds.\n",
					asfd->desc, asfd->max_network_timeout);
				return asfd_problem(asfd);
			}
		}
	}

end:
	as->last_time=as->now;
	return 0;
}
Ejemplo n.º 6
0
static int run_server(struct conf *conf, const char *conffile, int *rfd,
	const char *oldport, const char *oldstatusport)
{
	int ret=0;
	SSL_CTX *ctx=NULL;
	int found_normal_child=0;

	if(!(ctx=ssl_initialise_ctx(conf)))
	{
		logp("error initialising ssl ctx\n");
		return 1;
	}
	if((ssl_load_dh_params(ctx, conf)))
	{
		logp("error loading dh params\n");
		return 1;
	}

	if(!oldport
	  || strcmp(oldport, conf->port))
	{
		close_fd(rfd);
		if((*rfd=init_listen_socket(conf->port, 1))<0)
			return 1;
	}
	if(conf->status_port
	  && (!oldstatusport
		|| strcmp(oldstatusport, conf->status_port)))
	{
		close_fd(&sfd);
		if((sfd=init_listen_socket(conf->status_port, 0))<0)
			return 1;
	}

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

		if(sigchld)
		{
			chld_check_for_exiting();
			sigchld=0;
		}

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

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

		add_fd_to_sets(*rfd, &fsr, NULL, &fse, &mfd);
		if(sfd>=0) add_fd_to_sets(sfd, &fsr, NULL, &fse, &mfd);

		// Add read fds of normal children.
		found_normal_child=chld_add_fd_to_normal_sets(conf,
			&fsr, &fse, &mfd);

		// Leave if we had a SIGUSR1 and there are no children
		// running.
		if(gentleshutdown)
		{
			if(!gentleshutdown_logged)
			{
				logp("got SIGUSR2 gentle reload signal\n");
				logp("will shut down once children have exited\n");
				gentleshutdown_logged++;
			}
			else if(!found_normal_child)
			{
				logp("all children have exited - shutting down\n");
				break;
			}
		}

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

		if(FD_ISSET(*rfd, &fse))
		{
			// Happens when a client exits.
			//logp("error on listening socket.\n");
			if(!conf->forking) { gentleshutdown++; break; }
			continue;
		}

		if((sfd>=0 && FD_ISSET(sfd, &fse)))
		{
			// Happens when a client exits.
			//logp("error on status socket.\n");
			if(!conf->forking) { gentleshutdown++; break; }
			continue;
		}

		if(FD_ISSET(*rfd, &fsr))
		{
			// A normal client is incoming.
			if(process_incoming_client(*rfd, conf, ctx,
				conffile, 0 /* not a status client */))
			{
				ret=1;
				break;
			}
			if(!conf->forking) { gentleshutdown++; break; }
		}

		if(sfd>=0 && FD_ISSET(sfd, &fsr))
		{
			// A status client is incoming.
			//printf("status client?\n");
			if(process_incoming_client(sfd, conf, ctx,
				conffile, 1 /* a status client */))
			{
				ret=1;
				break;
			}
			if(!conf->forking) { gentleshutdown++; break; }
		}

		if(chld_fd_isset_normal(conf, &fsr, &fse))
		{
			ret=1;
			break;
		}

		// Have a separate select for writing to status server children

		mfd=-1;
		FD_ZERO(&fsw);
		FD_ZERO(&fse);
		if(!chld_add_fd_to_status_sets(conf, &fsw, &fse, &mfd))
		{
			// Did not find any status server children.
			// No need to do the select.
			continue;
		}

		// Do not hang around - doing the status stuff is a lower
		// priority thing than dealing with normal clients.
		tval.tv_sec=0;
		tval.tv_usec=500;

		//printf("try status server\n");

		if(select(mfd+1, NULL, &fsw, &fse, &tval)<0)
		{
			if(errno!=EAGAIN && errno!=EINTR)
			{
				logp("select error in status part of %s: %s\n",
					__func__, strerror(errno));
				ret=1;
				break;
			}
		}

		if(chld_fd_isset_status(conf, &fsw, &fse))
		{
			ret=1;
			break;
		}
	}

	if(hupreload) logp("got SIGHUP reload signal\n");

	ssl_destroy_ctx(ctx);

	return ret;
}