Exemplo n.º 1
0
int
main(int argc, char **argv)
{
    char *ptr, *server, *active;
    int c, errflag=0;
    int lockfd;
    char *inputtype;

    DefaultNntpProtocol = NntpIhaveProtocol;
    *DefaultNewsgroups = '\0';
    *DefaultModerator = '\0';
    *DefaultOrganization = '\0';
    *DefaultTrustFrom = '\0';
    *DefaultTrustfrom = '\0';
    inputtype = NntpInputType;
    while ((c = getopt(argc,argv,"f:F:m:o:g:w:r:p:a:s:t:h?ncv"))!= -1)
      switch (c) {
      case 'v':
       verboseon("bbsnnrp.log");
       break;
      case 'c':
       ResetActive = 1;
       break;
      case 'g':
       strncpy(DefaultNewsgroups, optarg, sizeof DefaultNewsgroups);
       break;
      case 'm':
       strncpy(DefaultModerator, optarg, sizeof DefaultModerator);
       break;
      case 'o':
       strncpy(DefaultOrganization, optarg, sizeof DefaultOrganization);
       break;
      case 'f':
       strncpy(DefaultTrustfrom, optarg, sizeof DefaultTrustfrom);
       break;
      case 'F':
       strncpy(DefaultTrustFrom, optarg, sizeof DefaultTrustFrom);
       break;
      case 'r': {
       char *hostptr;
       AskLocal = 0;
       DefaultRemoteHost = optarg;
       if ((hostptr = strchr(optarg,':')) != NULL) {
	 *hostptr = '\0';
	 DefaultRemoteHost = hostptr+1;
	 if (strcasecmp( optarg, "post" ) == 0)
	   DefaultNntpProtocol = NntpPostProtocol;
	 *hostptr = ':';
       }
       break;
      }
      case 'w':
       RunOnce = 0;
       DefaultWait = atoi(optarg);
       if (DefaultWait < MIN_WAIT) 
	 DefaultWait = MIN_WAIT;
       break;
      case 'p':
       if (AskLocal == 0) {
	  DefaultPort = optarg;
       } else {
	  DefaultPath = optarg;
       }
       break;
      case 'n':
       StatHistory = 0;
       break;
      case 'a':
       Max_Arts = atol(optarg);
       if (Max_Arts < 0) Max_Arts = 0;
       break;
      case 's':
       Max_Stats = atol(optarg);
       if (Max_Stats < 0) Max_Stats = 0;
       break;
      case 't':
       if ( strcasecmp(optarg,StdinInputType) == 0) {
	  inputtype = StdinInputType;
       } 
       break;
      case 'h':
      case '?':
      default:
        errflag ++;	
      }
    if (errflag > 0) {
       usage(argv[0]);
       return(1);
    }
    if (inputtype == NntpInputType && argc - optind < 2) {
       usage(argv[0]);
       exit(1);
    }
    if (inputtype == NntpInputType) {
     server = argv[optind];
     active = argv[optind+1];
     if ( isfile(active) ) {
       strncpy(BBSNNRP.activefile, active, sizeof BBSNNRP.activefile);
     } else if ( strchr(active,'/') == NULL) {
       sprintf(BBSNNRP.activefile, "%s/innd/%.*s",BBSHOME, sizeof BBSNNRP.activefile - 7 - strlen(BBSHOME), active);
     } else {
       strncpy(BBSNNRP.activefile, active, sizeof BBSNNRP.activefile);
     }

     strncpy(LockFile , (char*)fileglue("%s.lock",active), sizeof LockFile);
     if ((lockfd = open(LockFile, O_RDONLY)) >= 0) {
      char buf[10];
      int pid;

      if (read(lockfd, buf, sizeof buf) > 0 && (pid = atoi(buf))>0 && kill(pid,0)==0) {
	fprintf(stderr, "another process [%d] running\n", pid);
        exit(1);
      } else {
	fprintf(stderr, "no process [%d] running, but lock file existed, unlinked\n", pid);
	unlink(LockFile);
      }
      close(lockfd);
     }
     if ((lockfd = open(LockFile, O_RDWR|O_CREAT|O_EXCL,0644)) < 0) {
      fprintf( stderr, "maybe another %s process running\n",argv[0]);
      exit(1);
     } else {
      char buf[10];
      int pid;
      sprintf(buf,"%-.8d\n",getpid());
      write(lockfd, buf, strlen(buf));
      close(lockfd);
     }
     for (;;) {
      if (!initial_bbs(NULL)) {
       fprintf(stderr, "Initial BBS failed\n");
       exit(1);
      }
      initsockets(server, &BBSNNRP, inputtype);
      ptr = (char*)strrchr(active,'/');
      if (ptr != NULL) 
	ptr++;
      else 
	ptr = active;
      sprintf(BBSNNRP.rcfile,"%s/.newsrc.%s.%s",INNDHOME, server, ptr);
      initrcfiles(&BBSNNRP);

      signal(SIGTERM, doterm);
      signal(SIGKILL, doterm);
      signal(SIGHUP,  doterm);
      signal(SIGPIPE, doterm);

      readnews(&BBSNNRP);
      writerc(&BBSNNRP);
      closesockets();

      if (RunOnce) break;
      sleep(DefaultWait);
     }
     unlink(LockFile);
    } /* NntpInputType */
    else {
      if (!initial_bbs(NULL)) {
       fprintf(stderr, "Initial BBS failed\n");
       exit(1);
      }
      initsockets(server, &BBSNNRP, inputtype);
      signal(SIGTERM, doterm);
      signal(SIGKILL, doterm);
      signal(SIGHUP,  doterm);
      signal(SIGPIPE, doterm);

      stdinreadnews(&BBSNNRP);
      closesockets();
    } /* stdin input type */
    return 0;
}
Exemplo n.º 2
0
Arquivo: socket.c Projeto: kvirund/mmc
int	sconnect(char *addr,int port,char *laddr,int doproc,PSHANDLER hf,void *ha) {
    int			idx,opt;
    struct sockaddr_in	rem,loc;

#define FAIL0(m) { clwarnx(m); return -1; }
#define	FAIL1(m) { sockerrmsg(m,0); return -1; }
#define	FAIL2(m) { sockerrmsg(m,0); goto free_sock; }
#define	FAIL3(m) { sockerrmsg(m,0); goto free_event; }
#define	FAILD(m) { sockerrmsg(m,1); return -1; }

#ifdef WIN32
    if (initsockets()<0)
	return -1;
#endif

    if (!hf)
	return -1;
    for (idx=0;idx<NSOCK;idx++)
	if (!sockets[idx].inuse)
	    break;
    if (idx==NSOCK) {
	clwarnx("too many open sockets");
	return -1;
    }
    sockets[idx].handler=hf;
    sockets[idx].data=ha;
    sockets[idx].ilen=sockets[idx].olen=0;
    sockets[idx].lp=1;
    sockets[idx].lpevent=-1;
    sockets[idx].state=sNORMAL;
    sockets[idx].attr=7;
    sockets[idx].mode=SM_NORM;
    sockets[idx].opmode=doproc ? SM_NORM : SM_HALF;
    sockets[idx].type=RT_SOCK;
    sockets[idx].zsp=NULL;
    sockets[idx].rawin=sockets[idx].rawout=sockets[idx].procin=0;
    window_flush(); /* flush output before a long blocking operation */
    memset(&rem,0,sizeof(rem));
    rem.sin_family=AF_INET;
    rem.sin_port=htons((short)port);
    if ((rem.sin_addr.s_addr=inet_addr(addr))==INADDR_NONE) {
	struct hostent	*hp=gethostbyname(addr);

	if (!hp)
	    FAILD("can't get remote address");
	memcpy(&rem.sin_addr,hp->h_addr,sizeof(rem.sin_addr));
    }
    memcpy(&sockets[idx].remote,&rem,sizeof(sockets[idx].remote));
    if (laddr) {
	int   slen;
	char  *cp,*buf;

	memset(&loc,0,sizeof(loc));
	loc.sin_family=AF_INET;
	slen=strlen(laddr);
	for (cp=laddr+slen;cp>laddr;--cp)
	  if (*cp==':')
	    break;
	if (*cp==':') {
	  buf=malloc(cp-laddr+1);
	  if (!buf)
	    FAIL0("out of memory");
	  memcpy(buf,laddr,cp-laddr);
	  buf[cp-laddr]='\0';
	  ++cp;
	  loc.sin_port=htons((short)atoi(cp));
	} else
	  buf=laddr;
	if ((loc.sin_addr.s_addr=inet_addr(buf))==INADDR_NONE) {
	    struct hostent  *hp=gethostbyname(buf);

	    if (!hp)
		FAILD("can't get local address");
	    memcpy(&loc.sin_addr,hp->h_addr,sizeof(loc.sin_addr));
	}
	if (buf!=laddr)
	  free(buf);
    }
    if ((sockets[idx].sock=socket(PF_INET,SOCK_STREAM,0))<0)
	FAIL1("can't create socket");
    if (laddr)
	if (bind(sockets[idx].sock,(struct sockaddr *)&loc,sizeof(loc))<0)
	    FAIL2("can't bind socket");
#ifdef WIN32
    if ((sockets[idx].event=CreateEvent(NULL,FALSE,FALSE,NULL))==NULL) {
	clwarn("can't create event");
	goto free_sock;
    }
    if (WSAEventSelect(sockets[idx].sock,sockets[idx].event,FD_READ|FD_CLOSE|FD_CONNECT))
	FAIL3("can't bind event to socket");
#endif
#ifndef WIN32
    {
      int flags=fcntl(sockets[idx].sock,F_GETFL,0);
      if (flags<0)
	FAIL3("can't get fd flags");
      if (fcntl(sockets[idx].sock,F_SETFL,flags|O_NONBLOCK)<0)
	FAIL3("can't set fd flags");
    }
#endif
    opt=KERN_SOCKBUFSIZE;
    setsockopt(sockets[idx].sock,SOL_SOCKET,SO_RCVBUF,(void*)&opt,sizeof(opt)); /* ignore result */
    if (connect(sockets[idx].sock,(struct sockaddr *)&rem,sizeof(rem))<0) {
#ifdef WIN32
      if (WSAGetLastError()!=WSAEWOULDBLOCK)
#else
      if (errno!=EINPROGRESS)
#endif
	FAIL3("can't connect to remote host");
      sockets[idx].mode=SM_CONN;
      sockets[idx].inuse=1;
    } else {
      sockets[idx].inuse=1;
      if (sockets[idx].handler)
	sockets[idx].handler(idx,SCONN,sockets[idx].data,NULL,0);
    }
    return idx;
free_event:
#ifdef WIN32
    CloseHandle(sockets[idx].event);
#endif
free_sock:
    closesocket(sockets[idx].sock);
    return -1;
#undef FAIL0
#undef FAIL1
#undef FAIL2
#undef FAIL3
}
Exemplo n.º 3
0
static void init(int argc, char **argv) {
  int c;
  char *p;
  const char *user = NULL;
  const char *rootdir = NULL, *workdir = NULL, *pidfile = NULL;
  const char *bindaddr[MAXSOCK];
  int nba = 0;
  uid_t uid = 0;
  gid_t gid = 0;
  int nodaemon = 0, quickstart = 0, dump = 0, nover = 0, forkon = 0;
  int family = AF_UNSPEC;
  int cfd = -1;
  const struct zone *z;
#ifndef NO_DSO
  char *ext = NULL, *extarg = NULL;
  int (*extinit)(const char *arg, struct zone *zonelist) = NULL;
#endif

  if ((progname = strrchr(argv[0], '/')) != NULL)
    argv[0] = ++progname;
  else
    progname = argv[0];

  if (argc <= 1) usage(1);

  const char *const getopt_fmt = "u:r:b:w:t:c:p:nel:Lqs:h46dvaAfCx:X:zg";
  while((c = getopt(argc, argv, getopt_fmt)) != EOF)
    switch(c) {
    case 'u': user = optarg; break;
    case 'r': rootdir = optarg; break;
    case 'b':
      if (nba >= MAXSOCK)
        error(0, "too many addresses to listen on (%d max)", MAXSOCK);
      bindaddr[nba++] = optarg;
      break;
#ifndef NO_IPv6
    case '4': family = AF_INET; break;
    case '6': family = AF_INET6; break;
#else
    case '4': break;
    case '6': error(0, "IPv6 support isn't compiled in");
#endif
    case 'w': workdir = optarg; break;
    case 'p': pidfile = optarg; break;
    case 't':
      p = optarg;
      if (*p == ':') ++p;
      else {
        if (!(p = parse_time(p, &def_ttl)) || !def_ttl ||
            (*p && *p++ != ':'))
          error(0, "invalid ttl (-t) value `%.50s'", optarg);
      }
      if (*p == ':') ++p;
      else if (*p) {
        if (!(p = parse_time(p, &min_ttl)) || (*p && *p++ != ':'))
          error(0, "invalid minttl (-t) value `%.50s'", optarg);
      }
      if (*p == ':') ++p;
      else if (*p) {
        if (!(p = parse_time(p, &max_ttl)) || (*p && *p++ != ':'))
          error(0, "invalid maxttl (-t) value `%.50s'", optarg);
      }
      if (*p)
        error(0, "invalid value for -t (ttl) option: `%.50s'", optarg);
      if ((min_ttl && max_ttl && min_ttl > max_ttl) ||
          (min_ttl && def_ttl < min_ttl) ||
          (max_ttl && def_ttl > max_ttl))
        error(0, "inconsistent def:min:max ttl: %u:%u:%u",
              def_ttl, min_ttl, max_ttl);
      break;
    case 'c':
      if (!(p = parse_time(optarg, &recheck)) || *p)
        error(0, "invalid check interval (-c) value `%.50s'", optarg);
      break;
    case 'n': nodaemon = 1; break;
    case 'e': accept_in_cidr = 1; break;
    case 'l':
      logfile = optarg;
      if (*logfile != '+') flushlog = 0;
      else ++logfile, flushlog = 1;
      if (!*logfile) logfile = NULL, flushlog = 0;
      else if (logfile[0] == '-' && logfile[1] == '\0')
        logfile = NULL, flog = stdout;
      break;
    case 'L':
      verbose = 1; break;
break;
    case 's':
#ifdef NO_STATS
      fprintf(stderr,
        "%s: warning: no statistics counters support is compiled in\n",
        progname);
#else
      statsfile = optarg;
      if (*statsfile != '+') stats_relative = 0;
      else ++statsfile, stats_relative = 1;
      if (!*statsfile) statsfile = NULL;
#endif
      break;
    case 'q': quickstart = 1; break;
    case 'd':
#ifdef NO_MASTER_DUMP
      error(0, "master-format dump option (-d) isn't compiled in");
#endif
      dump = 1;
      break;
    case 'v': show_version = nover++ ? NULL : "rbldnsd"; break;
    case 'a': lazy = 1; break;
    case 'A': lazy = 0; break;
    case 'f': forkon = 1; break;
    case 'C': nouncompress = 1; break;
#ifndef NO_DSO
    case 'x': ext = optarg; break;
    case 'X': extarg = optarg; break;
#else
    case 'x':
    case 'X':
      error(0, "extension support is not compiled in");
#endif
#ifndef NO_ANONYMIZE
    case 'z': anonymize = 1; break;
#else
    case 'z':
      error(0, "anonymization support is not compiled in");
#endif
#ifndef NO_GEOIP
    case 'g': geoip = 1; break;
    case 'G': geoip = 1; geoip_path = optarg; break;

#else
    case 'g':
    case 'G':
      error(0, "geoip support is not compiled in");
#endif
    case 'h': usage(0);
    default: error(0, "type `%.50s -h' for help", progname);
    }

  if (!(argc -= optind))
    error(0, "no zone(s) to service specified (-h for help)");
  argv += optind;

#ifndef NO_MASTER_DUMP
  if (dump) {
    time_t now;
    logto = LOGTO_STDERR;
    for(c = 0; c < argc; ++c)
      zonelist = addzone(zonelist, argv[c]);
    init_zones_caches(zonelist);
    if (rootdir && (chdir(rootdir) < 0 || chroot(rootdir) < 0))
      error(errno, "unable to chroot to %.50s", rootdir);
    if (workdir && chdir(workdir) < 0)
      error(errno, "unable to chdir to %.50s", workdir);
    if (!do_reload(0))
      error(0, "zone loading errors, aborting");
    now = time(NULL);
    printf("; zone dump made %s", ctime(&now));
    printf("; rbldnsd version %s\n", version);
    for (z = zonelist; z; z = z->z_next)
      dumpzone(z, stdout);
    fflush(stdout);
    exit(ferror(stdout) ? 1 : 0);
  }
#endif

  if (!nba)
    error(0, "no address to listen on (-b option) specified");

  tzset();
  if (nodaemon)
    logto = LOGTO_STDOUT|LOGTO_STDERR;
  else {
    /* fork early so that logging will be from right pid */
    int pfd[2];
    if (pipe(pfd) < 0) error(errno, "pipe() failed");
    c = fork();
    if (c < 0) error(errno, "fork() failed");
    if (c > 0) {
      close(pfd[1]);
      if (read(pfd[0], &c, 1) < 1) exit(1);
      else exit(0);
    }
    cfd = pfd[1];
    close(pfd[0]);
    openlog(progname, LOG_PID|LOG_NDELAY, LOG_DAEMON);
    logto = LOGTO_STDERR|LOGTO_SYSLOG;
    if (!quickstart && !flog) logto |= LOGTO_STDOUT;
  }

  initsockets(bindaddr, nba, family);

#ifndef NO_DSO
  if (ext) {
    void *handle = dlopen(ext, RTLD_NOW);
    if (!handle)
      error(0, "unable to load extension `%s': %s", ext, dlerror());
    extinit = dlsym(handle, "rbldnsd_extension_init");
    if (!extinit)
      error(0, "unable to find extension init routine in `%s'", ext);
  }
#endif

  if (!user && !(uid = getuid()))
    user = "******";

  if (!user)
    p = NULL;
  else {
    if ((p = strchr(user, ':')) != NULL)
      *p++ = '\0';
    if ((c = satoi(user)) >= 0)
      uid = c, gid = c;
    else {
      struct passwd *pw = getpwnam(user);
      if (!pw)
        error(0, "unknown user `%s'", user);
      uid = pw->pw_uid;
      gid = pw->pw_gid;
      endpwent();
    }
  }
  if (!uid)
    error(0, "daemon should not run as root, specify -u option");
  if (p) {
    if ((c = satoi(p)) >= 0)
      gid = c;
    else {
      struct group *gr = getgrnam(p);
      if (!gr)
        error(0, "unknown group `%s'", p);
      gid = gr->gr_gid;
      endgrent();
    }
    p[-1] = ':';
  }

  if (pidfile) {
    int fdpid;
    char buf[40];
    c = sprintf(buf, "%ld\n", (long)getpid());
    fdpid = open(pidfile, O_CREAT|O_WRONLY|O_TRUNC, 0644);
    if (fdpid < 0 || write(fdpid, buf, c) < c)
      error(errno, "unable to write pidfile");
    close(fdpid);
  }

  if (rootdir && (chdir(rootdir) < 0 || chroot(rootdir) < 0))
    error(errno, "unable to chroot to %.50s", rootdir);
  if (workdir && chdir(workdir) < 0)
    error(errno, "unable to chdir to %.50s", workdir);

  if (user)
    if (setgroups(1, &gid) < 0 || setgid(gid) < 0 || setuid(uid) < 0)
      error(errno, "unable to setuid(%d:%d)", (int)uid, (int)gid);

  for(c = 0; c < argc; ++c)
    zonelist = addzone(zonelist, argv[c]);
  init_zones_caches(zonelist);

#ifndef NO_DSO
  if (extinit && extinit(extarg, zonelist) != 0)
    error(0, "unable to iniitialize extension `%s'", ext);
#endif

  if (!quickstart && !do_reload(0))
    error(0, "zone loading errors, aborting");

  /* count number of zones */
  for(c = 0, z = zonelist; z; z = z->z_next)
    ++c;
  numzones = c;

#if STATS_IPC_IOVEC
  stats_iov = (struct iovec *)emalloc(numzones * sizeof(struct iovec));
  for(c = 0, z = zonelist; z; z = z->z_next, ++c) {
    stats_iov[c].iov_base = (char*)&z->z_stats;
    stats_iov[c].iov_len = sizeof(z->z_stats);
  }
#endif
  dslog(LOG_INFO, 0, "rbldnsd version %s started (%d socket(s), %d zone(s))",
        version, numsock, numzones);
  initialized = 1;

  if (cfd >= 0) {
    write(cfd, "", 1);
    close(cfd);
    close(0); close(2);
    if (!flog) close(1);
    setsid();
    logto = LOGTO_SYSLOG;
  }

  if (quickstart)
    do_reload(0);

  /* only set "main" fork_on_reload after first reload */
  fork_on_reload = forkon;
}