home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / msgd / Common / deliver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-09  |  4.2 KB  |  175 lines

  1. #ifndef lint
  2. static char *RCSid = "$Header: /fsys4/usr/source/users/msg/Common/RCS/deliver.c,v 1.4 90/12/29 21:59:07 jmsellen Exp $";
  3. #endif
  4.  
  5. /* deliver.c
  6.    Deliver a message to a user on this machine.
  7. */
  8.  
  9. /*
  10.  * Old revision log:
  11.  *
  12.  * Revision 1.4  87/06/04  12:49:47  jmsellens
  13.  * Changes to put the msg save file in /usr/tmp
  14.  * rationalized the code a little, added the NO_STAT error condition
  15.  * 
  16.  * Revision 1.3  87/04/13  09:46:09  sahayman
  17.  * Make sure to do answerback() on unsuccessful messages (mesg n)
  18.  * as well as successful.
  19.  * 
  20.  * Revision 1.2  87/04/06  02:16:30  sahayman
  21.  * Print a "However ... " message when unable to deliver to some
  22.  * ttys but able to deliver to others.
  23.  * 
  24.  */
  25. #include "msg.h"
  26. #include <setjmp.h>
  27. #include <signal.h>
  28. #include <ctype.h>
  29.  
  30. static jmp_buf timeout;
  31.  
  32.  
  33. static
  34. wakeup()
  35. {
  36.     longjmp( timeout, 1 );
  37. }
  38.  
  39.  
  40.  
  41. int
  42. deliver( sender, user, message, fromroot )
  43. char *sender, *user, *message;
  44. {
  45.     struct utmp ut;
  46.     FILE *fp, *term;
  47.     char terminal[40];    /* should be enough ... */
  48.     int found = 0, errcode = 0;
  49.     int however = 0;    /* Should we print a "however ...." msg */
  50.     struct stat sbuf;
  51.     char line[sizeof(ut.ut_line)+5];
  52.     char successful_line[sizeof(ut.ut_line)+5];
  53.     int (*osig)();
  54. #ifdef SAVEMSG
  55.     int uid = -1;
  56. #endif
  57.  
  58.     successful_line[0] = '\0';
  59.  
  60.     if ( (fp=fopen( UTMP, "r" )) == FPNULL ) {
  61.     errmsg( NO_UTMP, hostname, syserr() );
  62.     return( NO_UTMP );
  63.     }
  64.     /* keep on until end of file in case s/he's signed on more than once */
  65.     while ( fread( &ut, sizeof(struct utmp), 1, fp ) == 1 ) {
  66.     if ( strncmp( user, ut.ut_name, sizeof(ut.ut_name) ) != 0 )
  67.         continue;
  68. #ifdef SYSV_UTMP
  69.     if ( ut.ut_type != USER_PROCESS )
  70.         continue;
  71. #endif
  72.     found++;
  73.     (void) strncpy( line, ut.ut_line, sizeof(ut.ut_line) );
  74.     line[sizeof(ut.ut_line)] = '\0';
  75.     (void) sprintf( terminal, "%s%s", DEV, line );
  76.     /* stat it to see if we're allowed to write */
  77.     if ( stat(terminal,&sbuf) == 0 ) {
  78. #ifdef SAVEMSG
  79.         uid = sbuf.st_uid;
  80. #endif
  81.         if ( ((sbuf.st_mode&ALLOW)==0) && !fromroot ) {
  82.         errmsg( MESG_OFF, user, hostname, line );
  83.         however++;
  84.         errcode++;
  85.         } else {
  86.         if ( setjmp( timeout ) ) {
  87.             errmsg( TIMEOUT, user, hostname, line );
  88.             however++;
  89.         } else {
  90.             osig = signal(SIGALRM, wakeup);
  91.             alarm( 5 );
  92.             if ( (term=fopen(terminal,"w")) != NULL ) {
  93.             fprintf(term, "\n\007%s: %s\n", sender, message);
  94.             /* we need this fflush() or else it would hang in the
  95.                fclose() after we've dealt with the alarm() */
  96.             fflush( term );
  97.             strcpy( successful_line, line );
  98.             }
  99.         }
  100.         alarm( 0 );
  101.         signal(SIGALRM, osig);
  102.         if (term == NULL) {
  103.             errmsg( NO_WRITE, user, hostname, line, syserr() );
  104.             however++;
  105.             errcode++;
  106.         } else
  107.             fclose( term );
  108.         }
  109. #ifdef ANSWERBACK
  110.         answerback( ANSWER, user, line );
  111. #endif
  112.     } else {
  113.         errmsg( NO_STAT, terminal, user, hostname, syserr() );
  114.         however++;
  115.         errcode++;
  116.     }
  117.     }
  118.     (void) fclose( fp );
  119. #ifdef SAVEMSG
  120.     /* note that these saves it even if mesg n was set */
  121.     if ( found && uid != -1 )
  122.     savemsg( uid, user, sender, message );
  123. #endif
  124.     if ( !found ) {
  125.     errmsg( NOT_ON, user, hostname );
  126.     errcode++;
  127.     }
  128.     /*
  129.      * A message like "so-and-so (ttyxx) is not receiving messages"
  130.      * is not too helpful when they are receiving messages
  131.      * on another terminal.  So mention that.
  132.      * ..sah 87/04/06
  133.      */
  134.  
  135.     if ( however && successful_line[0] ) {
  136.     errmsg( HOWEVER, user, hostname, successful_line );
  137.     }
  138.     return( errcode );
  139. }
  140.  
  141.  
  142. #define DEL    (127)
  143.  
  144. sanitize( mbuf, copy )
  145. char *mbuf;
  146. char *copy;
  147. {
  148.     char *p, *r;
  149.     /*
  150.      * Remove control characters to prevent nasties.
  151.      * Previously allowed isspace(*p), but having a \r in a message
  152.      * is asking for forgeries.  isprint() is sufficient.
  153.      * (And good programmers always use isascii() first, right?)
  154.      */
  155.     for ( p = mbuf, r = copy; *p; p++,r++ ) {
  156.     if ( ! isascii( *p ) ) {
  157.         *r++ = '\\';
  158.         *p = toascii( *p );
  159.     }
  160.     if ( ! isprint(*p) ) {
  161.         if ( *p == '\t' )
  162.         *r = ' ';
  163.         else if ( iscntrl( *p ) ) {
  164.         *r++ = '^';
  165.         if ( *p == DEL )
  166.             *r = '?';
  167.         else
  168.             *r = *p + '@';
  169.         } else    /* this shouldn't happen, but what the hell */
  170.         *r = 'X';
  171.     } else
  172.         *r = *p;
  173.     }
  174. }
  175.