aix51-64bit-exporter-20020107
[openafs.git] / src / export / cfgexport.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * cfgexport -  load/configure the EXPORT kernel extension
12  */
13 #include <afsconfig.h>
14 #include <afs/param.h>
15
16 RCSID("$Header$");
17
18 #include <stdio.h>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/device.h>
22 #include <sys/sysconfig.h>
23 #include <sys/uio.h>
24 #include <sys/xcoff.h>
25 #include <sys/ldr.h>
26 #include <setjmp.h>
27 #include <signal.h>
28 #include "export.h"
29 #include "sym.h"
30
31 extern char    *malloc(), *optarg;
32 extern int      errno;
33 extern int      sysconfig(int cmd, void *arg, int len);
34
35 int debug = 0 ;
36 char *syms = "/unix";
37 char *xstrings;
38
39 #include "AFS_component_version_number.c"
40
41 main(argc, argv)
42 char **argv; {
43         register add, del, opts;
44         register c;
45         char *file;
46         mid_t kmid;
47         struct cfg_load cload;
48         struct cfg_kmod cmod;
49         struct k_conf conf;
50         FILE *fp;
51
52 #ifdef  AFS_AIX32_ENV
53     /*
54      * The following signal action for AIX is necessary so that in case of a 
55      * crash (i.e. core is generated) we can include the user's data section 
56      * in the core dump. Unfortunately, by default, only a partial core is
57      * generated which, in many cases, isn't too useful.
58      */
59     struct sigaction nsa;
60     
61     sigemptyset(&nsa.sa_mask);
62     nsa.sa_handler = SIG_DFL;
63     nsa.sa_flags = SA_FULLDUMP;
64     sigaction(SIGSEGV, &nsa, NULL);
65 #endif
66         add = del = 0;
67
68         while ((c = getopt(argc, argv, "a:s:Z:d:")) != EOF) {
69                 switch (c) {
70                     case 'Z':           /* Zdebug option        */
71                         ++debug;
72                         break;
73
74                     case 'a':
75                         add  = 1;
76                         file = optarg;
77                         if (!file)
78                                 usage();
79                         break;
80
81                     case 'd':
82                         del = 1;
83                         file = optarg;
84                         if (!file)
85                                 usage();
86                         break;
87
88                     case 's':
89                         syms = optarg;
90                         break;
91
92                     default:
93                         usage();
94                         break;
95                 }
96         }
97
98         if (!add && !del)
99                 usage();
100
101         if (add) {
102             char *buf[1024];
103             char PidFile[256];
104
105             buf[0] = "execerror";
106             buf[1] = "cfgexport";
107             get_syms(&conf, syms);
108
109             cload.path = file;
110             if (sysconfig(SYS_KLOAD, &cload, sizeof(cload)) == -1) {
111                 loadquery(L_GETMESSAGES, &buf[2], sizeof buf - 8);
112                 execvp("/etc/execerror", buf);
113                 perror("SYS_KLOAD");
114                 exit(1);
115             }
116
117             cmod.kmid   = cload.kmid;
118             cmod.cmd    = CFG_INIT;
119             cmod.mdiptr = (caddr_t) &conf;
120             cmod.mdilen = sizeof (conf);
121
122             if (sysconfig(SYS_CFGKMOD, &cmod, sizeof(cmod)) == -1) {
123                 perror("SYS_CFGKMOD");
124                 cload.kmid = cload.kmid;
125                 sysconfig(SYS_KULOAD, &cload, sizeof(cload));
126                 exit(1);
127             }
128 #ifdef  notdef
129             printf("cfgexport -d 0x%x # to remove EXPORT\n", cload.kmid);
130 #endif
131             strcpy(PidFile, file);
132             strcat(PidFile, ".kmid");
133             fp = fopen(PidFile, "w");
134             if (fp) {
135                 (void) fprintf(fp, "%d\n", cload.kmid);
136                 (void) fclose(fp);
137             } else {
138                 printf("Can't open for write file %s (error=%d); ignored\n", PidFile, errno);
139             }
140             exit(0);
141         } else if (del) {
142             char PidFile[256];
143
144             strcpy(PidFile, file);
145             strcat(PidFile, ".kmid");
146             fp = fopen(PidFile, "r");
147             if (!fp) {
148                 printf("Can't read %s file (error=%d); aborting\n", PidFile, errno);
149                 exit(1);
150             }
151             (void) fscanf(fp, "%d\n", &kmid);
152             (void) fclose(fp);
153             unlink(PidFile);
154             cmod.kmid   = kmid;
155             cmod.cmd    = CFG_TERM;
156             cmod.mdiptr = NULL;
157             cmod.mdilen = 0;
158
159             if (sysconfig(SYS_CFGKMOD, &cmod, sizeof(cmod)) == -1) {
160                 perror("SYS_CFGKMOD");
161                 exit(1);
162             }
163
164             cload.kmid = kmid;
165             if (sysconfig(SYS_KULOAD, &cload, sizeof(cload)) == -1) {
166                 perror("SYS_KULOAD");
167                 exit(1);
168             }
169             exit(0);
170         }
171 }
172
173 usage() {
174
175         error("usage: cfgexport [-a mod_file [-s symbols]] [-d mod_file]\n");
176 }
177
178 /*
179  * get_syms -   get kernel symbol table info.
180  *
181  * Input:
182  *      conf    -       ^ to EXPORT extension configuration struct
183  *      syms    -       ^ to name of file containing XCOFF symbols
184  */
185 get_syms(conf, syms)
186 struct k_conf *conf; 
187 char *syms;
188 {
189         sym_t *k_symtab, *ksp;
190         struct syment *x_symtab, *xsp, *xsq;
191         char *kstrings;
192         struct xcoffhdr hdr;            /* XCOFF header from symbol file*/
193         sym_t k_sym;                    /* export version of symbol     */
194         struct syment xcoff_sym;        /* xcoff version of symbol      */
195         int i, nsyms, nksyms, nxsyms = 0;
196         int xstr_size, kstr_size;
197         FILE *fp;
198         int xsym_compar();
199
200         fp = fopen(syms, "r");
201         if (fp == NULL)
202                 sys_error(syms);
203
204         if (fread(&hdr, sizeof (hdr), 1, fp) != 1)
205                 sys_error(syms);
206
207         if (hdr.filehdr.f_nsyms == 0)
208                 error("%s: no symbols", syms);
209
210         switch (hdr.filehdr.f_magic) {
211             case U802WRMAGIC:
212             case U802ROMAGIC:
213             case U802TOCMAGIC:
214             case U800WRMAGIC:
215             case U800ROMAGIC:
216             case U800TOCMAGIC:
217             case U64_TOCMAGIC:
218                 break;
219
220             default:
221                 error("%s: funny magic number 0%o"
222                       , syms, hdr.filehdr.f_magic);
223         }
224
225         nsyms = hdr.filehdr.f_nsyms;
226         if (debug)
227                 printf("nsyms = %d\n", nsyms);
228
229         x_symtab = (struct syment *) malloc(nsyms * SYMESZ);
230         if (!x_symtab)
231                 error("no memory for symbol table");
232
233         /*
234          * try to snarf the string table: should be just past the
235          * symbol table: first 4 bytes is length of rest.
236          */
237         if (fseek(fp, hdr.filehdr.f_symptr + nsyms * SYMESZ, 0) < 0)
238                 sys_error("%s: seek to strtab", syms);
239
240         if (fread(&xstr_size, sizeof (xstr_size), 1, fp) != 1)
241                 error("%s: reading string table size", syms);
242
243         xstrings = malloc(xstr_size + sizeof (xstr_size));
244         if (!xstrings)
245                 error("no memory for string table");
246
247         /*
248          * seek back to the start of the strings
249          */
250         if (fseek(fp, hdr.filehdr.f_symptr + nsyms * SYMESZ, 0) < 0)
251                 sys_error("%s: seek to strtab", syms);
252
253         if (fread(xstrings, sizeof (*xstrings), xstr_size, fp) != xstr_size)
254                 error("%s: reading string table");
255
256         /*
257          * now seek back to the start of the symbol table, and read it
258          * all in.
259          */
260         if (fseek(fp, hdr.filehdr.f_symptr, 0) < 0)
261                 sys_error("%s: seek to symtab", syms);
262
263         xsp = &x_symtab[0];
264
265         for (i = nxsyms = 0; i < nsyms; ++i) {
266                 char name[16], *p;
267
268                 if (fread(&xcoff_sym, SYMESZ, 1, fp) != 1)
269                         error("%s: reading symbol entry", syms);
270
271 #ifdef __XCOFF64__
272                 p = xstrings + xcoff_sym.n_offset;
273 #else
274                 if (xcoff_sym.n_zeroes == 0) {
275                         /*
276                          * Need to relocate string table offset
277                          */
278                         p = xcoff_sym.n_nptr = xstrings + xcoff_sym.n_offset;
279                 } else {
280                         strncpy(name, xcoff_sym.n_name, 8);
281                         
282                         p = name, p[8] = 0;
283                 }
284 #endif
285
286                 if (debug > 2)
287                         dump_xsym(&xcoff_sym);
288
289                 switch (xcoff_sym.n_sclass) {
290                     case C_EXT:         /* external                     */
291                     case C_HIDEXT:      /* hidden external (sic)        */
292                         /*
293                          * filtre out the ones with the strange names
294                          */
295                         if (strchr(p, '@') || strchr(p, '$') || p[0] == 0)
296                                 break;
297
298                         *xsp++ = xcoff_sym;
299                         ++nxsyms;
300
301                         if (debug > 1)
302                                 dump_xsym(&xcoff_sym);
303
304                         break;
305                 }
306
307                 if (xcoff_sym.n_numaux) {
308                         fseek(fp, xcoff_sym.n_numaux * AUXESZ, 1);
309                         i += xcoff_sym.n_numaux;
310                 }
311         }
312
313         fclose(fp);
314
315         /*
316          * sort the symbol table
317          */
318         qsort((char *) x_symtab, nxsyms, sizeof (*x_symtab), xsym_compar);
319  
320         /*
321          * we will need no more than `nxsyms' symbols.
322          */
323         k_symtab = (sym_t *) malloc(nxsyms * sizeof (sym_t));
324         if (!k_symtab)
325                 error("no memory for EXPORT symbol table");
326
327         /*
328          * uniquify it, and xlate to funny EXPORT format
329          */
330         xsp = xsq = x_symtab;
331         ksp       = k_symtab;
332         kstrings  = 0;
333         kstr_size = 0;
334         nksyms    = 0;
335
336         memset(xsq = &xcoff_sym, 0, sizeof (*xsq));
337
338         for (i = 1; i < nxsyms; ++i, xsq = xsp++) {
339 #ifdef __XCOFF64__
340                 if (xsp->n_offset != xsq->n_offset
341                     || xsp->n_value  != xsq->n_value) {
342 #else
343                 if (xsp->n_zeroes != xsq->n_zeroes
344                     || xsp->n_offset != xsq->n_offset
345                     || xsp->n_value  != xsq->n_value) {
346 #endif
347                         xlate_xtok(xsp, ksp++, &kstrings, &kstr_size);
348                         ++nksyms;
349                 }
350         }
351
352         /*
353          * place the symbol table info into the `conf' data structure
354          *
355          * XXXXX: for today only, leave the string table the same.
356          */
357         conf->nsyms   = nksyms;
358         conf->symt_sz = nksyms * sizeof (sym_t);
359         conf->str_sz  = kstr_size;
360         conf->symtab  = (caddr_t) k_symtab;
361         conf->strtab  = kstrings;
362 }
363
364
365 /*
366  * xlate_xtok   -       xlate XCOFF to EXPORT format
367  *
368  * Input:
369  *      xp      -       ^ to XCOFF symbol
370  *      kp      -       ^ to EXPORT  symbol save area
371  *      strp    -       ^ to ^ to EXPORT string table
372  *      szp     -       ^ to EXPORT string table size
373  */
374 xlate_xtok(xp, kp, strp, szp)
375 register struct syment *xp;
376 register sym_t *kp;
377 char **strp;
378 uint *szp; {
379         register len;
380         static char *export_strings, *prev = "";
381         static left, offset, sz;
382
383         if (!export_strings) {
384                 export_strings = malloc(sz=1024);
385                 if (!export_strings)
386                         error("no memory for EXPORT string table");
387
388                 *strp = export_strings;
389                 *szp  = offset = sizeof (uint);
390                 left  = 1024 - offset;
391
392                 export_strings += offset;
393
394                 *(uint *) export_strings = 0;   /* initial 4 bytes      */
395         }
396                         
397 #ifdef __XCOFF64__
398         if (strcmp(prev, xstrings + xp->n_offset) == 0) {
399                 /*
400                  * same name as previous entry: just use previous
401                  */
402                 kp->n_offset = offset - strlen( *strp + xp->n_offset) - 1;
403         } else if (find_suffix(xstrings + xp->n_offset, *strp, offset, &kp->n_offset)) {
404                 /*
405                  * found a string that we are a suffix of
406                  */
407                 ;
408         } else {
409                 /*
410                  * need to add to our string table
411                  */
412                 len = strlen(xstrings + xp->n_offset) + 1;
413                 while (len >= left) {
414                         export_strings = (char *)realloc(*strp, sz += 1024);
415                         if (!export_strings)
416                                 error("no memory for EXPORT string table");
417                         *strp = export_strings;
418                         left += 1024;
419                         prev  = "";     /* lazy */
420                 }
421
422                 strcpy(prev = *strp + offset, xstrings + xp->n_offset);
423
424                 kp->n_offset = offset;
425                 offset += len;
426                 left   -= len;
427                 *szp   += len;
428         }
429 #else
430         if (kp->n_zeroes = xp->n_zeroes) {      /* sic  */
431                 kp->n_zeroes = xp->n_zeroes;
432                 kp->n_offset = xp->n_offset;
433         } else if (strcmp(prev, xp->n_nptr) == 0) {
434                 /*
435                  * same name as previous entry: just use previous
436                  */
437                 kp->n_offset = offset - strlen(xp->n_nptr) - 1;
438         } else if (find_suffix(xp->n_nptr, *strp, offset, &kp->n_offset)) {
439                 /*
440                  * found a string that we are a suffix of
441                  */
442                 ;
443         } else {
444                 /*
445                  * need to add to our string table
446                  */
447                 len = strlen(xp->n_nptr) + 1;
448                 while (len >= left) {
449                         export_strings = (char *)realloc(*strp, sz += 1024);
450                         if (!export_strings)
451                                 error("no memory for EXPORT string table");
452                         *strp = export_strings;
453                         left += 1024;
454                         prev  = "";     /* lazy */
455                 }
456
457                 strcpy(prev = *strp + offset, xp->n_nptr);
458
459                 kp->n_offset = offset;
460                 offset += len;
461                 left   -= len;
462                 *szp   += len;
463         }
464 #endif
465
466         kp->n_value  = xp->n_value;
467
468         if (debug)
469                 dump_ksym(kp, *strp);
470 }
471 \f
472 /*
473  * find_suffix  -       look for a string that arg string is suffix of
474  *
475  * Input:
476  *      p       -       ^ to string we hope is a suffix of another
477  *      strings -       ^ to string table
478  *      max     -       max offset of valid string in strings
479  *      offp    -       ^ to place to store offset, if containing string found
480  *
481  * Returns:
482  *       0      -       no containing string found
483  *      !0      -       string found of which `p' is a suffix
484  *
485  * NOTE:
486  *      This is rather inefficient.
487  */
488 find_suffix(p, strings, max, offp)
489 register char *p, *strings;
490 uint *offp; {
491         register char *q, *e;
492         register len = strlen(p) - 1;
493
494         strings += sizeof (uint);
495         max     -= sizeof (uint);
496
497         for (e = strings + max; e > strings; ) {
498                 /*
499                  * adjust `e' to point at last non-blank
500                  */
501                 if (*e == 0) {
502                         --e;
503                         continue;
504                 }
505
506                 for (q = p + len; q > p && *q == *e; )
507                         --q, --e;
508
509                 if (*q == *e) {
510                         if (debug)
511                                 printf("found_suffix: %s\n", p);
512                         return *offp = e - strings + sizeof (uint);
513                 }
514
515                 if (*e)
516                         while (*e && e > strings)
517                                 --e;
518         }
519
520         return 0;
521 }
522 \f
523 /*
524  * xsym_compar -        compare two XCOFF symbol table entries
525  *
526  * If the names are the same, sort by descending storage class, so that
527  * C_EXT < C_HIDEXT;
528  */
529 xsym_compar(xp, xq)
530 register struct syment *xp, *xq; {
531         register char *p, *q;
532         register compar;
533
534 #ifndef __XCOFF64__
535         p = (xp->n_zeroes ? xp->n_name : xp->n_nptr);
536         q = (xq->n_zeroes ? xq->n_name : xq->n_nptr);
537
538         if (xp->n_zeroes || xq->n_zeroes)
539                 compar = strncmp(p, q, 8);
540         else
541 #else 
542         p = xstrings + xp->n_offset;
543         q = xstrings + xq->n_offset;
544 #endif
545                 compar = strcmp(p, q);
546
547         if (compar == 0)
548                 compar = xp->n_sclass - xq->n_sclass;
549
550         return compar;
551 }
552 \f
553 /*
554  * dump_xsym -  print to XCOFF symbol
555  */
556 dump_xsym(xsp)
557 struct syment *xsp; {
558
559 #ifndef __XCOFF64__
560         if (xsp->n_zeroes)
561                 printf(
562 "nptr <%-8.8s  %8.8s> val %8.8x sc# %4.4x type %4.4x sclass %2.2x naux %2.2x\n"
563                        , xsp->n_name
564                        , ""
565                        , xsp->n_value
566                        , xsp->n_scnum & 0xffff
567                        , xsp->n_type
568
569                        , xsp->n_sclass
570                        , xsp->n_numaux);
571         else
572 #endif
573                 printf(
574 "nptr <%-17.17s> val %8.8x sc# %4.4x type %4.4x sclass %2.2x naux %2.2x\n"
575 #ifdef __XCOFF64__
576                        , xstrings + xsp->n_offset
577 #else
578                        , xsp->n_nptr
579 #endif
580                        , xsp->n_value
581                        , xsp->n_scnum & 0xffff
582                        , xsp->n_type
583                        , xsp->n_sclass
584                        , xsp->n_numaux);
585 }
586
587 dump_ksym(ksp, strings)
588 sym_t *ksp;
589 char *strings; {
590
591 #ifndef __XCOFF64__
592         if (ksp->n_zeroes)
593                 printf("%8.8x %-8.8s\n", ksp->n_value, ksp->n_name);
594         else
595 #endif
596                 printf("%8.8x %s\n", ksp->n_value, ksp->n_offset + strings);
597 }
598
599 error(p, a, b, c, d, e)
600 char *p; {
601
602         fprintf(stderr, p, a, b, c, d, e);
603         fprintf(stderr, "\n");
604         exit(1);
605 }
606
607 sys_error(p, a, b, c, d, e) 
608 char *p;
609 {
610
611         fprintf(stderr, p, a, b, c, d, e);
612         perror(": ");
613         exit(1);
614 }
615
616 warn(p, a, b, c, d, e) 
617 char *p;
618 {
619
620         fprintf(stderr, p, a, b, c, d, e);
621         fprintf(stderr, "\n");
622 }