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

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