main.c revision 46086
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 * 2046086Sbrian * $Id: main.c,v 1.152 1999/03/30 00:44:57 brian Exp $ 218857Srgrimes * 226059Samurai * TODO: 236059Samurai */ 2436285Sbrian 2543313Sbrian#include <sys/param.h> 2630715Sbrian#include <netinet/in.h> 2730715Sbrian#include <netinet/in_systm.h> 2830715Sbrian#include <netinet/ip.h> 2936285Sbrian#include <sys/un.h> 3030715Sbrian 3130715Sbrian#include <errno.h> 326059Samurai#include <fcntl.h> 3311336Samurai#include <paths.h> 3430715Sbrian#include <signal.h> 3530715Sbrian#include <stdio.h> 3630715Sbrian#include <string.h> 376059Samurai#include <sys/time.h> 386059Samurai#include <termios.h> 3918786Sjkh#include <unistd.h> 4030715Sbrian 4139395Sbrian#ifndef NOALIAS 4246086Sbrian#ifdef __FreeBSD__ 4346086Sbrian#include <alias.h> 4446086Sbrian#else 4539395Sbrian#include "alias.h" 4639395Sbrian#endif 4739395Sbrian#endif 4837141Sbrian#include "probe.h" 4930715Sbrian#include "mbuf.h" 5030715Sbrian#include "log.h" 5130715Sbrian#include "defs.h" 5231061Sbrian#include "id.h" 5330715Sbrian#include "timer.h" 5430715Sbrian#include "fsm.h" 5536285Sbrian#include "lqr.h" 566059Samurai#include "hdlc.h" 5731514Sbrian#include "lcp.h" 5813389Sphk#include "ccp.h" 5936285Sbrian#include "iplist.h" 6036285Sbrian#include "throughput.h" 6136285Sbrian#include "slcompress.h" 626059Samurai#include "ipcp.h" 6336285Sbrian#include "filter.h" 6436285Sbrian#include "descriptor.h" 6536285Sbrian#include "link.h" 6636285Sbrian#include "mp.h" 6743313Sbrian#ifndef NORADIUS 6843313Sbrian#include "radius.h" 6943313Sbrian#endif 7036285Sbrian#include "bundle.h" 716735Samurai#include "auth.h" 7213389Sphk#include "systems.h" 7323840Sbrian#include "sig.h" 7430715Sbrian#include "main.h" 7536285Sbrian#include "server.h" 7636285Sbrian#include "prompt.h" 7736285Sbrian#include "chat.h" 7836285Sbrian#include "chap.h" 7938174Sbrian#include "cbcp.h" 8036285Sbrian#include "datalink.h" 8140561Sbrian#include "iface.h" 826059Samurai 836735Samurai#ifndef O_NONBLOCK 846735Samurai#ifdef O_NDELAY 856735Samurai#define O_NONBLOCK O_NDELAY 866735Samurai#endif 876735Samurai#endif 886735Samurai 8936431Sbrianstatic void DoLoop(struct bundle *); 9030715Sbrianstatic void TerminalStop(int); 9131343Sbrianstatic const char *ex_desc(int); 9230715Sbrian 9336285Sbrianstatic struct bundle *SignalBundle; 9436285Sbrianstatic struct prompt *SignalPrompt; 956059Samurai 9610528Samuraivoid 9736285SbrianCleanup(int excode) 986059Samurai{ 9936285Sbrian SignalBundle->CleaningUp = 1; 10038008Sbrian bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 1016059Samurai} 1026059Samurai 1036059Samuraivoid 10436285SbrianAbortProgram(int excode) 1056059Samurai{ 10636285Sbrian server_Close(SignalBundle); 10736285Sbrian log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 10837007Sbrian bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 10936285Sbrian bundle_Destroy(SignalBundle); 11036285Sbrian log_Close(); 1116059Samurai exit(excode); 1126059Samurai} 1136059Samurai 1146059Samuraistatic void 11528679SbrianCloseConnection(int signo) 1166059Samurai{ 11726858Sbrian /* NOTE, these are manual, we've done a setsid() */ 11836285Sbrian sig_signal(SIGINT, SIG_IGN); 11936285Sbrian log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 12037018Sbrian bundle_Down(SignalBundle, CLOSE_STAYDOWN); 12136285Sbrian sig_signal(SIGINT, CloseConnection); 1226059Samurai} 1236059Samurai 1246059Samuraistatic void 12528679SbrianCloseSession(int signo) 1266059Samurai{ 12736285Sbrian log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 12828679Sbrian Cleanup(EX_TERM); 1296059Samurai} 1306059Samurai 13136285Sbrianstatic pid_t BGPid = 0; 13236285Sbrian 13310528Samuraistatic void 13436285SbrianKillChild(int signo) 13510528Samurai{ 13636285Sbrian log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 13736285Sbrian kill(BGPid, SIGINT); 13810528Samurai} 13910528Samurai 14010528Samuraistatic void 14136285SbrianTerminalCont(int signo) 14210528Samurai{ 14336285Sbrian signal(SIGCONT, SIG_DFL); 14436285Sbrian prompt_Continue(SignalPrompt); 14510528Samurai} 14610528Samurai 14726940Sbrianstatic void 14836285SbrianTerminalStop(int signo) 14926940Sbrian{ 15036285Sbrian prompt_Suspend(SignalPrompt); 15136285Sbrian signal(SIGCONT, TerminalCont); 15236285Sbrian raise(SIGSTOP); 15326940Sbrian} 15426940Sbrian 15531081Sbrianstatic void 15631081SbrianBringDownServer(int signo) 15731081Sbrian{ 15836285Sbrian /* Drops all child prompts too ! */ 15936285Sbrian server_Close(SignalBundle); 16031081Sbrian} 16131081Sbrian 16231343Sbrianstatic const char * 16325908Sbrianex_desc(int ex) 16425908Sbrian{ 16537010Sbrian static char num[12]; /* Used immediately if returned */ 16631343Sbrian static const char *desc[] = { 16731343Sbrian "normal", "start", "sock", "modem", "dial", "dead", "done", 16831343Sbrian "reboot", "errdead", "hangup", "term", "nodial", "nologin" 16931343Sbrian }; 17010528Samurai 17131962Sbrian if (ex >= 0 && ex < sizeof desc / sizeof *desc) 17225908Sbrian return desc[ex]; 17325908Sbrian snprintf(num, sizeof num, "%d", ex); 17425908Sbrian return num; 17525908Sbrian} 17625908Sbrian 17730715Sbrianstatic void 17831343SbrianUsage(void) 1796059Samurai{ 18020120Snate fprintf(stderr, 18131343Sbrian "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ]" 18231343Sbrian#ifndef NOALIAS 18331343Sbrian " [ -alias ]" 18431343Sbrian#endif 18540797Sbrian " [system ...]\n"); 1866059Samurai exit(EX_START); 1876059Samurai} 1886059Samurai 18940797Sbrianstatic int 19037191SbrianProcessArgs(int argc, char **argv, int *mode, int *alias) 1916059Samurai{ 19240797Sbrian int optc, newmode, arg; 1936059Samurai char *cp; 1946059Samurai 19540797Sbrian optc = 0; 19636465Sbrian *mode = PHYS_INTERACTIVE; 19737191Sbrian *alias = 0; 19840797Sbrian for (arg = 1; arg < argc && *argv[arg] == '-'; arg++, optc++) { 19940797Sbrian cp = argv[arg] + 1; 20036465Sbrian newmode = Nam2mode(cp); 20136465Sbrian switch (newmode) { 20236465Sbrian case PHYS_NONE: 20336465Sbrian if (strcmp(cp, "alias") == 0) { 20437191Sbrian#ifdef NOALIAS 20540797Sbrian log_Printf(LogWARN, "Cannot load alias library (compiled out)\n"); 20637191Sbrian#else 20737191Sbrian *alias = 1; 20836285Sbrian#endif 20936465Sbrian optc--; /* this option isn't exclusive */ 21036465Sbrian } else 21136465Sbrian Usage(); 21236465Sbrian break; 21336465Sbrian 21436465Sbrian case PHYS_ALL: 21536465Sbrian Usage(); 21636465Sbrian break; 21736465Sbrian 21836465Sbrian default: 21936465Sbrian *mode = newmode; 22036465Sbrian } 2216059Samurai } 22236465Sbrian 2236059Samurai if (optc > 1) { 22436285Sbrian fprintf(stderr, "You may specify only one mode.\n"); 2256059Samurai exit(EX_START); 2266059Samurai } 22731197Sbrian 22840797Sbrian if (*mode == PHYS_AUTO && arg == argc) { 22940797Sbrian fprintf(stderr, "A system must be specified in auto mode.\n"); 23036285Sbrian exit(EX_START); 23136285Sbrian } 23236285Sbrian 23340797Sbrian return arg; /* Don't SetLabel yet ! */ 2346059Samurai} 2356059Samurai 23640797Sbrianstatic void 23740797SbrianCheckLabel(const char *label, struct prompt *prompt, int mode) 23840797Sbrian{ 23940797Sbrian const char *err; 24040797Sbrian 24140797Sbrian if ((err = system_IsValid(label, prompt, mode)) != NULL) { 24240797Sbrian fprintf(stderr, "%s: %s\n", label, err); 24340797Sbrian if (mode == PHYS_DIRECT) 24440797Sbrian log_Printf(LogWARN, "Label %s rejected -direct connection: %s\n", 24540797Sbrian label, err); 24640797Sbrian log_Close(); 24740797Sbrian exit(1); 24840797Sbrian } 24940797Sbrian} 25040797Sbrian 25140797Sbrian 25226940Sbrianint 25328679Sbrianmain(int argc, char **argv) 2546059Samurai{ 25540797Sbrian char *name; 25643187Sbrian const char *lastlabel; 25740797Sbrian int nfds, mode, alias, label, arg; 25836285Sbrian struct bundle *bundle; 25936285Sbrian struct prompt *prompt; 26026516Sbrian 26131823Sbrian nfds = getdtablesize(); 26231823Sbrian if (nfds >= FD_SETSIZE) 26331823Sbrian /* 26431823Sbrian * If we've got loads of file descriptors, make sure they're all 26531823Sbrian * closed. If they aren't, we may end up with a seg fault when our 26631823Sbrian * `fd_set's get too big when select()ing ! 26731823Sbrian */ 26831823Sbrian while (--nfds > 2) 26931823Sbrian close(nfds); 27031823Sbrian 27130715Sbrian name = strrchr(argv[0], '/'); 27236285Sbrian log_Open(name ? name + 1 : argv[0]); 27326516Sbrian 27438198Sbrian#ifndef NOALIAS 27538198Sbrian PacketAliasInit(); 27638198Sbrian#endif 27740797Sbrian label = ProcessArgs(argc, argv, &mode, &alias); 27831121Sbrian 27936285Sbrian /* 28044539Sbrian * A FreeBSD & OpenBSD hack to dodge a bug in the tty driver that drops 28144539Sbrian * output occasionally.... I must find the real reason some time. To 28244539Sbrian * display the dodgy behaviour, comment out this bit, make yourself a large 28336285Sbrian * routing table and then run ppp in interactive mode. The `show route' 28436285Sbrian * command will drop chunks of data !!! 28536285Sbrian */ 28636465Sbrian if (mode == PHYS_INTERACTIVE) { 28736285Sbrian close(STDIN_FILENO); 28836285Sbrian if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 28936285Sbrian fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 29036285Sbrian return 2; 29136285Sbrian } 29236285Sbrian } 29336285Sbrian 29436285Sbrian /* Allow output for the moment (except in direct mode) */ 29536285Sbrian if (mode == PHYS_DIRECT) 29636285Sbrian prompt = NULL; 29743526Sbrian else 29836285Sbrian SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 29936285Sbrian 30031121Sbrian ID0init(); 30131158Sbrian if (ID0realuid() != 0) { 30231158Sbrian char conf[200], *ptr; 30331158Sbrian 30431158Sbrian snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE); 30531158Sbrian do { 30631158Sbrian if (!access(conf, W_OK)) { 30737019Sbrian log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", 30837019Sbrian conf); 30931158Sbrian return -1; 31031158Sbrian } 31131158Sbrian ptr = conf + strlen(conf)-2; 31231158Sbrian while (ptr > conf && *ptr != '/') 31331158Sbrian *ptr-- = '\0'; 31431158Sbrian } while (ptr >= conf); 31531158Sbrian } 31631158Sbrian 31740797Sbrian if (label < argc) 31840797Sbrian for (arg = label; arg < argc; arg++) 31940797Sbrian CheckLabel(argv[arg], prompt, mode); 32040797Sbrian else 32140797Sbrian CheckLabel("default", prompt, mode); 32231121Sbrian 32343526Sbrian prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(mode)); 32443526Sbrian 32536467Sbrian if ((bundle = bundle_Create(TUN_PREFIX, mode, (const char **)argv)) == NULL) { 32636285Sbrian log_Printf(LogWARN, "bundle_Create: %s\n", strerror(errno)); 32726940Sbrian return EX_START; 3286059Samurai } 32943187Sbrian 33043187Sbrian /* NOTE: We may now have changed argv[1] via a ``set proctitle'' */ 33143187Sbrian 33236314Sbrian if (prompt) { 33336314Sbrian prompt->bundle = bundle; /* couldn't do it earlier */ 33440561Sbrian prompt_Printf(prompt, "Using interface: %s\n", bundle->iface->name); 33536314Sbrian } 33636285Sbrian SignalBundle = bundle; 33737191Sbrian bundle->AliasEnabled = alias; 33840561Sbrian if (alias) 33940561Sbrian bundle->cfg.opt |= OPT_IFACEALIAS; 34031121Sbrian 34137008Sbrian if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0) 34236285Sbrian prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 34336285Sbrian 34436285Sbrian sig_signal(SIGHUP, CloseSession); 34536285Sbrian sig_signal(SIGTERM, CloseSession); 34636285Sbrian sig_signal(SIGINT, CloseConnection); 34736285Sbrian sig_signal(SIGQUIT, CloseSession); 34836285Sbrian sig_signal(SIGALRM, SIG_IGN); 34924753Sache signal(SIGPIPE, SIG_IGN); 3506059Samurai 35136465Sbrian if (mode == PHYS_INTERACTIVE) 35236285Sbrian sig_signal(SIGTSTP, TerminalStop); 35336285Sbrian 35436285Sbrian sig_signal(SIGUSR2, BringDownServer); 35536285Sbrian 35643187Sbrian lastlabel = argc == 2 ? bundle->argv1 : argv[argc - 1]; 35740797Sbrian for (arg = label; arg < argc; arg++) { 35840797Sbrian /* In case we use LABEL or ``set enddisc label'' */ 35943187Sbrian bundle_SetLabel(bundle, lastlabel); 36043187Sbrian system_Select(bundle, arg == 1 ? bundle->argv1 : argv[arg], 36143187Sbrian CONFFILE, prompt, NULL); 3626059Samurai } 36326940Sbrian 36440797Sbrian if (label < argc) 36540797Sbrian /* In case the last label did a ``load'' */ 36643187Sbrian bundle_SetLabel(bundle, lastlabel); 36740797Sbrian 36840797Sbrian if (mode == PHYS_AUTO && 36940797Sbrian bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 37040797Sbrian prompt_Printf(prompt, "You must ``set ifaddr'' with a peer address " 37140797Sbrian "in auto mode.\n"); 37240797Sbrian AbortProgram(EX_START); 37340797Sbrian } 37440797Sbrian 37536465Sbrian if (mode != PHYS_INTERACTIVE) { 37636285Sbrian if (mode != PHYS_DIRECT) { 37736285Sbrian int bgpipe[2]; 37836285Sbrian pid_t bgpid; 37936285Sbrian 38036465Sbrian if (mode == PHYS_BACKGROUND && pipe(bgpipe)) { 38136285Sbrian log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 38236285Sbrian AbortProgram(EX_SOCK); 38320813Sjkh } 3846059Samurai 38528679Sbrian bgpid = fork(); 38620813Sjkh if (bgpid == -1) { 38736285Sbrian log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 38836285Sbrian AbortProgram(EX_SOCK); 38920813Sjkh } 39036285Sbrian 39120813Sjkh if (bgpid) { 39220813Sjkh char c = EX_NORMAL; 39311336Samurai 39436465Sbrian if (mode == PHYS_BACKGROUND) { 39536285Sbrian close(bgpipe[1]); 39620813Sjkh BGPid = bgpid; 39736285Sbrian /* If we get a signal, kill the child */ 39836285Sbrian signal(SIGHUP, KillChild); 39936285Sbrian signal(SIGTERM, KillChild); 40036285Sbrian signal(SIGINT, KillChild); 40136285Sbrian signal(SIGQUIT, KillChild); 40236285Sbrian 40336285Sbrian /* Wait for our child to close its pipe before we exit */ 40436285Sbrian if (read(bgpipe[0], &c, 1) != 1) { 40536285Sbrian prompt_Printf(prompt, "Child exit, no status.\n"); 40636285Sbrian log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 40725908Sbrian } else if (c == EX_NORMAL) { 40836285Sbrian prompt_Printf(prompt, "PPP enabled.\n"); 40936285Sbrian log_Printf(LogPHASE, "Parent: PPP enabled.\n"); 41025908Sbrian } else { 41136285Sbrian prompt_Printf(prompt, "Child failed (%s).\n", ex_desc((int) c)); 41236285Sbrian log_Printf(LogPHASE, "Parent: Child failed (%s).\n", 41328679Sbrian ex_desc((int) c)); 41428679Sbrian } 41536285Sbrian close(bgpipe[0]); 41620813Sjkh } 41728679Sbrian return c; 41836465Sbrian } else if (mode == PHYS_BACKGROUND) { 41936285Sbrian close(bgpipe[0]); 42036285Sbrian bundle->notify.fd = bgpipe[1]; 42136285Sbrian } 42220813Sjkh 42336709Sbrian bundle_LockTun(bundle); /* we have a new pid */ 42436709Sbrian 42536285Sbrian /* -auto, -dedicated, -ddial & -background */ 42636285Sbrian prompt_Destroy(prompt, 0); 42736285Sbrian close(STDOUT_FILENO); 42836285Sbrian close(STDERR_FILENO); 42936285Sbrian close(STDIN_FILENO); 43026686Sbrian setsid(); 43136285Sbrian } else { 43236285Sbrian /* -direct: STDIN_FILENO gets used by modem_Open */ 43336285Sbrian prompt_TtyInit(NULL); 43436285Sbrian close(STDOUT_FILENO); 43536285Sbrian close(STDERR_FILENO); 43626686Sbrian } 4376059Samurai } else { 43836285Sbrian /* Interactive mode */ 43932129Sbrian close(STDERR_FILENO); 44036285Sbrian prompt_TtyInit(prompt); 44136285Sbrian prompt_TtyCommandMode(prompt); 44236285Sbrian prompt_Required(prompt); 4436059Samurai } 44429696Sbrian 44536285Sbrian log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(mode)); 44636431Sbrian DoLoop(bundle); 44736285Sbrian AbortProgram(EX_NORMAL); 4486059Samurai 44936285Sbrian return EX_NORMAL; 4506059Samurai} 4516059Samurai 4526059Samuraistatic void 45336431SbrianDoLoop(struct bundle *bundle) 4546059Samurai{ 4556059Samurai fd_set rfds, wfds, efds; 45637141Sbrian int i, nfds, nothing_done; 45737141Sbrian struct probe probe; 4586059Samurai 45937141Sbrian probe_Init(&probe); 46037141Sbrian 46136285Sbrian do { 46223598Sache nfds = 0; 46328679Sbrian FD_ZERO(&rfds); 46428679Sbrian FD_ZERO(&wfds); 46528679Sbrian FD_ZERO(&efds); 4667001Samurai 46736314Sbrian /* All our datalinks, the tun device and the MP socket */ 46836285Sbrian descriptor_UpdateSet(&bundle->desc, &rfds, &wfds, &efds, &nfds); 46925067Sbrian 47036314Sbrian /* All our prompts and the diagnostic socket */ 47136314Sbrian descriptor_UpdateSet(&server.desc, &rfds, NULL, NULL, &nfds); 47236314Sbrian 47336285Sbrian if (bundle_IsDead(bundle)) 47436285Sbrian /* Don't select - we'll be here forever */ 47536285Sbrian break; 47626551Sbrian 47745126Sbrian /* 47845126Sbrian * It's possible that we've had a signal since we last checked. If 47945126Sbrian * we don't check again before calling select(), we may end up stuck 48045126Sbrian * after having missed the event.... sig_Handle() tries to be as 48145126Sbrian * quick as possible if nothing is likely to have happened. 48245126Sbrian * This is only really likely if we block in open(... O_NONBLOCK) 48345126Sbrian * which will happen with a misconfigured device. 48445126Sbrian */ 48545126Sbrian if (sig_Handle()) 48645126Sbrian continue; 48745126Sbrian 48836285Sbrian i = select(nfds, &rfds, &wfds, &efds, NULL); 48926696Sbrian 49036345Sbrian if (i < 0 && errno != EINTR) { 49136285Sbrian log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 49236285Sbrian if (log_IsKept(LogTIMER)) { 49336285Sbrian struct timeval t; 49436285Sbrian 49536285Sbrian for (i = 0; i <= nfds; i++) { 49636285Sbrian if (FD_ISSET(i, &rfds)) { 49736285Sbrian log_Printf(LogTIMER, "Read set contains %d\n", i); 49836285Sbrian FD_CLR(i, &rfds); 49936285Sbrian t.tv_sec = t.tv_usec = 0; 50036285Sbrian if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 50136285Sbrian log_Printf(LogTIMER, "The culprit !\n"); 50236285Sbrian break; 50336285Sbrian } 50436285Sbrian } 50536285Sbrian if (FD_ISSET(i, &wfds)) { 50636285Sbrian log_Printf(LogTIMER, "Write set contains %d\n", i); 50736285Sbrian FD_CLR(i, &wfds); 50836285Sbrian t.tv_sec = t.tv_usec = 0; 50936285Sbrian if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 51036285Sbrian log_Printf(LogTIMER, "The culprit !\n"); 51136285Sbrian break; 51236285Sbrian } 51336285Sbrian } 51436285Sbrian if (FD_ISSET(i, &efds)) { 51536285Sbrian log_Printf(LogTIMER, "Error set contains %d\n", i); 51636285Sbrian FD_CLR(i, &efds); 51736285Sbrian t.tv_sec = t.tv_usec = 0; 51836285Sbrian if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 51936285Sbrian log_Printf(LogTIMER, "The culprit !\n"); 52036285Sbrian break; 52136285Sbrian } 52236285Sbrian } 52336285Sbrian } 52428679Sbrian } 52528679Sbrian break; 5268857Srgrimes } 5276059Samurai 52843693Sbrian log_Printf(LogTIMER, "Select returns %d\n", i); 52943693Sbrian 53036345Sbrian sig_Handle(); 53136345Sbrian 53236345Sbrian if (i <= 0) 53336345Sbrian continue; 53436345Sbrian 53536285Sbrian for (i = 0; i <= nfds; i++) 53636285Sbrian if (FD_ISSET(i, &efds)) { 53741654Sbrian log_Printf(LogPHASE, "Exception detected on descriptor %d\n", i); 53841654Sbrian /* We deal gracefully with link descriptor exceptions */ 53941654Sbrian if (!bundle_Exception(bundle, i)) { 54041654Sbrian log_Printf(LogERROR, "Exception cannot be handled !\n"); 54141654Sbrian break; 54241654Sbrian } 5436059Samurai } 54428679Sbrian 54536285Sbrian if (i <= nfds) 54636285Sbrian break; 54728536Sbrian 54837141Sbrian nothing_done = 1; 54937141Sbrian 55037141Sbrian if (descriptor_IsSet(&server.desc, &rfds)) { 55136285Sbrian descriptor_Read(&server.desc, bundle, &rfds); 55237141Sbrian nothing_done = 0; 55337141Sbrian } 55432039Sbrian 55537141Sbrian if (descriptor_IsSet(&bundle->desc, &rfds)) { 55637141Sbrian descriptor_Read(&bundle->desc, bundle, &rfds); 55737141Sbrian nothing_done = 0; 55837141Sbrian } 55937141Sbrian 56036285Sbrian if (descriptor_IsSet(&bundle->desc, &wfds)) 56137141Sbrian if (!descriptor_Write(&bundle->desc, bundle, &wfds) && nothing_done) { 56237141Sbrian /* 56337141Sbrian * This is disasterous. The OS has told us that something is 56437141Sbrian * writable, and all our write()s have failed. Rather than 56537141Sbrian * going back immediately to do our UpdateSet()s and select(), 56637141Sbrian * we sleep for a bit to avoid gobbling up all cpu time. 56737141Sbrian */ 56837141Sbrian struct timeval t; 56936285Sbrian 57037141Sbrian t.tv_sec = 0; 57137141Sbrian t.tv_usec = 100000; 57237141Sbrian select(0, NULL, NULL, NULL, &t); 57337141Sbrian } 57436345Sbrian 57536285Sbrian } while (bundle_CleanDatalinks(bundle), !bundle_IsDead(bundle)); 57636285Sbrian 57736285Sbrian log_Printf(LogDEBUG, "DoLoop done.\n"); 5786059Samurai} 579