summaryrefslogtreecommitdiffstats
path: root/perl-install/lang.pm
Commit message (Expand)AuthorAgeFilesLines
...
* changed arabic font for KDE ("Roya" doesn't have ascii glyphs; "Terafik" does)Pablo Saratxaga2005-02-091-1/+1
* changed LANGUAGE value for languages that will need renamingPablo Saratxaga2005-02-051-4/+9
* (console_font_files) perl_checker cleanupThierry Vignaud2005-01-281-1/+1
* - add vera fonts (normal and bold)Pascal Rigaux2005-01-101-1/+1
* install scim-chewing if zh is selected by localedrake. Fix font setting for z...Funda Wang2005-01-081-2/+3
* changed chinese font namesPablo Saratxaga2005-01-071-2/+2
* update UIM config for uim-0.4.5 (UTUMI Hirosi)Thierry Vignaud2005-01-061-3/+3
* s/jp/ja. Corrected spelling of locale jaFunda Wang2005-01-031-1/+1
* jp console should not be localizedFunda Wang2004-12-191-1/+1
* better english (writing style rather than spoken one)Thierry Vignaud2004-12-131-9/+9
* install scim-anthy as well for japanese usersThierry Vignaud2004-11-301-1/+1
* list Turkish language in both Asia and Europe (for Istanbul)Pablo Saratxaga2004-11-231-1/+1
* since we don't use ramdisk but clp, some code is deadPascal Rigaux2004-11-181-29/+0
* remove some unneeded ";", add some for normalization (as told by perl_checker)Pascal Rigaux2004-11-181-1/+1
* fix typo (thanks to bugzilla #12387)Pascal Rigaux2004-11-161-1/+1
* switch to gbk in zh_CNFunda Wang2004-11-141-1/+2
* s/fctix/fcitx. Critical typoFunda Wang2004-11-091-1/+1
* (configure_kdeglobals) set KDE in m17n emvironment if neededThierry Vignaud2004-09-301-1/+1
* (write) fix setting fonts at install timeThierry Vignaud2004-09-291-1/+1
* fix last commitThierry Vignaud2004-09-271-2/+2
* fixed KDE font names to match currently shiped Xfs font namesPablo Saratxaga2004-09-271-9/+15
* add support for SKIM IMThierry Vignaud2004-09-231-0/+5
* install x-unikey for vietnamese (aka sync with share/rpmsrate)Thierry Vignaud2004-09-231-0/+1
* use Sazanami Gothic for everything in japanese (Yukiko Bando)Thierry Vignaud2004-09-231-1/+1
* comment for default:LTRPablo Saratxaga2004-09-141-1/+3
* comment on default:LTRPablo Saratxaga2004-09-141-0/+3
* (write) fix ENC setting too (like thai IM, it got broken whenThierry Vignaud2004-09-091-2/+2
* fix thai IM that was broken for ages (but it was disabled in 10.0Thierry Vignaud2004-09-091-1/+1
* fix ENC and locale specific stuff even when IM is disabled (because of thai)Thierry Vignaud2004-09-091-3/+5
* simplify ENC settingThierry Vignaud2004-09-091-36/+12
* - sanitize some variable namesThierry Vignaud2004-09-091-13/+31
* (write) make it a little more readableThierry Vignaud2004-09-091-3/+5
* (write) kill unused variableThierry Vignaud2004-09-091-2/+1
* add a comment about font settings for installerThierry Vignaud2004-09-091-1/+1
* Singapore is en_SG not zh_SG !!!Thierry Vignaud2004-09-091-2/+2
* (read) fix chinput identificationThierry Vignaud2004-09-091-0/+3
* fix XIM_MODIFIER field for xcin and chinput IMThierry Vignaud2004-09-091-9/+9
* (write) set proper XIM_PROGRAM depending on both encoding and localeThierry Vignaud2004-09-091-1/+1
* (set_default_im) really just set default IM and nothing moreThierry Vignaud2004-09-091-2/+3
* (set_default_im) simplifyThierry Vignaud2004-09-091-2/+2
* (IM packages list) when configuring chinput, we need miniChinput (aThierry Vignaud2004-09-091-0/+1
* reduce font size in japanese installOlivier Blin2004-09-091-1/+1
* some more languages not supported on consolePablo Saratxaga2004-09-061-2/+2
* (write) fix log message when installing IM packagesThierry Vignaud2004-09-061-1/+1
* drop lang::write()'s prefix parameter in favor of $::prefix (which was alread...Thierry Vignaud2004-09-061-7/+7
* (write, configure_kdeglobals) log quite more explanationsThierry Vignaud2004-09-061-8/+25
* (write) really do nothing when no IM is set (harmfull but saner)Thierry Vignaud2004-09-061-1/+1
* (write) package list was already computedThierry Vignaud2004-09-061-1/+1
* fix english name for bretonThierry Vignaud2004-09-061-1/+1
* always set QT_IM_MODULE when setting GTK_IM_MODULEThierry Vignaud2004-09-061-3/+2
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998
print '
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

/* workaround for glibc and kernel header files not in sync */
#define dev_t dev_t

#include <ctype.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <resolv.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <sys/mount.h>
#include <linux/keyboard.h>
#include <linux/kd.h>
#include <linux/hdreg.h>
#include <linux/vt.h>
#include <linux/cdrom.h>
#include <linux/loop.h>
#include <net/if.h>
#include <net/route.h>

#include <libldetect.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#include <X11/extensions/xf86misc.h>
#include <term.h>

#define SECTORSIZE 512
';

$ENV{C_RPM} and print '
#undef Fflush
#undef Mkdir
#undef Stat
#include <rpm/rpmlib.h>

void rpmError_callback_empty(void) {}

int rpmError_callback_data;
void rpmError_callback(void) {
  if (rpmErrorCode() != RPMERR_UNLINK && rpmErrorCode() != RPMERR_RMDIR) {
    write(rpmError_callback_data, rpmErrorString(), strlen(rpmErrorString()));
    write(rpmError_callback_data, "\n", 1);
  }
}

';

print '

void initIMPS2() {
  unsigned char imps2_s1[] = { 243, 200, 243, 100, 243, 80, };
  unsigned char imps2_s2[] = { 246, 230, 244, 243, 100, 232, 3, };

  int fd = open("/dev/cdrom", O_WRONLY);
  if (fd < 0) return;

  write (fd, imps2_s1, sizeof (imps2_s1));
  usleep (30000);
  write (fd, imps2_s2, sizeof (imps2_s2));
  usleep (30000);
  tcflush (fd, TCIFLUSH);
  tcdrain(fd);
}

long long llseek(int fd, long long offset,  int whence);

MODULE = c::stuff		PACKAGE = c::stuff

int
Xtest(display)
  char *display
  CODE:
  int pid;
  if ((pid = fork()) == 0) {
    Display *d = XOpenDisplay(display);
    if (d) {
      XSetCloseDownMode(d, RetainPermanent);
      XCloseDisplay(d);
    }
    _exit(d != NULL);
  }
  waitpid(pid, &RETVAL, 0);
  OUTPUT:
  RETVAL

void
setMouseLive(display, type, emulate3buttons)
  char *display
  int type
  int emulate3buttons
  CODE:
  {
    XF86MiscMouseSettings mseinfo;
    Display *d = XOpenDisplay(display);
    if (d) {
      if (XF86MiscGetMouseSettings(d, &mseinfo) == True) {
        mseinfo.type = type;
        mseinfo.flags |= MF_REOPEN;
        mseinfo.emulate3buttons = emulate3buttons;
        XF86MiscSetMouseSettings(d, &mseinfo);
        XFlush(d);
        if (type == MTYPE_IMPS2) initIMPS2();
      }
    }
  }

void
XSetInputFocus(window)
  int window
  CODE:
  XSetInputFocus(GDK_DISPLAY(), window, RevertToParent, CurrentTime);

int
KTYP(x)
  int x
  CODE:
  RETVAL = KTYP(x);
  OUTPUT:
  RETVAL

int
lseek_sector(fd, sector, offset)
  int fd
  long sector
  long offset
  CODE:
  RETVAL = llseek(fd, (long long) sector * SECTORSIZE + offset, SEEK_SET) >= 0;
  OUTPUT:
  RETVAL

int
isBurner(fd)
  int fd
  CODE:
  RETVAL = ioctl(fd, CDROM_GET_CAPABILITY) & CDC_CD_RW;
  OUTPUT:
  RETVAL

unsigned int
total_sectors(fd)
  int fd
  CODE:
  {
    long s;
    RETVAL = ioctl(fd, BLKGETSIZE, &s) == 0 ? s : 0;
  }
  OUTPUT:
  RETVAL

void
unlimit_core()
  CODE:
  {
    struct rlimit rlim = { RLIM_INFINITY, RLIM_INFINITY };
    setrlimit(RLIMIT_CORE, &rlim);
  }

int
getlimit_core()
  CODE:
  {
    struct rlimit rlim;
    getrlimit(RLIMIT_CORE, &rlim);
    RETVAL = rlim.rlim_cur;
  }
  OUTPUT:
  RETVAL

void
openlog(ident)
  char *ident
  CODE:
  openlog(ident, 0, 0);

void
closelog()

void
syslog(mesg)
  char *mesg
  CODE:
  syslog(LOG_WARNING, mesg);

void
setsid()

void
_exit(status)
  int status
  
int
detectSMP()

void
pci_probe(probe_type)
  int probe_type
  PPCODE:
    struct pciusb_entries entries = pci_probe(probe_type);
    char buf[2048];
    int i;

    EXTEND(SP, entries.nb);
    for (i = 0; i < entries.nb; i++) {
      struct pciusb_entry e = entries.entries[i];
      snprintf(buf, sizeof(buf), "%04x\t%04x\t%04x\t%04x\t%s\t%s\t%s", 
               e.vendor, e.device, e.subvendor, e.subdevice, pci_class2text(e.class), e.module ? e.module : "unknown", e.text);
      PUSHs(sv_2mortal(newSVpv(buf, 0)));
    }
    pciusb_free(entries);

void
usb_probe()
  PPCODE:
    struct pciusb_entries entries = usb_probe();
    char buf[2048];
    int i;

    EXTEND(SP, entries.nb);
    for (i = 0; i < entries.nb; i++) {
      struct pciusb_entry e = entries.entries[i];
      snprintf(buf, sizeof(buf), "%04x\t%04x\t%s\t%s\t%s", 
               e.vendor, e.device, usb_class2text(e.class), e.module ? e.module : "unknown", e.text);
      PUSHs(sv_2mortal(newSVpv(buf, 0)));
    }
    pciusb_free(entries);

char*
crypt_md5(pw, salt)
  char *pw
  char *salt

unsigned int
getpagesize()

int
loadFont(fontFile)
  char *fontFile
  CODE:
    char font[8192];
    unsigned short map[E_TABSZ];
    struct unimapdesc d;
    struct unimapinit u;
    struct unipair desc[2048];
    int rc = 0;

	int fd = open(fontFile, O_RDONLY);
	read(fd, font, sizeof(font));
	read(fd, map, sizeof(map));
        read(fd, &d.entry_ct, sizeof(d.entry_ct));
        d.entries = desc;
        read(fd, desc, d.entry_ct * sizeof(desc[0]));
	close(fd);

	rc = ioctl(1, PIO_FONT, font);
	rc = ioctl(1, PIO_UNIMAPCLR, &u) || rc;
	rc = ioctl(1, PIO_UNIMAP, &d) || rc;
	rc = ioctl(1, PIO_UNISCRNMAP, map) || rc;
        RETVAL = rc == 0;
     OUTPUT:
     RETVAL

int
hasNetDevice(device)
  char * device
  CODE:
    struct ifreq req;
    int s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s == -1) { RETVAL = 0; return; }

    strcpy(req.ifr_name, device);

    RETVAL = ioctl(s, SIOCGIFFLAGS, &req) == 0;
    if (!RETVAL) close(s);
  OUTPUT:
  RETVAL

int
addDefaultRoute(gateway)
  char *gateway
  CODE:
    struct rtentry route;
    struct sockaddr_in addr;
    int s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s == -1) { RETVAL = 0; return; }

    memset(&route, 0, sizeof(route));

    addr.sin_family = AF_INET;
    addr.sin_port = 0;
    inet_aton(gateway, &addr.sin_addr);
    memcpy(&route.rt_gateway, &addr, sizeof(addr));

    addr.sin_addr.s_addr = INADDR_ANY;
    memcpy(&route.rt_dst, &addr, sizeof(addr));
    memcpy(&route.rt_genmask, &addr, sizeof(addr));

    route.rt_flags = RTF_UP | RTF_GATEWAY;
    route.rt_metric = 0;

    RETVAL = !ioctl(s, SIOCADDRT, &route);
  OUTPUT:
  RETVAL

char *
kernel_version()
  CODE:
  struct utsname u;
  if (uname(&u) == 0) RETVAL = u.release; else RETVAL = NULL;
  OUTPUT:
  RETVAL

char *
kernel_arch()
  CODE:
  struct utsname u;
  if (uname(&u) == 0) RETVAL = u.machine; else RETVAL = NULL;
  OUTPUT:
  RETVAL

int
set_loop(dev_fd, file)
  int dev_fd
  char *file
  CODE:
  RETVAL = 0;
{
  struct loop_info loopinfo;
  int file_fd = open(file, O_RDWR);

  if (file_fd < 0) return;

  memset(&loopinfo, 0, sizeof(loopinfo));
  strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
  loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;

  if (ioctl(dev_fd, LOOP_SET_FD, file_fd) < 0) return;
  if (ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo) < 0) {
    ioctl(dev_fd, LOOP_CLR_FD, 0);
    return;
  }
  close(file_fd);
  RETVAL = 1;
}
  OUTPUT:
  RETVAL

int
del_loop(device)
  char *device
  CODE:
  RETVAL = 0;
{
  int fd;
  if ((fd = open(device, O_RDONLY)) < 0) return;
  if (ioctl(fd, LOOP_CLR_FD, 0) < 0) return;
  close(fd);
  RETVAL = 1;
}
  OUTPUT:
  RETVAL

int
prom_open()

void
prom_close()

int
prom_getsibling(node)
  int node

int
prom_getchild(node)
  int node

void
prom_getopt(key)
  char *key
  PPCODE:
  int lenp = 0;
  char *value = NULL;
  value = prom_getopt(key, &lenp);
  EXTEND(sp, 1);
  if (value != NULL) {
    PUSHs(sv_2mortal(newSVpv(value, 0)));
  } else {
    PUSHs(&PL_sv_undef);
  }

void
prom_setopt(key, value)
  char *key
  char *value

void
prom_getproperty(key)
  char *key
  PPCODE:
  int lenp = 0;
  char *value = NULL;
  value = prom_getproperty(key, &lenp);
  EXTEND(sp, 1);
  if (value != NULL) {
    PUSHs(sv_2mortal(newSVpv(value, lenp)));
  } else {
    PUSHs(&PL_sv_undef);
  }

void
prom_getstring(key)
  char *key
  PPCODE:
  int lenp = 0;
  char *value = NULL;
  value = prom_getproperty(key, &lenp);
  EXTEND(sp, 1);
  if (value != NULL) {
    PUSHs(sv_2mortal(newSVpv(value, 0)));
  } else {
    PUSHs(&PL_sv_undef);
  }

int
prom_getbool(key)
  char *key



void
initSilo()

char *
disk2PromPath(disk)
  unsigned char *disk

int
hasAliases()

char *
promRootName()

void
setPromVars(linuxAlias, bootDevice)
  char *linuxAlias
  char *bootDevice
';

$ENV{C_RPM} and print '
int
rpmReadConfigFiles()
  CODE:
  RETVAL = rpmReadConfigFiles(NULL, NULL) == 0;
  OUTPUT:
  RETVAL

int
rpmdbInit(root, perms)
  char *root
  int perms
  CODE:
  RETVAL = rpmdbInit(root, perms) == 0;
  OUTPUT:
  RETVAL

void *
rpmdbOpen(root)
  char *root
  CODE:
  static rpmdb db;
  RETVAL = rpmdbOpen(root, &db, O_RDWR | O_CREAT, 0644) == 0 ||
           rpmdbOpen(root, &db, O_RDONLY, 0644) == 0 ? db : NULL;
  OUTPUT:
  RETVAL

void *
rpmdbOpenForTraversal(root)
  char *root
  CODE:
  static rpmdb db;
  rpmErrorCallBackType old_cb;
  old_cb = rpmErrorSetCallback(rpmError_callback_empty);
  rpmSetVerbosity(RPMMESS_FATALERROR);
  RETVAL = rpmdbOpen(root, &db, O_RDONLY, 0644) == 0 ? db : NULL;
  rpmErrorSetCallback(old_cb);
  rpmSetVerbosity(RPMMESS_NORMAL);
  OUTPUT:
  RETVAL

void
rpmdbClose(db)
  void *db

int
rpmdbTraverse(db, ...)
  void *db
  PREINIT:
  SV *callback = &PL_sv_undef;
  int count;
  Header h;
  rpmdbMatchIterator mi;
  CODE:
  if (items > 1) {
    callback = ST(1);
  }
  count = 0;
  mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
  while (h = rpmdbNextIterator(mi)) {
    if (callback != &PL_sv_undef && SvROK(callback)) {
      dSP;
      ENTER;
      SAVETMPS;
      PUSHMARK(sp);
      XPUSHs(sv_2mortal(newSViv((IV)(void *)h)));
      PUTBACK;
      perl_call_sv(callback, G_DISCARD | G_SCALAR);
      FREETMPS;
      LEAVE;
    }
    ++count;
  }
  rpmdbFreeIterator(mi);
  RETVAL = count;
  OUTPUT:
  RETVAL

int
rpmdbNameTraverse(db, name, ...)
  void *db
  char *name
  PREINIT:
  SV *callback = &PL_sv_undef;
  int count;
  Header h;
  rpmdbMatchIterator mi;
  rpmErrorCallBackType oldcb;
  CODE:
  if (items > 2) {
    callback = ST(2);
  }
  count = 0;
  mi = rpmdbInitIterator(db, RPMTAG_NAME, name, 0);
  oldcb = rpmErrorSetCallback(rpmError_callback_empty);
  while (h = rpmdbNextIterator(mi)) {
    if (callback != &PL_sv_undef && SvROK(callback)) {
      dSP;
      ENTER;
      SAVETMPS;
      PUSHMARK(sp);
      XPUSHs(sv_2mortal(newSViv((IV)(void *)h)));
      PUTBACK;
      perl_call_sv(callback, G_DISCARD | G_SCALAR);
      FREETMPS;
      LEAVE;
    }
    ++count;
  }
  rpmErrorSetCallback(oldcb);
  rpmdbFreeIterator(mi);
  RETVAL = count;
  OUTPUT:
  RETVAL


void *
rpmtransCreateSet(db, rootdir)
  void *db
  char *rootdir

void
rpmtransAvailablePackage(rpmdep, header, key)
  void *rpmdep
  void *header
  char *key
  CODE:
  rpmtransAvailablePackage(rpmdep, header, strdup(key));

int
rpmtransAddPackage(rpmdep, header, key, update)
  void *rpmdep
  void *header
  char *key
  int update
  CODE:
  rpmTransactionSet r = rpmdep;
  RETVAL = rpmtransAddPackage(r, header, NULL, strdup(key), update, NULL) == 0;
  /* rpminstall.c of rpm-4 call headerFree directly after, we can make the same ?*/
  OUTPUT:
  RETVAL

int
rpmtransRemovePackages(db, rpmdep, p)
  void *db
  void *rpmdep
  char *p
  CODE:
  rpmdb d = db;
  rpmTransactionSet r = rpmdep;
  Header h;
  rpmdbMatchIterator mi;
  int count = 0;
  mi = rpmdbInitIterator(db, RPMDBI_LABEL, p, 0);
  while (h = rpmdbNextIterator(mi)) {
    unsigned int recOffset = rpmdbGetIteratorOffset(mi);
    if (recOffset) {
      rpmtransRemovePackage(rpmdep, recOffset);
      ++count;
    }
  }
  rpmdbFreeIterator(mi);
  RETVAL=count;
  OUTPUT:
  RETVAL

int
rpmdepOrder(order)
  void *order
  CODE:
  RETVAL = rpmdepOrder(order) == 0;
  OUTPUT:
  RETVAL

void
rpmdepCheck(rpmdep)
  void *rpmdep
  PPCODE:
  struct rpmDependencyConflict * conflicts;
  int numConflicts, i;
  rpmdepCheck(rpmdep, &conflicts, &numConflicts);
  if (numConflicts) {
    EXTEND(SP, numConflicts);
    for (i = 0; i < numConflicts; i++)
      if (conflicts[i].sense == RPMDEP_SENSE_CONFLICTS) {
        fprintf(stderr, "%s conflicts with %s\n", conflicts[i].byName, conflicts[i].needsName);
      } else {
 	if (conflicts[i].suggestedPackage)
 	  PUSHs(sv_2mortal(newSVpv((char *) conflicts[i].suggestedPackage, 0)));
 	else {
 	  char *p = malloc(100 + strlen(conflicts[i].needsName) + strlen(conflicts[i].byName));
 	  sprintf(p, "%s needed but nothing provide it (%s)", conflicts[i].needsName, conflicts[i].byName);
 	  PUSHs(sv_2mortal(newSVpv(p, 0)));
 	  free(p);
      }
    }
  }

void
rpmdepCheckFrom(rpmdep)
  void *rpmdep
  PPCODE:
  struct rpmDependencyConflict * conflicts;
  int numConflicts, i;
  rpmdepCheck(rpmdep, &conflicts, &numConflicts);
  if (numConflicts) {
    EXTEND(SP, numConflicts);
    for (i = 0; i < numConflicts; i++)
        PUSHs(sv_2mortal(newSVpv(conflicts[i].byName, 0)));
  }

int
rpmdbRebuild(root)
  char *root
  CODE:
  rpmErrorCallBackType old_cb;
  old_cb = rpmErrorSetCallback(rpmError_callback_empty);
  rpmSetVerbosity(RPMMESS_FATALERROR);
  RETVAL = rpmdbRebuild(root) == 0;
  rpmErrorSetCallback(old_cb);
  rpmSetVerbosity(RPMMESS_NORMAL);
  OUTPUT:
  RETVAL

void
rpmtransFree(trans)
  void *trans

char *
rpmErrorString()

int
rpmVersionCompare(headerFirst, headerSecond)
  void *headerFirst
  void *headerSecond

void
rpmSetVeryVerbose()
  CODE:
  rpmSetVerbosity(RPMMESS_DEBUG);

void
rpmtransSetScriptFd(trans, fd)
  void *trans
  int fd
  CODE:
  static FD_t scriptFd = NULL;
  if (scriptFd != NULL) fdClose(scriptFd);
  scriptFd = fdDup(fd);
  rpmtransSetScriptFd(trans, scriptFd);

void
rpmRunTransactions(trans, callbackOpen, callbackClose, callbackMessage, force)
  void *trans
  SV *callbackOpen
  SV *callbackClose
  SV *callbackMessage
  int force
  PPCODE:
  rpmProblemSet probs;
  void *rpmRunTransactions_callback(const Header h, const rpmCallbackType what, const unsigned long amount, const unsigned long total, const void * pkgKey, void * data) {
      static int last_amount;
      static FD_t fd = NULL;
      char *msg = NULL;
      char *param_s = NULL;
      const unsigned long *param_ul1 = NULL;
      const unsigned long *param_ul2 = NULL;
      char *n = (char *) pkgKey;
      static struct timeval tprev;
      static struct timeval tcurr;
      long delta;

      switch (what) {
      case RPMCALLBACK_INST_OPEN_FILE: {
        int i;
  	dSP;
  	PUSHMARK(sp);
  	XPUSHs(sv_2mortal(newSVpv(n, 0)));
  	PUTBACK;
  	i = perl_call_sv(callbackOpen, G_SCALAR);
        SPAGAIN;
        if (i != 1) croak("Big trouble\n");
        i = POPi; fd = fdDup(i);
	fd = fdLink(fd, "persist DrakX");
  	PUTBACK;
        return fd;
      }

      case RPMCALLBACK_INST_CLOSE_FILE: {
	dSP;
  	PUSHMARK(sp);
  	XPUSHs(sv_2mortal(newSVpv(n, 0)));
  	PUTBACK;
  	perl_call_sv(callbackClose, G_DISCARD);
        free(n); /* was strdup in rpmtransAddPackage */
	fd = fdFree(fd, "persist DrakX");
	if (fd) {
	  fdClose(fd);
	  fd = NULL;
	}
  	break;
      }

      case RPMCALLBACK_TRANS_START: {
        switch (amount) {
        case 1: msg = "Examining packages to install..."; break;
        case 5: msg = "Examining files to install..."; break;
        case 6: msg = "Finding overlapping files..."; break;
        }
        if (msg) param_ul1 = &total;
      } break;

      case RPMCALLBACK_UNINST_START: {
        msg = "Removing old files...";
        param_ul1 = &total;
      } break;

      case RPMCALLBACK_TRANS_PROGRESS: {
        msg = "Progressing transaction";
        param_ul1 = &amount;
      } break;

      case RPMCALLBACK_UNINST_PROGRESS: {
        msg = "Progressing removing old files";
        param_ul1 = &amount;
      } break;

      case RPMCALLBACK_TRANS_STOP: {
        msg = "Done transaction";
      } break;

      case RPMCALLBACK_UNINST_STOP: {
        msg = "Done removing old files";
      } break;

      case RPMCALLBACK_INST_START: {
        msg = "Starting installing package";
	gettimeofday(&tprev, NULL);
        param_s = n;

        last_amount = 0;
      } break;

      case RPMCALLBACK_INST_PROGRESS:
        gettimeofday(&tcurr, NULL);
        delta = 1000000 * (tcurr.tv_sec - tprev.tv_sec) + (tcurr.tv_usec - tprev.tv_usec);
        if (delta > 200000 || amount >= total - 1) { /* (total && (amount - last_amount) * 22 / 4 / total)) { */
          msg = "Progressing installing package";
          param_s = n;
          param_ul1 = &amount;
          param_ul2 = &total;

	  tprev = tcurr;
          last_amount = amount;
  	} break;
      default: break;
      }

      if (msg) {
        dSP ;
        PUSHMARK(sp) ;
  	XPUSHs(sv_2mortal(newSVpv(msg, 0)));
        if (param_s) {
  	  XPUSHs(sv_2mortal(newSVpv(param_s, 0)));
        }
        if (param_ul1) {
  	  XPUSHs(sv_2mortal(newSViv(*param_ul1)));
        }
        if (param_ul2) {
          XPUSHs(sv_2mortal(newSViv(*param_ul2)));
        }
  	PUTBACK ;
  	perl_call_sv(callbackMessage, G_DISCARD);
      }
      return NULL;
  }
  if (rpmRunTransactions(trans, rpmRunTransactions_callback, NULL, NULL, &probs, 0, force ? ~0 : ~RPMPROB_FILTER_DISKSPACE)) {
    int i;
    /* printf("rpmRunTransactions finished, errors occured %d\n", probs->numProblems); fflush(stdout); */
    EXTEND(SP, probs->numProblems);
    for (i = 0; i < probs->numProblems; i++) {
      PUSHs(sv_2mortal(newSVpv(rpmProblemString(probs->probs[i]), 0)));
    }
  }

void
rpmErrorSetCallback(fd)
  int fd
  CODE:
  rpmError_callback_data = fd;
  rpmErrorSetCallback(rpmError_callback);

void *
rpmReadPackageHeader(fdno)
  int fdno
  CODE:
  Header h;
  int isSource, major;
  FD_t fd = fdDup(fdno);
  RETVAL = rpmReadPackageHeader(fd, &h, &isSource, &major, NULL) ? NULL : h;
  fdClose(fd);
  OUTPUT:
  RETVAL

void *
headerRead(fdno, magicp)
  int fdno
  int magicp
  CODE:
  FD_t fd = fdDup(fdno);
  RETVAL = (void *) headerRead(fd, magicp);
  fdClose(fd);
  OUTPUT:
  RETVAL

void
headerFree(header)
  void *header

char *
headerGetEntry_string(h, query)
  void *h
  int query
  CODE:
  int type, count;
  headerGetEntry((Header) h, query, &type, (void **) &RETVAL, &count);
  OUTPUT:
  RETVAL

int
headerGetEntry_int(h, query)
  void *h
  int query
  CODE:
  int type, count, *i;
  headerGetEntry((Header) h, query, &type, (void **) &i, &count);
  RETVAL = *i;
  OUTPUT:
  RETVAL

void
headerGetEntry_int_list(h, query)
  void *h
  int query
  PPCODE:
  int i, type, count = 0;
  int_32 *intlist = (int_32 *) NULL;
  if (headerGetEntry((Header) h, query, &type, (void**) &intlist, &count)) {
    if (count > 0) {
      EXTEND(SP, count);
      for (i = 0; i < count; i++) {
        PUSHs(sv_2mortal(newSViv(intlist[i])));
      }
    }
  }

void
headerGetEntry_string_list(h, query)
  void *h
  int query
  PPCODE:
  int i, type, count = 0;
  char **strlist = (char **) NULL;
  if (headerGetEntry((Header) h, query, &type, (void**) &strlist, &count)) {
    if (count > 0) {
      EXTEND(SP, count);
      for (i = 0; i < count; i++) {
        PUSHs(sv_2mortal(newSVpv(strlist[i], 0)));
      }
    }
    free(strlist);
  }

void
headerGetEntry_filenames(h)
  void *h
  PPCODE:
  int i, type, count = 0;
  char ** baseNames, ** dirNames;
  int_32 * dirIndexes;
  char **strlist = (char **) NULL;

  if (headerGetEntry((Header) h, RPMTAG_OLDFILENAMES, &type, (void**) &strlist, &count)) {
    if (count > 0) {
      EXTEND(SP, count);
      for (i = 0; i < count; i++) {
        PUSHs(sv_2mortal(newSVpv(strlist[i], 0)));
      }
    }
    free(strlist);
  } else {

    headerGetEntry(h, RPMTAG_BASENAMES, &type, (void **) &baseNames, &count);
    headerGetEntry(h, RPMTAG_DIRINDEXES, &type, (void **) &dirIndexes, NULL);
    headerGetEntry(h, RPMTAG_DIRNAMES, &type, (void **) &dirNames, NULL);

    if (baseNames && dirNames && dirIndexes) {
      EXTEND(SP, count);
      for(i = 0; i < count; i++) {
        char *p = malloc(strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1);
        if (p == NULL) croak("malloc failed");
        strcpy(p, dirNames[dirIndexes[i]]);
        strcat(p, baseNames[i]);
  	PUSHs(sv_2mortal(newSVpv(p, 0)));
        free(p);
      }
      free(baseNames);
      free(dirNames);
    }
  }
';

@macros = (
  [ qw(int S_IFCHR S_IFBLK KDSKBENT KT_SPEC NR_KEYS MAX_NR_KEYMAPS BLKRRPART TIOCSCTTY
       HDIO_GETGEO BLKGETSIZE LOOP_GET_STATUS
       MS_MGC_VAL MS_RDONLY O_NONBLOCK O_CREAT SECTORSIZE WNOHANG
       VT_ACTIVATE VT_WAITACTIVE VT_GETSTATE CDROM_LOCKDOOR CDROMEJECT
       ) ],
);
push @macros, [ qw(int RPMTAG_NAME RPMTAG_GROUP RPMTAG_SIZE RPMTAG_VERSION RPMTAG_SUMMARY RPMTAG_DESCRIPTION RPMTAG_RELEASE RPMTAG_ARCH RPMTAG_OBSOLETES RPMTAG_REQUIRENAME RPMTAG_FILEFLAGS     RPMFILE_CONFIG) ]
  if $ENV{C_RPM};

$\= "\n";
print;

foreach (@macros) {
    my ($type, @l) = @$_;
    foreach (@l) {
	print<< "END"
$type
$_()
  CODE:
  RETVAL = $_;

  OUTPUT:
  RETVAL

END

    }
}