1/* 2 * module.c - deal with dynamic modules 3 * 4 * This file is part of zsh, the Z shell. 5 * 6 * Copyright (c) 1996-1997 Zoltán Hidvégi 7 * All rights reserved. 8 * 9 * Permission is hereby granted, without written agreement and without 10 * license or royalty fees, to use, copy, modify, and distribute this 11 * software and to distribute modified versions of this software for any 12 * purpose, provided that the above copyright notice and the following 13 * two paragraphs appear in all copies of this software. 14 * 15 * In no event shall Zoltán Hidvégi or the Zsh Development Group be liable 16 * to any party for direct, indirect, special, incidental, or consequential 17 * damages arising out of the use of this software and its documentation, 18 * even if Zoltán Hidvégi and the Zsh Development Group have been advised of 19 * the possibility of such damage. 20 * 21 * Zoltán Hidvégi and the Zsh Development Group specifically disclaim any 22 * warranties, including, but not limited to, the implied warranties of 23 * merchantability and fitness for a particular purpose. The software 24 * provided hereunder is on an "as is" basis, and Zoltán Hidvégi and the 25 * Zsh Development Group have no obligation to provide maintenance, 26 * support, updates, enhancements, or modifications. 27 */ 28 29#include "zsh.mdh" 30#include "module.pro" 31 32/* 33 * List of linked-in modules. 34 * This is set up at boot and remains for the life of the shell; 35 * entries do not appear in "zmodload" listings. 36 */ 37 38/**/ 39LinkList linkedmodules; 40 41/* $module_path ($MODULE_PATH) */ 42 43/**/ 44char **module_path; 45 46/* Hash of modules */ 47 48/**/ 49mod_export HashTable modulestab; 50 51/* 52 * Bit flags passed as the "flags" argument of a autofeaturefn_t. 53 * Used in other places, such as the final argument to 54 * do_module_features(). 55 */ 56enum { 57 /* 58 * `-i' option: ignore errors pertaining to redefinitions, 59 * or indicate to do_module_features() that it should be 60 * silent. 61 */ 62 FEAT_IGNORE = 0x0001, 63 /* If a condition, condition is infix rather than prefix */ 64 FEAT_INFIX = 0x0002, 65 /* 66 * Enable all features in the module when autoloading. 67 * This is the traditional zmodload -a behaviour; 68 * zmodload -Fa only enables features explicitly marked for 69 * autoloading. 70 */ 71 FEAT_AUTOALL = 0x0004, 72 /* 73 * Remove feature: alternative to "-X:NAME" used if 74 * X is passed separately from NAME. 75 */ 76 FEAT_REMOVE = 0x0008, 77 /* 78 * For do_module_features(). Check that any autoloads 79 * for the module are actually provided. 80 */ 81 FEAT_CHECKAUTO = 0x0010 82}; 83 84/* 85 * All functions to add or remove autoloadable features fit 86 * the following prototype. 87 * 88 * "module" is the name of the module. 89 * 90 * "feature" is the name of the feature, minus any type prefix. 91 * 92 * "flags" is a set of the bits above. 93 * 94 * The return value is 0 for success, -1 for failure with no 95 * message needed, and one of the following to indicate the calling 96 * function should print a message: 97 * 98 * 1: failed to add [type] `[feature]' 99 * 2: [feature]: no such [type] 100 * 3: [feature]: [type] is already defined 101 */ 102typedef int (*autofeaturefn_t)(const char *module, const char *feature, 103 int flags); 104 105/* Bits in the second argument to find_module. */ 106enum { 107 /* 108 * Resolve any aliases to the underlying module. 109 */ 110 FINDMOD_ALIASP = 0x0001, 111 /* 112 * Create an element for the module in the list if 113 * it is not found. 114 */ 115 FINDMOD_CREATE = 0x0002, 116}; 117 118static void 119freemodulenode(HashNode hn) 120{ 121 Module m = (Module) hn; 122 123 if (m->node.flags & MOD_ALIAS) 124 zsfree(m->u.alias); 125 zsfree(m->node.nam); 126 if (m->autoloads) 127 freelinklist(m->autoloads, freestr); 128 if (m->deps) 129 freelinklist(m->deps, freestr); 130 zfree(m, sizeof(*m)); 131} 132 133/* flags argument to printmodulenode */ 134enum { 135 /* -L flag, output zmodload commands */ 136 PRINTMOD_LIST = 0x0001, 137 /* -e flag */ 138 PRINTMOD_EXIST = 0x0002, 139 /* -A flag */ 140 PRINTMOD_ALIAS = 0x0004, 141 /* -d flag */ 142 PRINTMOD_DEPS = 0x0008, 143 /* -F flag */ 144 PRINTMOD_FEATURES = 0x0010, 145 /* -l flag in combination with -L flag */ 146 PRINTMOD_LISTALL = 0x0020, 147 /* -a flag */ 148 PRINTMOD_AUTO = 0x0040 149}; 150 151/* Scan function for printing module details */ 152 153static void 154printmodulenode(HashNode hn, int flags) 155{ 156 Module m = (Module)hn; 157 /* 158 * If we check for a module loaded under an alias, we 159 * need the name of the alias. We can use it in other 160 * cases, too. 161 */ 162 const char *modname = m->node.nam; 163 164 if (flags & PRINTMOD_DEPS) { 165 /* 166 * Print the module's dependencies. 167 */ 168 LinkNode n; 169 170 if (!m->deps) 171 return; 172 173 if (flags & PRINTMOD_LIST) { 174 printf("zmodload -d "); 175 if (modname[0] == '-') 176 fputs("-- ", stdout); 177 quotedzputs(modname, stdout); 178 } else { 179 nicezputs(modname, stdout); 180 putchar(':'); 181 } 182 for (n = firstnode(m->deps); n; incnode(n)) { 183 putchar(' '); 184 if (flags & PRINTMOD_LIST) 185 quotedzputs((char *) getdata(n), stdout); 186 else 187 nicezputs((char *) getdata(n), stdout); 188 } 189 } else if (flags & PRINTMOD_EXIST) { 190 /* 191 * Just print the module name, provided the module is 192 * present under an alias or otherwise. 193 */ 194 if (m->node.flags & MOD_ALIAS) { 195 if (!(flags & PRINTMOD_ALIAS) || 196 !(m = find_module(m->u.alias, FINDMOD_ALIASP, NULL))) 197 return; 198 } 199 if (!m->u.handle || (m->node.flags & MOD_UNLOAD)) 200 return; 201 nicezputs(modname, stdout); 202 } else if (m->node.flags & MOD_ALIAS) { 203 /* 204 * Normal listing, but for aliases. 205 */ 206 if (flags & PRINTMOD_LIST) { 207 printf("zmodload -A "); 208 if (modname[0] == '-') 209 fputs("-- ", stdout); 210 quotedzputs(modname, stdout); 211 putchar('='); 212 quotedzputs(m->u.alias, stdout); 213 } else { 214 nicezputs(modname, stdout); 215 fputs(" -> ", stdout); 216 nicezputs(m->u.alias, stdout); 217 } 218 } else if (m->u.handle || (flags & PRINTMOD_AUTO)) { 219 /* 220 * Loaded module. 221 */ 222 if (flags & PRINTMOD_LIST) { 223 /* 224 * List with -L format. Possibly we are printing 225 * features, either enables or autoloads. 226 */ 227 char **features = NULL; 228 int *enables = NULL; 229 if (flags & PRINTMOD_AUTO) { 230 if (!m->autoloads || !firstnode(m->autoloads)) 231 return; 232 } else if (flags & PRINTMOD_FEATURES) { 233 if (features_module(m, &features) || 234 enables_module(m, &enables) || 235 !*features) 236 return; 237 } 238 printf("zmodload "); 239 if (flags & PRINTMOD_AUTO) { 240 fputs("-Fa ", stdout); 241 } else if (features) 242 fputs("-F ", stdout); 243 if(modname[0] == '-') 244 fputs("-- ", stdout); 245 quotedzputs(modname, stdout); 246 if (flags & PRINTMOD_AUTO) { 247 LinkNode an; 248 for (an = firstnode(m->autoloads); an; incnode(an)) { 249 putchar(' '); 250 quotedzputs((char *)getdata(an), stdout); 251 } 252 } else if (features) { 253 const char *f; 254 while ((f = *features++)) { 255 int on = *enables++; 256 if (flags & PRINTMOD_LISTALL) 257 printf(" %s", on ? "+" : "-"); 258 else if (!on) 259 continue; 260 else 261 putchar(' '); 262 quotedzputs(f, stdout); 263 } 264 } 265 } else /* -l */ 266 nicezputs(modname, stdout); 267 } else 268 return; 269 putchar('\n'); 270} 271 272/**/ 273HashTable 274newmoduletable(int size, char const *name) 275{ 276 HashTable ht; 277 ht = newhashtable(size, name, NULL); 278 279 ht->hash = hasher; 280 ht->emptytable = emptyhashtable; 281 ht->filltable = NULL; 282 ht->cmpnodes = strcmp; 283 ht->addnode = addhashnode; 284 /* DISABLED is not supported */ 285 ht->getnode = gethashnode2; 286 ht->getnode2 = gethashnode2; 287 ht->removenode = removehashnode; 288 ht->disablenode = NULL; 289 ht->enablenode = NULL; 290 ht->freenode = freemodulenode; 291 ht->printnode = printmodulenode; 292 293 return ht; 294} 295 296/************************************************************************ 297 * zsh/main standard module functions 298 ************************************************************************/ 299 300/* The `zsh/main' module contains all the base code that can't actually be * 301 * built as a separate module. It is initialised by main(), so there's * 302 * nothing for the boot function to do. */ 303 304/**/ 305int 306setup_(UNUSED(Module m)) 307{ 308 return 0; 309} 310 311/**/ 312int 313features_(UNUSED(Module m), UNUSED(char ***features)) 314{ 315 /* 316 * There are lots and lots of features, but they're not 317 * handled here. 318 */ 319 return 1; 320} 321 322/**/ 323int 324enables_(UNUSED(Module m), UNUSED(int **enables)) 325{ 326 return 1; 327} 328 329/**/ 330int 331boot_(UNUSED(Module m)) 332{ 333 return 0; 334} 335 336/**/ 337int 338cleanup_(UNUSED(Module m)) 339{ 340 return 0; 341} 342 343/**/ 344int 345finish_(UNUSED(Module m)) 346{ 347 return 0; 348} 349 350 351/************************************************************************ 352 * Module utility functions 353 ************************************************************************/ 354 355/* This registers a builtin module. */ 356 357/**/ 358void 359register_module(char *n, Module_void_func setup, 360 Module_features_func features, 361 Module_enables_func enables, 362 Module_void_func boot, 363 Module_void_func cleanup, 364 Module_void_func finish) 365{ 366 Linkedmod m; 367 368 m = (Linkedmod) zalloc(sizeof(*m)); 369 370 m->name = ztrdup(n); 371 m->setup = setup; 372 m->features = features; 373 m->enables = enables; 374 m->boot = boot; 375 m->cleanup = cleanup; 376 m->finish = finish; 377 378 zaddlinknode(linkedmodules, m); 379} 380 381/* Check if a module is linked in. */ 382 383/**/ 384Linkedmod 385module_linked(char const *name) 386{ 387 LinkNode node; 388 389 for (node = firstnode(linkedmodules); node; incnode(node)) 390 if (!strcmp(((Linkedmod) getdata(node))->name, name)) 391 return (Linkedmod) getdata(node); 392 393 return NULL; 394} 395 396 397/************************************************************************ 398 * Support for the various feature types. 399 * First, builtins. 400 ************************************************************************/ 401 402/* addbuiltin() can be used to add a new builtin. It returns zero on * 403 * success, 1 on failure. The only possible type of failure is that * 404 * a builtin with the specified name already exists. An autoloaded * 405 * builtin can be replaced using this function. */ 406 407/**/ 408static int 409addbuiltin(Builtin b) 410{ 411 Builtin bn = (Builtin) builtintab->getnode2(builtintab, b->node.nam); 412 if (bn && (bn->node.flags & BINF_ADDED)) 413 return 1; 414 if (bn) 415 builtintab->freenode(builtintab->removenode(builtintab, b->node.nam)); 416 builtintab->addnode(builtintab, b->node.nam, b); 417 return 0; 418} 419 420/* Define an autoloadable builtin. It returns 0 on success, or 1 on * 421 * failure. The only possible cause of failure is that a builtin * 422 * with the specified name already exists. */ 423 424/**/ 425static int 426add_autobin(const char *module, const char *bnam, int flags) 427{ 428 Builtin bn; 429 int ret; 430 431 bn = zshcalloc(sizeof(*bn)); 432 bn->node.nam = ztrdup(bnam); 433 bn->optstr = ztrdup(module); 434 if (flags & FEAT_AUTOALL) 435 bn->node.flags |= BINF_AUTOALL; 436 if ((ret = addbuiltin(bn))) { 437 builtintab->freenode(&bn->node); 438 if (!(flags & FEAT_IGNORE)) 439 return 1; 440 } 441 return 0; 442} 443 444/* Remove the builtin added previously by addbuiltin(). Returns * 445 * zero on succes and -1 if there is no builtin with that name. */ 446 447/**/ 448int 449deletebuiltin(const char *nam) 450{ 451 Builtin bn; 452 453 bn = (Builtin) builtintab->removenode(builtintab, nam); 454 if (!bn) 455 return -1; 456 builtintab->freenode(&bn->node); 457 return 0; 458} 459 460/* Remove an autoloaded added by add_autobin */ 461 462/**/ 463static int 464del_autobin(UNUSED(const char *module), const char *bnam, int flags) 465{ 466 Builtin bn = (Builtin) builtintab->getnode2(builtintab, bnam); 467 if (!bn) { 468 if(!(flags & FEAT_IGNORE)) 469 return 2; 470 } else if (bn->node.flags & BINF_ADDED) { 471 if (!(flags & FEAT_IGNORE)) 472 return 3; 473 } else 474 deletebuiltin(bnam); 475 476 return 0; 477} 478 479/* 480 * Manipulate a set of builtins. This should be called 481 * via setfeatureenables() (or, usually, via the next level up, 482 * handlefeatures()). 483 * 484 * "nam" is the name of the calling code builtin, probably "zmodload". 485 * 486 * "binl" is the builtin table containing an array of "size" builtins. 487 * 488 * "e" is either NULL, in which case all builtins in the 489 * table are removed, or else an array corresponding to "binl" 490 * with a 1 for builtins that are to be added and a 0 for builtins 491 * that are to be removed. Any builtin already in the appropriate 492 * state is left alone. 493 * 494 * Returns 1 on any error, 0 for success. The recommended way 495 * of handling errors is to compare the enables passed down 496 * with the set retrieved after the error to find what failed. 497 */ 498 499/**/ 500static int 501setbuiltins(char const *nam, Builtin binl, int size, int *e) 502{ 503 int ret = 0, n; 504 505 for(n = 0; n < size; n++) { 506 Builtin b = &binl[n]; 507 if (e && *e++) { 508 if (b->node.flags & BINF_ADDED) 509 continue; 510 if (addbuiltin(b)) { 511 zwarnnam(nam, 512 "name clash when adding builtin `%s'", b->node.nam); 513 ret = 1; 514 } else { 515 b->node.flags |= BINF_ADDED; 516 } 517 } else { 518 if (!(b->node.flags & BINF_ADDED)) 519 continue; 520 if (deletebuiltin(b->node.nam)) { 521 zwarnnam(nam, "builtin `%s' already deleted", b->node.nam); 522 ret = 1; 523 } else { 524 b->node.flags &= ~BINF_ADDED; 525 } 526 } 527 } 528 return ret; 529} 530 531/* 532 * Add multiple builtins. binl points to a table of `size' builtin 533 * structures. Those for which (.flags & BINF_ADDED) is false are to be 534 * added; that flag is set if they succeed. 535 * 536 * If any fail, an error message is printed, using nam as the leading name. 537 * Returns 0 on success, 1 for any failure. 538 * 539 * This should not be used from a module; instead, use handlefeatures(). 540 */ 541 542/**/ 543mod_export int 544addbuiltins(char const *nam, Builtin binl, int size) 545{ 546 int ret = 0, n; 547 548 for(n = 0; n < size; n++) { 549 Builtin b = &binl[n]; 550 if(b->node.flags & BINF_ADDED) 551 continue; 552 if(addbuiltin(b)) { 553 zwarnnam(nam, "name clash when adding builtin `%s'", b->node.nam); 554 ret = 1; 555 } else { 556 b->node.flags |= BINF_ADDED; 557 } 558 } 559 return ret; 560} 561 562 563/************************************************************************ 564 * Function wrappers. 565 ************************************************************************/ 566 567/* The list of function wrappers defined. */ 568 569/**/ 570FuncWrap wrappers; 571 572/* This adds a definition for a wrapper. Return value is one in case of * 573 * error and zero if all went fine. */ 574 575/**/ 576mod_export int 577addwrapper(Module m, FuncWrap w) 578{ 579 FuncWrap p, q; 580 581 /* 582 * We can't add a wrapper to an alias, since it's supposed 583 * to behave identically to the resolved module. This shouldn't 584 * happen since we usually add wrappers when a real module is 585 * loaded. 586 */ 587 if (m->node.flags & MOD_ALIAS) 588 return 1; 589 590 if (w->flags & WRAPF_ADDED) 591 return 1; 592 for (p = wrappers, q = NULL; p; q = p, p = p->next); 593 if (q) 594 q->next = w; 595 else 596 wrappers = w; 597 w->next = NULL; 598 w->flags |= WRAPF_ADDED; 599 w->module = m; 600 601 return 0; 602} 603 604/* This removes the given wrapper definition from the list. Returned is * 605 * one in case of error and zero otherwise. */ 606 607/**/ 608mod_export int 609deletewrapper(Module m, FuncWrap w) 610{ 611 FuncWrap p, q; 612 613 if (m->node.flags & MOD_ALIAS) 614 return 1; 615 616 if (w->flags & WRAPF_ADDED) { 617 for (p = wrappers, q = NULL; p && p != w; q = p, p = p->next); 618 619 if (p) { 620 if (q) 621 q->next = p->next; 622 else 623 wrappers = p->next; 624 p->flags &= ~WRAPF_ADDED; 625 626 return 0; 627 } 628 } 629 return 1; 630} 631 632 633/************************************************************************ 634 * Conditions. 635 ************************************************************************/ 636 637/* The list of module-defined conditions. */ 638 639/**/ 640mod_export Conddef condtab; 641 642/* This gets a condition definition with the given name. The first * 643 * argument says if we have to look for an infix condition. The last * 644 * argument is non-zero if we should autoload modules if needed. */ 645 646/**/ 647Conddef 648getconddef(int inf, const char *name, int autol) 649{ 650 Conddef p; 651 int f = 1; 652 653 do { 654 for (p = condtab; p; p = p->next) { 655 if ((!!inf == !!(p->flags & CONDF_INFIX)) && 656 !strcmp(name, p->name)) 657 break; 658 } 659 if (autol && p && p->module) { 660 /* 661 * This is a definition for an autoloaded condition; load the 662 * module if we haven't tried that already. 663 */ 664 if (f) { 665 (void)ensurefeature(p->module, 666 (p->flags & CONDF_INFIX) ? "C:" : "c:", 667 (p->flags & CONDF_AUTOALL) ? NULL : name); 668 f = 0; 669 p = NULL; 670 } else { 671 deleteconddef(p); 672 return NULL; 673 } 674 } else 675 break; 676 } while (!p); 677 return p; 678} 679 680/* 681 * This adds the given condition definition. The return value is zero on * 682 * success and 1 on failure. If there is a matching definition for an * 683 * autoloaded condition, it is removed. 684 * 685 * This is used for adding both an autoload definition or 686 * a real condition. In the latter case the caller is responsible 687 * for setting the CONDF_ADDED flag. 688 */ 689 690/**/ 691static int 692addconddef(Conddef c) 693{ 694 Conddef p = getconddef((c->flags & CONDF_INFIX), c->name, 0); 695 696 if (p) { 697 if (!p->module || (p->flags & CONDF_ADDED)) 698 return 1; 699 /* There is an autoload definition. */ 700 701 deleteconddef(p); 702 } 703 c->next = condtab; 704 condtab = c; 705 return 0; 706} 707 708/* This removes the given condition definition from the list(s). If this * 709 * is a definition for a autoloaded condition, the memory is freed. */ 710 711/**/ 712int 713deleteconddef(Conddef c) 714{ 715 Conddef p, q; 716 717 for (p = condtab, q = NULL; p && p != c; q = p, p = p->next); 718 719 if (p) { 720 if (q) 721 q->next = p->next; 722 else 723 condtab = p->next; 724 725 if (p->module) { 726 /* autoloaded, free it */ 727 zsfree(p->name); 728 zsfree(p->module); 729 zfree(p, sizeof(*p)); 730 } 731 return 0; 732 } 733 return -1; 734} 735 736/* 737 * Add or remove sets of conditions. The interface is 738 * identical to setbuiltins(). 739 */ 740 741/**/ 742static int 743setconddefs(char const *nam, Conddef c, int size, int *e) 744{ 745 int ret = 0; 746 747 while (size--) { 748 if (e && *e++) { 749 if (c->flags & CONDF_ADDED) { 750 c++; 751 continue; 752 } 753 if (addconddef(c)) { 754 zwarnnam(nam, "name clash when adding condition `%s'", 755 c->name); 756 ret = 1; 757 } else { 758 c->flags |= CONDF_ADDED; 759 } 760 } else { 761 if (!(c->flags & CONDF_ADDED)) { 762 c++; 763 continue; 764 } 765 if (deleteconddef(c)) { 766 zwarnnam(nam, "condition `%s' already deleted", c->name); 767 ret = 1; 768 } else { 769 c->flags &= ~CONDF_ADDED; 770 } 771 } 772 c++; 773 } 774 return ret; 775} 776 777/* This adds a definition for autoloading a module for a condition. */ 778 779/**/ 780static int 781add_autocond(const char *module, const char *cnam, int flags) 782{ 783 Conddef c; 784 785 c = (Conddef) zalloc(sizeof(*c)); 786 787 c->name = ztrdup(cnam); 788 c->flags = ((flags & FEAT_INFIX) ? CONDF_INFIX : 0); 789 if (flags & FEAT_AUTOALL) 790 c->flags |= CONDF_AUTOALL; 791 c->module = ztrdup(module); 792 793 if (addconddef(c)) { 794 zsfree(c->name); 795 zsfree(c->module); 796 zfree(c, sizeof(*c)); 797 798 if (!(flags & FEAT_IGNORE)) 799 return 1; 800 } 801 return 0; 802} 803 804/* Remove a condition added with add_autocond */ 805 806/**/ 807static int 808del_autocond(UNUSED(const char *modnam), const char *cnam, int flags) 809{ 810 Conddef cd = getconddef((flags & FEAT_INFIX) ? 1 : 0, cnam, 0); 811 812 if (!cd) { 813 if (!(flags & FEAT_IGNORE)) { 814 return 2; 815 } 816 } else if (cd->flags & CONDF_ADDED) { 817 if (!(flags & FEAT_IGNORE)) 818 return 3; 819 } else 820 deleteconddef(cd); 821 822 return 0; 823} 824 825/************************************************************************ 826 * Hook functions. 827 ************************************************************************/ 828 829/* This list of hook functions defined. */ 830 831/**/ 832Hookdef hooktab; 833 834/* Find a hook definition given the name. */ 835 836/**/ 837Hookdef 838gethookdef(char *n) 839{ 840 Hookdef p; 841 842 for (p = hooktab; p; p = p->next) 843 if (!strcmp(n, p->name)) 844 return p; 845 return NULL; 846} 847 848/* This adds the given hook definition. The return value is zero on * 849 * success and 1 on failure. */ 850 851/**/ 852int 853addhookdef(Hookdef h) 854{ 855 if (gethookdef(h->name)) 856 return 1; 857 858 h->next = hooktab; 859 hooktab = h; 860 h->funcs = znewlinklist(); 861 862 return 0; 863} 864 865/* 866 * This adds multiple hook definitions. This is like addbuiltins(). 867 * This allows a NULL module because we call it from init.c. 868 */ 869 870/**/ 871mod_export int 872addhookdefs(Module m, Hookdef h, int size) 873{ 874 int ret = 0; 875 876 while (size--) { 877 if (addhookdef(h)) { 878 zwarnnam(m ? m->node.nam : NULL, 879 "name clash when adding hook `%s'", h->name); 880 ret = 1; 881 } 882 h++; 883 } 884 return ret; 885} 886 887/* Delete hook definitions. */ 888 889/**/ 890int 891deletehookdef(Hookdef h) 892{ 893 Hookdef p, q; 894 895 for (p = hooktab, q = NULL; p && p != h; q = p, p = p->next); 896 897 if (!p) 898 return 1; 899 900 if (q) 901 q->next = p->next; 902 else 903 hooktab = p->next; 904 freelinklist(p->funcs, NULL); 905 return 0; 906} 907 908/* Remove multiple hook definitions. */ 909 910/**/ 911mod_export int 912deletehookdefs(UNUSED(Module m), Hookdef h, int size) 913{ 914 int ret = 0; 915 916 while (size--) { 917 if (deletehookdef(h)) 918 ret = 1; 919 h++; 920 } 921 return ret; 922} 923 924/* Add a function to a hook. */ 925 926/**/ 927int 928addhookdeffunc(Hookdef h, Hookfn f) 929{ 930 zaddlinknode(h->funcs, (void *) f); 931 932 return 0; 933} 934 935/**/ 936mod_export int 937addhookfunc(char *n, Hookfn f) 938{ 939 Hookdef h = gethookdef(n); 940 941 if (h) 942 return addhookdeffunc(h, f); 943 return 1; 944} 945 946/* Delete a function from a hook. */ 947 948/**/ 949int 950deletehookdeffunc(Hookdef h, Hookfn f) 951{ 952 LinkNode p; 953 954 for (p = firstnode(h->funcs); p; incnode(p)) 955 if (f == (Hookfn) getdata(p)) { 956 remnode(h->funcs, p); 957 return 0; 958 } 959 return 1; 960} 961 962/* Delete a hook. */ 963 964/**/ 965mod_export int 966deletehookfunc(char *n, Hookfn f) 967{ 968 Hookdef h = gethookdef(n); 969 970 if (h) 971 return deletehookdeffunc(h, f); 972 return 1; 973} 974 975/* Run the function(s) for a hook. */ 976 977/**/ 978mod_export int 979runhookdef(Hookdef h, void *d) 980{ 981 if (empty(h->funcs)) { 982 if (h->def) 983 return h->def(h, d); 984 return 0; 985 } else if (h->flags & HOOKF_ALL) { 986 LinkNode p; 987 int r; 988 989 for (p = firstnode(h->funcs); p; incnode(p)) 990 if ((r = ((Hookfn) getdata(p))(h, d))) 991 return r; 992 if (h->def) 993 return h->def(h, d); 994 return 0; 995 } else 996 return ((Hookfn) getdata(lastnode(h->funcs)))(h, d); 997} 998 999 1000 1001/************************************************************************ 1002 * Shell parameters. 1003 ************************************************************************/ 1004 1005/* 1006 * Check that it's possible to add a parameter. This 1007 * requires that either there's no parameter already present, 1008 * or it's a global parameter marked for autoloading. 1009 * 1010 * The special status 2 is to indicate it didn't work but 1011 * -i was in use so we didn't print a warning. 1012 */ 1013 1014static int 1015checkaddparam(const char *nam, int opt_i) 1016{ 1017 Param pm; 1018 1019 if (!(pm = (Param) gethashnode2(paramtab, nam))) 1020 return 0; 1021 1022 if (pm->level || !(pm->node.flags & PM_AUTOLOAD)) { 1023 /* 1024 * -i suppresses "it's already that way" warnings, 1025 * but not "this can't possibly work" warnings, so we print 1026 * the message anyway if there's a local parameter blocking 1027 * the parameter we want to add, not if there's a 1028 * non-autoloadable parameter already there. This 1029 * is consistent with the way add_auto* functions work. 1030 */ 1031 if (!opt_i || !pm->level) { 1032 zwarn("Can't add module parameter `%s': %s", 1033 nam, pm->level ? 1034 "local parameter exists" : 1035 "parameter already exists"); 1036 return 1; 1037 } 1038 return 2; 1039 } 1040 1041 unsetparam_pm(pm, 0, 1); 1042 return 0; 1043} 1044 1045/* This adds the given parameter definition. The return value is zero on * 1046 * success and 1 on failure. */ 1047 1048/**/ 1049int 1050addparamdef(Paramdef d) 1051{ 1052 Param pm; 1053 1054 if (checkaddparam(d->name, 0)) 1055 return 1; 1056 1057 if (d->getnfn) { 1058 if (!(pm = createspecialhash(d->name, d->getnfn, 1059 d->scantfn, d->flags))) 1060 return 1; 1061 } 1062 else if (!(pm = createparam(d->name, d->flags)) && 1063 !(pm = (Param) paramtab->getnode(paramtab, d->name))) 1064 return 1; 1065 1066 d->pm = pm; 1067 pm->level = 0; 1068 if (d->var) 1069 pm->u.data = d->var; 1070 if (d->var || d->gsu) { 1071 /* 1072 * If no get/set/unset class, use the appropriate 1073 * variable type, else use the one supplied. 1074 */ 1075 switch (PM_TYPE(pm->node.flags)) { 1076 case PM_SCALAR: 1077 pm->gsu.s = d->gsu ? (GsuScalar)d->gsu : &varscalar_gsu; 1078 break; 1079 1080 case PM_INTEGER: 1081 pm->gsu.i = d->gsu ? (GsuInteger)d->gsu : &varinteger_gsu; 1082 break; 1083 1084 case PM_FFLOAT: 1085 case PM_EFLOAT: 1086 pm->gsu.f = d->gsu; 1087 break; 1088 1089 case PM_ARRAY: 1090 pm->gsu.a = d->gsu ? (GsuArray)d->gsu : &vararray_gsu; 1091 break; 1092 1093 case PM_HASHED: 1094 /* hashes may behave like standard hashes */ 1095 if (d->gsu) 1096 pm->gsu.h = (GsuHash)d->gsu; 1097 break; 1098 1099 default: 1100 unsetparam_pm(pm, 0, 1); 1101 return 1; 1102 } 1103 } 1104 1105 return 0; 1106} 1107 1108/* Delete parameters defined. No error checking yet. */ 1109 1110/**/ 1111int 1112deleteparamdef(Paramdef d) 1113{ 1114 Param pm = (Param) paramtab->getnode(paramtab, d->name); 1115 1116 if (!pm) 1117 return 1; 1118 if (pm != d->pm) { 1119 /* 1120 * See if the parameter has been hidden. If so, 1121 * bring it to the front to unset it. 1122 */ 1123 Param prevpm, searchpm; 1124 for (prevpm = pm, searchpm = pm->old; 1125 searchpm; 1126 prevpm = searchpm, searchpm = searchpm->old) 1127 if (searchpm == d->pm) 1128 break; 1129 1130 if (!searchpm) 1131 return 1; 1132 1133 paramtab->removenode(paramtab, pm->node.nam); 1134 prevpm->old = searchpm->old; 1135 searchpm->old = pm; 1136 paramtab->addnode(paramtab, searchpm->node.nam, searchpm); 1137 1138 pm = searchpm; 1139 } 1140 pm->node.flags = (pm->node.flags & ~PM_READONLY) | PM_REMOVABLE; 1141 unsetparam_pm(pm, 0, 1); 1142 d->pm = NULL; 1143 return 0; 1144} 1145 1146/* 1147 * Add or remove sets of parameters. The interface is 1148 * identical to setbuiltins(). 1149 */ 1150 1151/**/ 1152static int 1153setparamdefs(char const *nam, Paramdef d, int size, int *e) 1154{ 1155 int ret = 0; 1156 1157 while (size--) { 1158 if (e && *e++) { 1159 if (d->pm) { 1160 d++; 1161 continue; 1162 } 1163 if (addparamdef(d)) { 1164 zwarnnam(nam, "error when adding parameter `%s'", d->name); 1165 ret = 1; 1166 } 1167 } else { 1168 if (!d->pm) { 1169 d++; 1170 continue; 1171 } 1172 if (deleteparamdef(d)) { 1173 zwarnnam(nam, "parameter `%s' already deleted", d->name); 1174 ret = 1; 1175 } 1176 } 1177 d++; 1178 } 1179 return ret; 1180} 1181 1182/* This adds a definition for autoloading a module for a parameter. */ 1183 1184/**/ 1185static int 1186add_autoparam(const char *module, const char *pnam, int flags) 1187{ 1188 Param pm; 1189 int ret; 1190 1191 queue_signals(); 1192 if ((ret = checkaddparam(pnam, (flags & FEAT_IGNORE)))) { 1193 unqueue_signals(); 1194 /* 1195 * checkaddparam() has already printed a message if one was 1196 * needed. If it wasn't owing to the presence of -i, ret is 2; 1197 * for consistency with other add_auto* functions we return 1198 * status 0 to indicate there's already such a parameter and 1199 * we've been told not to worry if so. 1200 */ 1201 return ret == 2 ? 0 : -1; 1202 } 1203 1204 pm = setsparam(dupstring(pnam), ztrdup(module)); 1205 1206 pm->node.flags |= PM_AUTOLOAD; 1207 if (flags & FEAT_AUTOALL) 1208 pm->node.flags |= PM_AUTOALL; 1209 unqueue_signals(); 1210 1211 return 0; 1212} 1213 1214/* Remove a parameter added with add_autoparam() */ 1215 1216/**/ 1217static int 1218del_autoparam(UNUSED(const char *modnam), const char *pnam, int flags) 1219{ 1220 Param pm = (Param) gethashnode2(paramtab, pnam); 1221 1222 if (!pm) { 1223 if (!(flags & FEAT_IGNORE)) 1224 return 2; 1225 } else if (!(pm->node.flags & PM_AUTOLOAD)) { 1226 if (!(flags & FEAT_IGNORE)) 1227 return 3; 1228 } else 1229 unsetparam_pm(pm, 0, 1); 1230 1231 return 0; 1232} 1233 1234/************************************************************************ 1235 * Math functions. 1236 ************************************************************************/ 1237 1238/* List of math functions. */ 1239 1240/**/ 1241MathFunc mathfuncs; 1242 1243/* 1244 * Remove a single math function form the list (utility function). 1245 * This does not delete a module math function, that's deletemathfunc(). 1246 */ 1247 1248/**/ 1249void 1250removemathfunc(MathFunc previous, MathFunc current) 1251{ 1252 if (previous) 1253 previous->next = current->next; 1254 else 1255 mathfuncs = current->next; 1256 1257 zsfree(current->name); 1258 zsfree(current->module); 1259 zfree(current, sizeof(*current)); 1260} 1261 1262/* Find a math function in the list, handling autoload if necessary. */ 1263 1264/**/ 1265MathFunc 1266getmathfunc(const char *name, int autol) 1267{ 1268 MathFunc p, q = NULL; 1269 1270 for (p = mathfuncs; p; q = p, p = p->next) 1271 if (!strcmp(name, p->name)) { 1272 if (autol && p->module && !(p->flags & MFF_USERFUNC)) { 1273 char *n = dupstring(p->module); 1274 int flags = p->flags; 1275 1276 removemathfunc(q, p); 1277 1278 (void)ensurefeature(n, "f:", (flags & MFF_AUTOALL) ? NULL : 1279 name); 1280 1281 p = getmathfunc(name, 0); 1282 if (!p) { 1283 zerr("autoloading module %s failed to define math function: %s", n, name); 1284 } 1285 } 1286 return p; 1287 } 1288 1289 return NULL; 1290} 1291 1292/* Add a single math function */ 1293 1294/**/ 1295static int 1296addmathfunc(MathFunc f) 1297{ 1298 MathFunc p, q = NULL; 1299 1300 if (f->flags & MFF_ADDED) 1301 return 1; 1302 1303 for (p = mathfuncs; p; q = p, p = p->next) 1304 if (!strcmp(f->name, p->name)) { 1305 if (p->module && !(p->flags & MFF_USERFUNC)) { 1306 /* 1307 * Autoloadable, replace. 1308 */ 1309 removemathfunc(q, p); 1310 break; 1311 } 1312 return 1; 1313 } 1314 1315 f->next = mathfuncs; 1316 mathfuncs = f; 1317 1318 return 0; 1319} 1320 1321/* Delete a single math function */ 1322 1323/**/ 1324mod_export int 1325deletemathfunc(MathFunc f) 1326{ 1327 MathFunc p, q; 1328 1329 for (p = mathfuncs, q = NULL; p && p != f; q = p, p = p->next); 1330 1331 if (p) { 1332 if (q) 1333 q->next = f->next; 1334 else 1335 mathfuncs = f->next; 1336 1337 /* the following applies to both unloaded and user-defined functions */ 1338 if (f->module) { 1339 zsfree(f->name); 1340 zsfree(f->module); 1341 zfree(f, sizeof(*f)); 1342 } else 1343 f->flags &= ~MFF_ADDED; 1344 1345 return 0; 1346 } 1347 return -1; 1348} 1349 1350/* 1351 * Add or remove sets of math functions. The interface is 1352 * identical to setbuiltins(). 1353 */ 1354 1355/**/ 1356static int 1357setmathfuncs(char const *nam, MathFunc f, int size, int *e) 1358{ 1359 int ret = 0; 1360 1361 while (size--) { 1362 if (e && *e++) { 1363 if (f->flags & MFF_ADDED) { 1364 f++; 1365 continue; 1366 } 1367 if (addmathfunc(f)) { 1368 zwarnnam(nam, "name clash when adding math function `%s'", 1369 f->name); 1370 ret = 1; 1371 } else { 1372 f->flags |= MFF_ADDED; 1373 } 1374 } else { 1375 if (!(f->flags & MFF_ADDED)) { 1376 f++; 1377 continue; 1378 } 1379 if (deletemathfunc(f)) { 1380 zwarnnam(nam, "math function `%s' already deleted", f->name); 1381 ret = 1; 1382 } else { 1383 f->flags &= ~MFF_ADDED; 1384 } 1385 } 1386 f++; 1387 } 1388 return ret; 1389} 1390 1391/* Add an autoload definition for a math function. */ 1392 1393/**/ 1394static int 1395add_automathfunc(const char *module, const char *fnam, int flags) 1396{ 1397 MathFunc f; 1398 1399 f = (MathFunc) zalloc(sizeof(*f)); 1400 1401 f->name = ztrdup(fnam); 1402 f->module = ztrdup(module); 1403 f->flags = 0; 1404 1405 if (addmathfunc(f)) { 1406 zsfree(f->name); 1407 zsfree(f->module); 1408 zfree(f, sizeof(*f)); 1409 1410 if (!(flags & FEAT_IGNORE)) 1411 return 1; 1412 } 1413 1414 return 0; 1415} 1416 1417/* Remove a math function added with add_automathfunc() */ 1418 1419/**/ 1420static int 1421del_automathfunc(UNUSED(const char *modnam), const char *fnam, int flags) 1422{ 1423 MathFunc f = getmathfunc(fnam, 0); 1424 1425 if (!f) { 1426 if (!(flags & FEAT_IGNORE)) 1427 return 2; 1428 } else if (f->flags & MFF_ADDED) { 1429 if (!(flags & FEAT_IGNORE)) 1430 return 3; 1431 } else 1432 deletemathfunc(f); 1433 1434 return 0; 1435} 1436 1437/************************************************************************ 1438 * Now support for dynamical loading and the fallback functions 1439 * we use for loading if dynamical loading is not available. 1440 ************************************************************************/ 1441 1442/**/ 1443#ifdef DYNAMIC 1444 1445/**/ 1446#ifdef AIXDYNAMIC 1447 1448#include <sys/ldr.h> 1449 1450static char *dlerrstr[256]; 1451 1452static void * 1453load_and_bind(const char *fn) 1454{ 1455 void *ret = (void *) load((char *) fn, L_NOAUTODEFER, NULL); 1456 1457 if (ret) { 1458 Module m; 1459 int i, err = loadbind(0, (void *) addbuiltin, ret); 1460 for (i = 0; i < modulestab->hsize && !err; i++) { 1461 for (m = (Module)modulestab->nodes[i]; m && !err; 1462 m = (Module)m->node.next) { 1463 if (!(m->node.flags & MOD_ALIAS) && 1464 m->u.handle && !(m->node.flags & MOD_LINKED)) 1465 err |= loadbind(0, m->u.handle, ret); 1466 } 1467 } 1468 1469 if (err) { 1470 loadquery(L_GETMESSAGES, dlerrstr, sizeof(dlerrstr)); 1471 unload(ret); 1472 ret = NULL; 1473 } 1474 } else 1475 loadquery(L_GETMESSAGES, dlerrstr, sizeof(dlerrstr)); 1476 1477 return ret; 1478} 1479 1480#define dlopen(X,Y) load_and_bind(X) 1481#define dlclose(X) unload(X) 1482#define dlerror() (dlerrstr[0]) 1483#ifndef HAVE_DLERROR 1484# define HAVE_DLERROR 1 1485#endif 1486 1487/**/ 1488#else 1489 1490#ifdef HAVE_DLFCN_H 1491# if defined(HAVE_DL_H) && defined(HPUX10DYNAMIC) 1492# include <dl.h> 1493# else 1494# include <dlfcn.h> 1495# endif 1496#else 1497# ifdef HAVE_DL_H 1498# include <dl.h> 1499# define RTLD_LAZY BIND_DEFERRED 1500# define RTLD_GLOBAL DYNAMIC_PATH 1501# else 1502# include <sys/types.h> 1503# include <nlist.h> 1504# include <link.h> 1505# endif 1506#endif 1507 1508/**/ 1509#ifdef HPUX10DYNAMIC 1510# define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0) 1511# define dlclose(handle) shl_unload((shl_t)(handle)) 1512 1513static 1514void * 1515hpux_dlsym(void *handle, char *name) 1516{ 1517 void *sym_addr; 1518 if (!shl_findsym((shl_t *)&handle, name, TYPE_UNDEFINED, &sym_addr)) 1519 return sym_addr; 1520 return NULL; 1521} 1522 1523# define dlsym(handle,name) hpux_dlsym(handle,name) 1524# ifdef HAVE_DLERROR /* paranoia */ 1525# undef HAVE_DLERROR 1526# endif 1527#else 1528# ifndef HAVE_DLCLOSE 1529# define dlclose(X) ((X), 0) 1530# endif 1531/**/ 1532#endif 1533 1534#ifdef DLSYM_NEEDS_UNDERSCORE 1535# define STR_SETUP "_setup_" 1536# define STR_FEATURES "_features_" 1537# define STR_ENABLES "_enables_" 1538# define STR_BOOT "_boot_" 1539# define STR_CLEANUP "_cleanup_" 1540# define STR_FINISH "_finish_" 1541#else /* !DLSYM_NEEDS_UNDERSCORE */ 1542# define STR_SETUP "setup_" 1543# define STR_FEATURES "features_" 1544# define STR_ENABLES "enables_" 1545# define STR_BOOT "boot_" 1546# define STR_CLEANUP "cleanup_" 1547# define STR_FINISH "finish_" 1548#endif /* !DLSYM_NEEDS_UNDERSCORE */ 1549 1550/**/ 1551#endif /* !AIXDYNAMIC */ 1552 1553#ifndef RTLD_LAZY 1554# define RTLD_LAZY 1 1555#endif 1556#ifndef RTLD_GLOBAL 1557# define RTLD_GLOBAL 0 1558#endif 1559 1560/* 1561 * Attempt to load a module. This is the lowest level of 1562 * zsh function for dynamical modules. Returns the handle 1563 * from the dynamic loader. 1564 */ 1565 1566/**/ 1567static void * 1568try_load_module(char const *name) 1569{ 1570 char buf[PATH_MAX + 1]; 1571 char **pp; 1572 void *ret = NULL; 1573 int l; 1574 1575 l = 1 + strlen(name) + 1 + strlen(DL_EXT); 1576 for (pp = module_path; !ret && *pp; pp++) { 1577 if (l + (**pp ? strlen(*pp) : 1) > PATH_MAX) 1578 continue; 1579 sprintf(buf, "%s/%s.%s", **pp ? *pp : ".", name, DL_EXT); 1580 ret = dlopen(unmeta(buf), RTLD_LAZY | RTLD_GLOBAL); 1581 } 1582 1583 return ret; 1584} 1585 1586/* 1587 * Load a module, with option to complain or not. 1588 * Returns the handle from the dynamic loader. 1589 */ 1590 1591/**/ 1592static void * 1593do_load_module(char const *name, int silent) 1594{ 1595 void *ret; 1596 1597 ret = try_load_module(name); 1598 if (!ret && !silent) { 1599#ifdef HAVE_DLERROR 1600 zwarn("failed to load module `%s': %s", name, 1601 metafy(dlerror(), -1, META_USEHEAP)); 1602#else 1603 zwarn("failed to load module: %s", name); 1604#endif 1605 } 1606 return ret; 1607} 1608 1609/**/ 1610#else /* !DYNAMIC */ 1611 1612/* 1613 * Dummy loader when no dynamic loading available; always fails. 1614 */ 1615 1616/**/ 1617static void * 1618do_load_module(char const *name, int silent) 1619{ 1620 if (!silent) 1621 zwarn("failed to load module: %s", name); 1622 1623 return NULL; 1624} 1625 1626/**/ 1627#endif /* !DYNAMIC */ 1628 1629/* 1630 * Find a module in the list. 1631 * flags is a set of bits defined in the enum above. 1632 * If namep is set, this is set to point to the last alias value resolved, 1633 * even if that module was not loaded. or the module name if no aliases. 1634 * Hence this is always the physical module to load in a chain of aliases. 1635 * Return NULL if the module named is not stored as a structure, or if we were 1636 * resolving aliases and the final module named is not stored as a 1637 * structure. 1638 */ 1639/**/ 1640static Module 1641find_module(const char *name, int flags, const char **namep) 1642{ 1643 Module m; 1644 1645 m = (Module)modulestab->getnode2(modulestab, name); 1646 if (m) { 1647 if ((flags & FINDMOD_ALIASP) && (m->node.flags & MOD_ALIAS)) { 1648 if (namep) 1649 *namep = m->u.alias; 1650 return find_module(m->u.alias, flags, namep); 1651 } 1652 if (namep) 1653 *namep = m->node.nam; 1654 return m; 1655 } 1656 if (!(flags & FINDMOD_CREATE)) 1657 return NULL; 1658 m = zshcalloc(sizeof(*m)); 1659 modulestab->addnode(modulestab, ztrdup(name), m); 1660 return m; 1661} 1662 1663/* 1664 * Unlink and free a module node from the linked list. 1665 */ 1666 1667/**/ 1668static void 1669delete_module(Module m) 1670{ 1671 modulestab->removenode(modulestab, m->node.nam); 1672 1673 modulestab->freenode(&m->node); 1674} 1675 1676/* 1677 * Return 1 if a module is fully loaded else zero. 1678 * A linked module may be marked as unloaded even though 1679 * we can't fully unload it; this returns 0 to try to 1680 * make that state transparently like an unloaded module. 1681 */ 1682 1683/**/ 1684mod_export int 1685module_loaded(const char *name) 1686{ 1687 Module m; 1688 1689 return ((m = find_module(name, FINDMOD_ALIASP, NULL)) && 1690 m->u.handle && 1691 !(m->node.flags & MOD_UNLOAD)); 1692} 1693 1694/* 1695 * Setup and cleanup functions: we don't search for aliases here, 1696 * since they should have been resolved before we try to load or unload 1697 * the module. 1698 */ 1699 1700/**/ 1701#ifdef DYNAMIC 1702 1703/**/ 1704#ifdef AIXDYNAMIC 1705 1706/**/ 1707static int 1708dyn_setup_module(Module m) 1709{ 1710 return ((int (*)_((int,Module, void*))) m->u.handle)(0, m, NULL); 1711} 1712 1713/**/ 1714static int 1715dyn_features_module(Module m, char ***features) 1716{ 1717 return ((int (*)_((int,Module, void*))) m->u.handle)(4, m, features); 1718} 1719 1720/**/ 1721static int 1722dyn_enables_module(Module m, int **enables) 1723{ 1724 return ((int (*)_((int,Module, void*))) m->u.handle)(5, m, enables); 1725} 1726 1727/**/ 1728static int 1729dyn_boot_module(Module m) 1730{ 1731 return ((int (*)_((int,Module, void*))) m->u.handle)(1, m, NULL); 1732} 1733 1734/**/ 1735static int 1736dyn_cleanup_module(Module m) 1737{ 1738 return ((int (*)_((int,Module, void*))) m->u.handle)(2, m, NULL); 1739} 1740 1741/**/ 1742static int 1743dyn_finish_module(Module m) 1744{ 1745 return ((int (*)_((int,Module,void *))) m->u.handle)(3, m, NULL); 1746} 1747 1748/**/ 1749#else 1750 1751static Module_generic_func 1752module_func(Module m, char *name) 1753{ 1754#ifdef DYNAMIC_NAME_CLASH_OK 1755 return (Module_generic_func) dlsym(m->u.handle, name); 1756#else /* !DYNAMIC_NAME_CLASH_OK */ 1757 VARARR(char, buf, strlen(name) + strlen(m->node.nam)*2 + 1); 1758 char const *p; 1759 char *q; 1760 strcpy(buf, name); 1761 q = strchr(buf, 0); 1762 for(p = m->node.nam; *p; p++) { 1763 if(*p == '/') { 1764 *q++ = 'Q'; 1765 *q++ = 's'; 1766 } else if(*p == '_') { 1767 *q++ = 'Q'; 1768 *q++ = 'u'; 1769 } else if(*p == 'Q') { 1770 *q++ = 'Q'; 1771 *q++ = 'q'; 1772 } else 1773 *q++ = *p; 1774 } 1775 *q = 0; 1776 return (Module_generic_func) dlsym(m->u.handle, buf); 1777#endif /* !DYNAMIC_NAME_CLASH_OK */ 1778} 1779 1780/**/ 1781static int 1782dyn_setup_module(Module m) 1783{ 1784 Module_void_func fn = (Module_void_func)module_func(m, STR_SETUP); 1785 1786 if (fn) 1787 return fn(m); 1788 zwarnnam(m->node.nam, "no setup function"); 1789 return 1; 1790} 1791 1792/**/ 1793static int 1794dyn_features_module(Module m, char ***features) 1795{ 1796 Module_features_func fn = 1797 (Module_features_func)module_func(m, STR_FEATURES); 1798 1799 if (fn) 1800 return fn(m, features); 1801 /* not a user-visible error if no features function */ 1802 return 1; 1803} 1804 1805/**/ 1806static int 1807dyn_enables_module(Module m, int **enables) 1808{ 1809 Module_enables_func fn = (Module_enables_func)module_func(m, STR_ENABLES); 1810 1811 if (fn) 1812 return fn(m, enables); 1813 /* not a user-visible error if no enables function */ 1814 return 1; 1815} 1816 1817/**/ 1818static int 1819dyn_boot_module(Module m) 1820{ 1821 Module_void_func fn = (Module_void_func)module_func(m, STR_BOOT); 1822 1823 if(fn) 1824 return fn(m); 1825 zwarnnam(m->node.nam, "no boot function"); 1826 return 1; 1827} 1828 1829/**/ 1830static int 1831dyn_cleanup_module(Module m) 1832{ 1833 Module_void_func fn = (Module_void_func)module_func(m, STR_CLEANUP); 1834 1835 if(fn) 1836 return fn(m); 1837 zwarnnam(m->node.nam, "no cleanup function"); 1838 return 1; 1839} 1840 1841/* Note that this function does more than just calling finish_foo(), * 1842 * it really unloads the module. */ 1843 1844/**/ 1845static int 1846dyn_finish_module(Module m) 1847{ 1848 Module_void_func fn = (Module_void_func)module_func(m, STR_FINISH); 1849 int r; 1850 1851 if (fn) 1852 r = fn(m); 1853 else { 1854 zwarnnam(m->node.nam, "no finish function"); 1855 r = 1; 1856 } 1857 dlclose(m->u.handle); 1858 return r; 1859} 1860 1861/**/ 1862#endif /* !AIXDYNAMIC */ 1863 1864/**/ 1865static int 1866setup_module(Module m) 1867{ 1868 return ((m->node.flags & MOD_LINKED) ? 1869 (m->u.linked->setup)(m) : dyn_setup_module(m)); 1870} 1871 1872/**/ 1873static int 1874features_module(Module m, char ***features) 1875{ 1876 return ((m->node.flags & MOD_LINKED) ? 1877 (m->u.linked->features)(m, features) : 1878 dyn_features_module(m, features)); 1879} 1880 1881/**/ 1882static int 1883enables_module(Module m, int **enables) 1884{ 1885 return ((m->node.flags & MOD_LINKED) ? 1886 (m->u.linked->enables)(m, enables) : 1887 dyn_enables_module(m, enables)); 1888} 1889 1890/**/ 1891static int 1892boot_module(Module m) 1893{ 1894 return ((m->node.flags & MOD_LINKED) ? 1895 (m->u.linked->boot)(m) : dyn_boot_module(m)); 1896} 1897 1898/**/ 1899static int 1900cleanup_module(Module m) 1901{ 1902 return ((m->node.flags & MOD_LINKED) ? 1903 (m->u.linked->cleanup)(m) : dyn_cleanup_module(m)); 1904} 1905 1906/**/ 1907static int 1908finish_module(Module m) 1909{ 1910 return ((m->node.flags & MOD_LINKED) ? 1911 (m->u.linked->finish)(m) : dyn_finish_module(m)); 1912} 1913 1914/**/ 1915#else /* !DYNAMIC */ 1916 1917/**/ 1918static int 1919setup_module(Module m) 1920{ 1921 return ((m->node.flags & MOD_LINKED) ? (m->u.linked->setup)(m) : 1); 1922} 1923 1924/**/ 1925static int 1926features_module(Module m, char ***features) 1927{ 1928 return ((m->node.flags & MOD_LINKED) ? (m->u.linked->features)(m, features) 1929 : 1); 1930} 1931 1932/**/ 1933static int 1934enables_module(Module m, int **enables) 1935{ 1936 return ((m->node.flags & MOD_LINKED) ? (m->u.linked->enables)(m, enables) 1937 : 1); 1938} 1939 1940/**/ 1941static int 1942boot_module(Module m) 1943{ 1944 return ((m->node.flags & MOD_LINKED) ? (m->u.linked->boot)(m) : 1); 1945} 1946 1947/**/ 1948static int 1949cleanup_module(Module m) 1950{ 1951 return ((m->node.flags & MOD_LINKED) ? (m->u.linked->cleanup)(m) : 1); 1952} 1953 1954/**/ 1955static int 1956finish_module(Module m) 1957{ 1958 return ((m->node.flags & MOD_LINKED) ? (m->u.linked->finish)(m) : 1); 1959} 1960 1961/**/ 1962#endif /* !DYNAMIC */ 1963 1964 1965/************************************************************************ 1966 * Functions called when manipulating modules 1967 ************************************************************************/ 1968 1969/* 1970 * Set the features for the module, which must be loaded 1971 * by now (though may not be fully set up). 1972 * 1973 * Return 0 for success, 1 for failure, 2 if some features 1974 * couldn't be set by the module itself (non-existent features 1975 * are tested here and cause 1 to be returned). 1976 */ 1977 1978/**/ 1979static int 1980do_module_features(Module m, Feature_enables enablesarr, int flags) 1981{ 1982 char **features; 1983 int ret = 0; 1984 1985 if (features_module(m, &features) == 0) { 1986 /* 1987 * Features are supported. If we were passed 1988 * a NULL array, enable all features, else 1989 * enable only the features listed. 1990 * (This may in principle be an empty array, 1991 * although that's not very pointful.) 1992 */ 1993 int *enables = NULL; 1994 if (enables_module(m, &enables)) { 1995 /* If features are supported, enables should be, too */ 1996 if (!(flags & FEAT_IGNORE)) 1997 zwarn("error getting enabled features for module `%s'", 1998 m->node.nam); 1999 return 1; 2000 } 2001 2002 if ((flags & FEAT_CHECKAUTO) && m->autoloads) { 2003 /* 2004 * Check autoloads are available. Since these 2005 * have been requested at some other point, they 2006 * don't affect the return status unless something 2007 * in enablesstr doesn't work. 2008 */ 2009 LinkNode an, nextn; 2010 for (an = firstnode(m->autoloads); an; an = nextn) { 2011 char *al = (char *)getdata(an), **ptr; 2012 /* careful, we can delete the current node */ 2013 nextn = nextnode(an); 2014 for (ptr = features; *ptr; ptr++) 2015 if (!strcmp(al, *ptr)) 2016 break; 2017 if (!*ptr) { 2018 char *arg[2]; 2019 if (!(flags & FEAT_IGNORE)) 2020 zwarn( 2021 "module `%s' has no such feature: `%s': autoload cancelled", 2022 m->node.nam, al); 2023 /* 2024 * This shouldn't happen, so it's not worth optimising 2025 * the call to autofeatures... 2026 */ 2027 arg[0] = al = dupstring(al); 2028 arg[1] = NULL; 2029 (void)autofeatures(NULL, m->node.nam, arg, 0, 2030 FEAT_IGNORE|FEAT_REMOVE); 2031 /* 2032 * don't want to try to enable *that*... 2033 * expunge it from the enable string. 2034 */ 2035 if (enablesarr) { 2036 Feature_enables fep; 2037 for (fep = enablesarr; fep->str; fep++) { 2038 char *str = fep->str; 2039 if (*str == '+' || *str == '-') 2040 str++; 2041 if (fep->pat ? pattry(fep->pat, al) : 2042 !strcmp(al, str)) { 2043 /* can't enable it after all, so return 1 */ 2044 ret = 1; 2045 while (fep->str) { 2046 fep->str = fep[1].str; 2047 fep->pat = fep[1].pat; 2048 fep++; 2049 } 2050 if (!fep->pat) 2051 break; 2052 } 2053 } 2054 } 2055 } 2056 } 2057 } 2058 2059 if (enablesarr) { 2060 Feature_enables fep; 2061 for (fep = enablesarr; fep->str; fep++) { 2062 char **fp, *esp = fep->str; 2063 int on = 1, found = 0; 2064 if (*esp == '+') 2065 esp++; 2066 else if (*esp == '-') { 2067 on = 0; 2068 esp++; 2069 } 2070 for (fp = features; *fp; fp++) 2071 if (fep->pat ? pattry(fep->pat, *fp) : !strcmp(*fp, esp)) { 2072 enables[fp - features] = on; 2073 found++; 2074 if (!fep->pat) 2075 break; 2076 } 2077 if (!found) { 2078 if (!(flags & FEAT_IGNORE)) 2079 zwarn(fep->pat ? 2080 "module `%s' has no feature matching: `%s'" : 2081 "module `%s' has no such feature: `%s'", 2082 m->node.nam, esp); 2083 return 1; 2084 } 2085 } 2086 } else { 2087 /* 2088 * Enable all features. This is used when loading 2089 * without using zmodload -F. 2090 */ 2091 int n_features = arrlen(features); 2092 int *ep; 2093 for (ep = enables; n_features--; ep++) 2094 *ep = 1; 2095 } 2096 2097 if (enables_module(m, &enables)) 2098 return 2; 2099 } else if (enablesarr) { 2100 if (!(flags & FEAT_IGNORE)) 2101 zwarn("module `%s' does not support features", m->node.nam); 2102 return 1; 2103 } 2104 /* Else it doesn't support features but we don't care. */ 2105 2106 return ret; 2107} 2108 2109/* 2110 * Boot the module, including setting up features. 2111 * As we've only just loaded the module, we don't yet 2112 * know what features it supports, so we get them passed 2113 * as a string. 2114 * 2115 * Returns 0 if OK, 1 if completely failed, 2 if some features 2116 * couldn't be set up. 2117 */ 2118 2119/**/ 2120static int 2121do_boot_module(Module m, Feature_enables enablesarr, int silent) 2122{ 2123 int ret = do_module_features(m, enablesarr, 2124 silent ? FEAT_IGNORE|FEAT_CHECKAUTO : 2125 FEAT_CHECKAUTO); 2126 2127 if (ret == 1) 2128 return 1; 2129 2130 if (boot_module(m)) 2131 return 1; 2132 return ret; 2133} 2134 2135/* 2136 * Cleanup the module. 2137 */ 2138 2139/**/ 2140static int 2141do_cleanup_module(Module m) 2142{ 2143 return (m->node.flags & MOD_LINKED) ? 2144 (m->u.linked && m->u.linked->cleanup(m)) : 2145 (m->u.handle && cleanup_module(m)); 2146} 2147 2148/* 2149 * Test a module name contains only valid characters: those 2150 * allowed in a shell identifier plus slash. Return 1 if so. 2151 */ 2152 2153/**/ 2154static int 2155modname_ok(char const *p) 2156{ 2157 do { 2158 p = itype_end(p, IIDENT, 0); 2159 if (!*p) 2160 return 1; 2161 } while(*p++ == '/'); 2162 return 0; 2163} 2164 2165/* 2166 * High level function to load a module, encapsulating 2167 * all the handling of module functions. 2168 * 2169 * "*enablesstr" is NULL if the caller is not feature-aware; 2170 * then the module should turn on all features. If it 2171 * is not NULL it points to an array of features to be 2172 * turned on. This function is responsible for testing whether 2173 * the module supports those features. 2174 * 2175 * If "silent" is 1, don't issue warnings for errors. 2176 * 2177 * Now returns 0 for success (changed post-4.3.4), 2178 * 1 for complete failure, 2 if some features couldn't be set. 2179 */ 2180 2181/**/ 2182mod_export int 2183load_module(char const *name, Feature_enables enablesarr, int silent) 2184{ 2185 Module m; 2186 void *handle = NULL; 2187 Linkedmod linked; 2188 int set, bootret; 2189 2190 if (!modname_ok(name)) { 2191 if (!silent) 2192 zerr("invalid module name `%s'", name); 2193 return 1; 2194 } 2195 /* 2196 * The following function call may alter name to the final name in a 2197 * chain of aliases. This makes sure the actual module loaded 2198 * is the right one. 2199 */ 2200 queue_signals(); 2201 if (!(m = find_module(name, FINDMOD_ALIASP, &name))) { 2202 if (!(linked = module_linked(name)) && 2203 !(handle = do_load_module(name, silent))) { 2204 unqueue_signals(); 2205 return 1; 2206 } 2207 m = zshcalloc(sizeof(*m)); 2208 if (handle) { 2209 m->u.handle = handle; 2210 m->node.flags |= MOD_SETUP; 2211 } else { 2212 m->u.linked = linked; 2213 m->node.flags |= MOD_SETUP | MOD_LINKED; 2214 } 2215 modulestab->addnode(modulestab, ztrdup(name), m); 2216 2217 if ((set = setup_module(m)) || 2218 (bootret = do_boot_module(m, enablesarr, silent)) == 1) { 2219 if (!set) 2220 do_cleanup_module(m); 2221 finish_module(m); 2222 delete_module(m); 2223 unqueue_signals(); 2224 return 1; 2225 } 2226 m->node.flags |= MOD_INIT_S | MOD_INIT_B; 2227 m->node.flags &= ~MOD_SETUP; 2228 unqueue_signals(); 2229 return bootret; 2230 } 2231 if (m->node.flags & MOD_SETUP) { 2232 unqueue_signals(); 2233 return 0; 2234 } 2235 if (m->node.flags & MOD_UNLOAD) 2236 m->node.flags &= ~MOD_UNLOAD; 2237 else if ((m->node.flags & MOD_LINKED) ? m->u.linked : m->u.handle) { 2238 unqueue_signals(); 2239 return 0; 2240 } 2241 if (m->node.flags & MOD_BUSY) { 2242 zerr("circular dependencies for module ;%s", name); 2243 return 1; 2244 } 2245 m->node.flags |= MOD_BUSY; 2246 /* 2247 * TODO: shouldn't we unload the module if one of 2248 * its dependencies fails? 2249 */ 2250 if (m->deps) { 2251 LinkNode n; 2252 for (n = firstnode(m->deps); n; incnode(n)) 2253 if (load_module((char *) getdata(n), NULL, silent) == 1) { 2254 m->node.flags &= ~MOD_BUSY; 2255 unqueue_signals(); 2256 return 1; 2257 } 2258 } 2259 m->node.flags &= ~MOD_BUSY; 2260 if (!m->u.handle) { 2261 handle = NULL; 2262 if (!(linked = module_linked(name)) && 2263 !(handle = do_load_module(name, silent))) { 2264 unqueue_signals(); 2265 return 1; 2266 } 2267 if (handle) { 2268 m->u.handle = handle; 2269 m->node.flags |= MOD_SETUP; 2270 } else { 2271 m->u.linked = linked; 2272 m->node.flags |= MOD_SETUP | MOD_LINKED; 2273 } 2274 if (setup_module(m)) { 2275 finish_module(m); 2276 if (handle) 2277 m->u.handle = NULL; 2278 else 2279 m->u.linked = NULL; 2280 m->node.flags &= ~MOD_SETUP; 2281 unqueue_signals(); 2282 return 1; 2283 } 2284 m->node.flags |= MOD_INIT_S; 2285 } 2286 m->node.flags |= MOD_SETUP; 2287 if ((bootret = do_boot_module(m, enablesarr, silent)) == 1) { 2288 do_cleanup_module(m); 2289 finish_module(m); 2290 if (m->node.flags & MOD_LINKED) 2291 m->u.linked = NULL; 2292 else 2293 m->u.handle = NULL; 2294 m->node.flags &= ~MOD_SETUP; 2295 unqueue_signals(); 2296 return 1; 2297 } 2298 m->node.flags |= MOD_INIT_B; 2299 m->node.flags &= ~MOD_SETUP; 2300 unqueue_signals(); 2301 return bootret; 2302} 2303 2304/* This ensures that the module with the name given as the first argument 2305 * is loaded. 2306 * The other argument is the array of features to set. If this is NULL 2307 * all features are enabled (even if the module was already loaded). 2308 * 2309 * If this is non-NULL the module features are set accordingly 2310 * whether or not the module is loaded; it is an error if the 2311 * module does not support the features passed (even if the feature 2312 * is to be turned off) or if the module does not support features 2313 * at all. 2314 * The return value is 0 if the module was found or loaded 2315 * (this changed post-4.3.4, because I got so confused---pws), 2316 * 1 if loading failed completely, 2 if some features couldn't be set. 2317 * 2318 * This function behaves like load_module() except that it 2319 * handles the case where the module was already loaded, and 2320 * sets features accordingly. 2321 */ 2322 2323/**/ 2324mod_export int 2325require_module(const char *module, Feature_enables features) 2326{ 2327 Module m = NULL; 2328 int ret = 0; 2329 2330 /* Resolve aliases and actual loadable module as for load_module */ 2331 queue_signals(); 2332 m = find_module(module, FINDMOD_ALIASP, &module); 2333 if (!m || !m->u.handle || 2334 (m->node.flags & MOD_UNLOAD)) 2335 ret = load_module(module, features, 0); 2336 else 2337 ret = do_module_features(m, features, 0); 2338 unqueue_signals(); 2339 2340 return ret; 2341} 2342 2343/* 2344 * Indicate that the module named "name" depends on the module 2345 * named "from". 2346 */ 2347 2348/**/ 2349void 2350add_dep(const char *name, char *from) 2351{ 2352 LinkNode node; 2353 Module m; 2354 2355 /* 2356 * If we were passed an alias, we must resolve it to a final 2357 * module name (and maybe add the corresponding struct), since otherwise 2358 * we would need to check all modules to see if they happen 2359 * to be aliased to the same thing to implement dependencies properly. 2360 * 2361 * This should mean that an attempt to add an alias which would 2362 * have the same name as a module which has dependencies is correctly 2363 * rejected, because then the module named already exists as a non-alias. 2364 * Better make sure. (There's no problem making a an alias which 2365 * *points* to a module with dependencies, of course.) 2366 */ 2367 m = find_module(name, FINDMOD_ALIASP|FINDMOD_CREATE, &name); 2368 if (!m->deps) 2369 m->deps = znewlinklist(); 2370 for (node = firstnode(m->deps); 2371 node && strcmp((char *) getdata(node), from); 2372 incnode(node)); 2373 if (!node) 2374 zaddlinknode(m->deps, ztrdup(from)); 2375} 2376 2377/* 2378 * Function to be used when scanning the builtins table to 2379 * find and print autoloadable builtins. 2380 */ 2381 2382/**/ 2383static void 2384autoloadscan(HashNode hn, int printflags) 2385{ 2386 Builtin bn = (Builtin) hn; 2387 2388 if(bn->node.flags & BINF_ADDED) 2389 return; 2390 if(printflags & PRINT_LIST) { 2391 fputs("zmodload -ab ", stdout); 2392 if(bn->optstr[0] == '-') 2393 fputs("-- ", stdout); 2394 quotedzputs(bn->optstr, stdout); 2395 if(strcmp(bn->node.nam, bn->optstr)) { 2396 putchar(' '); 2397 quotedzputs(bn->node.nam, stdout); 2398 } 2399 } else { 2400 nicezputs(bn->node.nam, stdout); 2401 if(strcmp(bn->node.nam, bn->optstr)) { 2402 fputs(" (", stdout); 2403 nicezputs(bn->optstr, stdout); 2404 putchar(')'); 2405 } 2406 } 2407 putchar('\n'); 2408} 2409 2410 2411/************************************************************************ 2412 * Handling for the zmodload builtin and its various options. 2413 ************************************************************************/ 2414 2415/* 2416 * Main builtin entry point for zmodload. 2417 */ 2418 2419/**/ 2420int 2421bin_zmodload(char *nam, char **args, Options ops, UNUSED(int func)) 2422{ 2423 int ops_bcpf = OPT_ISSET(ops,'b') || OPT_ISSET(ops,'c') || 2424 OPT_ISSET(ops,'p') || OPT_ISSET(ops,'f'); 2425 int ops_au = OPT_ISSET(ops,'a') || OPT_ISSET(ops,'u'); 2426 int ret = 1, autoopts; 2427 /* options only allowed with -F */ 2428 char *fonly = "lP", *fp; 2429 2430 if (ops_bcpf && !ops_au) { 2431 zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u"); 2432 return 1; 2433 } 2434 if (OPT_ISSET(ops,'F') && (ops_bcpf || OPT_ISSET(ops,'u'))) { 2435 zwarnnam(nam, "-b, -c, -f, -p and -u cannot be combined with -F"); 2436 return 1; 2437 } 2438 if (OPT_ISSET(ops,'A') || OPT_ISSET(ops,'R')) { 2439 if (ops_bcpf || ops_au || OPT_ISSET(ops,'d') || 2440 (OPT_ISSET(ops,'R') && OPT_ISSET(ops,'e'))) { 2441 zwarnnam(nam, "illegal flags combined with -A or -R"); 2442 return 1; 2443 } 2444 if (!OPT_ISSET(ops,'e')) 2445 return bin_zmodload_alias(nam, args, ops); 2446 } 2447 if (OPT_ISSET(ops,'d') && OPT_ISSET(ops,'a')) { 2448 zwarnnam(nam, "-d cannot be combined with -a"); 2449 return 1; 2450 } 2451 if (OPT_ISSET(ops,'u') && !*args) { 2452 zwarnnam(nam, "what do you want to unload?"); 2453 return 1; 2454 } 2455 if (OPT_ISSET(ops,'e') && (OPT_ISSET(ops,'I') || OPT_ISSET(ops,'L') || 2456 (OPT_ISSET(ops,'a') && !OPT_ISSET(ops,'F')) 2457 || OPT_ISSET(ops,'d') || 2458 OPT_ISSET(ops,'i') || OPT_ISSET(ops,'u'))) { 2459 zwarnnam(nam, "-e cannot be combined with other options"); 2460 /* except -F ... */ 2461 return 1; 2462 } 2463 for (fp = fonly; *fp; fp++) { 2464 if (OPT_ISSET(ops,STOUC(*fp)) && !OPT_ISSET(ops,'F')) { 2465 zwarnnam(nam, "-%c is only allowed with -F", *fp); 2466 return 1; 2467 } 2468 } 2469 queue_signals(); 2470 if (OPT_ISSET(ops, 'F')) 2471 ret = bin_zmodload_features(nam, args, ops); 2472 else if (OPT_ISSET(ops,'e')) 2473 ret = bin_zmodload_exist(nam, args, ops); 2474 else if (OPT_ISSET(ops,'d')) 2475 ret = bin_zmodload_dep(nam, args, ops); 2476 else if ((autoopts = OPT_ISSET(ops, 'b') + OPT_ISSET(ops, 'c') + 2477 OPT_ISSET(ops, 'p') + OPT_ISSET(ops, 'f')) || 2478 /* zmodload -a is equivalent to zmodload -ab, annoyingly */ 2479 OPT_ISSET(ops, 'a')) { 2480 if (autoopts > 1) { 2481 zwarnnam(nam, "use only one of -b, -c, or -p"); 2482 ret = 1; 2483 } else 2484 ret = bin_zmodload_auto(nam, args, ops); 2485 } else 2486 ret = bin_zmodload_load(nam, args, ops); 2487 unqueue_signals(); 2488 2489 return ret; 2490} 2491 2492/* zmodload -A */ 2493 2494/**/ 2495static int 2496bin_zmodload_alias(char *nam, char **args, Options ops) 2497{ 2498 /* 2499 * TODO: while it would be too nasty to have aliases, as opposed 2500 * to real loadable modules, with dependencies --- just what would 2501 * we need to load when, exactly? --- there is in principle no objection 2502 * to making it possible to force an alias onto an existing unloaded 2503 * module which has dependencies. This would simply transfer 2504 * the dependencies down the line to the aliased-to module name. 2505 * This is actually useful, since then you can alias zsh/zle=mytestzle 2506 * to load another version of zle. But then what happens when the 2507 * alias is removed? Do you transfer the dependencies back? And 2508 * suppose other names are aliased to the same file? It might be 2509 * kettle of fish best left unwormed. 2510 */ 2511 Module m; 2512 2513 if (!*args) { 2514 if (OPT_ISSET(ops,'R')) { 2515 zwarnnam(nam, "no module alias to remove"); 2516 return 1; 2517 } 2518 scanhashtable(modulestab, 1, MOD_ALIAS, 0, 2519 modulestab->printnode, 2520 OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0); 2521 return 0; 2522 } 2523 2524 for (; *args; args++) { 2525 char *eqpos = strchr(*args, '='); 2526 char *aliasname = eqpos ? eqpos+1 : NULL; 2527 if (eqpos) 2528 *eqpos = '\0'; 2529 if (!modname_ok(*args)) { 2530 zwarnnam(nam, "invalid module name `%s'", *args); 2531 return 1; 2532 } 2533 if (OPT_ISSET(ops,'R')) { 2534 if (aliasname) { 2535 zwarnnam(nam, "bad syntax for removing module alias: %s", 2536 *args); 2537 return 1; 2538 } 2539 m = find_module(*args, 0, NULL); 2540 if (m) { 2541 if (!(m->node.flags & MOD_ALIAS)) { 2542 zwarnnam(nam, "module is not an alias: %s", *args); 2543 return 1; 2544 } 2545 delete_module(m); 2546 } else { 2547 zwarnnam(nam, "no such module alias: %s", *args); 2548 return 1; 2549 } 2550 } else { 2551 if (aliasname) { 2552 const char *mname = aliasname; 2553 if (!modname_ok(aliasname)) { 2554 zwarnnam(nam, "invalid module name `%s'", aliasname); 2555 return 1; 2556 } 2557 do { 2558 if (!strcmp(mname, *args)) { 2559 zwarnnam(nam, "module alias would refer to itself: %s", 2560 *args); 2561 return 1; 2562 } 2563 } while ((m = find_module(mname, 0, NULL)) 2564 && (m->node.flags & MOD_ALIAS) 2565 && (mname = m->u.alias)); 2566 m = find_module(*args, 0, NULL); 2567 if (m) { 2568 if (!(m->node.flags & MOD_ALIAS)) { 2569 zwarnnam(nam, "module is not an alias: %s", *args); 2570 return 1; 2571 } 2572 zsfree(m->u.alias); 2573 } else { 2574 m = (Module) zshcalloc(sizeof(*m)); 2575 m->node.flags = MOD_ALIAS; 2576 modulestab->addnode(modulestab, ztrdup(*args), m); 2577 } 2578 m->u.alias = ztrdup(aliasname); 2579 } else { 2580 if ((m = find_module(*args, 0, NULL))) { 2581 if (m->node.flags & MOD_ALIAS) 2582 modulestab->printnode(&m->node, 2583 OPT_ISSET(ops,'L') ? 2584 PRINTMOD_LIST : 0); 2585 else { 2586 zwarnnam(nam, "module is not an alias: %s", *args); 2587 return 1; 2588 } 2589 } else { 2590 zwarnnam(nam, "no such module alias: %s", *args); 2591 return 1; 2592 } 2593 } 2594 } 2595 } 2596 2597 return 0; 2598} 2599 2600/* zmodload -e (without -F) */ 2601 2602/**/ 2603static int 2604bin_zmodload_exist(UNUSED(char *nam), char **args, Options ops) 2605{ 2606 Module m; 2607 2608 if (!*args) { 2609 scanhashtable(modulestab, 1, 0, 0, modulestab->printnode, 2610 OPT_ISSET(ops,'A') ? PRINTMOD_EXIST|PRINTMOD_ALIAS : 2611 PRINTMOD_EXIST); 2612 return 0; 2613 } else { 2614 int ret = 0; 2615 2616 for (; !ret && *args; args++) { 2617 if (!(m = find_module(*args, FINDMOD_ALIASP, NULL)) 2618 || !m->u.handle 2619 || (m->node.flags & MOD_UNLOAD)) 2620 ret = 1; 2621 } 2622 return ret; 2623 } 2624} 2625 2626/* zmodload -d */ 2627 2628/**/ 2629static int 2630bin_zmodload_dep(UNUSED(char *nam), char **args, Options ops) 2631{ 2632 Module m; 2633 if (OPT_ISSET(ops,'u')) { 2634 /* remove dependencies, which can't pertain to aliases */ 2635 const char *tnam = *args++; 2636 m = find_module(tnam, FINDMOD_ALIASP, &tnam); 2637 if (!m) 2638 return 0; 2639 if (*args && m->deps) { 2640 do { 2641 LinkNode dnode; 2642 for (dnode = firstnode(m->deps); dnode; incnode(dnode)) 2643 if (!strcmp(*args, getdata(dnode))) { 2644 zsfree(getdata(dnode)); 2645 remnode(m->deps, dnode); 2646 break; 2647 } 2648 } while(*++args); 2649 if (empty(m->deps)) { 2650 freelinklist(m->deps, freestr); 2651 m->deps = NULL; 2652 } 2653 } else { 2654 if (m->deps) { 2655 freelinklist(m->deps, freestr); 2656 m->deps = NULL; 2657 } 2658 } 2659 if (!m->deps && !m->u.handle) 2660 delete_module(m); 2661 return 0; 2662 } else if (!args[0] || !args[1]) { 2663 /* list dependencies */ 2664 int depflags = OPT_ISSET(ops,'L') ? 2665 PRINTMOD_DEPS|PRINTMOD_LIST : PRINTMOD_DEPS; 2666 if (args[0]) { 2667 if ((m = (Module)modulestab->getnode2(modulestab, args[0]))) 2668 modulestab->printnode(&m->node, depflags); 2669 } else { 2670 scanhashtable(modulestab, 1, 0, 0, modulestab->printnode, 2671 depflags); 2672 } 2673 return 0; 2674 } else { 2675 /* add dependencies */ 2676 int ret = 0; 2677 char *tnam = *args++; 2678 2679 for (; *args; args++) 2680 add_dep(tnam, *args); 2681 return ret; 2682 } 2683} 2684 2685/* 2686 * Function for scanning the parameter table to find and print 2687 * out autoloadable parameters. 2688 */ 2689 2690static void 2691printautoparams(HashNode hn, int lon) 2692{ 2693 Param pm = (Param) hn; 2694 2695 if (pm->node.flags & PM_AUTOLOAD) { 2696 if (lon) 2697 printf("zmodload -ap %s %s\n", pm->u.str, pm->node.nam); 2698 else 2699 printf("%s (%s)\n", pm->node.nam, pm->u.str); 2700 } 2701} 2702 2703/* zmodload -a/u [bcpf] */ 2704 2705/**/ 2706static int 2707bin_zmodload_auto(char *nam, char **args, Options ops) 2708{ 2709 int fchar, flags; 2710 char *modnam; 2711 2712 if (OPT_ISSET(ops,'c')) { 2713 if (!*args) { 2714 /* list autoloaded conditions */ 2715 Conddef p; 2716 2717 for (p = condtab; p; p = p->next) { 2718 if (p->module) { 2719 if (OPT_ISSET(ops,'L')) { 2720 fputs("zmodload -ac", stdout); 2721 if (p->flags & CONDF_INFIX) 2722 putchar('I'); 2723 printf(" %s %s\n", p->module, p->name); 2724 } else { 2725 if (p->flags & CONDF_INFIX) 2726 fputs("infix ", stdout); 2727 else 2728 fputs("post ", stdout); 2729 printf("%s (%s)\n",p->name, p->module); 2730 } 2731 } 2732 } 2733 return 0; 2734 } 2735 fchar = OPT_ISSET(ops,'I') ? 'C' : 'c'; 2736 } else if (OPT_ISSET(ops,'p')) { 2737 if (!*args) { 2738 /* list autoloaded parameters */ 2739 scanhashtable(paramtab, 1, 0, 0, printautoparams, 2740 OPT_ISSET(ops,'L')); 2741 return 0; 2742 } 2743 fchar = 'p'; 2744 } else if (OPT_ISSET(ops,'f')) { 2745 if (!*args) { 2746 /* list autoloaded math functions */ 2747 MathFunc p; 2748 2749 for (p = mathfuncs; p; p = p->next) { 2750 if (!(p->flags & MFF_USERFUNC) && p->module) { 2751 if (OPT_ISSET(ops,'L')) { 2752 fputs("zmodload -af", stdout); 2753 printf(" %s %s\n", p->module, p->name); 2754 } else 2755 printf("%s (%s)\n",p->name, p->module); 2756 } 2757 } 2758 return 0; 2759 } 2760 fchar = 'f'; 2761 } else { 2762 /* builtins are the default; zmodload -ab or just zmodload -a */ 2763 if (!*args) { 2764 /* list autoloaded builtins */ 2765 scanhashtable(builtintab, 1, 0, 0, 2766 autoloadscan, OPT_ISSET(ops,'L') ? PRINT_LIST : 0); 2767 return 0; 2768 } 2769 fchar = 'b'; 2770 } 2771 2772 flags = FEAT_AUTOALL; 2773 if (OPT_ISSET(ops,'i')) 2774 flags |= FEAT_IGNORE; 2775 if (OPT_ISSET(ops,'u')) { 2776 /* remove autoload */ 2777 flags |= FEAT_REMOVE; 2778 modnam = NULL; 2779 } else { 2780 /* add autoload */ 2781 modnam = *args; 2782 2783 if (args[1]) 2784 args++; 2785 } 2786 return autofeatures(nam, modnam, args, fchar, flags); 2787} 2788 2789/* Backend handler for zmodload -u */ 2790 2791/**/ 2792int 2793unload_module(Module m) 2794{ 2795 int del; 2796 2797 /* 2798 * Only unload the real module, so resolve aliases. 2799 */ 2800 if (m->node.flags & MOD_ALIAS) { 2801 m = find_module(m->u.alias, FINDMOD_ALIASP, NULL); 2802 if (!m) 2803 return 1; 2804 } 2805 /* 2806 * We may need to clean up the module any time setup_ has been 2807 * called. After cleanup_ is successful we are no longer in the 2808 * booted state (because features etc. are deregistered), so remove 2809 * MOD_INIT_B, and also MOD_INIT_S since we won't need to cleanup 2810 * again if this succeeded. 2811 */ 2812 if ((m->node.flags & MOD_INIT_S) && 2813 !(m->node.flags & MOD_UNLOAD) && 2814 do_cleanup_module(m)) 2815 return 1; 2816 m->node.flags &= ~(MOD_INIT_B|MOD_INIT_S); 2817 2818 del = (m->node.flags & MOD_UNLOAD); 2819 2820 if (m->wrapper) { 2821 m->node.flags |= MOD_UNLOAD; 2822 return 0; 2823 } 2824 m->node.flags &= ~MOD_UNLOAD; 2825 2826 /* 2827 * We always need to finish the module (and unload it) 2828 * if it is present. 2829 */ 2830 if (m->node.flags & MOD_LINKED) { 2831 if (m->u.linked) { 2832 m->u.linked->finish(m); 2833 m->u.linked = NULL; 2834 } 2835 } else { 2836 if (m->u.handle) { 2837 finish_module(m); 2838 m->u.handle = NULL; 2839 } 2840 } 2841 2842 if (del && m->deps) { 2843 /* The module was unloaded delayed, unload all modules * 2844 * on which it depended. */ 2845 LinkNode n; 2846 2847 for (n = firstnode(m->deps); n; incnode(n)) { 2848 Module dm = find_module((char *) getdata(n), 2849 FINDMOD_ALIASP, NULL); 2850 2851 if (dm && 2852 (dm->node.flags & MOD_UNLOAD)) { 2853 /* See if this is the only module depending on it. */ 2854 Module am; 2855 int du = 1, i; 2856 /* Scan hash table the hard way */ 2857 for (i = 0; du && i < modulestab->hsize; i++) { 2858 for (am = (Module)modulestab->nodes[i]; du && am; 2859 am = (Module)am->node.next) { 2860 LinkNode sn; 2861 /* 2862 * Don't scan the module we're unloading; 2863 * ignore if no dependencies. 2864 */ 2865 if (am == m || !am->deps) 2866 continue; 2867 /* Don't scan if not loaded nor linked */ 2868 if ((am->node.flags & MOD_LINKED) ? 2869 !am->u.linked : !am->u.handle) 2870 continue; 2871 for (sn = firstnode(am->deps); du && sn; 2872 incnode(sn)) { 2873 if (!strcmp((char *) getdata(sn), 2874 dm->node.nam)) 2875 du = 0; 2876 } 2877 } 2878 } 2879 if (du) 2880 unload_module(dm); 2881 } 2882 } 2883 } 2884 if (m->autoloads && firstnode(m->autoloads)) { 2885 /* 2886 * Module has autoloadable features. Restore them 2887 * so that the module will be reloaded when needed. 2888 */ 2889 autofeatures("zsh", m->node.nam, 2890 hlinklist2array(m->autoloads, 0), 0, FEAT_IGNORE); 2891 } else if (!m->deps) { 2892 delete_module(m); 2893 } 2894 return 0; 2895} 2896 2897/* 2898 * Unload a module by name (modname); nam is the command name. 2899 * Optionally don't print some error messages (always print 2900 * dependency errors). 2901 */ 2902 2903/**/ 2904int 2905unload_named_module(char *modname, char *nam, int silent) 2906{ 2907 const char *mname; 2908 Module m; 2909 int ret = 0; 2910 2911 m = find_module(modname, FINDMOD_ALIASP, &mname); 2912 if (m) { 2913 int i, del = 0; 2914 Module dm; 2915 2916 for (i = 0; i < modulestab->hsize; i++) { 2917 for (dm = (Module)modulestab->nodes[i]; dm; 2918 dm = (Module)dm->node.next) { 2919 LinkNode dn; 2920 if (!dm->deps || !dm->u.handle) 2921 continue; 2922 for (dn = firstnode(dm->deps); dn; incnode(dn)) { 2923 if (!strcmp((char *) getdata(dn), mname)) { 2924 if (dm->node.flags & MOD_UNLOAD) 2925 del = 1; 2926 else { 2927 zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname); 2928 return 1; 2929 } 2930 } 2931 } 2932 } 2933 } 2934 if (del) 2935 m->wrapper++; 2936 if (unload_module(m)) 2937 ret = 1; 2938 if (del) 2939 m->wrapper--; 2940 } else if (!silent) { 2941 zwarnnam(nam, "no such module %s", modname); 2942 ret = 1; 2943 } 2944 2945 return ret; 2946} 2947 2948/* zmodload -u without -d */ 2949 2950/**/ 2951static int 2952bin_zmodload_load(char *nam, char **args, Options ops) 2953{ 2954 int ret = 0; 2955 if(OPT_ISSET(ops,'u')) { 2956 /* unload modules */ 2957 for(; *args; args++) { 2958 if (unload_named_module(*args, nam, OPT_ISSET(ops,'i'))) 2959 ret = 1; 2960 } 2961 return ret; 2962 } else if(!*args) { 2963 /* list modules */ 2964 scanhashtable(modulestab, 1, 0, MOD_UNLOAD|MOD_ALIAS, 2965 modulestab->printnode, 2966 OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0); 2967 return 0; 2968 } else { 2969 /* load modules */ 2970 for (; *args; args++) { 2971 int tmpret = require_module(*args, NULL); 2972 if (tmpret && ret != 1) 2973 ret = tmpret; 2974 } 2975 2976 return ret; 2977 } 2978} 2979 2980/* zmodload -F */ 2981 2982/**/ 2983static int 2984bin_zmodload_features(const char *nam, char **args, Options ops) 2985{ 2986 int iarg; 2987 char *modname = *args; 2988 Patprog *patprogs; 2989 Feature_enables features, fep; 2990 2991 if (modname) 2992 args++; 2993 else if (OPT_ISSET(ops,'L')) { 2994 int printflags = PRINTMOD_LIST|PRINTMOD_FEATURES; 2995 if (OPT_ISSET(ops,'P')) { 2996 zwarnnam(nam, "-P is only allowed with a module name"); 2997 return 1; 2998 } 2999 if (OPT_ISSET(ops,'l')) 3000 printflags |= PRINTMOD_LISTALL; 3001 if (OPT_ISSET(ops,'a')) 3002 printflags |= PRINTMOD_AUTO; 3003 scanhashtable(modulestab, 1, 0, MOD_ALIAS, 3004 modulestab->printnode, printflags); 3005 return 0; 3006 } 3007 3008 if (!modname) { 3009 zwarnnam(nam, "-F requires a module name"); 3010 return 1; 3011 } 3012 3013 if (OPT_ISSET(ops,'m')) { 3014 char **argp; 3015 Patprog *patprogp; 3016 3017 /* not NULL terminated */ 3018 patprogp = patprogs = 3019 (Patprog *)zhalloc(arrlen(args)*sizeof(Patprog)); 3020 for (argp = args; *argp; argp++, patprogp++) { 3021 char *arg = *argp; 3022 if (*arg == '+' || *arg == '-') 3023 arg++; 3024 tokenize(arg); 3025 *patprogp = patcompile(arg, 0, 0); 3026 } 3027 } else 3028 patprogs = NULL; 3029 3030 if (OPT_ISSET(ops,'l') || OPT_ISSET(ops,'L') || OPT_ISSET(ops,'e')) { 3031 /* 3032 * With option 'l', list all features one per line with + or -. 3033 * With option 'L', list as zmodload statement showing 3034 * only options turned on. 3035 * With both options, list as zmodload showing options 3036 * to be turned both on and off. 3037 */ 3038 Module m; 3039 char **features, **fp, **arrset = NULL, **arrp = NULL; 3040 int *enables = NULL, *ep; 3041 char *param = OPT_ARG_SAFE(ops,'P'); 3042 3043 m = find_module(modname, FINDMOD_ALIASP, NULL); 3044 if (OPT_ISSET(ops,'a')) { 3045 LinkNode ln; 3046 /* 3047 * If there are no autoloads defined, return status 1. 3048 */ 3049 if (!m || !m->autoloads) 3050 return 1; 3051 if (OPT_ISSET(ops,'e')) { 3052 for (fp = args; *fp; fp++) { 3053 char *fstr = *fp; 3054 int sense = 1; 3055 if (*fstr == '+') 3056 fstr++; 3057 else if (*fstr == '-') { 3058 fstr++; 3059 sense = 0; 3060 } 3061 if ((linknodebystring(m->autoloads, fstr) != NULL) != 3062 sense) 3063 return 1; 3064 } 3065 return 0; 3066 } 3067 if (param) { 3068 arrp = arrset = (char **)zalloc(sizeof(char*) * 3069 (countlinknodes(m->autoloads)+1)); 3070 } else if (OPT_ISSET(ops,'L')) { 3071 printf("zmodload -aF %s%c", m->node.nam, 3072 m->autoloads && firstnode(m->autoloads) ? ' ' : '\n'); 3073 arrp = NULL; 3074 } 3075 for (ln = firstnode(m->autoloads); ln; incnode(ln)) { 3076 char *al = (char *)getdata(ln); 3077 if (param) 3078 *arrp++ = ztrdup(al); 3079 else 3080 printf("%s%c", al, 3081 OPT_ISSET(ops,'L') && nextnode(ln) ? ' ' : '\n'); 3082 } 3083 if (param) { 3084 *arrp = NULL; 3085 if (!setaparam(param, arrset)) 3086 return 1; 3087 } 3088 return 0; 3089 } 3090 if (!m || !m->u.handle || (m->node.flags & MOD_UNLOAD)) { 3091 if (!OPT_ISSET(ops,'e')) 3092 zwarnnam(nam, "module `%s' is not yet loaded", modname); 3093 return 1; 3094 } 3095 if (features_module(m, &features)) { 3096 if (!OPT_ISSET(ops,'e')) 3097 zwarnnam(nam, "module `%s' does not support features", 3098 m->node.nam); 3099 return 1; 3100 } 3101 if (enables_module(m, &enables)) { 3102 /* this shouldn't ever happen, so don't silence this error */ 3103 zwarnnam(nam, "error getting enabled features for module `%s'", 3104 m->node.nam); 3105 return 1; 3106 } 3107 for (arrp = args, iarg = 0; *arrp; arrp++, iarg++) { 3108 char *arg = *arrp; 3109 int on, found = 0; 3110 if (*arg == '-') { 3111 on = 0; 3112 arg++; 3113 } else if (*arg == '+') { 3114 on = 1; 3115 arg++; 3116 } else 3117 on = -1; 3118 for (fp = features, ep = enables; *fp; fp++, ep++) { 3119 if (patprogs ? pattry(patprogs[iarg], *fp) : 3120 !strcmp(arg, *fp)) { 3121 /* for -e, check given state, if any */ 3122 if (OPT_ISSET(ops,'e') && on != -1 && 3123 on != (*ep & 1)) 3124 return 1; 3125 found++; 3126 if (!patprogs) 3127 break; 3128 } 3129 } 3130 if (!found) { 3131 if (!OPT_ISSET(ops,'e')) 3132 zwarnnam(nam, patprogs ? 3133 "module `%s' has no feature matching: `%s'" : 3134 "module `%s' has no such feature: `%s'", 3135 modname, *arrp); 3136 return 1; 3137 } 3138 } 3139 if (OPT_ISSET(ops,'e')) /* yep, everything we want exists */ 3140 return 0; 3141 if (param) { 3142 int arrlen = 0; 3143 for (fp = features, ep = enables; *fp; fp++, ep++) { 3144 if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l') && 3145 !*ep) 3146 continue; 3147 if (*args) { 3148 char **argp; 3149 for (argp = args, iarg = 0; *argp; argp++, iarg++) { 3150 char *arg = *argp; 3151 /* ignore +/- for consistency */ 3152 if (*arg == '+' || *arg == '-') 3153 arg++; 3154 if (patprogs ? pattry(patprogs[iarg], *fp) : 3155 !strcmp(*fp, arg)) 3156 break; 3157 } 3158 if (!*argp) 3159 continue; 3160 } 3161 arrlen++; 3162 } 3163 arrp = arrset = zalloc(sizeof(char *) * (arrlen+1)); 3164 } else if (OPT_ISSET(ops, 'L')) 3165 printf("zmodload -F %s ", m->node.nam); 3166 for (fp = features, ep = enables; *fp; fp++, ep++) { 3167 char *onoff; 3168 int term; 3169 if (*args) { 3170 char **argp; 3171 for (argp = args, iarg = 0; *argp; argp++, iarg++) { 3172 char *arg = *argp; 3173 if (*arg == '+' || *arg == '-') 3174 arg++; 3175 if (patprogs ? pattry(patprogs[iarg], *fp) : 3176 !strcmp(*fp, *argp)) 3177 break; 3178 } 3179 if (!*argp) 3180 continue; 3181 } 3182 if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l')) { 3183 if (!*ep) 3184 continue; 3185 onoff = ""; 3186 } else if (*ep) { 3187 onoff = "+"; 3188 } else { 3189 onoff = "-"; 3190 } 3191 if (param) { 3192 *arrp++ = bicat(onoff, *fp); 3193 } else { 3194 if (OPT_ISSET(ops, 'L') && fp[1]) { 3195 term = ' '; 3196 } else { 3197 term = '\n'; 3198 } 3199 printf("%s%s%c", onoff, *fp, term); 3200 } 3201 } 3202 if (param) { 3203 *arrp = NULL; 3204 if (!setaparam(param, arrset)) 3205 return 1; 3206 } 3207 return 0; 3208 } else if (OPT_ISSET(ops,'P')) { 3209 zwarnnam(nam, "-P can only be used with -l or -L"); 3210 return 1; 3211 } else if (OPT_ISSET(ops,'a')) { 3212 if (OPT_ISSET(ops,'m')) { 3213 zwarnnam(nam, "-m cannot be used with -a"); 3214 return 1; 3215 } 3216 /* 3217 * With zmodload -aF, we always use the effect of -i. 3218 * The thinking is that marking a feature for 3219 * autoload is separate from enabling or disabling it. 3220 * Arguably we could do this with the zmodload -ab method 3221 * but I've kept it there for old time's sake. 3222 * The decoupling has meant FEAT_IGNORE/-i also 3223 * suppresses an error for attempting to remove an 3224 * autoload when the feature is enabled, which used 3225 * to be a hard error before. 3226 */ 3227 return autofeatures(nam, modname, args, 0, FEAT_IGNORE); 3228 } 3229 3230 fep = features = 3231 (Feature_enables)zhalloc((arrlen(args)+1)*sizeof(*fep)); 3232 3233 while (*args) { 3234 fep->str = *args++; 3235 fep->pat = patprogs ? *patprogs++ : NULL; 3236 fep++; 3237 } 3238 fep->str = NULL; 3239 fep->pat = NULL; 3240 3241 return require_module(modname, features); 3242} 3243 3244 3245/************************************************************************ 3246 * Generic feature support. 3247 * These functions are designed to be called by modules. 3248 ************************************************************************/ 3249 3250/* 3251 * Construct a features array out of the list of concrete 3252 * features given, leaving space for any abstract features 3253 * to be added by the module itself. 3254 * 3255 * Note the memory is from the heap. 3256 */ 3257 3258/**/ 3259mod_export char ** 3260featuresarray(UNUSED(Module m), Features f) 3261{ 3262 int bn_size = f->bn_size, cd_size = f->cd_size; 3263 int mf_size = f->mf_size, pd_size = f->pd_size; 3264 int features_size = bn_size + cd_size + pd_size + mf_size + f->n_abstract; 3265 Builtin bnp = f->bn_list; 3266 Conddef cdp = f->cd_list; 3267 MathFunc mfp = f->mf_list; 3268 Paramdef pdp = f->pd_list; 3269 char **features = (char **)zhalloc((features_size + 1) * sizeof(char *)); 3270 char **featurep = features; 3271 3272 while (bn_size--) 3273 *featurep++ = dyncat("b:", (bnp++)->node.nam); 3274 while (cd_size--) { 3275 *featurep++ = dyncat((cdp->flags & CONDF_INFIX) ? "C:" : "c:", 3276 cdp->name); 3277 cdp++; 3278 } 3279 while (mf_size--) 3280 *featurep++ = dyncat("f:", (mfp++)->name); 3281 while (pd_size--) 3282 *featurep++ = dyncat("p:", (pdp++)->name); 3283 3284 features[features_size] = NULL; 3285 return features; 3286} 3287 3288/* 3289 * Return the current set of enables for the features in a 3290 * module using heap memory. Leave space for abstract 3291 * features. The array is not zero terminated. 3292 */ 3293/**/ 3294mod_export int * 3295getfeatureenables(UNUSED(Module m), Features f) 3296{ 3297 int bn_size = f->bn_size, cd_size = f->cd_size; 3298 int mf_size = f->mf_size, pd_size = f->pd_size; 3299 int features_size = bn_size + cd_size + mf_size + pd_size + f->n_abstract; 3300 Builtin bnp = f->bn_list; 3301 Conddef cdp = f->cd_list; 3302 MathFunc mfp = f->mf_list; 3303 Paramdef pdp = f->pd_list; 3304 int *enables = zhalloc(sizeof(int) * features_size); 3305 int *enablep = enables; 3306 3307 while (bn_size--) 3308 *enablep++ = ((bnp++)->node.flags & BINF_ADDED) ? 1 : 0; 3309 while (cd_size--) 3310 *enablep++ = ((cdp++)->flags & CONDF_ADDED) ? 1 : 0; 3311 while (mf_size--) 3312 *enablep++ = ((mfp++)->flags & MFF_ADDED) ? 1 : 0; 3313 while (pd_size--) 3314 *enablep++ = (pdp++)->pm ? 1 : 0; 3315 3316 return enables; 3317} 3318 3319/* 3320 * Add or remove the concrete features passed in arguments, 3321 * depending on the corresponding element of the array e. 3322 * If e is NULL, disable everything. 3323 * Return 0 for success, 1 for failure; does not attempt 3324 * to imitate the return values of addbuiltins() etc. 3325 * Any failure in adding a requested feature is an 3326 * error. 3327 */ 3328 3329/**/ 3330mod_export int 3331setfeatureenables(Module m, Features f, int *e) 3332{ 3333 int ret = 0; 3334 3335 if (f->bn_size) { 3336 if (setbuiltins(m->node.nam, f->bn_list, f->bn_size, e)) 3337 ret = 1; 3338 if (e) 3339 e += f->bn_size; 3340 } 3341 if (f->cd_size) { 3342 if (setconddefs(m->node.nam, f->cd_list, f->cd_size, e)) 3343 ret = 1; 3344 if (e) 3345 e += f->cd_size; 3346 } 3347 if (f->mf_size) { 3348 if (setmathfuncs(m->node.nam, f->mf_list, f->mf_size, e)) 3349 ret = 1; 3350 } 3351 if (f->pd_size) { 3352 if (setparamdefs(m->node.nam, f->pd_list, f->pd_size, e)) 3353 ret = 1; 3354 if (e) 3355 e += f->pd_size; 3356 } 3357 return ret; 3358} 3359 3360/* 3361 * Convenient front-end to get or set features which 3362 * can be used in a module enables_() function. 3363 */ 3364 3365/**/ 3366mod_export int 3367handlefeatures(Module m, Features f, int **enables) 3368{ 3369 if (!enables || *enables) 3370 return setfeatureenables(m, f, *enables); 3371 *enables = getfeatureenables(m, f); 3372 return 0; 3373} 3374 3375/* 3376 * Ensure module "modname" is providing feature with "prefix" 3377 * and "feature" (e.g. "b:", "limit"). If feature is NULL, 3378 * ensure all features are loaded (used for compatibility 3379 * with the pre-feature autoloading behaviour). 3380 * 3381 * This will usually be called from the main shell to handle 3382 * loading of an autoloadable feature. 3383 * 3384 * Returns 0 on success, 1 for error in module, 2 for error 3385 * setting the feature. However, this isn't actually all 3386 * that useful for testing immediately on an autoload since 3387 * it could be a failure to autoload a different feature 3388 * from the one we want. We could fix this but it's 3389 * possible to test other ways. 3390 */ 3391 3392/**/ 3393mod_export int 3394ensurefeature(const char *modname, const char *prefix, const char *feature) 3395{ 3396 char *f; 3397 struct feature_enables features[2]; 3398 3399 if (!feature) 3400 return require_module(modname, NULL); 3401 f = dyncat(prefix, feature); 3402 3403 features[0].str = f; 3404 features[0].pat = NULL; 3405 features[1].str = NULL; 3406 features[1].pat = NULL; 3407 return require_module(modname, features); 3408} 3409 3410/* 3411 * Add autoloadable features for a given module. 3412 */ 3413 3414/**/ 3415int 3416autofeatures(const char *cmdnam, const char *module, char **features, 3417 int prefchar, int defflags) 3418{ 3419 int ret = 0, subret; 3420 Module defm, m; 3421 char **modfeatures = NULL; 3422 int *modenables = NULL; 3423 if (module) { 3424 defm = (Module)find_module(module, 3425 FINDMOD_ALIASP|FINDMOD_CREATE, NULL); 3426 if ((defm->node.flags & MOD_LINKED) ? defm->u.linked : 3427 defm->u.handle) { 3428 (void)features_module(defm, &modfeatures); 3429 (void)enables_module(defm, &modenables); 3430 } 3431 } else 3432 defm = NULL; 3433 3434 for (; *features; features++) { 3435 char *fnam, *typnam, *feature; 3436 int add, fchar, flags = defflags; 3437 autofeaturefn_t fn; 3438 3439 if (prefchar) { 3440 /* 3441 * "features" is list of bare features with no 3442 * type prefix; prefchar gives type character. 3443 */ 3444 add = 1; /* unless overridden by flag */ 3445 fchar = prefchar; 3446 fnam = *features; 3447 feature = zhalloc(strlen(fnam) + 3); 3448 sprintf(feature, "%c:%s", fchar, fnam); 3449 } else { 3450 feature = *features; 3451 if (*feature == '-') { 3452 add = 0; 3453 feature++; 3454 } else { 3455 add = 1; 3456 if (*feature == '+') 3457 feature++; 3458 } 3459 3460 if (!*feature || feature[1] != ':') { 3461 zwarnnam(cmdnam, "bad format for autoloadable feature: `%s'", 3462 feature); 3463 ret = 1; 3464 continue; 3465 } 3466 fnam = feature + 2; 3467 fchar = feature[0]; 3468 } 3469 if (flags & FEAT_REMOVE) 3470 add = 0; 3471 3472 switch (fchar) { 3473 case 'b': 3474 fn = add ? add_autobin : del_autobin; 3475 typnam = "builtin"; 3476 break; 3477 3478 case 'C': 3479 flags |= FEAT_INFIX; 3480 /* FALLTHROUGH */ 3481 case 'c': 3482 fn = add ? add_autocond : del_autocond; 3483 typnam = "condition"; 3484 break; 3485 3486 case 'f': 3487 fn = add ? add_automathfunc : del_automathfunc; 3488 typnam = "math function"; 3489 break; 3490 3491 case 'p': 3492 fn = add ? add_autoparam : del_autoparam; 3493 typnam = "parameter"; 3494 break; 3495 3496 default: 3497 zwarnnam(cmdnam, "bad autoloadable feature type: `%c'", 3498 fchar); 3499 ret = 1; 3500 continue; 3501 } 3502 3503 if (strchr(fnam, '/')) { 3504 zwarnnam(cmdnam, "%s: `/' is illegal in a %s", fnam, typnam); 3505 ret = 1; 3506 continue; 3507 } 3508 3509 if (!module) { 3510 /* 3511 * Traditional un-autoload syntax doesn't tell us 3512 * which module this came from. 3513 */ 3514 int i; 3515 for (i = 0, m = NULL; !m && i < modulestab->hsize; i++) { 3516 for (m = (Module)modulestab->nodes[i]; m; 3517 m = (Module)m->node.next) { 3518 if (m->autoloads && 3519 linknodebystring(m->autoloads, feature)) 3520 break; 3521 } 3522 } 3523 if (!m) { 3524 if (!(flags & FEAT_IGNORE)) { 3525 ret = 1; 3526 zwarnnam(cmdnam, "%s: no such %s", fnam, typnam); 3527 } 3528 continue; 3529 } 3530 } else 3531 m = defm; 3532 3533 subret = 0; 3534 if (add) { 3535 char **ptr; 3536 if (modfeatures) { 3537 /* 3538 * If the module is already available, check that 3539 * it does in fact provide the necessary feature. 3540 */ 3541 for (ptr = modfeatures; *ptr; ptr++) 3542 if (!strcmp(*ptr, feature)) 3543 break; 3544 if (!*ptr) { 3545 zwarnnam(cmdnam, "module `%s' has no such feature: `%s'", 3546 m->node.nam, feature); 3547 ret = 1; 3548 continue; 3549 } 3550 /* 3551 * If the feature is already provided by the module, there's 3552 * nothing more to do. 3553 */ 3554 if (modenables[ptr-modfeatures]) 3555 continue; 3556 /* 3557 * Otherwise, marking it for autoload will do the 3558 * right thing when the feature is eventually used. 3559 */ 3560 } 3561 if (!m->autoloads) { 3562 m->autoloads = znewlinklist(); 3563 zaddlinknode(m->autoloads, ztrdup(feature)); 3564 } else { 3565 /* Insert in lexical order */ 3566 LinkNode ln, prev = (LinkNode)m->autoloads; 3567 while ((ln = nextnode(prev))) { 3568 int cmp = strcmp(feature, (char *)getdata(ln)); 3569 if (cmp == 0) { 3570 /* Already there. Never an error. */ 3571 break; 3572 } 3573 if (cmp < 0) { 3574 zinsertlinknode(m->autoloads, prev, 3575 ztrdup(feature)); 3576 break; 3577 } 3578 prev = ln; 3579 } 3580 if (!ln) 3581 zaddlinknode(m->autoloads, ztrdup(feature)); 3582 } 3583 } else if (m->autoloads) { 3584 LinkNode ln; 3585 if ((ln = linknodebystring(m->autoloads, feature))) 3586 zsfree((char *)remnode(m->autoloads, ln)); 3587 else { 3588 /* 3589 * With -i (or zmodload -Fa), removing an autoload 3590 * that's not there is not an error. 3591 */ 3592 subret = (flags & FEAT_IGNORE) ? -2 : 2; 3593 } 3594 } 3595 3596 if (subret == 0) 3597 subret = fn(module, fnam, flags); 3598 3599 if (subret != 0) { 3600 /* -2 indicates not an error, just skip running fn() */ 3601 if (subret != -2) 3602 ret = 1; 3603 switch (subret) { 3604 case 1: 3605 zwarnnam(cmdnam, "failed to add %s `%s'", typnam, fnam); 3606 break; 3607 3608 case 2: 3609 zwarnnam(cmdnam, "%s: no such %s", fnam, typnam); 3610 break; 3611 3612 case 3: 3613 zwarnnam(cmdnam, "%s: %s is already defined", fnam, typnam); 3614 break; 3615 3616 default: 3617 /* no (further) message needed */ 3618 break; 3619 } 3620 } 3621 } 3622 3623 return ret; 3624} 3625