main.c revision 37191
16059Samurai/* 26059Samurai * User Process PPP 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 196059Samurai * 2037191Sbrian * $Id: main.c,v 1.137 1998/06/27 12:03:37 brian Exp $ 218857Srgrimes * 226059Samurai * TODO: 236059Samurai */ 2436285Sbrian 2536452Sbrian#include <sys/types.h> 2630715Sbrian#include <sys/socket.h> 2730715Sbrian#include <netinet/in.h> 2830715Sbrian#include <netinet/in_systm.h> 2930715Sbrian#include <netinet/ip.h> 3036285Sbrian#include <sys/un.h> 3130715Sbrian 3230715Sbrian#include <errno.h> 336059Samurai#include <fcntl.h> 3411336Samurai#include <paths.h> 3530715Sbrian#include <signal.h> 3630715Sbrian#include <stdio.h> 3730715Sbrian#include <string.h> 386059Samurai#include <sys/time.h> 396059Samurai#include <termios.h> 4018786Sjkh#include <unistd.h> 4130715Sbrian 4237141Sbrian#include "probe.h" 4330715Sbrian#include "mbuf.h" 4430715Sbrian#include "log.h" 4530715Sbrian#include "defs.h" 4631061Sbrian#include "id.h" 4730715Sbrian#include "timer.h" 4830715Sbrian#include "fsm.h" 4936285Sbrian#include "lqr.h" 506059Samurai#include "hdlc.h" 5131514Sbrian#include "lcp.h" 5213389Sphk#include "ccp.h" 5336285Sbrian#include "iplist.h" 5436285Sbrian#include "throughput.h" 5536285Sbrian#include "slcompress.h" 566059Samurai#include "ipcp.h" 5736285Sbrian#include "filter.h" 5836285Sbrian#include "descriptor.h" 5936285Sbrian#include "link.h" 6036285Sbrian#include "mp.h" 6136285Sbrian#include "bundle.h" 6226142Sbrian#include "loadalias.h" 636735Samurai#include "auth.h" 6413389Sphk#include "systems.h" 6513389Sphk#include "ip.h" 6623840Sbrian#include "sig.h" 6730715Sbrian#include "main.h" 6831195Sbrian#include "tun.h" 6936285Sbrian#include "server.h" 7036285Sbrian#include "prompt.h" 7136285Sbrian#include "chat.h" 7236285Sbrian#include "chap.h" 7336285Sbrian#include "datalink.h" 746059Samurai 756735Samurai#ifndef O_NONBLOCK 766735Samurai#ifdef O_NDELAY 776735Samurai#define O_NONBLOCK O_NDELAY 786735Samurai#endif 796735Samurai#endif 806735Samurai 8136431Sbrianstatic void DoLoop(struct bundle *); 8230715Sbrianstatic void TerminalStop(int); 8331343Sbrianstatic const char *ex_desc(int); 8430715Sbrian 8536285Sbrianstatic struct bundle *SignalBundle; 8636285Sbrianstatic struct prompt *SignalPrompt; 876059Samurai 8810528Samuraivoid 8936285SbrianCleanup(int excode) 906059Samurai{ 9136285Sbrian SignalBundle->CleaningUp = 1; 9236285Sbrian if (bundle_Phase(SignalBundle) != PHASE_DEAD) 9337007Sbrian bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 946059Samurai} 956059Samurai 966059Samuraivoid 9736285SbrianAbortProgram(int excode) 986059Samurai{ 9936285Sbrian server_Close(SignalBundle); 10036285Sbrian log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 10137007Sbrian bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 10236285Sbrian bundle_Destroy(SignalBundle); 10336285Sbrian log_Close(); 1046059Samurai exit(excode); 1056059Samurai} 1066059Samurai 1076059Samuraistatic void 10828679SbrianCloseConnection(int signo) 1096059Samurai{ 11026858Sbrian /* NOTE, these are manual, we've done a setsid() */ 11136285Sbrian sig_signal(SIGINT, SIG_IGN); 11236285Sbrian log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 11337018Sbrian bundle_Down(SignalBundle, CLOSE_STAYDOWN); 11436285Sbrian sig_signal(SIGINT, CloseConnection); 1156059Samurai} 1166059Samurai 1176059Samuraistatic void 11828679SbrianCloseSession(int signo) 1196059Samurai{ 12036285Sbrian log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 12128679Sbrian Cleanup(EX_TERM); 1226059Samurai} 1236059Samurai 12436285Sbrianstatic pid_t BGPid = 0; 12536285Sbrian 12610528Samuraistatic void 12736285SbrianKillChild(int signo) 12810528Samurai{ 12936285Sbrian log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 13036285Sbrian kill(BGPid, SIGINT); 13110528Samurai} 13210528Samurai 13310528Samuraistatic void 13436285SbrianTerminalCont(int signo) 13510528Samurai{ 13636285Sbrian signal(SIGCONT, SIG_DFL); 13736285Sbrian prompt_Continue(SignalPrompt); 13810528Samurai} 13910528Samurai 14026940Sbrianstatic void 14136285SbrianTerminalStop(int signo) 14226940Sbrian{ 14336285Sbrian prompt_Suspend(SignalPrompt); 14436285Sbrian signal(SIGCONT, TerminalCont); 14536285Sbrian raise(SIGSTOP); 14626940Sbrian} 14726940Sbrian 14831081Sbrianstatic void 14931081SbrianBringDownServer(int signo) 15031081Sbrian{ 15136285Sbrian /* Drops all child prompts too ! */ 15236285Sbrian server_Close(SignalBundle); 15331081Sbrian} 15431081Sbrian 15531343Sbrianstatic const char * 15625908Sbrianex_desc(int ex) 15725908Sbrian{ 15837010Sbrian static char num[12]; /* Used immediately if returned */ 15931343Sbrian static const char *desc[] = { 16031343Sbrian "normal", "start", "sock", "modem", "dial", "dead", "done", 16131343Sbrian "reboot", "errdead", "hangup", "term", "nodial", "nologin" 16231343Sbrian }; 16310528Samurai 16431962Sbrian if (ex >= 0 && ex < sizeof desc / sizeof *desc) 16525908Sbrian return desc[ex]; 16625908Sbrian snprintf(num, sizeof num, "%d", ex); 16725908Sbrian return num; 16825908Sbrian} 16925908Sbrian 17030715Sbrianstatic void 17131343SbrianUsage(void) 1726059Samurai{ 17320120Snate fprintf(stderr, 17431343Sbrian "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ]" 17531343Sbrian#ifndef NOALIAS 17631343Sbrian " [ -alias ]" 17731343Sbrian#endif 17831343Sbrian " [system]\n"); 1796059Samurai exit(EX_START); 1806059Samurai} 1816059Samurai 18231197Sbrianstatic char * 18337191SbrianProcessArgs(int argc, char **argv, int *mode, int *alias) 1846059Samurai{ 18536465Sbrian int optc, labelrequired, newmode; 1866059Samurai char *cp; 1876059Samurai 18836285Sbrian optc = labelrequired = 0; 18936465Sbrian *mode = PHYS_INTERACTIVE; 19037191Sbrian *alias = 0; 1916059Samurai while (argc > 0 && **argv == '-') { 1926059Samurai cp = *argv + 1; 19336465Sbrian newmode = Nam2mode(cp); 19436465Sbrian switch (newmode) { 19536465Sbrian case PHYS_NONE: 19636465Sbrian if (strcmp(cp, "alias") == 0) { 19737191Sbrian#ifdef NOALIAS 19837191Sbrian log_Printf(LogWARN, "Cannot load alias library\n"); 19937191Sbrian#else 20037191Sbrian *alias = 1; 20136285Sbrian#endif 20236465Sbrian optc--; /* this option isn't exclusive */ 20336465Sbrian } else 20436465Sbrian Usage(); 20536465Sbrian break; 20636465Sbrian 20736465Sbrian case PHYS_ALL: 20836465Sbrian Usage(); 20936465Sbrian break; 21036465Sbrian 21136465Sbrian case PHYS_AUTO: 21236465Sbrian case PHYS_BACKGROUND: 21336465Sbrian case PHYS_DDIAL: 21436465Sbrian labelrequired = 1; 21536465Sbrian /* fall through */ 21636465Sbrian 21736465Sbrian default: 21836465Sbrian *mode = newmode; 21936465Sbrian } 2206059Samurai optc++; 22128679Sbrian argv++; 22228679Sbrian argc--; 2236059Samurai } 22436465Sbrian 2256059Samurai if (argc > 1) { 22636285Sbrian fprintf(stderr, "You may specify only one system label.\n"); 2276059Samurai exit(EX_START); 2286059Samurai } 2296059Samurai 2306059Samurai if (optc > 1) { 23136285Sbrian fprintf(stderr, "You may specify only one mode.\n"); 2326059Samurai exit(EX_START); 2336059Samurai } 23431197Sbrian 23536285Sbrian if (labelrequired && argc != 1) { 23636285Sbrian fprintf(stderr, "Destination system must be specified in" 23736285Sbrian " auto, background or ddial mode.\n"); 23836285Sbrian exit(EX_START); 23936285Sbrian } 24036285Sbrian 24131197Sbrian return argc == 1 ? *argv : NULL; /* Don't SetLabel yet ! */ 2426059Samurai} 2436059Samurai 24426940Sbrianint 24528679Sbrianmain(int argc, char **argv) 2466059Samurai{ 24731197Sbrian char *name, *label; 24837191Sbrian int nfds, mode, alias; 24936285Sbrian struct bundle *bundle; 25036285Sbrian struct prompt *prompt; 25126516Sbrian 25231823Sbrian nfds = getdtablesize(); 25331823Sbrian if (nfds >= FD_SETSIZE) 25431823Sbrian /* 25531823Sbrian * If we've got loads of file descriptors, make sure they're all 25631823Sbrian * closed. If they aren't, we may end up with a seg fault when our 25731823Sbrian * `fd_set's get too big when select()ing ! 25831823Sbrian */ 25931823Sbrian while (--nfds > 2) 26031823Sbrian close(nfds); 26131823Sbrian 26230715Sbrian name = strrchr(argv[0], '/'); 26336285Sbrian log_Open(name ? name + 1 : argv[0]); 26426516Sbrian 26537191Sbrian label = ProcessArgs(argc - 1, argv + 1, &mode, &alias); 26631121Sbrian 26736285Sbrian#ifdef __FreeBSD__ 26836285Sbrian /* 26936285Sbrian * A FreeBSD hack to dodge a bug in the tty driver that drops output 27036285Sbrian * occasionally.... I must find the real reason some time. To display 27136285Sbrian * the dodgy behaviour, comment out this bit, make yourself a large 27236285Sbrian * routing table and then run ppp in interactive mode. The `show route' 27336285Sbrian * command will drop chunks of data !!! 27436285Sbrian */ 27536465Sbrian if (mode == PHYS_INTERACTIVE) { 27636285Sbrian close(STDIN_FILENO); 27736285Sbrian if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 27836285Sbrian fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 27936285Sbrian return 2; 28036285Sbrian } 28136285Sbrian } 28236285Sbrian#endif 28336285Sbrian 28436285Sbrian /* Allow output for the moment (except in direct mode) */ 28536285Sbrian if (mode == PHYS_DIRECT) 28636285Sbrian prompt = NULL; 28736285Sbrian else { 28836285Sbrian SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 28936465Sbrian prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(mode)); 29036285Sbrian } 29136285Sbrian 29231121Sbrian ID0init(); 29331158Sbrian if (ID0realuid() != 0) { 29431158Sbrian char conf[200], *ptr; 29531158Sbrian 29631158Sbrian snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE); 29731158Sbrian do { 29831158Sbrian if (!access(conf, W_OK)) { 29937019Sbrian log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", 30037019Sbrian conf); 30131158Sbrian return -1; 30231158Sbrian } 30331158Sbrian ptr = conf + strlen(conf)-2; 30431158Sbrian while (ptr > conf && *ptr != '/') 30531158Sbrian *ptr-- = '\0'; 30631158Sbrian } while (ptr >= conf); 30731158Sbrian } 30831158Sbrian 30936285Sbrian if (!system_IsValid(label, prompt, mode)) { 31031121Sbrian fprintf(stderr, "You may not use ppp in this mode with this label\n"); 31136285Sbrian if (mode == PHYS_DIRECT) { 31231157Sbrian const char *l; 31331197Sbrian l = label ? label : "default"; 31436285Sbrian log_Printf(LogWARN, "Label %s rejected -direct connection\n", l); 31531157Sbrian } 31636285Sbrian log_Close(); 31731121Sbrian return 1; 31829083Sbrian } 31931121Sbrian 32036467Sbrian if ((bundle = bundle_Create(TUN_PREFIX, mode, (const char **)argv)) == NULL) { 32136285Sbrian log_Printf(LogWARN, "bundle_Create: %s\n", strerror(errno)); 32226940Sbrian return EX_START; 3236059Samurai } 32436314Sbrian if (prompt) { 32536314Sbrian prompt->bundle = bundle; /* couldn't do it earlier */ 32636314Sbrian prompt_Printf(prompt, "Using interface: %s\n", bundle->ifp.Name); 32736314Sbrian } 32836285Sbrian SignalBundle = bundle; 32937191Sbrian bundle->AliasEnabled = alias; 33031121Sbrian 33137008Sbrian if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0) 33236285Sbrian prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 33336285Sbrian 33436285Sbrian sig_signal(SIGHUP, CloseSession); 33536285Sbrian sig_signal(SIGTERM, CloseSession); 33636285Sbrian sig_signal(SIGINT, CloseConnection); 33736285Sbrian sig_signal(SIGQUIT, CloseSession); 33836285Sbrian sig_signal(SIGALRM, SIG_IGN); 33924753Sache signal(SIGPIPE, SIG_IGN); 3406059Samurai 34136465Sbrian if (mode == PHYS_INTERACTIVE) 34236285Sbrian sig_signal(SIGTSTP, TerminalStop); 34336285Sbrian 34436285Sbrian sig_signal(SIGUSR2, BringDownServer); 34536285Sbrian 34631197Sbrian if (label) { 34731197Sbrian /* 34836285Sbrian * Set label both before and after system_Select ! 34936285Sbrian * This way, "set enddisc label" works during system_Select, and we 35036285Sbrian * also end up with the correct label if we have embedded load 35136285Sbrian * commands. 35231197Sbrian */ 35336285Sbrian bundle_SetLabel(bundle, label); 35437008Sbrian if (system_Select(bundle, label, CONFFILE, prompt, NULL) < 0) { 35536285Sbrian prompt_Printf(prompt, "Destination system (%s) not found.\n", label); 35636285Sbrian AbortProgram(EX_START); 3576059Samurai } 35836285Sbrian bundle_SetLabel(bundle, label); 35936465Sbrian if (mode == PHYS_AUTO && 36036285Sbrian bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 36136285Sbrian prompt_Printf(prompt, "You must \"set ifaddr\" with a peer address " 36236285Sbrian "in label %s for auto mode.\n", label); 36336285Sbrian AbortProgram(EX_START); 36436285Sbrian } 3656059Samurai } 36626940Sbrian 36736465Sbrian if (mode != PHYS_INTERACTIVE) { 36836285Sbrian if (mode != PHYS_DIRECT) { 36936285Sbrian int bgpipe[2]; 37036285Sbrian pid_t bgpid; 37136285Sbrian 37236465Sbrian if (mode == PHYS_BACKGROUND && pipe(bgpipe)) { 37336285Sbrian log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 37436285Sbrian AbortProgram(EX_SOCK); 37520813Sjkh } 3766059Samurai 37728679Sbrian bgpid = fork(); 37820813Sjkh if (bgpid == -1) { 37936285Sbrian log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 38036285Sbrian AbortProgram(EX_SOCK); 38120813Sjkh } 38236285Sbrian 38320813Sjkh if (bgpid) { 38420813Sjkh char c = EX_NORMAL; 38511336Samurai 38636465Sbrian if (mode == PHYS_BACKGROUND) { 38736285Sbrian close(bgpipe[1]); 38820813Sjkh BGPid = bgpid; 38936285Sbrian /* If we get a signal, kill the child */ 39036285Sbrian signal(SIGHUP, KillChild); 39136285Sbrian signal(SIGTERM, KillChild); 39236285Sbrian signal(SIGINT, KillChild); 39336285Sbrian signal(SIGQUIT, KillChild); 39436285Sbrian 39536285Sbrian /* Wait for our child to close its pipe before we exit */ 39636285Sbrian if (read(bgpipe[0], &c, 1) != 1) { 39736285Sbrian prompt_Printf(prompt, "Child exit, no status.\n"); 39836285Sbrian log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 39925908Sbrian } else if (c == EX_NORMAL) { 40036285Sbrian prompt_Printf(prompt, "PPP enabled.\n"); 40136285Sbrian log_Printf(LogPHASE, "Parent: PPP enabled.\n"); 40225908Sbrian } else { 40336285Sbrian prompt_Printf(prompt, "Child failed (%s).\n", ex_desc((int) c)); 40436285Sbrian log_Printf(LogPHASE, "Parent: Child failed (%s).\n", 40528679Sbrian ex_desc((int) c)); 40628679Sbrian } 40736285Sbrian close(bgpipe[0]); 40820813Sjkh } 40928679Sbrian return c; 41036465Sbrian } else if (mode == PHYS_BACKGROUND) { 41136285Sbrian close(bgpipe[0]); 41236285Sbrian bundle->notify.fd = bgpipe[1]; 41336285Sbrian } 41420813Sjkh 41536709Sbrian bundle_LockTun(bundle); /* we have a new pid */ 41636709Sbrian 41736285Sbrian /* -auto, -dedicated, -ddial & -background */ 41836285Sbrian prompt_Destroy(prompt, 0); 41936285Sbrian close(STDOUT_FILENO); 42036285Sbrian close(STDERR_FILENO); 42136285Sbrian close(STDIN_FILENO); 42226686Sbrian setsid(); 42336285Sbrian } else { 42436285Sbrian /* -direct: STDIN_FILENO gets used by modem_Open */ 42536285Sbrian prompt_TtyInit(NULL); 42636285Sbrian close(STDOUT_FILENO); 42736285Sbrian close(STDERR_FILENO); 42826686Sbrian } 4296059Samurai } else { 43036285Sbrian /* Interactive mode */ 43132129Sbrian close(STDERR_FILENO); 43236285Sbrian prompt_TtyInit(prompt); 43336285Sbrian prompt_TtyCommandMode(prompt); 43436285Sbrian prompt_Required(prompt); 4356059Samurai } 43629696Sbrian 43736285Sbrian log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(mode)); 43836431Sbrian DoLoop(bundle); 43936285Sbrian AbortProgram(EX_NORMAL); 4406059Samurai 44136285Sbrian return EX_NORMAL; 4426059Samurai} 4436059Samurai 4446059Samuraistatic void 44536431SbrianDoLoop(struct bundle *bundle) 4466059Samurai{ 4476059Samurai fd_set rfds, wfds, efds; 44837141Sbrian int i, nfds, nothing_done; 44937141Sbrian struct probe probe; 4506059Samurai 45137141Sbrian probe_Init(&probe); 45237141Sbrian 45336285Sbrian do { 45423598Sache nfds = 0; 45528679Sbrian FD_ZERO(&rfds); 45628679Sbrian FD_ZERO(&wfds); 45728679Sbrian FD_ZERO(&efds); 4587001Samurai 45936314Sbrian /* All our datalinks, the tun device and the MP socket */ 46036285Sbrian descriptor_UpdateSet(&bundle->desc, &rfds, &wfds, &efds, &nfds); 46125067Sbrian 46236314Sbrian /* All our prompts and the diagnostic socket */ 46336314Sbrian descriptor_UpdateSet(&server.desc, &rfds, NULL, NULL, &nfds); 46436314Sbrian 46536285Sbrian if (bundle_IsDead(bundle)) 46636285Sbrian /* Don't select - we'll be here forever */ 46736285Sbrian break; 46826551Sbrian 46936285Sbrian i = select(nfds, &rfds, &wfds, &efds, NULL); 47026696Sbrian 47136345Sbrian if (i < 0 && errno != EINTR) { 47236285Sbrian log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 47336285Sbrian if (log_IsKept(LogTIMER)) { 47436285Sbrian struct timeval t; 47536285Sbrian 47636285Sbrian for (i = 0; i <= nfds; i++) { 47736285Sbrian if (FD_ISSET(i, &rfds)) { 47836285Sbrian log_Printf(LogTIMER, "Read set contains %d\n", i); 47936285Sbrian FD_CLR(i, &rfds); 48036285Sbrian t.tv_sec = t.tv_usec = 0; 48136285Sbrian if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 48236285Sbrian log_Printf(LogTIMER, "The culprit !\n"); 48336285Sbrian break; 48436285Sbrian } 48536285Sbrian } 48636285Sbrian if (FD_ISSET(i, &wfds)) { 48736285Sbrian log_Printf(LogTIMER, "Write set contains %d\n", i); 48836285Sbrian FD_CLR(i, &wfds); 48936285Sbrian t.tv_sec = t.tv_usec = 0; 49036285Sbrian if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 49136285Sbrian log_Printf(LogTIMER, "The culprit !\n"); 49236285Sbrian break; 49336285Sbrian } 49436285Sbrian } 49536285Sbrian if (FD_ISSET(i, &efds)) { 49636285Sbrian log_Printf(LogTIMER, "Error set contains %d\n", i); 49736285Sbrian FD_CLR(i, &efds); 49836285Sbrian t.tv_sec = t.tv_usec = 0; 49936285Sbrian if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 50036285Sbrian log_Printf(LogTIMER, "The culprit !\n"); 50136285Sbrian break; 50236285Sbrian } 50336285Sbrian } 50436285Sbrian } 50528679Sbrian } 50628679Sbrian break; 5078857Srgrimes } 5086059Samurai 50936345Sbrian sig_Handle(); 51036345Sbrian 51136345Sbrian if (i <= 0) 51236345Sbrian continue; 51336345Sbrian 51436285Sbrian for (i = 0; i <= nfds; i++) 51536285Sbrian if (FD_ISSET(i, &efds)) { 51637019Sbrian log_Printf(LogERROR, "Exception detected on descriptor %d\n", i); 51736285Sbrian break; 5186059Samurai } 51928679Sbrian 52036285Sbrian if (i <= nfds) 52136285Sbrian break; 52228536Sbrian 52337141Sbrian nothing_done = 1; 52437141Sbrian 52537141Sbrian if (descriptor_IsSet(&server.desc, &rfds)) { 52636285Sbrian descriptor_Read(&server.desc, bundle, &rfds); 52737141Sbrian nothing_done = 0; 52837141Sbrian } 52932039Sbrian 53037141Sbrian if (descriptor_IsSet(&bundle->desc, &rfds)) { 53137141Sbrian descriptor_Read(&bundle->desc, bundle, &rfds); 53237141Sbrian nothing_done = 0; 53337141Sbrian } 53437141Sbrian 53536285Sbrian if (descriptor_IsSet(&bundle->desc, &wfds)) 53637141Sbrian if (!descriptor_Write(&bundle->desc, bundle, &wfds) && nothing_done) { 53737141Sbrian /* 53837141Sbrian * This is disasterous. The OS has told us that something is 53937141Sbrian * writable, and all our write()s have failed. Rather than 54037141Sbrian * going back immediately to do our UpdateSet()s and select(), 54137141Sbrian * we sleep for a bit to avoid gobbling up all cpu time. 54237141Sbrian */ 54337141Sbrian struct timeval t; 54436285Sbrian 54537141Sbrian t.tv_sec = 0; 54637141Sbrian t.tv_usec = 100000; 54737141Sbrian select(0, NULL, NULL, NULL, &t); 54837141Sbrian } 54936345Sbrian 55036285Sbrian } while (bundle_CleanDatalinks(bundle), !bundle_IsDead(bundle)); 55136285Sbrian 55236285Sbrian log_Printf(LogDEBUG, "DoLoop done.\n"); 5536059Samurai} 554