]> arthur.barton.de Git - netatalk.git/blob - contrib/timelord/timelord.c
Warning fixes.
[netatalk.git] / contrib / timelord / timelord.c
1 /*
2  * $Id: timelord.c,v 1.6 2001-08-30 13:14:53 srittau Exp $
3  *
4  * Copyright (c) 1990,1992 Regents of The University of Michigan.
5  * All Rights Reserved. See COPYRIGHT.
6  *
7  * The "timelord protocol" was reverse engineered from Timelord,
8  * distributed with CAP, Copyright (c) 1990, The University of
9  * Melbourne.  The following copyright, supplied by The University
10  * of Melbourne, may apply to this code:
11  *
12  *      This version of timelord.c is based on code distributed
13  *      by the University of Melbourne as part of the CAP package.
14  *
15  *      The tardis/Timelord package for Macintosh/CAP is
16  *      Copyright (c) 1990, The University of Melbourne.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif /* HAVE_CONFIG_H */
22
23 #include <sys/param.h>
24 #include <sys/types.h>
25 #include <sys/time.h>
26 #include <sys/file.h>
27 #include <sys/uio.h>
28
29 #include <unistd.h>
30
31 #include <netatalk/at.h>
32 #include <netatalk/endian.h>
33 #include <atalk/atp.h>
34 #include <atalk/nbp.h>
35
36 #include <time.h>
37 #ifdef HAVE_SGTTY_H
38 #include <sgtty.h>
39 #endif /* HAVE_SGTTY_H */
40 #include <errno.h>
41 #include <signal.h>
42 #include <syslog.h>
43 #include <stdio.h>
44 #include <string.h>
45 #ifdef HAVE_NETDB_H
46 #include <netdb.h>
47 #endif /* HAVE_NETDB_H */
48
49 #ifdef HAVE_FCNTL_H
50 #include <fcntl.h>
51 #endif /* HAVE_FCNTL_H */
52 #ifdef HAVE_SYS_FCNTL_H
53 #include <sys/fcntl.h>
54 #endif /* HAVE_SYS_FCNTL_H */
55
56 #ifdef HAVE_TERMIOS_H
57 #include <termios.h>
58 #endif /* HAVE_TERMIOS_H */
59 #ifdef HAVE_SYS_TERMIOS_H
60 #include <sys/termios.h>
61 #endif /* HAVE_SYS_TERMIOS_H */
62
63 #define TL_GETTIME      0
64 #define TL_OK           12
65 #define TL_BAD          10
66 #define EPOCH           0x7C25B080      /* 00:00:00 GMT Jan 1, 1970 for Mac */
67
68 int     debug = 0;
69 char    *bad = "Bad request!";
70 char    buf[ 4624 ];
71 char    *server;
72
73 void usage( char *p )
74 {
75     char        *s;
76
77     if (( s = rindex( p, '/' )) == NULL ) {
78         s = p;
79     } else {
80         s++;
81     }
82     fprintf( stderr, "Usage:\t%s -d -n nbpname\n", s );
83     exit( 1 );
84 }
85
86 /*
87  * Unregister ourself on signal.
88  */
89 void
90 goaway(int signal)
91 {
92     if ( nbp_unrgstr( server, "TimeLord", "*", NULL ) < 0 ) {
93         syslog( LOG_ERR, "Can't unregister %s", server );
94         exit( 1 );
95     }
96     syslog( LOG_INFO, "going down" );
97     exit( 0 );
98 }
99
100 int main( int ac, char **av )
101 {
102     ATP                 atp;
103     struct sockaddr_at  sat;
104     struct atp_block    atpb;
105     struct timeval      tv;
106     struct timezone     tz;
107     struct iovec        iov;
108     struct tm           *tm;
109     char                hostname[ MAXHOSTNAMELEN ];
110     char                *p;
111     int                 c;
112     long                req, mtime, resp;
113     extern char         *optarg;
114     extern int          optind;
115
116     if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
117         perror( "gethostname" );
118         exit( 1 );
119     }
120     if (( server = index( hostname, '.' )) != 0 ) {
121         *server = '\0';
122     }
123     server = hostname;
124
125     while (( c = getopt( ac, av, "dn:" )) != EOF ) {
126         switch ( c ) {
127         case 'd' :
128             debug++;
129             break;
130         case 'n' :
131             server = optarg;
132             break;
133         default :
134             fprintf( stderr, "Unknown option -- '%c'\n", c );
135             usage( *av );
136         }
137     }
138
139     /*
140      * Disassociate from controlling tty.
141      */
142     if ( !debug ) {
143         int             i, dt;
144
145         switch ( fork()) {
146         case 0 :
147             dt = getdtablesize();
148             for ( i = 0; i < dt; i++ ) {
149                 (void)close( i );
150             }
151             if (( i = open( "/dev/tty", O_RDWR )) >= 0 ) {
152                 (void)ioctl( i, TIOCNOTTY, 0 );
153                 setpgid( 0, getpid());
154                 (void)close( i );
155             }
156             break;
157         case -1 :
158             perror( "fork" );
159             exit( 1 );
160         default :
161             exit( 0 );
162         }
163     }
164
165     if (( p = rindex( *av, '/' )) == NULL ) {
166         p = *av;
167     } else {
168         p++;
169     }
170
171 #ifdef ultrix
172     openlog( p, LOG_PID );
173 #else /* ultrix */
174     openlog( p, LOG_NDELAY|LOG_PID, LOG_DAEMON );
175 #endif /* ultrix */
176
177     /* allocate memory */
178     memset (&sat.sat_addr, 0, sizeof (sat.sat_addr));
179
180     if (( atp = atp_open( ATADDR_ANYPORT, &sat.sat_addr )) == NULL ) {
181         syslog( LOG_ERR, "main: atp_open: %s", strerror( errno ) );
182         exit( 1 );
183     }
184
185     if ( nbp_rgstr( atp_sockaddr( atp ), server, "TimeLord", "*" ) < 0 ) {
186         syslog( LOG_ERR, "Can't register %s", server );
187         exit( 1 );
188     }
189     syslog( LOG_INFO, "%s:TimeLord started", server );
190
191         signal(SIGHUP, goaway);
192         signal(SIGTERM, goaway);
193
194     for (;;) {
195         /*
196          * Something seriously wrong with atp, since these assigns must
197          * be in the loop...
198          */
199         atpb.atp_saddr = &sat;
200         atpb.atp_rreqdata = buf;
201         bzero( &sat, sizeof( struct sockaddr_at ));
202         atpb.atp_rreqdlen = sizeof( buf );
203         if ( atp_rreq( atp, &atpb ) < 0 ) {
204             syslog( LOG_ERR, "main: atp_rreq: %s", strerror( errno ) );
205             exit( 1 );
206         }
207
208         p = buf;
209         bcopy( p, &req, sizeof( long ));
210         req = ntohl( req );
211         p += sizeof( long );
212
213         switch( req ) {
214         case TL_GETTIME :
215             if ( atpb.atp_rreqdlen > 5 ) {
216                     bcopy( p + 1, &mtime, sizeof( long ));
217                     mtime = ntohl( mtime );
218                     syslog( LOG_INFO, "gettime from %s %s was %lu",
219                             (*( p + 5 ) == '\0' ) ? "<unknown>" : p + 5,
220                             ( *p == 0 ) ? "at boot" : "in chooser",
221                             mtime );
222             } else {
223                     syslog( LOG_INFO, "gettime" );
224             }
225
226             if ( gettimeofday( &tv, &tz ) < 0 ) {
227                 syslog( LOG_ERR, "main: gettimeofday: %s", strerror( errno ) );
228                 exit( 1 );
229             }
230             if (( tm = gmtime( &tv.tv_sec )) == 0 ) {
231                 perror( "localtime" );
232                 exit( 1 );
233             }
234
235             mtime = tv.tv_sec + EPOCH;
236             mtime = htonl( mtime );
237
238             resp = TL_OK;
239             bcopy( &resp, buf, sizeof( long ));
240             bcopy( &mtime, buf + sizeof( long ), sizeof( long ));
241             iov.iov_len = sizeof( long ) + sizeof( long );
242             break;
243
244         default :
245             syslog( LOG_ERR, bad );
246
247             resp = TL_BAD;
248             bcopy( &resp, buf, sizeof( long ));
249             *( buf + 4 ) = (unsigned char)strlen( bad );
250             strcpy( buf + 5, bad );
251             iov.iov_len = sizeof( long ) + 2 + strlen( bad );
252             break;
253         }
254
255         iov.iov_base = buf;
256         atpb.atp_sresiov = &iov;
257         atpb.atp_sresiovcnt = 1;
258         if ( atp_sresp( atp, &atpb ) < 0 ) {
259             syslog( LOG_ERR, "main: atp_sresp: %s", strerror( errno ) );
260             exit( 1 );
261         }
262     }
263 }