2 * Copyright (c) 1995, the EUROPAGATE consortium (see below).
4 * The EUROPAGATE consortium members are:
6 * University College Dublin
7 * Danmarks Teknologiske Videnscenter
8 * An Chomhairle Leabharlanna
9 * Consejo Superior de Investigaciones Cientificas
11 * Permission to use, copy, modify, distribute, and sell this software and
12 * its documentation, in whole or in part, for any purpose, is hereby granted,
15 * 1. This copyright and permission notice appear in all copies of the
16 * software and its documentation. Notices of copyright or attribution
17 * which appear at the beginning of any file must remain unchanged.
19 * 2. The names of EUROPAGATE or the project partners may not be used to
20 * endorse or promote products derived from this software without specific
21 * prior written permission.
23 * 3. Users of this software (implementors and gateway operators) agree to
24 * inform the EUROPAGATE consortium of their use of the software. This
25 * information will be used to evaluate the EUROPAGATE project and the
26 * software, and to plan further developments. The consortium may use
27 * the information in later publications.
29 * 4. Users of this software agree to make their best efforts, when
30 * documenting their use of the software, to acknowledge the EUROPAGATE
31 * consortium, and the role played by the software in their work.
33 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
34 * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
35 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
36 * IN NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE
37 * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF
38 * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
39 * OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND
40 * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
41 * USE OR PERFORMANCE OF THIS SOFTWARE.
45 * Iso2709 record management
47 * Europagate, 1994-1995.
50 * Revision 1.17 1995/12/20 16:28:08 adam
51 * Extra parameter block to gw_db_open. If block is 0 gw_db_open
52 * returns NULL if lock couldn't be satisfied.
53 * Minor changes in iso2709.c.
55 * Revision 1.16 1995/05/16 09:40:53 adam
58 * Revision 1.15 1995/03/31 10:42:41 adam
61 * Revision 1.14 1995/03/30 14:22:18 adam
62 * More work on new MARC anchor functions.
64 * Revision 1.13 1995/03/30 07:33:32 adam
65 * New 2709 function: iso2709_mk.
66 * First implementation of iso2709_a_insert.
68 * Revision 1.12 1995/03/29 16:08:56 adam
69 * Better error recovery when using bad records.
71 * Revision 1.11 1995/03/28 16:07:07 adam
72 * New function: iso2709_out. This function is the reverse of iso2709_cvt.
74 * Revision 1.10 1995/03/10 09:10:56 adam
75 * Removed dbc2709_cvt function. Makes heuristic guess for DBC2709 records.
77 * Revision 1.9 1995/03/08 12:36:39 adam
78 * New function: dbc2709_cvt.
80 * Revision 1.8 1995/03/08 12:03:15 adam
81 * Hack: When tags 00? are used, every separator (DC[1-3]) marks
82 * the end of the data field.
84 * Revision 1.7 1995/02/22 21:28:03 adam
87 * Revision 1.5 1995/02/22 15:24:14 adam
88 * Function iso2709_cvt makes a litte check for the format. It returns
89 * NULL if the buffer parameter can never be a MARC record.
91 * Revision 1.4 1995/02/15 17:45:44 adam
92 * Bug fix in iso2709 module.
94 * Revision 1.3 1995/02/10 17:05:18 adam
95 * New function iso2709_display to display MARC records in a
96 * line-by-line format. The iso2709_cvt function no longer
97 * prints the record to stderr.
99 * Revision 1.2 1995/02/10 16:50:32 adam
100 * Indicator field moved to 'struct iso2709_dir' from 'struct
102 * Function iso2709_rm implemented - to delete a MARC record.
104 * Revision 1.1.1.1 1995/02/09 17:27:11 adam
105 * Initial version of email gateway under CVS control.
115 #include <iso2709p.h>
117 static int atoin (const char *buf, int n)
123 val = val*10 + (*buf - '0');
129 static void strncpyx (char *d, const char *s, int n)
131 while (--n >= 0 && *s)
132 if (*s != ISO2709_IDFS)
142 char *iso2709_read (FILE *inf)
148 if (fread (length_str, 1, 5, inf) != 5)
150 size = atoin (length_str, 5);
153 if (!(buf = malloc (size+1)))
155 if (fread (buf+5, 1, size-5, inf) != (size-5))
160 memcpy (buf, length_str, 5);
165 Iso2709Rec iso2709_mk (void)
169 if (!(p = malloc (sizeof(*p))))
172 p->record_length = 0;
173 strncpyx (p->record_status, " ", 1);
174 strncpyx (p->implementation_codes, " ", 4);
175 p->indicator_length = 2;
176 p->identifier_length = 2;
178 strncpyx (p->user_systems, " ", 3);
179 p->length_data_entry = 4;
180 p->length_starting = 5;
181 p->length_implementation = 0;
182 strncpyx (p->future_use, " ", 1);
188 Iso2709Rec iso2709_cvt (const char *buf)
190 struct iso2709_dir **dpp, *dp;
194 if (!(p = malloc (sizeof(*p))))
197 /* deal with record label (24 characters) */
198 p->record_length = atoin (buf, 5);
199 strncpyx (p->record_status, buf+5, 1);
200 strncpyx (p->implementation_codes, buf+6, 4);
201 p->indicator_length = atoin (buf+10, 1);
202 p->identifier_length = atoin (buf+11, 1);
203 p->base_address = atoin (buf+12, 4);
204 strncpyx (p->user_systems, buf+17, 3);
206 if (p->record_length < 26)
211 p->length_data_entry = atoin (buf+20, 1);
212 p->length_starting = atoin (buf+21, 1);
213 p->length_implementation = atoin (buf+22, 1);
214 strncpyx (p->future_use, buf+23, 1);
216 /* deal with directory */
219 while (buf[pos] != ISO2709_FS)
221 if (!(*dpp = malloc (sizeof(**dpp))))
227 (*dpp)->fields = NULL;
228 (*dpp)->indicator = NULL;
229 strncpyx ((*dpp)->tag, buf+pos, 3);
231 (*dpp)->length = atoin (buf+pos, p->length_data_entry);
232 pos += p->length_data_entry;
233 (*dpp)->offset = atoin (buf+pos, p->length_starting);
234 pos += p->length_starting + p->length_implementation;
237 if (pos > p->record_length)
244 /* deal with datafields */
245 for (dp = p->directory; dp; dp = dp->next)
248 struct iso2709_field **fpp;
249 int dpos = pos+dp->offset;
250 int epos = pos+dp->offset+dp->length-1;
259 if (!(*fpp = malloc (sizeof(**fpp))))
267 if (p->indicator_length)
270 if (buf[dpos+p->indicator_length] != ISO2709_IDFS)
273 if (!memcmp (dp->tag, "00", 2))
277 else if (!memcmp (dp->tag, "00", 2))
279 if (identifier_flag && p->indicator_length)
281 if (!(dp->indicator = malloc (p->indicator_length+1)))
286 strncpyx (dp->indicator, buf+dpos, p->indicator_length);
287 dpos += p->indicator_length;
290 dp->indicator = NULL;
294 if (p->identifier_length && identifier_flag)
296 strncpyx ((*fpp)->identifier, buf+dpos+1,
297 p->identifier_length-1);
298 dpos_n = dpos += p->identifier_length;
299 while (buf[dpos_n] != ISO2709_FS && buf[dpos_n] != ISO2709_RS
300 && buf[dpos_n] != ISO2709_IDFS && dpos_n < epos)
305 *(*fpp)->identifier = '\0';
307 while (buf[dpos_n] != ISO2709_FS && buf[dpos_n] != ISO2709_RS
311 if (!((*fpp)->data = malloc (dpos_n - dpos + 1)))
316 strncpyx ((*fpp)->data, buf+dpos, dpos_n - dpos);
321 if (buf[dpos] != ISO2709_FS && buf[dpos] != ISO2709_RS)
322 fprintf (stderr, "Missing separator at end of field "
323 "in %s %s\n", dp->tag, (*fpp)->identifier);
326 if (buf[dpos] == ISO2709_FS || buf[dpos] == ISO2709_RS)
328 fprintf (stderr, "Unexpected separator inside field %s %s\n",
329 dp->tag, (*fpp)->identifier);
333 if (!(*fpp = malloc (sizeof(**fpp))))
344 void iso2709_rm (Iso2709Rec rec)
346 struct iso2709_dir *dir, *dir1;
348 for (dir = rec->directory; dir; dir = dir1)
350 struct iso2709_field *field, *field1;
352 for (field = dir->fields; field; field = field1)
355 field1 = field->next;
358 free (dir->indicator);