merge 64-bit fixes from Fernando Lucas Rodriguez <fernando_lr@terra.es>
[debian/gcpegg] / genlib.c
1 /* PROGRAM:     eggsh
2  * FILE:        $Header: /home/egg/src/RCS/genlib.c,v 1.6 1999/02/28 20:05:18 ghn Exp $
3  * PURPOSE:     General library
4  * AUTHOR:      Greg Nelson
5  * DATE:        98-05-09
6  *
7  * REVISED:
8  * $Log: genlib.c,v $
9  * Revision 1.6  1999/02/28 20:05:18  ghn
10  * Version 5.1: Changed dquad2sockaddr interface to support ip/mm mask,
11  * created hl2dquad to translate host-long to dotted quad, and modified
12  * sockaddr2dquad to use this.
13  *
14  * Revision 1.5  1998/12/31 22:07:56  ghn
15  * Rev 5 code: includes multi-reg support, HTML, etc.
16  *
17  * Revision 1.4  1998/08/03 20:43:35  kelvin
18  * File byte-order independence.
19  *
20  * Revision 1.3  1998/08/01  18:51:25  ghn
21  * Added John's byte-order-independence changes.
22  *
23  * Revision 1.2  1998/08/01 17:07:29  ghn
24  * Casting fixes from John plus better parsing.
25  *
26  * Revision 1.1  1998/07/21 11:38:15  ghn
27  * Initial revision
28  * 
29  * Copyright 1998 - Greg Nelson
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/utsname.h>
38 #include "global.h"
39 #include "genlib.h"
40
41 uint32 getzulutime(struct timeval *ztv) {
42   struct timeval ttv;
43
44   if (ztv) {
45     gettimeofday(ztv, NULL);
46     return ztv->tv_sec;
47   } else {
48     gettimeofday(&ttv, NULL);
49     return ttv.tv_sec;
50   }
51 }
52
53 /* Get time difference (tv1-tv2) in msec.  Only works if less than 24
54    days have passed. */
55 int32 deltams(struct timeval *tv1, struct timeval *tv2) {
56   return (tv1->tv_sec - tv2->tv_sec) * 1000L +
57          (tv1->tv_usec - tv2->tv_usec) / 1000L;
58 }
59
60 /* Look up an EGG id.  If we can't get it from environment, do a nutty
61    thing using CRC of uname block, which should be pretty unique. */
62 uint16 GetID(void) {
63   char *idstr;
64   struct utsname utsname;
65
66   if ((idstr = getenv("EGGID")) != NULL) {
67     return atoi(idstr);
68   } else {
69     uname(&utsname);
70     return BlockCRC16((byte *)(&utsname), sizeof(struct utsname));
71   }
72 }
73
74 char *Packetize(EggCarton *src) {
75   char *rbuf;
76   uint32 lbuf;
77   uint16 pktsize, rec;
78   char *pktP;
79
80   pktsize = (7 * sizeof(uint16)) + sizeof(trial) +          /* Header */
81             sizeof(char) +                                  /* ...including pad byte for trialsz */
82             (src->hdr.numrec * (sizeof(uint32) +            /* Trial data */
83                 src->hdr.samp_rec * sizeof(trial))) +
84             sizeof(uint32);                                 /* CRC and terminator */
85   rbuf = pktP = (char *) malloc(pktsize);
86
87   /* Assemble header fields into data packet. */
88
89   pack16(src->hdr.type = DATA_PACKET);
90   pack16(src->hdr.pktsize = pktsize);
91   pack16(src->hdr.eggid);
92   pack16(src->hdr.samp_rec);
93   pack16(src->hdr.sec_rec);
94   pack16(src->hdr.rec_pkt);
95   pack8(0);                           /* Pad byte in case we want to expand trialsz */
96   pack8(src->hdr.trialsz);
97   pack16(src->hdr.numrec);
98
99   /* Append data records to packet. */
100
101   for (rec = 0; rec < src->hdr.numrec; rec++) {
102     pack32(src->records[rec].timestamp);
103     pack8s(&(src->records[rec].trials), src->hdr.samp_rec);
104   }
105
106   /* Get CRC, pack into base(32,32,64) notation, and add tag byte (0xFF) */
107   lbuf = BlockCRC16((byte *) rbuf, pktP - rbuf);
108   lbuf = ((lbuf & 0xF800) << 13) |
109          ((lbuf & 0x07C0) << 10) |
110          ((lbuf & 0x003F) << 8) |
111          (0x00FF);
112   pack32(lbuf);
113
114   if ((pktP - rbuf) != pktsize) {
115     fprintf(stderr, "Length mismatch assembling packet.  Computed: %d, actually packed: %ld.\n",
116         pktsize, pktP - rbuf);
117   }
118   return rbuf;
119 }
120
121 int32 Unpacketize(EggCarton *dst, char *src) {
122   char *pktP = src;
123   char pad;
124   uint16 rec;
125   uint32 lbuf, filecrc;
126
127   /* Unpack the portable header into a host-order and aligned
128      EggHeader packet. */
129
130   unpack16(dst->hdr.type);
131   unpack16(dst->hdr.pktsize);
132   unpack16(dst->hdr.eggid);
133   unpack16(dst->hdr.samp_rec);
134   unpack16(dst->hdr.sec_rec);
135   unpack16(dst->hdr.rec_pkt);
136   unpack8(pad);               /* Pad in case we later grow trialsz */
137   unpack8(dst->hdr.trialsz);
138   unpack16(dst->hdr.numrec);
139
140   if (dst->hdr.type != DATA_PACKET) {
141 #ifdef DEBUG
142     fprintf(stderr, "Invalid header type 0x%04X in packet read from file.\n", dst->hdr.type);
143 #endif
144     return -1;
145   }
146
147   /* Unpack the data records from the file packet. */
148
149   for (rec = 0; rec < dst->hdr.numrec; rec++) {
150     unpack32(dst->records[rec].timestamp);
151     /* Assumes sizeof(trial) = 1 */
152     unpack8s(&(dst->records[rec].trials), dst->hdr.samp_rec);
153   }
154
155   /* Compute the CRC, reassemble into record terminator,
156      and compare with terminator in file. */
157
158   lbuf = BlockCRC16((byte *) src, pktP - src);
159   lbuf = ((lbuf & 0xF800) << 13) |
160          ((lbuf & 0x07C0) << 10) |
161          ((lbuf & 0x003F) << 8) |
162          (0x00FF);
163
164   unpack32(filecrc);
165
166   if (lbuf != filecrc) {
167 #ifdef DEBUG
168     fprintf(stderr, "Bad CRC in packet read from file.  Read 0x%08X, computed 0x%08X.\n", filecrc, lbuf);
169 #endif
170     return -2;
171   }
172
173   if (dst->hdr.pktsize != (pktP - src)) {
174 #ifdef DEBUG
175     fprintf(stderr, "Length mismatch decoding packet.  Header: %d, length decoded: %ld.\n",
176       dst->hdr.pktsize, pktP - src);
177 #endif
178     return -1;
179   }
180
181   /* One final little tweak.  Since we included a pad byte to allow
182      for growth in trialsz, hdr.pktsize will include it.  Subtract
183      one to hide the existence of the pad in the file from the
184      caller.  In all probability the caller isn't going to look at
185      pktsize, but you can't be too careful. */
186
187   dst->hdr.pktsize--;
188
189   return 0;
190 }
191
192 void Parse(char *input, int *argc, char *argv[]) {
193   char *tp;
194
195   *argc = 0;
196
197   tp = strtok(input, " \t\n");
198   while (tp != NULL && *argc < MAX_PARSE) {
199     argv[*argc] = tp;
200     *argc += 1;
201     tp = strtok(NULL, " \t\n");
202   }
203 }
204
205 char *mallocpy(char *input) {
206   char *res;
207
208   res = (char *)malloc(1+strlen(input));
209   if (res) strcpy(res, input);
210   return res;
211 }
212
213 void dquad2sockaddr(struct sockaddr_in *sinp, int16 *mask, char *dquad) {
214   char *tp, *loser;
215   uint32 saddr;
216   short qcount;
217
218   loser = mallocpy(dquad);
219
220   tp = strtok(loser, ".");
221   for (qcount = 0, saddr = 0; qcount < 4 && tp != NULL; qcount++) {
222     saddr = (saddr << 8) | (atoi(tp) & 0xFF);
223     tp = strtok(NULL, ".");
224   }
225   if (mask) {
226     *mask = 32;
227     strcpy(loser, dquad);
228     tp = strtok(loser, "/");
229     if (tp) {
230       tp = strtok(NULL, "/");
231       if (tp) *mask = atoi(tp);
232     }
233   }
234   free(loser);
235
236   sinp->sin_family = AF_INET;
237   sinp->sin_port = 0;           /* To be filled in later */
238   sinp->sin_addr.s_addr = htonl(saddr);
239 }
240
241 char *sockaddr2dquad(struct sockaddr_in *sinp) {
242   uint32 saddr;
243   
244   saddr = ntohl(sinp->sin_addr.s_addr);
245   return hl2dquad(saddr);
246 }
247
248 char *hl2dquad(uint32 addr) {
249   static char resout[16];
250
251   sprintf(resout, "%u.%u.%u.%u",
252           (addr >> 24) & 0xFF, (addr >> 16) & 0xFF,
253           (addr >> 8) & 0xFF, addr & 0xFF);
254   
255   return resout;
256 }