source: trunk/athena/bin/gms/message_daemon.c @ 1511

Revision 1511, 5.6 KB checked in by eichin, 36 years ago (diff)
fixed sign problem in logging printf's so that syslogs are more useable.
Line 
1/* This file is part of the Project Athena Global Message System.
2 * Created by: Mark W. Eichin <eichin@athena.mit.edu>
3 * $Source: /afs/dev.mit.edu/source/repository/athena/bin/gms/message_daemon.c,v $
4 * $Author: eichin $
5 *
6 *      Copyright (c) 1988 by the Massachusetts Institute of Technology.
7 *      For copying and distribution information, see the file
8 *      "mit-copyright.h".
9 */
10#include <mit-copyright.h>
11#ifndef lint
12static char rcsid_message_daemon_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/gms/message_daemon.c,v 1.4 1988-10-12 04:06:11 eichin Exp $";
13#endif lint
14
15#include "globalmessage.h"
16#ifndef GMS_SERVER_MESSAGE
17#define GMS_SERVER_MESSAGE "/site/Message"
18#endif /* GMS_SERVER_MESSAGE */
19
20#include <fcntl.h>
21#include <errno.h>
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <sys/stat.h>
26
27/*
28 * This version of the daemon is run out of inetd, with a conf line of:
29 * globalmessage dgram udp wait unswitched nobody /etc/messaged messaged
30 */
31#include <syslog.h>
32char *error_message();
33
34#define saddr_list(sin) (unsigned)sin[0],(unsigned)sin[1],(unsigned)sin[2],(unsigned)sin[3]
35main(argc,argv)
36     int argc;
37     char **argv;
38{
39  char buf[BFSZ];
40  int readstat, errstat, readlen, msgfile;
41  char *index();
42  struct sockaddr from;
43  /* these strange casts are so that I can print out the address of
44   * the incoming packet.
45   */
46  struct sockaddr_in *cast1 = (struct sockaddr_in *)&from;
47  char *cast2 = (char *)(&(cast1->sin_addr.s_addr));
48  int fromlen = sizeof(from);
49  time_t timestamp;
50  int headerlen;
51
52  /* initialize syslog connection for DAEMON */
53  /* log_pid has the side effect of forcing log messages to be unique,
54   * not listed as ``message the same, repeated 6 times'' but that
55   * shouldn't be a problem.
56   */
57  openlog(argv[0], LOG_PID, LOG_DAEMON);
58 
59  /* gms is just return values; the other com_err tables used will
60   * init themselves.
61   */
62  init_gms_err_tbl();
63
64  /* read the packet from the socket (stdin, since we run from inetd)
65   * and also record the from address so we can send a reply.
66   */
67  readstat = recvfrom(0, buf, BFSZ, 0, &from, &fromlen);
68  if(readstat == -1) {
69    syslog(LOG_INFO, "GMS daemon recvfrom failure %s", error_message(errno));
70    exit(errno);
71  }
72
73  /* We got a packet successfully, so if logging is enabled record the
74   * requesting address.
75   */
76  if(argc>1 && !strcmp(argv[1],"-log")) {
77    syslog(LOG_INFO, "GMS request succeeded [%s] from %ud.%ud.%ud.%ud",
78           buf, saddr_list(cast2));
79  }
80
81  /* Check the version number, and log if it is in error. */
82  if(strncmp(buf, GMS_VERSION_STRING, GMS_VERSION_STRING_LEN)) {
83    syslog(LOG_INFO, "GMS bogus version [%s] from %ud.%ud.%ud.%ud",
84           buf, saddr_list(cast2));
85    exit(GMS_CLIENT_VERSION);
86  }
87
88  /* Open the message file to read it in. Note that even were we to
89   * want to cache the data for efficiency, we must stat the file to
90   * make sure it hasn't changed under us. Since we're running, we
91   * must open it because we have no state.
92   */
93  msgfile = open(GMS_SERVER_MESSAGE, O_RDONLY, 0);
94
95  if(msgfile == -1) {
96    /* no file, special case of 0 timestamp indicating to also delete
97     * the remote cached copy. If the error is ENOENT, then we just
98     * assume it is an expected disappearance; all other errors are
99     * `interesting' and are logged. In any case, the tester can see
100     * that there is no new message.
101     */
102    if(errno == ENOENT) {
103      /* it didn't exist, we can deal with that... */
104      timestamp = 0;
105    } else {
106      /* something went wrong, but we can't do much about it;
107       * let's not trash the remote state -- just don't answer the
108       * connection.
109       */
110      syslog(LOG_INFO, "GMS daemon open error [%s] reading message file <%s>",
111             error_message(errno), GMS_SERVER_MESSAGE);
112      exit(errno);
113    }
114  } else {
115    struct stat sbuf;
116   
117    fstat(msgfile, &sbuf);
118    if(sbuf.st_size == 0) {
119      /* an empty file means the same to the remote as a missing one. */
120      timestamp = 0;
121    } else {
122      /* for convenient maintenance, use the real timestamp as version
123       * number. */
124      timestamp = sbuf.st_mtime;
125    }
126  }
127  strcpy(buf,GMS_VERSION_STRING);
128  {
129    char tsbuf[GMS_TIMESTAMP_LEN];
130
131    /* sprintf (and _doprnt in general) are slow memory hogs. However,
132     * syslog is already including _doprnt, so it's already over; it
133     * is cheaper just to use sprintf here instead of coding or
134     * linking in the fast integer one.
135     * It is almost readable, too...
136     */
137    sprintf(tsbuf, " %lu\n", timestamp);
138    strcat(buf,tsbuf);
139    headerlen = strlen(buf);
140  }
141
142  /* Now that we have the header, we have to read the rest of the file
143   * into the packet after it. The length-1 specification is to
144   * preserve a NUL at the end of the buffer. Use msgfile to remember
145   * that we couldn't open it.
146   */
147  if(msgfile != -1) {
148    readlen = read(msgfile, buf + headerlen, BFSZ-headerlen-1);
149    if(readlen == -1) {
150      /* read failed but open didn't, so record the error */
151      syslog(LOG_INFO, "GMS daemon read error [%s] reading message file <%s>",
152             error_message(errno), GMS_SERVER_MESSAGE);
153      exit(errno);
154    }
155    /* protect the fencepost... */
156    buf[BFSZ-1] = '\0';
157    close(msgfile);
158  }
159  /* send the packet back where it came from */
160  if(-1 == sendto(0, buf, readlen+headerlen, 0, &from, sizeof(from))) {
161    /* the send failed (probably a local error, or bad address or
162     * something so log the attempt.
163     */
164    syslog(LOG_INFO, "GMS daemon sendto failure [%s] to %d.%d.%d.%d",
165           error_message(errno), saddr_list(cast2));
166    exit(errno);
167  }
168  /* everything worked, die happy... */
169  exit(0);
170}
Note: See TracBrowser for help on using the repository browser.