modules/up/src/Core/sys/File.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. private_strerror
  2. File
  3. File
  4. setHandlers
  5. read
  6. write
  7. DatagramSocket
  8. DatagramSocket
  9. recvFrom
  10. sendTo
  11. defaultInterface
  12. RawSocket
  13. RawSocket
  14. recvFrom
  15. sendTo
  16. join
  17. MulticastSocket
  18. MulticastSocket
  19. defaultInterface
  20. setTTL
  21. StreamSocket
  22. StreamSocket
  23. StreamSocket
  24. ListenSocket
  25. ListenSocket
  26. accept
  27. DiskFile
  28. DiskFile
  29. seekTo
  30. seekEnd
  31. lock
  32. truncate
  33. createDir
  34. openPidFile
  35. closePidFile
  36. daemonize

   1 //
   2 // $Id: File.cc,v 1.1.1.1 2000/03/10 16:32:20 engin Exp $
   3 //
   4 // system.cc
   5 // Author: Ramesh Govindan <govindan@isi.edu>
   6 //
   7 // Abstracted OS facilities for file system access and
   8 // for communication primitives. This file contains implementations of:
   9 //      - network addresses (Address class)
  10 //      - OS file descriptors and descriptor sets
  11 //      - a common time representation
  12 //
  13 
  14 #ifdef HAVE_CONFIG_H
  15 #include <config.h>
  16 #endif
  17 
  18 #include <cstdio>
  19 #include <cstdlib>
  20 #include <cerrno>
  21 
  22 extern "C" {
  23 #if HAVE_UNISTD_H
  24 #include <unistd.h>
  25 #endif // HAVE_UNISTD_H
  26 
  27 #include <sys/types.h>
  28 #include <sys/socket.h>
  29 #include <sys/time.h>
  30 #include <sys/file.h>    
  31 #include <sys/resource.h>
  32 #include <sys/termios.h>
  33 #include <sys/ioctl.h>
  34 #include <netinet/in.h>
  35 #include <sys/socket.h>
  36 #include <arpa/inet.h>
  37 #include <sys/stat.h>
  38 #include <fcntl.h>
  39 #include <signal.h>
  40 
  41 #ifdef HOST_OS_IS_SOLARIS
  42 #include <sys/systeminfo.h>
  43 #include <netdb.h>
  44 #endif    
  45 }
  46 
  47 #include "util/Types.hh"
  48 #include "util/List.hh"
  49 #include "util/Handler.hh"
  50 #include "util/Trail.hh"
  51 
  52 #include "sys/Address.hh"
  53 #include "sys/File.hh"
  54 #include "sys/Signal.hh"
  55 #include "sched/Dispatcher.hh"
  56 #include "network/Headers.hh"
  57 
  58 // Added by wlee to port to FreeBSD and BSDI
  59 #ifndef INADDR_LOOPBACK
  60 #define INADDR_LOOPBACK         (u_long)0x7F000001
  61 #endif
  62 
  63 extern "C" {
  64 #ifndef STDC_HEADERS
  65 extern int socket(...);
  66 extern int bind(...);
  67 extern int connect(...);
  68 extern int read(...);
  69 extern int write(...);
  70 extern int setsockopt(...);
  71 extern int getsockname(...);
  72 extern int close(...);
  73 extern int recvfrom(...);
  74 extern int sendto(...);
  75 extern int listen(...);
  76 extern int accept(...);
  77 extern off_t lseek(...);
  78 extern int flock(...);
  79 extern int ftruncate(...);
  80 extern int stat(...);
  81 #endif
  82 }
  83 
  84 // For printing out system error messages: from GNU textutils lib
  85 #if HAVE_STRERROR
  86 #ifndef strerror
  87 extern "C" char *strerror(int);
  88 #endif
  89 #else
  90 extern int sys_nerr;
  91 extern char* sys_errlist[];
  92 
  93 static char*
  94 private_strerror(int errnum)
     /* [<][>][^][v][top][bottom][index][help] */
  95 {
  96     if (errnum > 0 && errnum <= sys_nerr)
  97         return sys_errlist[errnum];
  98     return "Unknown system error";
  99 }
 100 #define strerror private_strerror
 101 #endif // HAVE_STRERROR
 102 
 103 #ifdef ACCEPT_USES_SOCKLEN_T
 104 #define SOCKLEN_T socklen_t
 105 #elif ACCEPT_USES_SIZE_T
 106 #define SOCKLEN_T size_t
 107 #else
 108 #define SOCKLEN_T int 
 109 #endif
 110 
 111 // File local variables
 112 static TraceCode        traceFile("file");
 113 static Handler          nullHandler(NULL, NULL);
 114 static int              pidDescriptor = -1;
 115 
 116 File::File(int fd,
     /* [<][>][^][v][top][bottom][index][help] */
 117            FileMode m,
 118            const Handler& rh,
 119            const Handler& wh)
 120         : ListNode()
 121 {
 122     descriptor_ = fd;
 123     mode_ = m;
 124 
 125     if (descriptor_ < 0) {
 126         FATAL("couldn't open file descriptor: %s\n",
 127               strerror(errno));
 128         // NotReached
 129     }
 130     
 131     readHandler = rh;
 132     writeHandler = wh;
 133     dispatcher.files.inset(this);
 134 }
 135 
 136 File::~File()
     /* [<][>][^][v][top][bottom][index][help] */
 137 {
 138     TRACE(traceFile,
 139           "closing file %d\n",
 140           descriptor_);
 141     close(descriptor_);
 142     dispatcher.files.outset(this);
 143 }
 144 
 145 void
 146 File::setHandlers(Handler& rh,
     /* [<][>][^][v][top][bottom][index][help] */
 147                   Handler& wh)
 148 {
 149     dispatcher.files.outset(this);
 150     readHandler = rh;
 151     writeHandler = wh;
 152     dispatcher.files.inset(this);
 153 }
 154 
 155 int
 156 File::read(char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 157            int  bufferLength)
 158 {
 159     int retval;
 160     
 161     if (mode_ != FileModeReadOnly
 162         && mode_ != FileModeReadWrite) {
 163         ERROR("illegal attempt to read from descriptor\n");
 164         return FileOpHardError;
 165     }
 166     
 167     TRACE(traceFile,
 168           "read file %d length %d\n",
 169           descriptor_,
 170           bufferLength);
 171     
 172     retval = ::read(descriptor_,
 173                     buffer,
 174                     bufferLength);
 175     if (retval < 0) {
 176         switch (errno) {
 177             case EWOULDBLOCK:
 178 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
 179             case EAGAIN:
 180 #endif
 181             case EINTR:
 182                 return FileOpSoftError;
 183             default:
 184                 return FileOpHardError;
 185         }
 186     }
 187     return retval;
 188 }
 189 
 190 int
 191 File::write(char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 192             int  bufferLength)
 193 {
 194     int retval;
 195     
 196     if (mode_ != FileModeReadWrite) {
 197         ERROR("attempt to write on read-only file descriptor\n");
 198         return FileOpHardError;
 199     }
 200     
 201     TRACE(traceFile,
 202           "write file %d length %d\n",
 203           descriptor_,
 204           bufferLength);
 205     
 206     retval = ::write(descriptor_,
 207                      buffer,
 208                      bufferLength);
 209     if (retval < 0) {
 210         switch (errno) {
 211             case EWOULDBLOCK:
 212 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
 213             case EAGAIN:
 214 #endif
 215             case EINTR:
 216                 return FileOpSoftError;
 217             default:
 218                 return FileOpHardError;
 219         }
 220     }
 221     return retval;
 222 }
 223 
 224 DatagramSocket::DatagramSocket(const Handler& rh,
     /* [<][>][^][v][top][bottom][index][help] */
 225                                const Handler& wh)
 226         : File(::socket(AF_INET, SOCK_DGRAM, 0),
 227                FileModeReadWrite,
 228                rh,
 229                wh)
 230 {
 231     // Empty
 232 }
 233 
 234 DatagramSocket::~DatagramSocket()
     /* [<][>][^][v][top][bottom][index][help] */
 235 {
 236     // Empty
 237 }
 238 
 239 int
 240 DatagramSocket::recvFrom(char* buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 241                          int bufferLength,
 242                          Address& addr,
 243                          Port *port)
 244 {
 245     struct sockaddr_in sin;
 246     int retval;
 247     size_t socklen = sizeof(sin);
 248     
 249     retval = ::recvfrom(descriptor_,
 250                         buffer,
 251                         bufferLength,
 252                         0,
 253                         (struct sockaddr *) &sin,
 254                         (SOCKLEN_T*)&socklen);
 255 
 256     if (retval < 0) {
 257         switch (errno) {
 258             case EWOULDBLOCK:
 259 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
 260             case EAGAIN:
 261 #endif
 262             case EINTR:
 263                 return FileOpSoftError;
 264             default:
 265                 return FileOpHardError;
 266         }
 267     }
 268 
 269     addr.set((U32) ntohl(sin.sin_addr.s_addr));
 270     *port = ntohs(sin.sin_port);
 271     TRACE(traceFile,
 272           "read %d bytes on socket %d from %s\n",
 273           retval,
 274           descriptor_,
 275           addr.name());
 276     return retval;
 277 }
 278 
 279 int
 280 DatagramSocket::sendTo(char* buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 281                        int bufferLength,
 282                        Address& addr,
 283                        Port port)
 284 {
 285     struct sockaddr_in sin;
 286     int retval;
 287 
 288     sin.sin_family = AF_INET;
 289     sin.sin_addr.s_addr = htonl(addr.get());
 290     sin.sin_port = htons(port);
 291     retval = ::sendto(descriptor_,
 292                       buffer,
 293                       bufferLength,
 294                       0,
 295                       (struct sockaddr *) &sin,
 296                       sizeof(sin));
 297     if (retval < 0) {
 298         switch (errno) {
 299             case EWOULDBLOCK:
 300 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
 301             case EAGAIN:
 302 #endif
 303             case EINTR:
 304                 return FileOpSoftError;
 305             default:
 306                 return FileOpHardError;
 307         }
 308     }
 309 
 310     TRACE(traceFile,
 311           "wrote %d bytes on socket %d from %s\n",
 312           retval,
 313           descriptor_,
 314           addr.name());
 315     
 316     return retval;
 317 }
 318 
 319 int
 320 DatagramSocket::defaultInterface(Address& localAddress, const Address &dst) {
     /* [<][>][^][v][top][bottom][index][help] */
 321 #ifndef ALLOW_MULTIPLE_IFACES
 322         static bool hashed= false;
 323         static Address myOnlyIface;
 324         if (hashed) 
 325                 localAddress.set(myOnlyIface.get());
 326         return FileOpOK;
 327 #endif
 328     int sock;
 329     struct sockaddr_in sin;
 330     size_t socklen = sizeof(sin);
 331 
 332     sin.sin_family = AF_INET;
 333     sin.sin_addr.s_addr = htonl(dst.get());
 334     //xxx: sin.sin_port = htons(port);          // We can then use write
 335     
 336     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 337         ERROR("couldn't open socket for getting local address: %s\n",
 338               strerror(errno));
 339         return FileOpHardError;
 340     }
 341 
 342     if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
 343         ERROR("couldn't connect for getting local address: %s\n",
 344               strerror(errno));
 345         return FileOpHardError;
 346     }
 347 
 348     if (getsockname(sock, 
 349                     (struct sockaddr *) &sin, 
 350                     (SOCKLEN_T*)&socklen) < 0) {
 351         ERROR("couldn't get local address: %s\n",
 352               strerror(errno));
 353         return FileOpHardError;
 354     }
 355     
 356 #ifdef HOST_OS_IS_SOLARIS
 357     if (sin.sin_addr.s_addr == 0) {
 358         char myhostname[256];
 359         struct hostent *hp;
 360         int error;
 361     
 362         error = sysinfo(SI_HOSTNAME, myhostname, sizeof(myhostname));
 363         if (error == -1) {
 364             ERROR("failed on sysinfo: %s\n",
 365                   strerror(errno));
 366             exit(-1);
 367         }
 368 
 369         hp = gethostbyname(myhostname);
 370         if (hp == NULL || hp->h_addrtype != AF_INET ||
 371             hp->h_length != sizeof(sin.sin_addr)) {
 372             ERROR("failed on gethostbyname: %s\n",
 373                   strerror(errno));
 374             exit(-1);
 375         }
 376         memcpy((char *)&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
 377     }
 378 #endif
 379 
 380     localAddress.set(ntohl(sin.sin_addr.s_addr));
 381     close(sock);
 382     TRACE(traceFile,
 383           "default interface for dst %s is %s\n",
 384           dst.name(),
 385           localAddress.name());
 386 #ifndef ALLOW_MULTIPLE_IFACES
 387     myOnlyIface= localAddress.get();
 388     hashed= true;
 389 #endif
 390     return FileOpOK;
 391 }       
 392 
 393 RawSocket::RawSocket(Handler& rh,
     /* [<][>][^][v][top][bottom][index][help] */
 394                      Handler& wh,
 395                      RawSocketType type)
 396         : File(::socket(AF_INET, SOCK_RAW, type),
 397                FileModeReadWrite,
 398                rh,
 399                wh)
 400 {
 401     int bufSize = 48*1024;
 402     int bval = 1;
 403 
 404 #ifdef  IP_HDRINCL
 405     if(setsockopt(descriptor_, IPPROTO_IP, IP_HDRINCL,
 406                   (char *)&bval, sizeof(bval)) < 0) {
 407         FATAL("setsockopt IP_HDRINCL %u", bval);
 408         // Not Reached
 409     }
 410 #endif
 411     if(setsockopt(descriptor_, SOL_SOCKET, SO_RCVBUF, (char *)&bufSize,
 412                   sizeof(bufSize)) < 0) {
 413         FATAL("setsockopt SO_RCVBUF %u", bufSize);
 414         // Not Reached
 415     }
 416 }
 417 
 418 RawSocket::~RawSocket()
     /* [<][>][^][v][top][bottom][index][help] */
 419 {
 420     // Empty
 421 }
 422 
 423 int
 424 RawSocket::recvFrom(char* buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 425                     int bufferLength,
 426                     Address& addr,
 427                     Port *port)
 428 {
 429     struct sockaddr_in sin;
 430     int retval;
 431     size_t socklen = sizeof(sin);
 432     
 433     retval = ::recvfrom(descriptor_,
 434                         buffer,
 435                         bufferLength,
 436                         0,
 437                         (struct sockaddr *) &sin,
 438                         (SOCKLEN_T*)&socklen);
 439     if (retval < 0) {
 440         switch (errno) {
 441             case EWOULDBLOCK:
 442 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
 443             case EAGAIN:
 444 #endif
 445             case EINTR:
 446                 return FileOpSoftError;
 447             default:
 448                 return FileOpHardError;
 449         }
 450     }
 451 
 452     addr.set((U32) ntohl(sin.sin_addr.s_addr));
 453     *port = ntohs(sin.sin_port);
 454     TRACE(traceFile,
 455           "read %d bytes on raw socket %d from %s\n",
 456           retval,
 457           descriptor_,
 458           addr.name());
 459 #ifdef HOST_OS_IS_FREEBSD
 460     IP* iph= (IP*) buffer;
 461     iph->totalLength+= sizeof(IP);
 462 #endif
 463     return retval;
 464 }
 465 
 466 int
 467 RawSocket::sendTo(char* buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 468                   int bufferLength,
 469                   Address& addr,
 470                   Port port) const
 471 {
 472     struct sockaddr_in sin;
 473     int retval;
 474 
 475     sin.sin_family = AF_INET;
 476     sin.sin_addr.s_addr = htonl(addr.get());
 477     sin.sin_port = htons(port);
 478     retval = ::sendto(descriptor_,
 479                       buffer,
 480                       bufferLength,
 481                       0,
 482                       (struct sockaddr *) &sin,
 483                       sizeof(sin));
 484     if (retval < 0) {
 485         switch (errno) {
 486             case EWOULDBLOCK:
 487 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
 488             case EAGAIN:
 489 #endif
 490             case EINTR:
 491                 return FileOpSoftError;
 492             default:
 493                 return FileOpHardError;
 494         }
 495     }
 496 
 497     TRACE(traceFile,
 498           "wrote %d bytes on socket %d from %s\n",
 499           retval,
 500           descriptor_,
 501           addr.name());
 502     
 503     return retval;
 504 }
 505 
 506 int
 507 RawSocket::join(Address& group)
     /* [<][>][^][v][top][bottom][index][help] */
 508 {
 509     struct ip_mreq mreq;
 510 
 511     mreq.imr_multiaddr.s_addr = htonl(group.get());
 512     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
 513 
 514     TRACE(traceFile,
 515           "joining group %s on %d\n",
 516           group.name(),
 517           descriptor_);
 518 
 519     if (::setsockopt(descriptor_,
 520                      IPPROTO_IP,
 521                      IP_ADD_MEMBERSHIP,
 522                      (char *) &mreq,
 523                      sizeof(mreq)) < 0) {
 524         FATAL("failed group join on %d: %s\n",
 525               descriptor_,
 526               strerror(errno));
 527         // NotReached
 528     }
 529 
 530     return FileOpOK;
 531 }
 532 
 533 MulticastSocket::MulticastSocket(const Address& addr,
     /* [<][>][^][v][top][bottom][index][help] */
 534                                  Port localPort,
 535                                  const Handler& rh,
 536                                  const Handler& wh)
 537         : DatagramSocket(rh, wh)
 538 {
 539     struct ip_mreq mreq;
 540     struct sockaddr_in sin;
 541     char loop;
 542 
 543     group = addr;
 544     port = localPort;
 545     sin.sin_family = AF_INET;
 546     sin.sin_port = htons(localPort);
 547     sin.sin_addr.s_addr = htonl(INADDR_ANY);
 548     
 549     TRACE(traceFile,
 550           "binding socket %d to port %d\n",
 551           descriptor_,
 552           localPort);
 553 
 554     if (::bind(descriptor_,
 555                (struct sockaddr *) &sin,
 556                sizeof(sin)) < 0) {
 557         FATAL("failed bind on %d: %s\n",
 558               descriptor_,
 559               strerror(errno));
 560         // NotReached
 561     }
 562 
 563     mreq.imr_multiaddr.s_addr = htonl(group.get());
 564     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
 565 
 566     TRACE(traceFile,
 567           "joining group %s on %d\n",
 568           group.name(),
 569           descriptor_);
 570 
 571     if (::setsockopt(descriptor_,
 572                      IPPROTO_IP,
 573                      IP_ADD_MEMBERSHIP,
 574                      (char *) &mreq,
 575                      sizeof(mreq)) < 0) {
 576         FATAL("failed group join on %d: %s\n",
 577               descriptor_,
 578               strerror(errno));
 579         // NotReached
 580     }
 581 
 582     // Disable loopback of packets
 583     loop = 0;
 584     if (::setsockopt(descriptor_,
 585                      IPPROTO_IP,
 586                      IP_MULTICAST_LOOP,
 587                      &loop,
 588                      sizeof(loop)) < 0) {
 589         FATAL("unable to disable multicast loopback on %d: %s\n",
 590               descriptor_,
 591               strerror(errno));
 592         // NotReached
 593     }
 594 }
 595 
 596 MulticastSocket::~MulticastSocket()
     /* [<][>][^][v][top][bottom][index][help] */
 597 {
 598     struct ip_mreq mreq;
 599 
 600     mreq.imr_multiaddr.s_addr = htonl(group.get());
 601     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
 602     
 603     TRACE(traceFile,
 604           "deleting multicast socket for group %s on %d\n",
 605           group.name(),
 606           descriptor_);
 607     
 608     (void) ::setsockopt(descriptor_,
 609                         IPPROTO_IP,
 610                         IP_DROP_MEMBERSHIP,
 611                         (char *) &mreq,
 612                         sizeof(mreq));
 613     return;
 614 }
 615 
 616 int
 617 MulticastSocket::defaultInterface(Address& localAddress)
     /* [<][>][^][v][top][bottom][index][help] */
 618 {
 619     int sock;
 620     struct sockaddr_in sin;
 621     size_t socklen = sizeof(sin);
 622 
 623     sin.sin_family = AF_INET;
 624     sin.sin_addr.s_addr = htonl(group.get());
 625     sin.sin_port = htons(port);         // We can then use write
 626     
 627     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 628         ERROR("couldn't open socket for getting local address: %s\n",
 629               strerror(errno));
 630         return FileOpHardError;
 631     }
 632 
 633     if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
 634         ERROR("couldn't connect for getting local address: %s\n",
 635               strerror(errno));
 636         return FileOpHardError;
 637     }
 638 
 639     if (getsockname(sock, 
 640                     (struct sockaddr *) &sin, 
 641                     (SOCKLEN_T*)&socklen) < 0) {
 642         ERROR("couldn't get local address: %s\n",
 643               strerror(errno));
 644         return FileOpHardError;
 645     }
 646     
 647 #ifdef HOST_OS_IS_SOLARIS
 648     if (sin.sin_addr.s_addr == 0) {
 649         char myhostname[256];
 650         struct hostent *hp;
 651         int error;
 652     
 653         error = sysinfo(SI_HOSTNAME, myhostname, sizeof(myhostname));
 654         if (error == -1) {
 655             ERROR("failed on sysinfo: %s\n",
 656                   strerror(errno));
 657             exit(-1);
 658         }
 659 
 660         hp = gethostbyname(myhostname);
 661         if (hp == NULL || hp->h_addrtype != AF_INET ||
 662             hp->h_length != sizeof(sin.sin_addr)) {
 663             ERROR("failed on gethostbyname: %s\n",
 664                   strerror(errno));
 665             exit(-1);
 666         }
 667         memcpy((char *)&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
 668     }
 669 #endif
 670 
 671     localAddress.set(ntohl(sin.sin_addr.s_addr));
 672     close(sock);
 673     TRACE(traceFile,
 674           "default interface for group %s is %s\n",
 675           group.name(),
 676           localAddress.name());
 677     
 678     return FileOpOK;
 679 }
 680 
 681 int
 682 MulticastSocket::setTTL(int ttl)
     /* [<][>][^][v][top][bottom][index][help] */
 683 {
 684     char t = ttl;
 685 
 686     TRACE(traceFile,
 687           "setting ttl %d on %d\n",
 688           ttl,
 689           descriptor_);
 690     
 691     if (::setsockopt(descriptor_,
 692                      IPPROTO_IP,
 693                      IP_MULTICAST_TTL,
 694                      (char *) &t,
 695                      sizeof(t)) < 0) {
 696         ERROR("failed ttl set on %d: %s\n",
 697               descriptor_,
 698               strerror(errno));
 699         return FileOpHardError;
 700     }
 701     return FileOpOK;
 702 }
 703 
 704 StreamSocket::StreamSocket(Address& addr,
     /* [<][>][^][v][top][bottom][index][help] */
 705                            Port port,
 706                            Handler& rh,
 707                            Handler& wh)
 708         : File(::socket(AF_INET, SOCK_STREAM, 0),
 709                FileModeReadWrite, 
 710                rh, 
 711                wh)
 712 {
 713     struct sockaddr_in sin;
 714     int retval;
 715 
 716     // Only stream sockets are non-blocking
 717     if (fcntl(descriptor_,
 718               F_SETFL,
 719               O_NDELAY) < 0) {
 720         FATAL("non-blocking descriptor error: %s\n",
 721               strerror(errno));
 722         // Not Reached
 723     }
 724 
 725     sin.sin_family = AF_INET;
 726     sin.sin_addr.s_addr = htonl(addr.get());
 727     sin.sin_port = htons(port);
 728     
 729     retval = ::connect(descriptor_,
 730                        (struct sockaddr *) &sin,
 731                        sizeof(sin));
 732     //    ASSERT((retval < 0) && (errno == EWOULDBLOCK));       // XXX
 733 }
 734 
 735 StreamSocket::StreamSocket(int d,
     /* [<][>][^][v][top][bottom][index][help] */
 736                            Handler& rh,
 737                            Handler& wh)
 738         : File(d, FileModeReadWrite, rh, wh)
 739 {
 740     // Only stream sockets are non-blocking
 741     if (fcntl(descriptor_,
 742               F_SETFL,
 743               O_NDELAY) < 0) {
 744         FATAL("non-blocking descriptor error: %s\n",
 745               strerror(errno));
 746         // Not Reached
 747     }
 748 }
 749 
 750 StreamSocket::~StreamSocket()
     /* [<][>][^][v][top][bottom][index][help] */
 751 {
 752     // Empty
 753 }
 754 
 755 ListenSocket::ListenSocket(Port port,
     /* [<][>][^][v][top][bottom][index][help] */
 756                            Handler& lh,
 757                            Boolean local)
 758         : File(::socket(AF_INET, SOCK_STREAM, 0),
 759                FileModeReadWrite,
 760                lh,
 761                nullHandler)
 762 {
 763     int         retval;
 764     int         reuse;
 765     sockaddr_in sin;
 766 
 767     sin.sin_family = AF_INET;
 768     sin.sin_port = htons(port);
 769     if (local) {
 770         sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 771     } else {
 772         sin.sin_addr.s_addr = htonl(INADDR_ANY);
 773     }
 774     
 775     TRACE(traceFile,
 776           "binding socket %d to port %d\n",
 777           descriptor_,
 778           port);
 779 
 780     reuse = 1;
 781     if (::setsockopt(descriptor_,
 782                      SOL_SOCKET,
 783                      SO_REUSEADDR,
 784                      (char*) &reuse,
 785                      sizeof(reuse)) < 0) {
 786         FATAL("failed to set %d to be reusable: %s\n",
 787               descriptor_,
 788               strerror(errno));
 789         // NotReached
 790     }
 791 
 792     if (::bind(descriptor_,
 793                (struct sockaddr *) &sin,
 794                sizeof(sin)) < 0) {
 795         FATAL("failed bind on %d: %s\n",
 796               descriptor_,
 797               strerror(errno));
 798         // NotReached
 799     }
 800 
 801     TRACE(traceFile,
 802           "setting file %d to listen\n",
 803           descriptor_);
 804 
 805     retval = ::listen(descriptor_, 5);
 806     if (retval < 0) {
 807         FATAL("listen failed on file %d\n",
 808               descriptor_);
 809         // NotReached
 810     }
 811     return;
 812 }
 813 
 814 ListenSocket::~ListenSocket()
     /* [<][>][^][v][top][bottom][index][help] */
 815 {
 816     // Empty
 817 }
 818 
 819 int
 820 ListenSocket::accept(StreamSocket** sock,
     /* [<][>][^][v][top][bottom][index][help] */
 821                      Address& remote,
 822                      Port *remotePort,
 823                      Handler& read,
 824                      Handler& write)
 825 {
 826     int retval;
 827     struct sockaddr_in sin;
 828     size_t socklen;
 829 
 830     TRACE(traceFile,
 831           "accepting incoming connection on file %d\n",
 832           descriptor_);
 833 
 834     socklen = sizeof(sin);
 835     retval = ::accept(descriptor_,
 836                       (struct sockaddr *) &sin,
 837                       (SOCKLEN_T*)&socklen);
 838     if (retval < 0) {
 839         switch (errno) {
 840             case EWOULDBLOCK:
 841 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
 842             case EAGAIN:
 843 #endif
 844             case EINTR:
 845                 return FileOpSoftError;
 846             default:
 847                 return FileOpHardError;
 848         }
 849     }
 850 
 851     remote.set(ntohl(sin.sin_addr.s_addr));
 852     *remotePort = ntohs(sin.sin_port);
 853 
 854     *sock = new StreamSocket(retval, read, write);
 855     return FileOpOK;
 856 }
 857 
 858 DiskFile::DiskFile(char* fileName,
     /* [<][>][^][v][top][bottom][index][help] */
 859                    Boolean readOnly,
 860                    Handler& rh,
 861                    Handler& wh)
 862         : File(::open(fileName,
 863                       (readOnly) ? O_RDONLY : (O_CREAT | O_RDWR),
 864                       0644),
 865                (readOnly) ? FileModeReadOnly : FileModeReadWrite,
 866                rh,
 867                wh)
 868 {
 869     // Empty
 870 }
 871 
 872 DiskFile::~DiskFile()
     /* [<][>][^][v][top][bottom][index][help] */
 873 {
 874     // Empty
 875 }
 876 
 877 int
 878 DiskFile::seekTo(u_long offset)
     /* [<][>][^][v][top][bottom][index][help] */
 879 {
 880     int retval;
 881     
 882     TRACE(traceFile,
 883           "seeking to off %u on descriptor %d\n",
 884           offset,
 885           descriptor_);
 886     
 887     retval = ::lseek(descriptor_, (off_t) offset, SEEK_SET);
 888     if (retval < 0) {
 889         return FileOpHardError;
 890     }
 891     return retval;
 892 }
 893 
 894 int
 895 DiskFile::seekEnd()
     /* [<][>][^][v][top][bottom][index][help] */
 896 {
 897     int retval;
 898     
 899     TRACE(traceFile,
 900           "seeking to end on descriptor %d\n",
 901           descriptor_);
 902     
 903     retval = ::lseek(descriptor_, (off_t) 0, SEEK_END);
 904     if (retval < 0) {
 905         return FileOpHardError;
 906     }
 907     return retval;
 908 }
 909 
 910 int
 911 DiskFile::lock()
     /* [<][>][^][v][top][bottom][index][help] */
 912 {
 913     int retval;
 914 
 915 #ifdef HAVE_FLOCK
 916     retval = ::flock(descriptor_, LOCK_EX|LOCK_NB);
 917 #elif HAVE_LOCKF
 918     retval = ::lockf(descriptor_, F_LOCK, 0);
 919 #else
 920     retval = 0;
 921 #endif
 922     
 923     if (retval < 0) {
 924         switch (errno) {
 925             case EWOULDBLOCK:
 926 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
 927             case EAGAIN:
 928 #endif
 929                 TRACE(traceFile,
 930                       "descriptor %d already locked\n",
 931                       descriptor_);
 932                 
 933                 return FileOpSoftError;
 934             default:
 935                 break;
 936         }
 937         return FileOpHardError;
 938     }
 939 
 940     TRACE(traceFile,
 941           "descriptor %d not locked by another process\n",
 942           descriptor_);
 943     
 944     return FileOpOK;
 945 }
 946 
 947 int
 948 DiskFile::truncate(u_int size)
     /* [<][>][^][v][top][bottom][index][help] */
 949 {
 950     int retval;
 951 
 952     retval = ::ftruncate(descriptor_, size);
 953     if (retval < 0) {
 954         return FileOpHardError;
 955     }
 956 
 957     TRACE(traceFile,
 958           "truncated descriptor %d to size %u\n",
 959           descriptor_,
 960           size);
 961     return FileOpOK;
 962 }    
 963 
 964 void
 965 createDir(char* name)
     /* [<][>][^][v][top][bottom][index][help] */
 966 {
 967     int retval;
 968     struct stat statbuf;
 969 
 970     retval = stat(name, &statbuf);
 971     if (retval < 0) {   // Name doesn't exist
 972         retval = mkdir(name, 0755);
 973         if (retval < 0) {
 974             FATAL("couldn't create directory %s: %s\n", name,
 975                   strerror(errno));
 976             // NotReached
 977         }
 978         return;
 979     }
 980     if (!S_ISDIR(statbuf.st_mode)) {
 981         FATAL("expected %s to be a directory, it isn't\n",
 982               name);
 983         // NotReached
 984     }
 985 }
 986 
 987 static char*    pidFileName = NULL;
 988 
 989 void
 990 openPidFile(const char* name)
     /* [<][>][^][v][top][bottom][index][help] */
 991 {
 992     int         retval;
 993     char        buf[20];
 994     int         pid;
 995     int         len;
 996 
 997     pidFileName = new char[strlen(name) + 1];
 998     memcpy(pidFileName, name, strlen(name) + 1);
 999 
1000     pidDescriptor = open(name, O_RDWR | O_CREAT | 
1001 #ifdef HOST_OS_IS_FREEBSD
1002                          O_FSYNC
1003 #else
1004                          O_SYNC
1005 #endif 
1006                          , 0664);
1007     if (pidDescriptor < 0) {
1008         ERROR("couldn't open pid file %s: %s\n", name, strerror(errno));
1009         exit(2);
1010     }
1011 
1012 #ifdef HAVE_FLOCK
1013     retval = ::flock(pidDescriptor, LOCK_EX|LOCK_NB);
1014 #elif HAVE_LOCKF
1015     retval = ::lockf(pidDescriptor, F_LOCK, 0);
1016 #else
1017     retval = 0;
1018 #endif
1019 
1020     if (retval < 0) {
1021         switch (errno) {
1022             case EWOULDBLOCK:
1023 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
1024             case EAGAIN:
1025 #endif
1026                 len = read(pidDescriptor, buf, sizeof buf);
1027                 if (len > 0 &&  (pid = atoi(buf))) {
1028                     ERROR("another already running, pid %d\n",
1029                           pid);
1030                 } else {
1031                     ERROR("is some other %s running?");
1032                 }
1033                 break;
1034 
1035             default:
1036                 ERROR("flock failed: %s\n", strerror(errno));
1037         }
1038         close(pidDescriptor);
1039         pidDescriptor = -1;
1040         exit(2);
1041     }
1042 
1043     (void) sprintf(buf, "%d\n", getpid());
1044     len = strlen(buf);
1045 
1046 #ifndef SEEK_SET
1047 #define SEEK_SET        L_SET
1048 #endif  /* SEEK_SET */
1049     /* Back up to the beginning and truncate the file */
1050     if (lseek(pidDescriptor, (off_t) 0, SEEK_SET) < 0
1051         || ftruncate(pidDescriptor, (off_t) 0) < 0
1052         || write(pidDescriptor, buf, len) != len) {
1053         ERROR("couldn't write to %s: %s\n", name, strerror(errno));
1054         exit(2);
1055     }
1056 
1057     return;
1058 }
1059 
1060 void
1061 closePidFile()
     /* [<][>][^][v][top][bottom][index][help] */
1062 {
1063     if (!pidFileName) {
1064         return;
1065     }
1066 
1067     if (pidDescriptor > -1) {
1068         if (close(pidDescriptor) == -1
1069             || unlink(pidFileName) == -1) {
1070             ERROR("could not close or remove %s: %s\n",
1071                   pidFileName, strerror(errno));
1072             exit(2);
1073         }
1074         pidDescriptor = -1;
1075     }
1076 
1077     delete [] pidFileName;
1078     return;
1079 }
1080 
1081 void
1082 daemonize()
     /* [<][>][^][v][top][bottom][index][help] */
1083 {
1084     int         t;
1085     Signal*     sig;
1086 
1087     // Ignore several signals
1088     sig = new Signal("ttou", NULL);
1089     sig = new Signal("ttin", NULL);
1090     sig = new Signal("tstp", NULL);
1091 
1092     // Fork once
1093     switch (fork()) {
1094         case 0:
1095             break;
1096         case -1:
1097             perror("daemonize: fork");
1098             exit(1);
1099         default:
1100             exit(0);
1101     }
1102 
1103 #ifdef SETPGRP_VOID
1104     t = setpgrp();
1105     if (t < 0) {
1106         perror("daemonize: setprgp");
1107         exit(1);
1108     }
1109 
1110     sig = new Signal("hup", NULL);
1111 
1112     switch (fork()) {
1113         case 0:
1114             break;
1115         case -1:
1116             perror("daemonize: fork");
1117             exit(1);
1118         default:
1119             exit(0);
1120     } 
1121 #else // SETPRGP_VOID
1122     t = setpgrp(0, getpid());
1123     if (t < 0) {
1124         perror("daemonize: setpgrp");
1125         exit(1);
1126     }
1127     
1128     while ((t = open("/dev/tty", O_RDWR, 0)) == -1 && errno == EINTR);
1129     if (t >= 0) {
1130         if (ioctl(t, TIOCNOTTY, (caddr_t) 0) < 0) {
1131             perror("daemonize: ioctl(TIOCNOTTY)");
1132             exit(1);
1133         }
1134         close(t);
1135     }
1136 #endif // SETPGRP_VOID
1137 
1138     // Can close all open files, and reset umask
1139     {
1140 #ifndef NOFILE
1141 #ifdef  _NFILE
1142 #define NOFILE  _NFILE
1143 #else   /* _NFILE */
1144 #ifdef  OPEN_MAX
1145 #define NOFILE  OPEN_MAX
1146 #else   /* OPEN_MAX */
1147 #define NOFILE  20
1148 #endif  /* OPEN_MAX */
1149 #endif  /* _NFILE */
1150 #endif  /* NOFILE */
1151         t = NOFILE;
1152         do {
1153             (void) close(t);
1154         } while (--t);
1155 
1156     }
1157             
1158     /* Reset umask */
1159     umask(022);
1160 }
1161 
1162 //
1163 //  Copyright (c) 1994 by the University of Southern California.
1164 //  All rights reserved.
1165 //
1166 //  Permission to use, copy, modify, and distribute this software and
1167 //  its documentation in source and binary forms for lawful
1168 //  non-commercial purposes and without fee is hereby granted, provided
1169 //  that the above copyright notice appear in all copies and that both
1170 //  the copyright notice and this permission notice appear in supporting
1171 //  documentation, and that any documentation, advertising materials,
1172 //  and other materials related to such distribution and use acknowledge
1173 //  that the software was developed by the University of Southern
1174 //  California and/or Information Sciences Institute.
1175 //  The name of the University of Southern California may not
1176 //  be used to endorse or promote products derived from this software
1177 //  without specific prior written permission.
1178 //
1179 //  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
1180 //  ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS
1181 //  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
1182 //  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1183 //  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND 
1184 //  NON-INFRINGEMENT.
1185 //
1186 //  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
1187 //  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
1188 //  TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
1189 //  THE USE OR PERFORMANCE OF THIS SOFTWARE.
1190 //
1191 //  Questions concerning this software should be directed to 
1192 //  info-ra@isi.edu.
1193 //

/* [<][>][^][v][top][bottom][index][help] */