home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / infoserv / gopher / Unix / gopher-gateways / techinfo / techinpher / v1.0 / netio.c.Z / netio.c
Encoding:
C/C++ Source or Header  |  1993-02-04  |  9.9 KB  |  413 lines

  1. /*
  2.  *------------------------------------------------------------------
  3.  *
  4.  * $Source: /afs/net.mit.edu/dapps/project/techinfodev/src/srv_ti/RCS/netio.c,v $
  5.  * $Revision: 1.5 $
  6.  * $Date: 92/08/28 16:09:26 $
  7.  * $State: Exp $
  8.  * $Author: ark $
  9.  * $Locker: ark $
  10.  *
  11.  * $Log:    netio.c,v $
  12.  * Revision 1.5  92/08/28  16:09:26  ark
  13.  * Summer 1992 final version
  14.  * 
  15.  * Revision 1.4  92/08/27  17:11:11  ark
  16.  * Retropatched error message file to allow old clients to work
  17.  * 
  18.  * Revision 1.3  92/08/06  18:43:47  ark
  19.  * Admin command "B" no longer crashes when there are many connections.
  20.  * 
  21.  * Revision 1.2  92/08/04  16:27:31  ark
  22.  * Test production version 8/4/92
  23.  * 
  24.  * Revision 1.1  92/07/22  11:09:18  ark
  25.  * Saber loads quietly; ANSI use standardized; command line options; no behavioral changes
  26.  * 
  27.  * Revision 1.0  92/07/10  12:32:28  ark
  28.  * Initial revision
  29.  * 
  30.  * Revision 1.1  91/07/15  10:40:20  thorne
  31.  * Initial revision
  32.  * 
  33.  *------------------------------------------------------------------
  34.  */
  35.  
  36. #ifndef lint
  37. #ifndef SABER
  38. static char *rcsid_foo_c = "$Header: /afs/net.mit.edu/dapps/project/techinfodev/src/srv_ti/RCS/netio.c,v 1.5 92/08/28 16:09:26 ark Exp Locker: ark $";
  39. #endif SABER
  40. #endif  lint
  41.  /*
  42.   Copyright (C) 1989 by the Massachusetts Institute of Technology
  43.  
  44.    Export of this software from the United States of America is assumed
  45.    to require a specific license from the United States Government.
  46.    It is the responsibility of any person or organization contemplating
  47.    export to obtain such a license before exporting.
  48.  
  49. WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  50. distribute this software and its documentation for any purpose and
  51. without fee is hereby granted, provided that the above copyright
  52. notice appear in all copies and that both that copyright notice and
  53. this permission notice appear in supporting documentation, and that
  54. the name of M.I.T. not be used in advertising or publicity pertaining
  55. to distribution of the software without specific, written prior
  56. permission.  M.I.T. makes no representations about the suitability of
  57. this software for any purpose.  It is provided "as is" without express
  58. or implied warranty.
  59.  
  60. */
  61. /* These routines handle most of the non-blocking IO for the server. This does
  62.    not use the LWP package. Its pupose is to allow the server to go ahead and
  63.    do something else if a connection blocks. 
  64.    S. Thorne 3/28/91 */
  65.  
  66. #include <stdio.h>
  67. #include <errno.h>
  68. #include <sys/types.h>
  69. #include <sys/time.h>
  70. #include <sys/stat.h>
  71. #include <sys/socket.h>
  72. #include <sys/file.h>
  73. #include "pdb.h"
  74. #include "network.h"
  75. #include "messages.h"
  76.  
  77. TOSEND *firstrec = NULL;
  78. TOREC  *first = NULL;
  79.  
  80. extern CONN conntab[];
  81.  
  82. extern int ActiveJobs;
  83.  
  84.  
  85.  
  86. char    _sendbuf[BUFSIZ];
  87. char    *_sendbuf_pos = _sendbuf;
  88. extern char *msglist[]; 
  89. extern void log_trans(char *str);
  90. extern int  is_directory(int fd);
  91. extern int cur_sock;
  92. extern int debug;
  93.  
  94. int dosend(char *str, char *buf, char **curpos);
  95. int dodeliver(char *buf, char **curpos, int sock);
  96. void nio_send_file(int sock, char *filename, long startpoint, long requested);
  97. void add_send(char *start, char *ptr, int size, int sock);
  98. void remove_send(TOSEND *ptr);
  99. void add_recv(int fd, char *file_name, int sock);
  100. void remove_rec(TOREC *ptr);
  101. int sendbuf(char *buf, int size, int sock);
  102. int send_more(TOSEND *ptr);
  103. void nio_rec_more(TOREC *ptr); 
  104. void send_msg(char *str, int sock);
  105. void close_recfile(TOREC *ptr);
  106.  
  107.  
  108. /* macros and all that junk were too damn kludgy for me --lam */
  109.  
  110. void send_msg (char *str, int sock)
  111. {
  112.   char *ptr;
  113. #define NOMSG "99:There is no error msg text assigned here"
  114.  
  115.   if (!str) {
  116.     ptr = domalloc (sizeof(NOMSG) + EOLM_LEN);
  117.     strcpy (ptr, NOMSG);
  118.   }
  119.   else {
  120.     ptr = domalloc (strlen(str)+ 1 + EOLM_LEN);
  121.     strcpy (ptr, str);
  122.   }
  123.   strcat (ptr, EOLM);
  124.   sendbuf (ptr, strlen(ptr), sock);
  125. }
  126.  
  127. void
  128. nio_send_file(int sock, char *filename, long startpoint, long requested)
  129. {
  130.     long            fd, red,len, should_send;
  131.     char *iobuf, *cp;
  132.     struct stat    st;
  133.  
  134.     if ((fd = open(filename, O_RDONLY, 0644)) < 0) {
  135.       /* 
  136.        * This error message has no code because of the format of the
  137.        * header returned below; in order to be backward compatible with
  138.        * old clients, atoi() on this error message must return 0.
  139.        */
  140.       send_msg(msglist[ SENDFILE_CANT_ACCESS ], sock);
  141.       return;
  142.     }
  143.     fstat(fd, &st);
  144.     if (st.st_mode & S_IFDIR)
  145.       {
  146.         send_msg(msglist[ SENDFILE_IS_DIRECTORY ], sock);
  147.         close(fd);
  148.         return;
  149.       }
  150.  
  151.     lseek(fd, startpoint, L_SET);
  152.     
  153.     should_send = min(st.st_size - startpoint + EOLM_LEN,requested + EOLM_LEN);
  154.     if (should_send < 0)
  155.       should_send = EOLM_LEN;
  156.     iobuf =  domalloc((unsigned int) should_send + 200);
  157.     bzero(iobuf,should_send +200);
  158.     sprintf(iobuf,"%ld Total Characters :%ld sent:This document was last modified on %s\n",
  159.         st.st_size, should_send, ctime(&st.st_mtime));
  160.     len = strlen(iobuf);
  161.     cp = index(iobuf,'\0');
  162.     red = read(fd,cp,should_send - EOLM_LEN);
  163.     if (red < 0)
  164.       {
  165.         send_msg(msglist[ SENDFILE_CANT_ACCESS ], sock);
  166.         close(fd);
  167.         return;
  168.       }
  169.     cp = cp + red;
  170.     bcopy(EOLM,cp,EOLM_LEN);
  171.     sendbuf(iobuf,len + red + EOLM_LEN, sock);
  172.     close(fd);
  173.     return;
  174.  
  175. }
  176.  
  177. /* If a write would have blocked, save it away so that we can send the 
  178.    remaining text later */
  179. void
  180. add_send(char *start, char *ptr, int size, int sock) 
  181. {
  182.   TOSEND *rec;
  183.   int    i;
  184.   
  185.   if (debug)
  186.     printf("Starting blocked send to socket #%d.\n", sock);
  187.   ActiveJobs++;
  188.   rec = (TOSEND *) domalloc((unsigned int) sizeof(TOSEND));
  189.   rec->sock = sock;
  190.   rec->ptr = ptr;
  191.   rec->buf = start;
  192.   rec->size = size;
  193.   
  194.   for (i = 0; i < FD_SETSIZE; i++) { 
  195.     if (conntab[i].c_socket == sock) {
  196.       conntab[i].c_ptr = rec;
  197.       break;
  198.     }
  199.   }
  200.   return;
  201. }
  202.  
  203. /* remove a pending send */
  204. void
  205. remove_send(TOSEND *ptr) 
  206. {
  207.   int    i;
  208.  
  209.   ActiveJobs--;
  210.   for (i = 0; i < FD_SETSIZE; i++) {
  211.     if (conntab[i].c_ptr == ptr) {
  212.       if (debug)
  213.     printf("Finished blocked send to socket #%d.\n", conntab[i].c_socket);
  214.       break;
  215.     }
  216.   }
  217.   if (ptr->buf != _sendbuf)
  218.     do_free(ptr->buf); /* do_free the text buffer */
  219.   do_free(ptr);
  220.   conntab[i].c_ptr = NULL;
  221.  
  222.   return;
  223. }
  224.  
  225. /* add a pending receive */
  226. void
  227. add_recv(int fd, char *file_name, int sock) 
  228. {
  229.   TOREC *rec;
  230.   int    i;
  231.   
  232.   ActiveJobs++;
  233.   rec = (TOREC *) domalloc((unsigned int) sizeof(TOREC));
  234.   rec->sock = sock;
  235.   rec->the_fd = fd;
  236.   rec->filename = file_name;
  237.   for (i = 0; i < FD_SETSIZE; i++) { 
  238.     if (conntab[i].c_socket == sock) {
  239.       conntab[i].c_recptr = rec;
  240.       break;
  241.     }
  242.   }
  243.   return;
  244. }
  245.  
  246. void
  247. remove_rec(TOREC *ptr) /* remove a pending receive from the list */
  248. {
  249.   int    i;
  250.   
  251.   ActiveJobs--;
  252.   for (i = 0; i < FD_SETSIZE; i++) 
  253.     if (conntab[i].c_recptr == ptr)
  254.       break;
  255.  
  256.   do_free(ptr->filename);
  257.   do_free(ptr);
  258.  
  259.   conntab[i].c_recptr = NULL;
  260.   return;
  261. }
  262.  
  263. int
  264. sendbuf(char *buf, int size, int sock)
  265. {
  266.   int len = BUFSIZ,rc;
  267.   char *startbuf;
  268.   
  269.   startbuf = buf;
  270.   
  271.   while (size)
  272.     {
  273.       if (size <= BUFSIZ)
  274.     len = size;
  275.  
  276.       rc = write(sock,buf,len);
  277.       if (rc < 0)
  278.     {
  279.       if (errno == EWOULDBLOCK) /* would block, so save info, and leave it 
  280.                        will be done later */
  281.         {
  282.           if (debug)
  283.         printf("Write blocked on socket #%d.\n", sock);
  284.           add_send(startbuf,buf,size,sock);
  285.           return 1;
  286.         }
  287.       if (startbuf != _sendbuf)
  288.         do_free(startbuf);
  289.       return -1;
  290.     }
  291.       size = size - rc;
  292.       buf = buf + rc;
  293.     }
  294.   if (startbuf != _sendbuf)
  295.     do_free(startbuf);
  296.   return 0;
  297. }
  298.  
  299. int
  300. send_more(TOSEND *ptr)
  301. {
  302.   int size,len = BUFSIZ,rc,sock;
  303.   char *buf;
  304.   
  305.   if (ptr == NULL) { 
  306.     return 0;
  307.   }
  308.  
  309.   size = ptr->size;
  310.   buf = ptr->ptr;
  311.   sock = ptr->sock;
  312.   if (debug)
  313.     printf("Continuing send to socket #%d.\n",sock);
  314.   while (size)
  315.     {      
  316.       if (size <= BUFSIZ)
  317.     len = size;
  318.       
  319.       rc = write(sock,buf,len);
  320.       if (rc <= 0){
  321.     ptr->size = size;      /* update the TOSEND record */
  322.     ptr->ptr = buf;
  323.     if (errno == EWOULDBLOCK) /* would block, so save info, and leave it 
  324.                      will be done later */
  325.       {
  326.         if (debug)
  327.           printf("Write blocked again on socket #%d.\n", sock);
  328.         return 1;
  329.       }
  330.     return -1;
  331.       }
  332.       size = size - rc;
  333.       buf = buf + rc;
  334.     }
  335.   remove_send(ptr);
  336.   return 0;    /* Added for consistency 7/15/92 ark */
  337. }
  338.  
  339. /* does the work of receiving a file */
  340. void
  341. nio_rec_more(TOREC *ptr) 
  342. {
  343.   
  344.   int  red, done;
  345.   char in_buff[BUFSIZ];
  346.   
  347.   errno = 0;
  348.   done = FALSE;
  349.   for (;;) {
  350.     red = read(ptr->sock, in_buff, BUFSIZ);
  351.     if (debug)
  352.       printf("Received %d bytes from socket #%d.\n", red, ptr->sock);
  353.     while (red > 0) 
  354.       {
  355.     if (!strncmp(&in_buff[red - EOM_LEN], EOM, EOM_LEN)) 
  356.       {
  357.         write(ptr->the_fd, in_buff, red - EOM_LEN);
  358.         done = TRUE;
  359.         break;
  360.       } 
  361.     else
  362.       write(ptr->the_fd, in_buff, red);
  363.     red = read(ptr->sock, in_buff, BUFSIZ);
  364.       }        /* end of while */
  365.     
  366.     if (done) {
  367.       close_recfile(ptr);
  368.       remove_rec(ptr);
  369.       break;
  370.     }
  371.     else  /*  EWOULDBLOCK  */
  372.       return; /* no settings to update, so just leave  */
  373.   } /* end of forever */
  374. }
  375.  
  376. /* Try to back up destination file with a ~ on the end of its
  377.    filename.  Then move our temporary file, ending with .tmp, to the
  378.    destination file. */
  379. void
  380. close_recfile(TOREC *ptr)
  381. {
  382.   char tempfile[MAXPATHLEN],backup_fname[MAXPATHLEN],in_buff[BUFSIZ];
  383.   int rc;
  384.   
  385.   sprintf(tempfile,"%s.tmp",ptr->filename);
  386.   sprintf(backup_fname,"%s~",ptr->filename);
  387.   if (close(ptr->the_fd))
  388.     printf("Couldn't close file descriptor %d on receipt of file!\n", 
  389.        ptr->the_fd);
  390.  
  391.   /* We really shouldn't try to do this rename if the file doesn't exist! */
  392.   rc = rename(ptr->filename, backup_fname);
  393.   if (rc == 0)
  394.     if (debug)
  395.       printf("Backed up existing file %s to %s.\n", 
  396.          ptr->filename, backup_fname);
  397.  
  398.   rc = rename(tempfile,ptr->filename);
  399.   if (rc)
  400.     printf("Temporary file %s couldn't be renamed!\n", tempfile);
  401.   else 
  402.     printf("Wrote file %s.\n", ptr->filename);
  403.  
  404.   chmod(ptr->filename,0644);
  405.  
  406.   /* Tell client if final rename worked */
  407.   if (rc)
  408.     sprintf(in_buff, "%s\n%s", msglist[ CANT_OPEN ], EOM);
  409.   else
  410.     sprintf(in_buff, "%s\n%s", msglist[ OK ], EOM);
  411.   write(ptr->sock, in_buff,strlen(in_buff));
  412. }
  413.