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