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