home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume28 / sybperl / part01 < prev    next >
Encoding:
Text File  |  1992-02-09  |  58.3 KB  |  2,221 lines

  1. Newsgroups: comp.sources.misc
  2. From: mpeppler@itf0.itf.ch (Michael Peppler)
  3. Subject:  v28i033:  sybperl - Sybase DB-library extensions to Perl, Part01/01
  4. Message-ID: <1992Feb10.170828.8388@sparky.imd.sterling.com>
  5. X-Md4-Signature: 32f35045753ff2ad364a1da4dab8a5c9
  6. Date: Mon, 10 Feb 1992 17:08:28 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: mpeppler@itf0.itf.ch (Michael Peppler)
  10. Posting-number: Volume 28, Issue 33
  11. Archive-name: sybperl/part01
  12. Environment: UNIX, Perl, Sybase
  13. Supersedes: sybperl: Volume 25, Issue 40
  14.  
  15. This is Sybperl, a set of subroutine extensions to Perl to interface
  16. directly to a Sybase dataserver.
  17.  
  18. Sybperl is very usefull for writing ad-hoc reports, when other tools
  19. are too cumbersome for the task. I use sybperl for all the reports in a
  20. production environment here at ITF Management.
  21.  
  22. Sybperl has been tested at a number of sites, and should work with no
  23. problem provided Perl works on your system.
  24.  
  25. This version adds support for Perl based error handlers (a la
  26. dberrhandle()), limited support for SYBTEXT datatypes, and cleans up a
  27. couple of loose ends. See the CHANGES file for details.
  28.  
  29. Michael Peppler                 mpeppler@itf.ch {uunet,mcsun}!chsun!itf1!mpeppler
  30. ITF Management SA            BIX:   mpeppler                         
  31. 13 Rue de la Fontaine        Phone: (+4122) 312 1311  
  32. CH-1204 Geneva, Switzerland  Fax:   (+4122) 312 1322  
  33. ------------
  34. #! /bin/sh
  35. # This is a shell archive.  Remove anything before this line, then feed it
  36. # into a shell via "sh file" or similar.  To overwrite existing files,
  37. # type "sh file -c".
  38. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  39. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  40. # Contents:  README BUGS CHANGES Makefile PACKING.LST eg eg/capture.pl
  41. #   eg/report.pl eg/space.pl eg/sql.pl lib lib/sybdb.ph lib/sybperl.pl
  42. #   patchlevel.h sybperl.1 sybperl.c t t/sbex.pl
  43. # Wrapped by kent@sparky on Mon Feb 10 11:01:39 1992
  44. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  45. echo If this archive is complete, you will see the following message:
  46. echo '          "shar: End of archive 1 (of 1)."'
  47. if test -f 'README' -a "${1}" != "-c" ; then 
  48.   echo shar: Will not clobber existing file \"'README'\"
  49. else
  50.   echo shar: Extracting \"'README'\" \(2762 characters\)
  51.   sed "s/^X//" >'README' <<'END_OF_FILE'
  52. X
  53. X                 Sybperl, version 1.0
  54. X
  55. X
  56. X
  57. X   Sybperl is a set of user-defined subroutines letting you access a
  58. X   Sybase data server using Perl.
  59. X
  60. X   Requirements: Perl ver 3.0.27 or higher.
  61. X         Sybase DB-Library (aka Open Client)
  62. X
  63. X
  64. X   Compiling & Installing Sybperl:
  65. X   
  66. X   Unshar somewhere convenient, and edit Makefile to reflect your
  67. X   system setup. The following macros/defines may need to be set:
  68. X
  69. X       PERL_VERSION     Uncomment if you're using a Perl version
  70. X             earlier than 4.03
  71. X       UPERL/SAVESTR     See the comments in the Makefile, and the
  72. X             BUGS file. The defaults should work.
  73. X       HAS_CALLBACK     This enables the use of Perl subroutines as
  74. X             DB-Library error & message handlers. This is
  75. X             a new feature of Perl 4.018, but it might
  76. X             work with earlier versions.
  77. X       OLD_SYBPERL     This is a backwards compatibility flag -
  78. X             mainly for myself :-). It's main impact is to
  79. X             silently call dblogin()/dbopen() with default
  80. X             arguments if you omit to do so in the script.
  81. X
  82. X   The Makefile will not attempt to build uperl.o if it can't find it.
  83. X
  84. X   You may also need to edit the lib/sybperl.pl file to addapt it to
  85. X   your environment.
  86. X
  87. X   There are some test scripts in the t directory which you can run to
  88. X   see if all is well, and to get an idea of what can be done with
  89. X   sybperl. There are also some example scripts in the 'eg' directory.
  90. X
  91. X   Sybperl has been tested succesfully in the following environments:
  92. X
  93. X   Sun Sparc, SunOS 4.1.1, Sybase 4.0.1, Perl 4.010
  94. X   Sun 3/80, SunOS 4.0.3, Sybase 4.0.1, Perl 4.010
  95. X   Sun Sparc, SunOS 4.1, Sybase 4.2, Perl 4.010
  96. X   Pyramid MIServer 2/2, OSx V5.1a, Sybase 4.0, Perl 4.010
  97. X   
  98. X   I use sybperl daily in a production environment on a Sun 4/65 under
  99. X   SunOS 4.1.1, with Sybase version 4.0.1 and Perl 4.019
  100. X
  101. X   BUGS:
  102. X
  103. X   There seems to be a major incompatibility between Perl and
  104. X   DB-Library, but I've been able to code around it. See the BUGS file
  105. X   for details.
  106. X
  107. X
  108. X
  109. X   Have fun using it and let me know of any improvements, problems,
  110. X   whatever...
  111. X
  112. X   Michael Peppler            mpeppler@itf.ch {uunet,mcsun}!chsun!itf1!mpeppler
  113. X   ITF Management SA            BIX:   mpeppler                         
  114. X   13 Rue de la Fontaine        Phone: (+4122) 312 1311  
  115. X   CH-1204 Geneva, Switzerland  Fax:   (+4122) 312 1322  
  116. X
  117. X   
  118. X
  119. X                   NOTICE - Warranty and Copyright
  120. X
  121. X           
  122. X   Sybperl is not a product of ITF Management. There is no warranty,
  123. X   and no official support.
  124. X
  125. X   Sybperl is copyright, but may be freely distributed under the
  126. X   same terms as Perl itself.
  127. X
  128. X
  129. X
  130. X   My thanks to the following people for testing Perl:
  131. X
  132. X   Teemu Torma
  133. X   Matthew Merzbacher
  134. X   Dan Banay
  135. X   Jeffrey Wong
  136. X   Anders Ardo
  137. X   Minh Ton Ha
  138. X   Gijs Mos
  139. X   G. Roderick Singleton
  140. X   Peter Gutmann
  141. X   
  142. END_OF_FILE
  143.   if test 2762 -ne `wc -c <'README'`; then
  144.     echo shar: \"'README'\" unpacked with wrong size!
  145.   fi
  146.   # end of 'README'
  147. fi
  148. if test -f 'BUGS' -a "${1}" != "-c" ; then 
  149.   echo shar: Will not clobber existing file \"'BUGS'\"
  150. else
  151.   echo shar: Extracting \"'BUGS'\" \(1734 characters\)
  152.   sed "s/^X//" >'BUGS' <<'END_OF_FILE'
  153. X
  154. X    
  155. X    The Sybase DB-Library - Perl savestr() conflict
  156. X    ------------------------------------------------
  157. X
  158. X
  159. X    Ah! The joys of tying different packages together!
  160. X
  161. X    Both Perl and DB-Library have a function called savestr(). The
  162. X    DB-Library version is used in dbcmd() to add an SQL command to the
  163. X    list of commands pointed to by dpproc->dbcmdbuf, and in dbuse() as
  164. X    well. Now there are several ways to work around this problem.
  165. X
  166. X    1) Compile sybperl.c with -DBROKEN_DBCMD. I've written some code
  167. X       that emulates calls to dbcmd() and dbuse(). This works OK on my
  168. X       machine/OS/Version of Perl/Version of DBlib, but it relies on
  169. X       the internal storing method used by DBlib, and that might
  170. X       change in the future.
  171. X
  172. X    2) Recompile Perl (specifically, uperl.o in the Perl source
  173. X       directory) with some suitable flags (eg -Dsavestr=p_savestr).
  174. X       This does not create any compatibility problems, but is a
  175. X       lengthy procedure.
  176. X
  177. X    3) Do something like:
  178. X       cc -c sybperl.c
  179. X       ld -r -o sybperl2.o sybperl.o -lsybdb
  180. X       [edit sybperl2.o and replace `_savestr' with something like `_savest1']
  181. X       cc -o sybperl uperl.o sybperl2.o
  182. X       This is not a bad solution, but won't work if you have shared
  183. X       library versions of libsybdb.a
  184. X
  185. X    4) Edit uperl.o and replace savestr with something else. This is
  186. X       the solution I've chosen as the default. It is relatively fast,
  187. X       does not rely on any internal knowledge of DB-Library, and does
  188. X       not require Perl to be recompiled.
  189. X
  190. X    The Makefile gives some information on how to achieve these
  191. X    different options.
  192. X       
  193. X    Thanks to Teemu Torma for providing the initial input on this problem.    
  194. X
  195. X
  196. X    Michael
  197. END_OF_FILE
  198.   if test 1734 -ne `wc -c <'BUGS'`; then
  199.     echo shar: \"'BUGS'\" unpacked with wrong size!
  200.   fi
  201.   # end of 'BUGS'
  202. fi
  203. if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  204.   echo shar: Will not clobber existing file \"'CHANGES'\"
  205. else
  206.   echo shar: Extracting \"'CHANGES'\" \(557 characters\)
  207.   sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
  208. X    Sybperl CHANGES:
  209. X
  210. X    
  211. X    1.004    Added support for Perl based error and message
  212. X        handlers (as made possible by Perl 4.018). Many Thanks
  213. X        to Teemu Torma for this code.
  214. X        Added limited support for SYBTEXT datatypes.
  215. X        Added &dbstrcpy() to retrieve the current command buffer.
  216. X        The DBPROCESS parameter to most &db*() calls can now
  217. X        be omitted: it will default to the first DBPROCESS
  218. X        opened (the one that is returned by &dblogin()).
  219. X        Added lib/sybdb.ph
  220. X        Added a couple of example scripts in eg/*.pl, courtesy
  221. X        of Gijs Mos (Thank You!).
  222. X    1.003    Base version.
  223. END_OF_FILE
  224.   if test 557 -ne `wc -c <'CHANGES'`; then
  225.     echo shar: \"'CHANGES'\" unpacked with wrong size!
  226.   fi
  227.   # end of 'CHANGES'
  228. fi
  229. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  230.   echo shar: Will not clobber existing file \"'Makefile'\"
  231. else
  232.   echo shar: Extracting \"'Makefile'\" \(2598 characters\)
  233.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  234. X#    @(#)Makefile    1.6    11/25/91
  235. X#
  236. X    
  237. XCC = cc
  238. XPERLSRC = ..                # where to find uperl.o
  239. XSYBINCS = /usr/local/sybase/include    # where to find the sybase .h files
  240. XLOCINCS =                # other includes ?
  241. XSYBLIBDIR = /usr/local/lib        # Sybase libraries
  242. XSYBLIBS = -lsybdb            # db-library
  243. X
  244. X# Uncomment this if you are compiling sybperl for Perl version 3.xx
  245. X
  246. X# PERL_VERSION = -DVERSION3
  247. X
  248. X# The Perl/Sybase savestr() conflict.
  249. X# Both Perl and Sybase DB-Library have a function called savestr(),
  250. X# and this creates a problem when using functions such as dbcmd().
  251. X# There are several ways around this.
  252. X# You can:
  253. X#
  254. X#    - define BROKEN_DBCMD: this enables some code emulating
  255. X#      dbcmd() that I've written.
  256. X#    - Recompile uperl.o with a -Dsavestr=psvestr (or something similar).
  257. X#    - Edit an existing uperl.o and change _savestr to _psvestr.
  258. X#
  259. X# To use the first option, uncomment the following definitions for
  260. X# SAVESTR and UPERL
  261. X# SAVESTR = -DBROKEN_DBCMD
  262. X# UPERL = $(PERLSRC)/uperl.o
  263. X#
  264. X# To use the second option, you have to reconfigure & recompile Perl
  265. X# manually, and then set compile sybperl with the following line
  266. X# uncommented:
  267. X# UPERL = $(PERLSRC)/uperl.o
  268. X#
  269. X# The default is to use the third solution:
  270. XUPERL = uperl2.o
  271. X
  272. X
  273. XHAS_CALLBACK= -DHAS_CALLBACK        # Remove this if you don't
  274. X                    # have Perl 4 patchlevel 18
  275. X                    # User defined, perl based
  276. X                    # error/message handlers are
  277. X                    # not possible without this, however.
  278. XOLD_SYBPERL= -DOLD_SYBPERL        # some backward compatibility stuff.                    
  279. X
  280. XCFLAGS = -O                 # 
  281. XCPPFLAGS = -I$(PERLSRC) -I$(LOCINCS) -I$(SYBINCS) $(PERL_VERSION) \
  282. X        $(SAVESTR) $(HAS_CALLBACK) $(OLD_SYBPERL)
  283. XBINDIR = /usr/local/bin            # where does the executable go
  284. XPERLLIB = /usr/local/lib/perl        # where does lib/sybperl.pl
  285. X                    # and lib/sybdb.ph go
  286. XMANDIR = /usr/local/man            # where do we put the manual page
  287. XMANEXT = l
  288. X
  289. X
  290. Xsybperl: $(UPERL) sybperl.o
  291. X    $(CC) $(CFLAGS) -L$(SYBLIBDIR) $(UPERL) sybperl.o $(SYBLIBS) -lm -o sybperl
  292. X
  293. Xsybperl.o: sybperl.c
  294. X    $(CC) -c $(CFLAGS) $(CPPFLAGS) sybperl.c
  295. X
  296. X# Create uperl.o IF you wish to use the 3rd way of resolving the
  297. X# Perl/Sybase savestr conflict.
  298. X$(UPERL): $(PERLSRC)/uperl.o
  299. X    cp $(PERLSRC)/uperl.o $(UPERL)
  300. X    perl -p -i.bak -e 's/savestr/psvestr/g;' $(UPERL)
  301. X
  302. Xclean:
  303. X    rm -f sybperl *.o *~ core
  304. X
  305. Xinstall: sybperl
  306. X    install -s -m 775 sybperl $(BINDIR)
  307. X    cp lib/syb*.p? $(PERLLIB)/perllib.pl
  308. X    cp sybperl.1 $(MANDIR)/man$(MANEXT)/sybperl.$(MANEXT)
  309. X
  310. Xshar:
  311. X    rm -f sybperl.shar
  312. X    shar.pl README PACKING.LST BUGS CHANGES Makefile sybperl.c \
  313. X    sybperl.1 patchlevel.h lib/sybperl.pl lib/sybdb.ph t/sbex.pl \
  314. X    eg/sql.pl eg/space.pl eg/capture.pl eg/report.pl >sybperl.shar
  315. X
  316. X
  317. X
  318. END_OF_FILE
  319.   if test 2598 -ne `wc -c <'Makefile'`; then
  320.     echo shar: \"'Makefile'\" unpacked with wrong size!
  321.   fi
  322.   # end of 'Makefile'
  323. fi
  324. if test -f 'PACKING.LST' -a "${1}" != "-c" ; then 
  325.   echo shar: Will not clobber existing file \"'PACKING.LST'\"
  326. else
  327.   echo shar: Extracting \"'PACKING.LST'\" \(725 characters\)
  328.   sed "s/^X//" >'PACKING.LST' <<'END_OF_FILE'
  329. X
  330. X
  331. X    
  332. X    The Sybperl package should contain the following files:
  333. X
  334. X
  335. X        PACKING.LST        This file
  336. X        README        Read Me!
  337. X        BUGS        Perl/DB-library incompatibility description
  338. X        CHANGES
  339. X        Makefile
  340. X        sybperl.c        Sybperl source
  341. X        sybperl.1        Man page
  342. X        patchlevel.h
  343. X        t/sbex.pl        Example of sybperl script
  344. X        lib/sybperl.pl  A Perl library file.
  345. X        lib/sybdb.ph    Some of the DB-Library include files, run
  346. X                through h2ph.
  347. X        eg/space.pl        How much space does your sybase databases use?
  348. X        eg/capture.pl   Create a table extracted from /etc/passwd
  349. X        eg/report.pl    Report from table created by capture.pl
  350. X        eg/sql.pl        Utility routines used by the above example programs.
  351. X        
  352. END_OF_FILE
  353.   if test 725 -ne `wc -c <'PACKING.LST'`; then
  354.     echo shar: \"'PACKING.LST'\" unpacked with wrong size!
  355.   fi
  356.   # end of 'PACKING.LST'
  357. fi
  358. if test ! -d 'eg' ; then
  359.     echo shar: Creating directory \"'eg'\"
  360.     mkdir 'eg'
  361. fi
  362. if test -f 'eg/capture.pl' -a "${1}" != "-c" ; then 
  363.   echo shar: Will not clobber existing file \"'eg/capture.pl'\"
  364. else
  365.   echo shar: Extracting \"'eg/capture.pl'\" \(1606 characters\)
  366.   sed "s/^X//" >'eg/capture.pl' <<'END_OF_FILE'
  367. X#! /usr/local/bin/sybperl
  368. X
  369. Xrequire "sybperl.pl";
  370. Xrequire "sql.pl";
  371. X
  372. X#
  373. X# Log us in to Sybase.
  374. X#
  375. X$d = &dblogin;
  376. X
  377. X&sql($d, "set statistics io on");
  378. X&sql($d, "set statistics time on");
  379. X
  380. X#
  381. X# Count the number off password tables.
  382. X#
  383. X@results = &sql($d, '
  384. X        select count(*) from sysobjects
  385. X        where name = "password" and type = "U"'
  386. X       );
  387. X
  388. X#
  389. X# If there is none create it else truncate it.
  390. X#
  391. Xif(@results[0] == 0) {
  392. X    &sql($d, '
  393. X        create table password(
  394. X            username char(8),
  395. X            uid int,
  396. X            gid int,
  397. X            shell varchar(30),
  398. X            home varchar(30)
  399. X        )'
  400. X    );
  401. X    print "The password table has been created.\n";
  402. X} else {
  403. X    &sql($d, 'truncate table password');
  404. X    print "The password table already exists. Table truncated!\n";
  405. X};
  406. X
  407. X#
  408. X# Read the password entries and add them to the database.
  409. X#
  410. Xwhile (($n,$p,$u,$g,$q,$c,$gc,$d,$s)= getpwent) {
  411. X    print "Adding $n.\n";
  412. X    &sql($d, "
  413. X        insert password
  414. X        values(\"$n\", $u, $g, \"$s\", \"$d\")
  415. X        "
  416. X    );
  417. X};
  418. Xendpwent;
  419. X
  420. X#
  421. X# Count the number off group tables.
  422. X#
  423. X@results = &sql($d, '
  424. X        select count(*) from sysobjects
  425. X        where name = "groups" and type = "U"'
  426. X       );
  427. X
  428. X#
  429. X# If there is none create it else truncate it.
  430. X#
  431. Xif(@results[0] == 0) {
  432. X    &sql($d, '
  433. X        create table groups(
  434. X            groupname char(8),
  435. X            gid int
  436. X        )'
  437. X    );
  438. X    print "The groups table has been created.\n";
  439. X} else {
  440. X    &sql($d, 'truncate table groups');
  441. X    print "The groups table already exists. Table truncated!\n";
  442. X};
  443. X
  444. X#
  445. X# Read the group entries and add them to the database.
  446. X#
  447. Xwhile (($gn,$gp,$gg,$gm)= getgrent) {
  448. X    print "Adding group $gn.\n";
  449. X    &sql($d, "
  450. X        insert groups
  451. X        values(\"$gn\", $gg)
  452. X        "
  453. X    );
  454. X};
  455. Xendgrent;
  456. X
  457. END_OF_FILE
  458.   if test 1606 -ne `wc -c <'eg/capture.pl'`; then
  459.     echo shar: \"'eg/capture.pl'\" unpacked with wrong size!
  460.   fi
  461.   chmod +x 'eg/capture.pl'
  462.   # end of 'eg/capture.pl'
  463. fi
  464. if test -f 'eg/report.pl' -a "${1}" != "-c" ; then 
  465.   echo shar: Will not clobber existing file \"'eg/report.pl'\"
  466. else
  467.   echo shar: Extracting \"'eg/report.pl'\" \(720 characters\)
  468.   sed "s/^X//" >'eg/report.pl' <<'END_OF_FILE'
  469. X#! /usr/local/bin/sybperl
  470. X
  471. Xrequire "sybperl.pl";
  472. Xrequire "sql.pl";
  473. X
  474. X#
  475. X# Log us in to Sybase.
  476. X#
  477. X$d = &dblogin;
  478. X
  479. X#
  480. X# define the format
  481. X#
  482. Xformat top=
  483. X             PASSWORD FILE
  484. XLogin      Uid Group      Shell                   Home directory
  485. X-------- ----- ---------- ----------------------- ----------------------
  486. X. 
  487. Xformat stdout=
  488. X@<<<<<<< @>>>> @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<
  489. X$n,      $u,   $gn,       $s,                     $d
  490. X. 
  491. X
  492. X#
  493. X# See if everything is there.
  494. X#
  495. X@results = &sql($d, '
  496. X    select username, uid, isnull(groupname,convert(char,p.gid)), shell, home
  497. X    from password p, groups g
  498. X    where    p.gid *= g.gid
  499. X    order by uid
  500. X    ');
  501. Xforeach $x (@results) {
  502. X    ($n,$u,$gn,$s,$d) = split("~",$x);
  503. X    write;
  504. X}
  505. X
  506. END_OF_FILE
  507.   if test 720 -ne `wc -c <'eg/report.pl'`; then
  508.     echo shar: \"'eg/report.pl'\" unpacked with wrong size!
  509.   fi
  510.   chmod +x 'eg/report.pl'
  511.   # end of 'eg/report.pl'
  512. fi
  513. if test -f 'eg/space.pl' -a "${1}" != "-c" ; then 
  514.   echo shar: Will not clobber existing file \"'eg/space.pl'\"
  515. else
  516.   echo shar: Extracting \"'eg/space.pl'\" \(1384 characters\)
  517.   sed "s/^X//" >'eg/space.pl' <<'END_OF_FILE'
  518. X#! /usr/local/bin/sybperl
  519. X
  520. Xrequire "sybperl.pl";
  521. Xrequire "sql.pl";
  522. X
  523. X#
  524. X# Log us in to Sybase.
  525. X#
  526. Xprint "Server: ";
  527. X$server = <>; chop($server);
  528. Xif($server ne '')
  529. X{
  530. X    $ENV{'DSQUERY'};
  531. X}
  532. Xelse
  533. X{
  534. X    $server = $ENV{'DSQUERY'};
  535. X}
  536. X
  537. Xprint "SA password: ";
  538. X$sapw = <>; chop($sapw);
  539. X
  540. X$d = &dblogin("sa", $sapw);
  541. X
  542. X
  543. X$server = $server . '.';
  544. X
  545. X
  546. X&sql($d, "use master");
  547. X@dbs = &sql($d, "select name from sysdatabases order by name");
  548. X
  549. Xforeach $n (@dbs) {
  550. X    &sql($d, "use $n");
  551. X    $x = join('~', &sql($d, 'sp_spaceused'));
  552. X    $x =~ s/ //g;
  553. X    $x =~ s/MB|KB//g;
  554. X    ($name, $size, $res, $data, $index, $free ) = split("~",$x);
  555. X    $unused = $size * 1024 - $res;
  556. X    write;
  557. X    $ts += $size;
  558. X    $tr += $res;
  559. X    $td += $data;
  560. X    $ti += $index;
  561. X    $tf += $free;
  562. X}
  563. X
  564. Xprint '-' x 78, "\n"; 
  565. X$name = 'TOTAL';
  566. X$size = $ts;
  567. X$res = $tr;
  568. X$data = $td;
  569. X$index = $ti;
  570. X$free = $tf;
  571. X$unused = $size * 1024 - $res;
  572. Xwrite;
  573. X
  574. Xformat top=
  575. XSpace usage per database for server @<<<<<<<<<<<<<<<
  576. X                    $server
  577. XName             Size    Reserved       Data      Index       Free     Unused
  578. X             (MB)        (KB)       (KB)       (KB)       (KB)       (KB)
  579. X-----------------------------------------------------------------------------
  580. X. 
  581. Xformat stdout=
  582. X@<<<<<<<<<  @>>>>>>>>  @>>>>>>>>>  @>>>>>>>>  @>>>>>>>>  @>>>>>>>>  @>>>>>>>>
  583. X$name,      $size,     $res,       $data,     $index,    $free,     $unused
  584. X. 
  585. X
  586. X
  587. END_OF_FILE
  588.   if test 1384 -ne `wc -c <'eg/space.pl'`; then
  589.     echo shar: \"'eg/space.pl'\" unpacked with wrong size!
  590.   fi
  591.   chmod +x 'eg/space.pl'
  592.   # end of 'eg/space.pl'
  593. fi
  594. if test -f 'eg/sql.pl' -a "${1}" != "-c" ; then 
  595.   echo shar: Will not clobber existing file \"'eg/sql.pl'\"
  596. else
  597.   echo shar: Extracting \"'eg/sql.pl'\" \(1708 characters\)
  598.   sed "s/^X//" >'eg/sql.pl' <<'END_OF_FILE'
  599. Xsub sql {
  600. X    local($db,$sql,$sep)=@_;            # local copy parameters
  601. X
  602. X    $sep = '~' unless $sep;            # provide default for sep
  603. X
  604. X    @res = ();                    # clear result array
  605. X
  606. X    &dbcmd($db,$sql);                # pass sql to server
  607. X    &dbsqlexec($db);                # execute sql
  608. X
  609. X    while(&dbresults($db) != $NO_MORE_RESULTS) {    # copy all results
  610. X    while (@data = &dbnextrow($db1)) {
  611. X        push(@res,join($sep,@data));
  612. X    }
  613. X    }
  614. X
  615. X    @res;                    # return the result array
  616. X}
  617. X
  618. X
  619. X# Message and error handlers.
  620. X
  621. Xsub sql_message_handler
  622. X{
  623. X    local ($db, $message, $state, $severity, $text, $server, $procedure, $line)
  624. X    = @_;
  625. X
  626. X    if ($severity > 0)
  627. X    {
  628. X    print ("Sybase message ", $message, ", Severity ", $severity,
  629. X           ", state ", $state);
  630. X    print ("\nServer `", $server, "'") if defined ($server);
  631. X    print ("\nProcedure `", $procedure, "'") if defined ($procedure);
  632. X    print ("\nLine ", $line) if defined ($line);
  633. X    print ("\n    ", $text, "\n\n");
  634. X
  635. X# &dbstrcpy returns the command buffer.
  636. X
  637. X    local ($lineno) = 1;    # 
  638. X    foreach $row (split (/\n/, &dbstrcpy ($db)))
  639. X    {
  640. X        print (sprintf ("%5d", $lineno ++), "> ", $row, "\n");
  641. X    }
  642. X    }
  643. X    elsif ($message == 0)
  644. X    {
  645. X    print ($text, "\n");
  646. X    }
  647. X    
  648. X    0;
  649. X}
  650. X
  651. Xsub sql_error_handler {
  652. X    # Check the error code to see if we should report this.
  653. X    if ($_[2] != &SYBESMSG) {
  654. X    local ($db, $severity, $error, $os_error, $error_msg, $os_error_msg)
  655. X        = @_;
  656. X    print ("Sybase error: ", $error_msg, "\n");
  657. X    print ("OS Error: ", $os_error_msg, "\n") if defined ($os_error_msg);
  658. X    }
  659. X
  660. X    &INT_CANCEL;
  661. X}
  662. X
  663. X
  664. Xif( defined(&dbmsghandle))    # Is this a modern version of sybperl? ;-)
  665. X{
  666. X    &dbmsghandle ("sql_message_handler"); # Some user defined error handlers
  667. X    &dberrhandle ("sql_error_handler");
  668. X}
  669. X
  670. X
  671. X1;
  672. X
  673. END_OF_FILE
  674.   if test 1708 -ne `wc -c <'eg/sql.pl'`; then
  675.     echo shar: \"'eg/sql.pl'\" unpacked with wrong size!
  676.   fi
  677.   chmod +x 'eg/sql.pl'
  678.   # end of 'eg/sql.pl'
  679. fi
  680. if test ! -d 'lib' ; then
  681.     echo shar: Creating directory \"'lib'\"
  682.     mkdir 'lib'
  683. fi
  684. if test -f 'lib/sybdb.ph' -a "${1}" != "-c" ; then 
  685.   echo shar: Will not clobber existing file \"'lib/sybdb.ph'\"
  686. else
  687.   echo shar: Extracting \"'lib/sybdb.ph'\" \(2788 characters\)
  688.   sed "s/^X//" >'lib/sybdb.ph' <<'END_OF_FILE'
  689. X;#    @(#)sybdb.ph    1.1    11/8/91
  690. X;#
  691. X;#
  692. X
  693. Xsub SYBESYNC {20001;}
  694. Xsub SYBEFCON {20002;}
  695. Xsub SYBETIME {20003;}
  696. Xsub SYBEREAD {20004;}
  697. Xsub SYBEBUFL {20005;}
  698. Xsub SYBEWRIT {20006;}
  699. Xsub SYBEVMS {20007;}
  700. Xsub SYBESOCK {20008;}
  701. Xsub SYBECONN {20009;}
  702. Xsub SYBEMEM {20010;}
  703. Xsub SYBEDBPS {20011;}
  704. Xsub SYBEINTF {20012;}
  705. Xsub SYBEUHST {20013;}
  706. Xsub SYBEPWD {20014;}
  707. Xsub SYBEOPIN {20015;}
  708. Xsub SYBEINLN {20016;}
  709. Xsub SYBESEOF {20017;}
  710. Xsub SYBESMSG {20018;}
  711. Xsub SYBERPND {20019;}
  712. Xsub SYBEBTOK {20020;}
  713. Xsub SYBEITIM {20021;}
  714. Xsub SYBEOOB {20022;}
  715. Xsub SYBEBTYP {20023;}
  716. Xsub SYBEBNCR {20024;}
  717. Xsub SYBEIICL {20025;}
  718. Xsub SYBECNOR {20026;}
  719. Xsub SYBENPRM {20027;}
  720. Xsub SYBEUVDT {20028;}
  721. Xsub SYBEUFDT {20029;}
  722. Xsub SYBEWAID {20030;}
  723. Xsub SYBECDNS {20031;}
  724. Xsub SYBEABNC {20032;}
  725. Xsub SYBEABMT {20033;}
  726. Xsub SYBEABNP {20034;}
  727. Xsub SYBEAAMT {20035;}
  728. Xsub SYBENXID {20036;}
  729. Xsub SYBERXID {20037;}
  730. Xsub SYBEICN {20038;}
  731. Xsub SYBENMOB {20039;}
  732. Xsub SYBEAPUT {20040;}
  733. Xsub SYBEASNL {20041;}
  734. Xsub SYBENTLL {20042;}
  735. Xsub SYBEASUL {20043;}
  736. Xsub SYBERDNR {20044;}
  737. Xsub SYBENSIP {20045;}
  738. Xsub SYBEABNV {20046;}
  739. Xsub SYBEDDNE {20047;}
  740. Xsub SYBECUFL {20048;}
  741. Xsub SYBECOFL {20049;}
  742. Xsub SYBECSYN {20050;}
  743. Xsub SYBECLPR {20051;}
  744. Xsub SYBECNOV {20052;}
  745. Xsub SYBERDCN {20053;}
  746. Xsub SYBESFOV {20054;}
  747. Xsub SYBEUNT {20055;}
  748. Xsub SYBECLOS {20056;}
  749. Xsub SYBEUAVE {20057;}
  750. Xsub SYBEUSCT {20058;}
  751. Xsub SYBEEQVA {20059;}
  752. Xsub SYBEUDTY {20060;}
  753. Xsub SYBETSIT {20061;}
  754. Xsub SYBEAUTN {20062;}
  755. Xsub SYBEBDIO {20063;}
  756. Xsub SYBEBCNT {20064;}
  757. Xsub SYBEIFNB {20065;}
  758. Xsub SYBETTS {20066;}
  759. Xsub SYBEKBCO {20067;}
  760. Xsub SYBEBBCI {20068;}
  761. Xsub SYBEKBCI {20069;}
  762. Xsub SYBEBCRE {20070;}
  763. Xsub SYBETPTN {20071;}
  764. Xsub SYBEBCWE {20072;}
  765. Xsub SYBEBCNN {20073;}
  766. Xsub SYBEBCOR {20074;}
  767. Xsub SYBEBCIS {20075;}
  768. Xsub SYBEBCPI {20076;}
  769. Xsub SYBEBCPN {20077;}
  770. Xsub SYBEBCPB {20078;}
  771. Xsub SYBEVDPT {20079;}
  772. Xsub SYBEBIVI {20080;}
  773. Xsub SYBEBCBC {20081;}
  774. Xsub SYBEBCFO {20082;}
  775. Xsub SYBEBCVH {20083;}
  776. Xsub SYBEBCUO {20084;}
  777. Xsub SYBEBCUC {20085;}
  778. Xsub SYBEBUOE {20086;}
  779. Xsub SYBEBUCE {20087;}
  780. Xsub SYBEBWEF {20088;}
  781. Xsub SYBEASTF {20089;}
  782. Xsub SYBEUACS {20090;}
  783. Xsub SYBEASEC {20091;}
  784. Xsub SYBETMTD {20092;}
  785. Xsub SYBENTTN {20093;}
  786. Xsub SYBEDNTI {20094;}
  787. Xsub SYBEBTMT {20095;}
  788. Xsub SYBEORPF {20096;}
  789. Xsub SYBEUVBF {20097;}
  790. Xsub SYBEBUOF {20098;}
  791. Xsub SYBEBUCF {20099;}
  792. Xsub SYBEBRFF {20100;}
  793. Xsub SYBEBWFF {20101;}
  794. Xsub SYBEBUDF {20102;}
  795. Xsub SYBEBIHC {20103;}
  796. Xsub SYBEBEOF {20104;}
  797. Xsub SYBEBCNL {20105;}
  798. Xsub SYBEBCSI {20106;}
  799. Xsub SYBEBCIT {20107;}
  800. Xsub SYBEBCSA {20108;}
  801. Xsub SYBENULL {20109;}
  802. Xsub SYBEUNAM {20110;}
  803. Xsub SYBEBCRO {20111;}
  804. Xsub SYBEMPLL {20112;}
  805. Xsub SYBERPIL {20113;}
  806. Xsub SYBERPUL {20114;}
  807. Xsub SYBEUNOP {20115;}
  808. Xsub SYBECRNC {20116;}
  809. Xsub SYBERTCC {20117;}
  810. Xsub SYBERTSC {20118;}
  811. Xsub SYBEUCRR {20119;}
  812. Xsub SYBERPNA {20120;}
  813. Xsub SYBEOPNA {20121;}
  814. X
  815. Xsub SUCCEED {1;}
  816. Xsub FAIL {0;}
  817. X
  818. Xsub INT_EXIT {0;}
  819. Xsub INT_CONTINUE {1;}
  820. Xsub INT_CANCEL {2;}
  821. X
  822. X1;
  823. X
  824. END_OF_FILE
  825.   if test 2788 -ne `wc -c <'lib/sybdb.ph'`; then
  826.     echo shar: \"'lib/sybdb.ph'\" unpacked with wrong size!
  827.   fi
  828.   # end of 'lib/sybdb.ph'
  829. fi
  830. if test -f 'lib/sybperl.pl' -a "${1}" != "-c" ; then 
  831.   echo shar: Will not clobber existing file \"'lib/sybperl.pl'\"
  832. else
  833.   echo shar: Extracting \"'lib/sybperl.pl'\" \(464 characters\)
  834.   sed "s/^X//" >'lib/sybperl.pl' <<'END_OF_FILE'
  835. X;#     @(#)sybperl.pl    1.2    11/25/91
  836. X
  837. X;# This file, when interpreted, sets the appropriate environment
  838. X;# variables for Sybase's use DB-Library & isql.
  839. X;#
  840. X;# usage:
  841. X;#    require 'sybperl.pl';
  842. X;#
  843. X;# We don't set the environment if it is already set.
  844. X
  845. Xrequire 'sybdb.ph';
  846. X
  847. X$ENV{'SYBASE'} = "/usr/local/sybase" unless $ENV{'SYBASE'};
  848. X$ENV{'DSQUERY'}= "SYBASE" unless $ENV{'DSQUERY'};
  849. X$ENV{'PATH'}="$ENV{'PATH'}:$ENV{'SYBASE'}/bin" unless $ENV{'PATH'} =~ /$ENV{'SYBASE'}/;
  850. X
  851. X
  852. END_OF_FILE
  853.   if test 464 -ne `wc -c <'lib/sybperl.pl'`; then
  854.     echo shar: \"'lib/sybperl.pl'\" unpacked with wrong size!
  855.   fi
  856.   # end of 'lib/sybperl.pl'
  857. fi
  858. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  859.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  860. else
  861.   echo shar: Extracting \"'patchlevel.h'\" \(41 characters\)
  862.   sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  863. X#define VERSION 1
  864. X#define PATCHLEVEL 4
  865. X
  866. X
  867. END_OF_FILE
  868.   if test 41 -ne `wc -c <'patchlevel.h'`; then
  869.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  870.   fi
  871.   # end of 'patchlevel.h'
  872. fi
  873. if test -f 'sybperl.1' -a "${1}" != "-c" ; then 
  874.   echo shar: Will not clobber existing file \"'sybperl.1'\"
  875. else
  876.   echo shar: Extracting \"'sybperl.1'\" \(3426 characters\)
  877.   sed "s/^X//" >'sybperl.1' <<'END_OF_FILE'
  878. X.\".po 4
  879. X.TH SYBPERL 1 "3 September 1991"
  880. X.ad
  881. X.nh
  882. X.SH NAME
  883. Xsybperl \- Perl access to Sybase databases
  884. X.SH SYNOPSIS
  885. X.nf
  886. X$dbproc  = &dblogin([$user[, $pwd]])
  887. X$dbproc1 = &dbopen()
  888. X       &dbclose($dbproc)
  889. X$ret     = &dbcmd($dbproc, $sql_cmd)
  890. X$ret     = &dbsqlexec($dbproc)
  891. X$ret     = &dbresults($dbproc)
  892. X@data    = &dbnextrow($dbproc)
  893. X$ret     = &dbuse($dbproc, $database)
  894. X$ret     = &dbcancel($dbproc)
  895. X$ret     = &dbcanquery($dbproc)
  896. X$ret     = &dbexit($dbproc)
  897. X$string  = &dbstrcpy($dbproc)
  898. X$ret     = &dberrhandle($handler)
  899. X$ret     = &dbmsghandle($handler)
  900. X
  901. X$SUCCEED
  902. X$FAIL
  903. X$NO_MORE_ROWS
  904. X$NO_MORE_RESULTS
  905. X$ComputeId
  906. X$DBstatus
  907. X$SybperlVer
  908. X.fi
  909. X.SH DESCRIPTION
  910. X\fBSybperl\fP is a version of \fIPerl\fP which has been extended (via
  911. Xthe \fIusersubs\fP feature) to allow access to \fISybase\fP databases.
  912. X.SH Functions
  913. X\fBSybperl\fP basically maps the calls existing in the \fISybase
  914. XDB-Library\fP to \fIPerl\fP. The usage of these functions is the same
  915. Xas in \fIDB-Library\fP, unless specifically noted.
  916. X
  917. XThe following functions are provided:
  918. X
  919. X.nf
  920. X\fB$dbproc  = &dblogin([$user[, $pwd]])\fP
  921. X\fB&dbproc1 = &dbopen()\fP
  922. X\fB          &dbclose($dbproc)\fP
  923. X\fB$status  = &dbcmd($dbproc, $sql_cmd)\fP
  924. X\fB$status  = &dbsqlexec($dbproc)\fP
  925. X\fB$status  = &dbresults($dbproc)\fP
  926. X\fB@data    = &dbnextrow($dbproc)\fP
  927. X\fB$status  = &dbuse($dbproc, $database)\fP
  928. X\fB$status  = &dbcancel($dbproc)\fP
  929. X\fB$status  = &dbcanquery($dbproc)\fP
  930. X\fB$status  = &dbexit($dbproc)\fP
  931. X\fB$string  = &dbstrcpy($dbproc)\fP
  932. X\fB$old_handler  = &dberrhandle($handler)\fP
  933. X\fB$old_handler  = &dbmsghandle($handler)\fP
  934. X.fi
  935. X
  936. XDifferences with DB-Library:
  937. X
  938. X\fB&dblogin\fP takes 2 optional arguements (the userid and the
  939. Xpassword). These default to the Unix userid, and the null password.
  940. X
  941. X\fB&dblogin\fP returns a \fBDBPROCESS\fP, not a \fBLOGINREC\fP. This
  942. Xsimplifies the call to open a connection to a Sybase dataserver
  943. Xsomewhat. Further \fBDBPROCESSes\fP can be opened using
  944. X\fB&dbopen()\fP (No arguments). The number of simultaneous DBPROCESSes
  945. Xis limited to 25 (This can be changed by altering a #define in sybperl.c).
  946. X
  947. XThe \fB$dbproc\fP parameter is optional, and defaults to the DBPROCESS returned
  948. Xby \fB&dblogin\fP.
  949. X
  950. X\fB&dbnextrow\fP returns an array of formatted data, based on the
  951. Xdatatype of the corresponding columns. \fB&dbnextrow\fP sets the
  952. Xvariable \fB$ComputeId\fP when the result row is a computed row (the
  953. Xresult of a \fIcompute by\fP clause).
  954. X
  955. X.SH "UNIMPLEMENTED FEATURES"
  956. X
  957. XThe \fBSYBIMAGE\fP data type is not implemented.
  958. X
  959. XThe \fBSYBTEXT\fP data type is only implemented for reading (ie
  960. X\fIdbmoretext()\fP is not implemented).
  961. X
  962. X\fB&dbfcmd\fP is not implemented, but can be emulated by using
  963. X\fIsprintf\fP as in \fI&dbcmd($dbproc, sprintf("%d", $num_val))\;\fP
  964. X
  965. XOne cannot log in to a specific server (ie \fIdbopen()\fP is always
  966. Xcalled with a \fINULL\fP second parameter. However, setting the
  967. X\fBDSQUERY\fP environment variable (as in \fI$ENV{'DSQUERY'} =
  968. X$server\fP) will work.
  969. X
  970. X.SH OPTIONS
  971. X
  972. XSee the \fIPerl(1)\fP manual page.
  973. X
  974. X.SH FILES
  975. X
  976. X\fI$PERLLIB/sybperl.pl\fP should be called in all \fBsybperl\fP
  977. Xscripts to set the correct environment variables used by DB-Library.
  978. XA sample \fI$PERLLIB/sybdb.ph\fP is provided with sybperl. You may
  979. Xwant to use \fBh2ph\fP to add definitions to this file.
  980. X
  981. X.SH "SEE ALSO"
  982. X
  983. X\fIPerl(1L), Sybase Open Client DB Library Reference Manual, h2ph(1L).\fP
  984. X
  985. X.SH AUTHOR
  986. X
  987. XMichael Peppler, ITF Management SA \- mpeppler@itf.ch
  988. END_OF_FILE
  989.   if test 3426 -ne `wc -c <'sybperl.1'`; then
  990.     echo shar: \"'sybperl.1'\" unpacked with wrong size!
  991.   fi
  992.   # end of 'sybperl.1'
  993. fi
  994. if test -f 'sybperl.c' -a "${1}" != "-c" ; then 
  995.   echo shar: Will not clobber existing file \"'sybperl.c'\"
  996. else
  997.   echo shar: Extracting \"'sybperl.c'\" \(23786 characters\)
  998.   sed "s/^X//" >'sybperl.c' <<'END_OF_FILE'
  999. Xstatic char SccsId[] = "@(#)sybperl.c    1.9    12/20/91";
  1000. X/************************************************************************/
  1001. X/*    Copyright 1991 by Michael Peppler and ITF Management SA     */
  1002. X/*                                    */
  1003. X/*    Full ownership of this software, and all rights pertaining to     */
  1004. X/*    the for-profit distribution of this software, are retained by     */
  1005. X/*    Michael Peppler and ITF Management SA.  You are permitted to     */
  1006. X/*    use this software without fee.  This software is provided "as     */
  1007. X/*    is" without express or implied warranty.  You may redistribute     */
  1008. X/*    this software, provided that this copyright notice is retained,    */
  1009. X/*    and that the software is not distributed for profit.  If you     */
  1010. X/*    wish to use this software in a profit-making venture, you must     */
  1011. X/*    first license this code and its underlying technology from     */
  1012. X/*    ITF Management SA.                         */
  1013. X/*                                    */
  1014. X/*    Bottom line: you can have this software, you can use it, you     */
  1015. X/*    can give it away.  You just can't sell any or all parts of it     */
  1016. X/*    without prior permission from ITF Management SA.        */
  1017. X/************************************************************************/
  1018. X
  1019. X/* sybperl.c
  1020. X *
  1021. X * Call Sybase DB-Library functions from Perl.
  1022. X * Written by Michael Peppler (mpeppler@itf.ch)
  1023. X * ITF Management SA, 13 rue de la Fontaine
  1024. X * CH-1204 Geneva, Switzerland
  1025. X * Tel: (+4122) 312 1311 Fax: (+4122) 312 1322
  1026. X */
  1027. X
  1028. X/* 
  1029. X * The Perl/Sybase savestr() conflict.
  1030. X * Both Perl and Sybase DB-Library have a function called savestr(). 
  1031. X * This creates a problem when calling dbcmd() and dbuse(). There are 
  1032. X * several ways to work around this, one of which is to #define 
  1033. X * BROKEN_DBCMD, which enables some code that I've written to simulate 
  1034. X * dbcmd() locally. See Makefile and BUGS for details.
  1035. X */
  1036. X#include "EXTERN.h"
  1037. X#include "perl.h"
  1038. X#undef MAX
  1039. X#undef MIN
  1040. X
  1041. X#if !defined(VERSION3)
  1042. X#define str_2static(s)        str_2mortal(s)
  1043. X#endif
  1044. X
  1045. X#include <sybfront.h>
  1046. X#include <sybdb.h>
  1047. X#include <syberror.h>
  1048. X
  1049. X#include "patchlevel.h"
  1050. X
  1051. Xextern int wantarray;
  1052. X
  1053. X/* 
  1054. X * The variables that the Sybase routines set, and that you may want 
  1055. X * to test in your Perl script. These variables are READ-ONLY.
  1056. X */
  1057. Xstatic enum uservars
  1058. X{
  1059. X    UV_SUCCEED,            /* Returns SUCCEED */
  1060. X    UV_FAIL,            /* Returns FAIL */
  1061. X    UV_NO_MORE_ROWS,        /* Returns NO_MORE_ROWS */
  1062. X    UV_NO_MORE_RESULTS,        /* Returns NO_MORE_RESULTS */
  1063. X    UV_ComputeId,        /* Returns the compute id of the row (in dbnextrow()) */
  1064. X    UV_SybperlVer,        /* Returns Sybperl Version/Patchlevel */
  1065. X    UV_DBstatus,        /* The value status value of the last dbnextrow() call */
  1066. X};
  1067. X
  1068. X/* 
  1069. X * User subroutines that we have implemented. I've found that I can do 
  1070. X * all the stuff I want to with this subset of DB-Library. Let me know 
  1071. X * if you implement further routines.
  1072. X * The names are self-explanatory.
  1073. X */
  1074. Xstatic enum usersubs
  1075. X{
  1076. X    US_dblogin,            /* This also performs the first dbopen()  */
  1077. X    US_dbopen,
  1078. X    US_dbclose,
  1079. X    US_dbcmd,
  1080. X    US_dbsqlexec,
  1081. X    US_dbresults,
  1082. X    US_dbnextrow,
  1083. X    US_dbcancel,
  1084. X    US_dbcanquery,
  1085. X    US_dbexit,
  1086. X    US_dbuse,
  1087. X#ifdef HAS_CALLBACK
  1088. X    US_dberrhandle,
  1089. X    US_dbmsghandle,
  1090. X#endif
  1091. X    US_dbstrcpy,
  1092. X};
  1093. X
  1094. X#ifndef MAX_DBPROCS
  1095. X#define MAX_DBPROCS 25        /* Change this if you really want your perl script to talk to */
  1096. X                /* more than 25 dataserver connections at a time ...*/
  1097. X#endif
  1098. X
  1099. Xstatic LOGINREC *login;
  1100. Xstatic DBPROCESS *dbproc[MAX_DBPROCS];
  1101. Xstatic int exitCalled = 0;    /* Set to 1 if dbexit() has been called. */
  1102. Xstatic int ComputeId;
  1103. Xstatic int DBstatus;        /* Set by dbnextrow() */
  1104. X
  1105. X/* Stack pointer for the error routines.  This is set to the stack pointer
  1106. X   when entering into the sybase subroutines.  Error and message
  1107. X   handling needs this.  */
  1108. X
  1109. Xstatic int perl_sp;
  1110. X
  1111. X/* Current error handler name. */
  1112. X
  1113. Xstatic char *err_handler_sub;
  1114. X
  1115. X/* Current message handler subroutine name */
  1116. X
  1117. Xstatic char *msg_handler_sub;
  1118. X
  1119. X/* Macro to access the stack.  This is necessary since error handlers may
  1120. X   call perl routines and thus the stack may change.  I hope most compilers
  1121. X   will optimize this reasonably. */
  1122. X
  1123. X#define STACK(SP) (stack->ary_array + (SP))
  1124. X
  1125. X
  1126. Xstatic int usersub();
  1127. Xstatic int userset();
  1128. Xstatic int userval();
  1129. Xstatic int err_handler(), msg_handler();
  1130. X
  1131. Xint userinit()
  1132. X{
  1133. X    init_sybase();
  1134. X}
  1135. X
  1136. Xint
  1137. Xinit_sybase()
  1138. X{
  1139. X    struct ufuncs uf;
  1140. X    char *filename = "sybase.c";
  1141. X
  1142. X    if (dbinit() == FAIL)    /* initialize dblibrary */
  1143. X    exit(ERREXIT);
  1144. X/*
  1145. X * Install the user-supplied error-handling and message-handling routines.
  1146. X * They are defined at the bottom of this source file.
  1147. X */
  1148. X    dberrhandle(err_handler);
  1149. X    dbmsghandle(msg_handler);
  1150. X
  1151. X    if(MAX_DBPROCS > 25)
  1152. X    dbsetmaxprocs(MAX_DBPROCS);
  1153. X    
  1154. X    uf.uf_set = userset;
  1155. X    uf.uf_val = userval;
  1156. X
  1157. X#define MAGICVAR(name, ix) uf.uf_index = ix, magicname(name, &uf, sizeof uf)
  1158. X
  1159. X    MAGICVAR("SUCCEED",    UV_SUCCEED);
  1160. X    MAGICVAR("FAIL",UV_FAIL);
  1161. X    MAGICVAR("NO_MORE_ROWS",    UV_NO_MORE_ROWS);
  1162. X    MAGICVAR("NO_MORE_RESULTS",    UV_NO_MORE_RESULTS);
  1163. X    MAGICVAR("ComputeId",    UV_ComputeId);
  1164. X    MAGICVAR("SybperlVer",    UV_SybperlVer);
  1165. X
  1166. X    make_usub("dblogin",    US_dblogin,    usersub, filename);
  1167. X    make_usub("dbopen",        US_dbopen,    usersub, filename);
  1168. X    make_usub("dbclose",    US_dbclose,    usersub, filename);
  1169. X    make_usub("dbcmd",        US_dbcmd,    usersub, filename);
  1170. X    make_usub("dbsqlexec",    US_dbsqlexec,    usersub, filename);
  1171. X    make_usub("dbresults",    US_dbresults,    usersub, filename);
  1172. X    make_usub("dbnextrow",    US_dbnextrow,    usersub, filename);
  1173. X    make_usub("dbcancel",    US_dbcancel,    usersub, filename);
  1174. X    make_usub("dbcanquery",    US_dbcanquery,    usersub, filename);
  1175. X    make_usub("dbexit",    US_dbexit,    usersub, filename);
  1176. X    make_usub("dbuse",    US_dbuse,    usersub, filename);
  1177. X#ifdef HAS_CALLBACK
  1178. X    make_usub("dberrhandle", US_dberrhandle, usersub, filename);
  1179. X    make_usub("dbmsghandle", US_dbmsghandle, usersub, filename);
  1180. X#endif
  1181. X    make_usub("dbstrcpy", US_dbstrcpy, usersub, filename);
  1182. X
  1183. X}
  1184. X
  1185. Xstatic int
  1186. Xusersub(ix, sp, items)
  1187. Xint ix;
  1188. Xregister int sp;
  1189. Xregister int items;
  1190. X{
  1191. X    STR **st = stack->ary_array + sp;
  1192. X    ARRAY *ary = stack;    
  1193. X    register int i;
  1194. X    register STR *Str;        /* used in str_get and str_gnum macros */
  1195. X    int inx = -1;        /* Index into dbproc[] array. Passed as first parameter to nearly all &dbxxx() calls */
  1196. X
  1197. X
  1198. X    if(exitCalled)
  1199. X    fatal("&dbexit() has been called. Access to Sybase impossible.");
  1200. X
  1201. X    perl_sp = sp + items;
  1202. X
  1203. X    /* 
  1204. X     * We're calling some dblib function, but dblogin has not been 
  1205. X     * called. Two actions are possible: either fail the call, or call 
  1206. X     * dblogin/dbopen with the default info. The second option is used 
  1207. X     * to keep backwards compatibility with an older version of 
  1208. X     * sybperl. A call to fatal(msg) is probably better.
  1209. X     */
  1210. X    if(!login && (ix != US_dblogin) && (ix != US_dbmsghandle) && (ix != US_dberrhandle))
  1211. X    {                /* You can call &dbmsghandle/errhandle before calling &dblogin */
  1212. X#ifdef OLD_SYBPERL
  1213. X    login = dblogin();
  1214. X    dbproc[0] = dbopen(login, NULL);
  1215. X#else
  1216. X    fatal("&dblogin has not been called yet!");
  1217. X#endif
  1218. X    }
  1219. X    
  1220. X    switch (ix)
  1221. X    {
  1222. X      case US_dblogin:
  1223. X    if (items > 2)
  1224. X        fatal("Usage: &dblogin([user[,pwd]])");
  1225. X    if (login)
  1226. X        fatal("&dblogin() called twice.");
  1227. X    else
  1228. X    {
  1229. X        int retval;
  1230. X
  1231. X        login = dblogin();
  1232. X        if(items)
  1233. X        {
  1234. X        DBSETLUSER(login, (char *)str_get(STACK(sp)[1]));
  1235. X        if(items > 1)
  1236. X            DBSETLPWD(login, (char *)str_get(STACK(sp)[2]));
  1237. X        }
  1238. X
  1239. X        dbproc[0] = dbopen(login, NULL);
  1240. X        str_numset(STACK(sp)[0], (double) 0);
  1241. X    }
  1242. X    break;
  1243. X      case US_dbopen:
  1244. X    if (items != 0)
  1245. X        fatal("Usage: $dbproc = &dbopen;");
  1246. X    else
  1247. X    {
  1248. X        int j;
  1249. X        for(j = 0; j < MAX_DBPROCS; ++j)
  1250. X        if(dbproc[j] == NULL)
  1251. X            break;
  1252. X        if(j == MAX_DBPROCS)
  1253. X        fatal("&dbopen: No more dbprocs available.");
  1254. X        dbproc[j] = dbopen(login, NULL);
  1255. X        str_numset(STACK(sp)[0], (double) j);
  1256. X    }
  1257. X    break;
  1258. X      case US_dbclose:
  1259. X    if (items != 1)
  1260. X        fatal("Usage: $ret = &dbclose($dbproc);");
  1261. X    else
  1262. X    {
  1263. X        inx = getDbProc(STACK(sp)[1]);
  1264. X
  1265. X        dbclose(dbproc[inx]);
  1266. X        dbproc[inx] = (DBPROCESS *)NULL;
  1267. X    }
  1268. X    break;
  1269. X      case US_dbcancel:
  1270. X    if (items > 1)
  1271. X        fatal("Usage: &dbcancel($dbproc)");
  1272. X    else
  1273. X    {
  1274. X        int retval;
  1275. X#if defined(BROKEN_DBCMD)
  1276. X        DBSTRING *ptr;
  1277. X        DBSTRING *old;
  1278. X#endif
  1279. X        if(items)
  1280. X        inx = getDbProc(STACK(sp)[1]);
  1281. X        else
  1282. X        inx = 0;
  1283. X
  1284. X        retval = dbcancel(dbproc[inx]);
  1285. X        str_numset(STACK(sp)[0], (double) retval);
  1286. X#if defined(BROKEN_DBCMD)
  1287. X        ptr = dbproc[inx]->dbcmdbuf;
  1288. X        while(ptr)
  1289. X        {
  1290. X        old = ptr;
  1291. X        ptr = ptr->strnext;
  1292. X        free(old->strtext);
  1293. X        free(old);
  1294. X        }
  1295. X        dbproc[inx]->dbcmdbuf = NULL;
  1296. X#endif
  1297. X    }
  1298. X    break;
  1299. X
  1300. X      case US_dbcanquery:
  1301. X    if (items > 1)
  1302. X        fatal("Usage: &dbcanquery($dbproc)");
  1303. X    else
  1304. X    {
  1305. X        int retval;
  1306. X
  1307. X        if(items)
  1308. X        inx = getDbProc(STACK(sp)[1]);
  1309. X        else
  1310. X        inx = 0;
  1311. X
  1312. X        retval = dbcanquery(dbproc[inx]);
  1313. X        str_numset(STACK(sp)[0], (double) retval);
  1314. X    }
  1315. X    break;
  1316. X
  1317. X      case US_dbexit:
  1318. X    if (items != 0)
  1319. X        fatal("Usage: &dbexit()");
  1320. X    else
  1321. X    {
  1322. X        dbexit(dbproc[0]);
  1323. X        exitCalled++;
  1324. X        str_numset(STACK(sp)[0], (double) 1);
  1325. X    }
  1326. X    break;
  1327. X
  1328. X      case US_dbuse:
  1329. X    if (items > 2)
  1330. X        fatal("Usage: &dbuse($dbproc, $database)");
  1331. X    else
  1332. X    {
  1333. X#if defined(BROKEN_DBCMD)
  1334. X        /* 
  1335. X         * Why doesn't this $@#! dbuse() call not work from within 
  1336. X         * Perl????? (So we emulate it here, but I sure can't 
  1337. X         * guarantee anything about portability to future versions 
  1338. X         * of DB-Library!
  1339. X         */
  1340. X        DBSTRING *new;
  1341. X        DBSTRING *sav;
  1342. X        char buff[256];
  1343. X        int ret, off;
  1344. X
  1345. X        if(items == 2)
  1346. X        {
  1347. X        inx = getDbProc(STACK(sp)[1]);
  1348. X        off = 2;
  1349. X        }
  1350. X        else
  1351. X        inx = 0, off = 1;
  1352. X
  1353. X        strcpy(buff, "use ");
  1354. X        strcat(buff, (char *)str_get(STACK(sp)[off]));
  1355. X        sav = dbproc[inx]->dbcmdbuf;
  1356. X
  1357. X        Newz(902, new, 1, DBSTRING);
  1358. X        New(902, new->strtext, strlen(buff) + 1, BYTE);
  1359. X        strcpy(new->strtext, buff);
  1360. X        new->strtotlen = strlen(new->strtext)+1;
  1361. X        dbproc[inx]->dbcmdbuf = new;
  1362. X
  1363. X        ret = dbsqlexec(dbproc[inx]);
  1364. X        ret = dbresults(dbproc[inx]);
  1365. X        while((ret = dbnextrow(dbproc[inx])) != NO_MORE_ROWS)
  1366. X        ;
  1367. X
  1368. X        Safefree(new->strtext);
  1369. X        Safefree(new);
  1370. X        
  1371. X        dbproc[inx]->dbcmdbuf = sav;
  1372. X        str_numset(STACK(sp)[0], (double) SUCCEED);
  1373. X#else
  1374. X        int retval, off;
  1375. X        char str[255];
  1376. X        
  1377. X        if(items == 2)
  1378. X        {
  1379. X        inx = getDbProc(STACK(sp)[1]);
  1380. X        off = 2;
  1381. X        }
  1382. X        else
  1383. X        inx = 0, off = 1;
  1384. X        
  1385. X        strcpy(str, (char *)str_get(STACK(sp)[off]));
  1386. X
  1387. X
  1388. X        retval = dbuse(dbproc[inx], str);
  1389. X        str_numset(STACK(sp)[0], (double) retval);
  1390. X#endif
  1391. X    }
  1392. X    break;
  1393. X
  1394. X      case US_dbsqlexec:
  1395. X    if (items > 1)
  1396. X        fatal("Usage: &dbsqlexec($dbproc)");
  1397. X    else
  1398. X    {
  1399. X        int retval;
  1400. X        if(items)
  1401. X        inx = getDbProc(STACK(sp)[1]);
  1402. X        else
  1403. X        inx = 0;
  1404. X
  1405. X        retval = dbsqlexec(dbproc[inx]);
  1406. X        str_numset(STACK(sp)[0], (double) retval);
  1407. X    }
  1408. X    break;
  1409. X
  1410. X      case US_dbresults:
  1411. X    if (items > 1)
  1412. X        fatal("Usage: &dbresults($dbproc)");
  1413. X    else
  1414. X    {
  1415. X        int retval;
  1416. X
  1417. X        if(items)
  1418. X        inx = getDbProc(STACK(sp)[1]);
  1419. X        else
  1420. X        inx = 0;
  1421. X
  1422. X        retval = dbresults(dbproc[inx]);
  1423. X        str_numset(STACK(sp)[0], (double) retval);
  1424. X#if defined(BROKEN_DBCMD)
  1425. X        if(retval==NO_MORE_RESULTS)
  1426. X        {
  1427. X        DBSTRING *ptr = dbproc[inx]->dbcmdbuf;
  1428. X        DBSTRING *old;
  1429. X
  1430. X        while(ptr)
  1431. X        {
  1432. X            old = ptr;
  1433. X            ptr = ptr->strnext;
  1434. X            Safefree(old->strtext);
  1435. X            Safefree(old);
  1436. X        }
  1437. X        dbproc[inx]->dbcmdbuf = NULL;
  1438. X        }
  1439. X#endif
  1440. X    }
  1441. X    break;
  1442. X
  1443. X      case US_dbcmd:
  1444. X    if (items > 2)
  1445. X        fatal("Usage: &dbcmd($dbproc, $str)");
  1446. X    else
  1447. X    {
  1448. X        int retval, off;
  1449. X#if defined(BROKEN_DBCMD)
  1450. X        DBSTRING *ptr;
  1451. X        DBSTRING *new, *old;
  1452. X        char *strdup();
  1453. X#endif
  1454. X        if(items == 2)
  1455. X        {
  1456. X        inx = getDbProc(STACK(sp)[1]);
  1457. X        off = 2;
  1458. X        }
  1459. X        else
  1460. X        inx = 0, off = 1;
  1461. X        
  1462. X#if defined(BROKEN_DBCMD)
  1463. X        ptr = dbproc[inx]->dbcmdbuf;
  1464. X
  1465. X        Newz(902, new, 1, DBSTRING);
  1466. X        New(902, new->strtext, strlen((char *)str_get(STACK(sp)[off])) + 1, BYTE);
  1467. X        strcpy(new->strtext, (char *)str_get(STACK(sp)[off]));
  1468. X        new->strtotlen = strlen(new->strtext)+1;
  1469. X        if(!ptr)
  1470. X        dbproc[inx]->dbcmdbuf = new;
  1471. X        else
  1472. X        {
  1473. X        while(ptr->strnext)
  1474. X            ptr = ptr->strnext;
  1475. X        ptr->strnext = new;
  1476. X        }
  1477. X#else
  1478. X        retval = dbcmd(dbproc[inx], (char *)str_get(STACK(sp)[off]));
  1479. X#endif
  1480. X        str_numset(STACK(sp)[0], (double) retval);
  1481. X    }
  1482. X    break;
  1483. X
  1484. X    case US_dbnextrow:
  1485. X    if (items > 1)
  1486. X        fatal("Usage: @arr = &dbnextrow($dbproc)");
  1487. X    else
  1488. X    {
  1489. X        int retval;
  1490. X        if(items)
  1491. X        inx = getDbProc(STACK(sp)[1]);
  1492. X        else
  1493. X        inx = 0;
  1494. X
  1495. X        --sp;        /* otherwise you get an empty element at the beginning of the results array! */
  1496. X
  1497. X        DBstatus = retval = dbnextrow(dbproc[inx]);
  1498. X        if(retval == REG_ROW)
  1499. X        {
  1500. X            char buff[1024], *p = NULL, *t;
  1501. X        BYTE *data;
  1502. X        int col, type, numcols = dbnumcols(dbproc[inx]);
  1503. X        int len;
  1504. X        DBFLT8 tmp;
  1505. X
  1506. X        ComputeId = 0;
  1507. X
  1508. X        for(col = 1, buff[0] = 0; col <= numcols; ++col)
  1509. X        {
  1510. X            type = dbcoltype(dbproc[inx], col);
  1511. X            len = dbdatlen(dbproc[inx],col);
  1512. X            data = (BYTE *)dbdata(dbproc[inx],col);
  1513. X            t = &buff[0];
  1514. X            if(!data && !len)
  1515. X            {
  1516. X            strcpy(buff,"NULL");
  1517. X            }
  1518. X            else
  1519. X            {
  1520. X            switch(type)
  1521. X            {
  1522. X              case SYBCHAR:
  1523. X                strncpy(buff,data,len);
  1524. X                buff[len] = 0;
  1525. X                break;
  1526. X              case SYBTEXT:
  1527. X                New(902, p, len + 1, char);
  1528. X                strncpy(p, data, len);
  1529. X                p[len] = 0;
  1530. X                t = p;
  1531. X                break;
  1532. X              case SYBINT1:
  1533. X              case SYBBIT: /* a bit is at least a byte long... */
  1534. X                sprintf(buff,"%u",*(unsigned char *)data);
  1535. X                break;
  1536. X              case SYBINT2:
  1537. X                sprintf(buff,"%d",*(short *)data);
  1538. X                break;
  1539. X              case SYBINT4:
  1540. X                sprintf(buff,"%d",*(long *)data);
  1541. X                break;
  1542. X              case SYBFLT8:
  1543. X                sprintf(buff,"%.6f",*(double *)data);
  1544. X                break;
  1545. X              case SYBMONEY:
  1546. X                dbconvert(dbproc[inx], SYBMONEY, data, len, SYBFLT8, &tmp, -1);
  1547. X                sprintf(buff,"%.6f",tmp);
  1548. X                break;
  1549. X              case SYBDATETIME:
  1550. X                dbconvert(dbproc[inx], SYBDATETIME, data, len, SYBCHAR, buff, -1);
  1551. X                break;
  1552. X              case SYBBINARY:
  1553. X                dbconvert(dbproc[inx], type, data, len, SYBCHAR, buff, -1);
  1554. X                break;
  1555. X              default:
  1556. X                /* ignored for the moment */
  1557. X                break;
  1558. X            }
  1559. X            }
  1560. X            (void)astore(ary,++sp,str_2static(str_make(t, 0)));
  1561. X            /* 
  1562. X             * If we've allocated some space to retrieve a 
  1563. X             * SYBTEXT field, then free it now.
  1564. X             */
  1565. X            if(t == p)
  1566. X            {
  1567. X            Safefree(p);
  1568. X            p = NULL;
  1569. X            }
  1570. X        }
  1571. X        }
  1572. X        if (retval > 0)
  1573. X        {
  1574. X            char buff[1024], *p = NULL, *t;
  1575. X        BYTE *data;
  1576. X        int col, type, numcols;
  1577. X        int len;
  1578. X        DBFLT8 tmp;
  1579. X
  1580. X        ComputeId = retval;
  1581. X        numcols = dbnumalts(dbproc[inx], ComputeId);
  1582. X
  1583. X        for(col = 1, buff[0] = 0; col <= numcols; ++col)
  1584. X        {
  1585. X            type = dbalttype(dbproc[inx], ComputeId, col);
  1586. X            len = dbadlen(dbproc[inx], ComputeId, col);
  1587. X            data = (BYTE *)dbadata(dbproc[inx], ComputeId, col);
  1588. X            t = &buff[0];
  1589. X            if(!data && !len)
  1590. X            {
  1591. X            strcpy(buff,"NULL");
  1592. X            }
  1593. X            else
  1594. X            {
  1595. X            switch(type)
  1596. X            {
  1597. X              case SYBCHAR:
  1598. X                strncpy(buff,data,len);
  1599. X                buff[len] = 0;
  1600. X                break;
  1601. X              case SYBTEXT:
  1602. X                New(902, p, len + 1, char);
  1603. X                strncpy(p, data, len);
  1604. X                p[len] = 0;
  1605. X                t = p;
  1606. X                break;
  1607. X              case SYBINT1:
  1608. X              case SYBBIT: /* a bit is at least a byte long... */
  1609. X                sprintf(buff,"%d",*(char *)data);
  1610. X                break;
  1611. X              case SYBINT2:
  1612. X                sprintf(buff,"%d",*(short *)data);
  1613. X                break;
  1614. X              case SYBINT4:
  1615. X                sprintf(buff,"%d",*(long *)data);
  1616. X                break;
  1617. X              case SYBFLT8:
  1618. X                sprintf(buff,"%.6f",*(double *)data);
  1619. X                break;
  1620. X              case SYBMONEY:
  1621. X                dbconvert(dbproc[inx], SYBMONEY, data, len, SYBFLT8, &tmp, -1);
  1622. X                sprintf(buff,"%.6f",tmp);
  1623. X                break;
  1624. X              case SYBDATETIME:
  1625. X                dbconvert(dbproc[inx], SYBDATETIME, data, len, SYBCHAR, buff, -1);
  1626. X                break;
  1627. X              case SYBBINARY:
  1628. X                dbconvert(dbproc[inx], type, data, len, SYBCHAR, buff, -1);
  1629. X                break;
  1630. X              default:
  1631. X                /* ignored at the moment... */
  1632. X                break;
  1633. X            }
  1634. X            }
  1635. X            (void)astore(ary,++sp,str_2static(str_make(t, 0)));
  1636. X            /* 
  1637. X             * If we've allocated some space because the field 
  1638. X             * was a text field, then free it now:
  1639. X             */
  1640. X            if(t == p)
  1641. X            {
  1642. X            Safefree(p);
  1643. X            p = NULL;
  1644. X            }
  1645. X                
  1646. X        }
  1647. X        }        
  1648. X#if defined(BROKEN_DBCMD)
  1649. X        /* 
  1650. X         * We can't rely on dbcmd(),dbresults() etc. to clean up 
  1651. X         * the dbcmdbuf linked list, so we have to it ourselves...
  1652. X         */
  1653. X        if(retval == NO_MORE_ROWS && !DBMORECMDS(dbproc[inx]))
  1654. X        {
  1655. X        DBSTRING *ptr = dbproc[inx]->dbcmdbuf;
  1656. X        DBSTRING *new, *old;
  1657. X
  1658. X        while(ptr)
  1659. X        {
  1660. X            old = ptr;
  1661. X            ptr = ptr->strnext;
  1662. X            Safefree(old->strtext);
  1663. X            Safefree(old);
  1664. X        }
  1665. X        dbproc[inx]->dbcmdbuf = NULL;
  1666. X        }
  1667. X#endif
  1668. X    }
  1669. X    break;
  1670. X#ifdef HAS_CALLBACK
  1671. X      case US_dberrhandle:
  1672. X    if (items > 1)
  1673. X        fatal ("Usage: &dberrhandle($handler)");
  1674. X    else
  1675. X    {
  1676. X        char *old = err_handler_sub;
  1677. X        if (items == 1)
  1678. X        {
  1679. X        if (STACK (sp)[1] == &str_undef)
  1680. X            err_handler_sub = 0;
  1681. X        else
  1682. X        {
  1683. X            char *sub = (char *) str_get (STACK (sp)[1]);    
  1684. X            New (902, err_handler_sub, strlen (sub) + 1, char);
  1685. X            strcpy (err_handler_sub, sub);
  1686. X        }
  1687. X        }
  1688. X
  1689. X        if (old)
  1690. X        {
  1691. X        STACK (sp)[0] = str_2mortal (str_make (old, strlen (old)));
  1692. X        if (items == 1)
  1693. X            Safefree (old);
  1694. X        }
  1695. X        else
  1696. X        STACK (sp)[0] = &str_undef;
  1697. X    }
  1698. X    break;
  1699. X      case US_dbmsghandle:
  1700. X    if (items > 1)
  1701. X        fatal ("Usage: &dbmsghandle($handler)");
  1702. X    else
  1703. X    {
  1704. X        char *old = msg_handler_sub;
  1705. X        if (items == 1)
  1706. X        {
  1707. X        if (STACK (sp)[1] == &str_undef)
  1708. X            msg_handler_sub = 0;
  1709. X        else
  1710. X        {
  1711. X            char *sub = (char *) str_get (STACK (sp)[1]);    
  1712. X            New (902, msg_handler_sub, strlen (sub) + 1, char);
  1713. X            strcpy (msg_handler_sub, sub);
  1714. X        }
  1715. X        }
  1716. X
  1717. X        if (old)
  1718. X        {
  1719. X        STACK (sp)[0] = str_2mortal (str_make (old, strlen (old)));
  1720. X        if (items == 1)
  1721. X            Safefree (old);
  1722. X        }
  1723. X        else
  1724. X        STACK (sp)[0] = &str_undef;
  1725. X    }
  1726. X    break;
  1727. X#endif                /* HAS_CALLBACK */
  1728. X      case US_dbstrcpy:
  1729. X    if (items > 1)
  1730. X        fatal("Usage: $string = &dbstrcpy($dbproc)");
  1731. X    else
  1732. X    {
  1733. X        int retval, len;
  1734. X        char *buff;
  1735. X
  1736. X        if(items)
  1737. X        inx = getDbProc(STACK(sp)[1]);
  1738. X        else
  1739. X        inx = 0;
  1740. X
  1741. X        if(dbproc[inx] && (len = dbstrlen(dbproc[inx])))
  1742. X        {
  1743. X        New(902, buff, len+1, char);
  1744. X        retval = dbstrcpy(dbproc[inx], 0, -1, buff);
  1745. X        str_set(STACK(sp)[0], buff);
  1746. X        Safefree(buff);
  1747. X        }
  1748. X        else
  1749. X        str_set(STACK(sp)[0], "");
  1750. X    }
  1751. X    break;
  1752. X
  1753. X      default:
  1754. X    fatal("Unimplemented user-defined subroutine");
  1755. X    }
  1756. X    return sp;
  1757. X}
  1758. X
  1759. X/* 
  1760. X * Return the value of a userdefined variable. These variables are all 
  1761. X * READ-ONLY in Perl.
  1762. X */
  1763. Xstatic int
  1764. Xuserval(ix, str)
  1765. Xint ix;
  1766. XSTR *str;
  1767. X{
  1768. X    char buff[24];
  1769. X    
  1770. X    switch (ix)
  1771. X    {
  1772. X      case UV_SUCCEED:
  1773. X    str_numset(str, (double)SUCCEED);
  1774. X    break;
  1775. X      case UV_FAIL:
  1776. X    str_numset(str, (double)FAIL);
  1777. X    break;
  1778. X      case UV_NO_MORE_ROWS:
  1779. X    str_numset(str, (double)NO_MORE_ROWS);
  1780. X    break;
  1781. X      case UV_NO_MORE_RESULTS:
  1782. X    str_numset(str, (double)NO_MORE_RESULTS);
  1783. X    break;
  1784. X      case UV_ComputeId:
  1785. X    str_numset(str, (double)ComputeId);
  1786. X    break;
  1787. X      case UV_SybperlVer:
  1788. X    sprintf(buff, "%d.%3.3d", VERSION, PATCHLEVEL);
  1789. X    str_set(str, buff);
  1790. X    break;
  1791. X      case UV_DBstatus:
  1792. X    str_numset(str, (double)DBstatus);
  1793. X    break;
  1794. X     }
  1795. X    return 0;
  1796. X}
  1797. X
  1798. Xstatic int
  1799. Xuserset(ix, str)        /* Not used. None of these variables are user-settable */
  1800. Xint ix;
  1801. XSTR *str;
  1802. X{
  1803. X    return 0;
  1804. X}
  1805. X
  1806. X
  1807. X/*ARGSUSED*/
  1808. Xstatic int err_handler(db, severity, dberr, oserr, dberrstring, oserrstr)
  1809. X    DBPROCESS *db;
  1810. X    int severity;
  1811. X    int dberr;
  1812. X    int oserr;
  1813. X    char *dberrstring;
  1814. X    char *oserrstr;
  1815. X{
  1816. X#ifdef HAS_CALLBACK
  1817. X    /* If we have error handler subroutine, use it. */
  1818. X    if (err_handler_sub)
  1819. X    {
  1820. X    int sp = perl_sp;
  1821. X    int j;
  1822. X
  1823. X    for(j = 0; j < MAX_DBPROCS; ++j)
  1824. X        if(db == dbproc[j])
  1825. X        break;
  1826. X    if(j == MAX_DBPROCS)
  1827. X        j = 0;
  1828. X    
  1829. X    /* Reserve spot for return value. */
  1830. X    astore (stack, ++ sp, Nullstr);
  1831. X    
  1832. X    /* Set up arguments. */
  1833. X    astore (stack, ++ sp,
  1834. X        str_2mortal (str_nmake ((double) j)));
  1835. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) severity)));
  1836. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) dberr)));
  1837. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) oserr)));
  1838. X    if (dberrstring && *dberrstring)
  1839. X        astore (stack, ++ sp, str_2mortal (str_make (dberrstring, 0)));
  1840. X    else
  1841. X        astore (stack, ++ sp, &str_undef);
  1842. X    if (oserrstr && *oserrstr)
  1843. X        astore (stack, ++ sp, str_2mortal (str_make (oserrstr, 0)));
  1844. X    else
  1845. X        astore (stack, ++ sp, &str_undef);
  1846. X    
  1847. X    /* Call it. */
  1848. X    sp = callback (err_handler_sub, sp, 0, 1, 6);
  1849. X    
  1850. X    /* Return whatever it returned. */
  1851. X    return (int) str_gnum (STACK (sp)[0]);
  1852. X    }
  1853. X#endif                /* HAS_CALLBACK */
  1854. X    if ((db == NULL) || (DBDEAD(db)))
  1855. X    return(INT_EXIT);
  1856. X    else 
  1857. X    {
  1858. X    fprintf(stderr,"DB-Library error:\n\t%s\n", dberrstring);
  1859. X    
  1860. X    if (oserr != DBNOERR)
  1861. X        fprintf(stderr,"Operating-system error:\n\t%s\n", oserrstr);
  1862. X    
  1863. X    return(INT_CANCEL);
  1864. X    }
  1865. X}
  1866. X
  1867. X/*ARGSUSED*/
  1868. X
  1869. Xstatic int msg_handler(db, msgno, msgstate, severity, msgtext, srvname, procname, line)
  1870. X    DBPROCESS *db;
  1871. X    DBINT msgno;
  1872. X    int msgstate;
  1873. X    int severity;
  1874. X    char *msgtext;
  1875. X    char *srvname;
  1876. X    char *procname;
  1877. X    DBUSMALLINT line;
  1878. X{
  1879. X#ifdef HAS_CALLBACK
  1880. X    /* If we have message handler subroutine, use it. */
  1881. X    if (msg_handler_sub)
  1882. X    {
  1883. X    int sp = perl_sp;
  1884. X    int j;
  1885. X
  1886. X    for(j = 0; j < MAX_DBPROCS; ++j)
  1887. X        if(db == dbproc[j])
  1888. X        break;
  1889. X    if(j == MAX_DBPROCS)
  1890. X        j = 0;
  1891. X    
  1892. X    /* Reserve spot for return value. */
  1893. X    astore (stack, ++ sp, Nullstr);
  1894. X    
  1895. X    /* Set up arguments. */
  1896. X    astore (stack, ++ sp,
  1897. X        str_2mortal (str_nmake ((double) j)));
  1898. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) msgno)));
  1899. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) msgstate)));
  1900. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) severity)));
  1901. X    if (msgtext && *msgtext)
  1902. X        astore (stack, ++ sp, str_2mortal (str_make (msgtext, 0)));
  1903. X    else
  1904. X        astore (stack, ++ sp, &str_undef);
  1905. X    if (srvname && *srvname)
  1906. X        astore (stack, ++ sp, str_2mortal (str_make (srvname, 0)));
  1907. X    else
  1908. X        astore (stack, ++ sp, &str_undef);
  1909. X    if (procname && *procname)
  1910. X        astore (stack, ++ sp, str_2mortal (str_make (procname, 0)));
  1911. X    else
  1912. X        astore (stack, ++ sp, &str_undef);
  1913. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) line)));
  1914. X    
  1915. X    /* Call it. */
  1916. X    sp = callback (msg_handler_sub, sp, 0, 1, 8);
  1917. X    
  1918. X    /* Return whatever it returned. */
  1919. X    return (int) str_gnum (STACK (sp)[0]);
  1920. X    }
  1921. X#endif                /* HAS_CALLBACK */
  1922. X#ifdef OLD_SYBPERL
  1923. X    if(!severity)
  1924. X    return 0;
  1925. X#endif
  1926. X    fprintf (stderr,"Msg %ld, Level %d, State %d\n", 
  1927. X         msgno, severity, msgstate);
  1928. X    if (strlen(srvname) > 0)
  1929. X    fprintf (stderr,"Server '%s', ", srvname);
  1930. X    if (strlen(procname) > 0)
  1931. X    fprintf (stderr,"Procedure '%s', ", procname);
  1932. X    if (line > 0)
  1933. X    fprintf (stderr,"Line %d", line);
  1934. X    
  1935. X    fprintf(stderr,"\n\t%s\n", msgtext);
  1936. X    
  1937. X    return(0);
  1938. X}
  1939. X
  1940. X/* 
  1941. X * Get the index into the dbproc[] array from a Perl STR datatype. 
  1942. X * Check that the index is reasonably valid...
  1943. X */
  1944. Xint getDbProc(Str)
  1945. X    STR *Str;
  1946. X{
  1947. X    int ix = (int)str_gnum(Str);
  1948. X
  1949. X    if(ix < 0 || ix >= MAX_DBPROCS)
  1950. X    fatal("$dbproc parameter is out of range.");
  1951. X    return ix;
  1952. X}
  1953. X
  1954. X#ifdef HAS_CALLBACK
  1955. X
  1956. X/* Taken from Perl 4.018 usub/usersub.c. mp. */
  1957. X
  1958. X/* Be sure to refetch the stack pointer after calling these routines. */
  1959. X
  1960. Xint
  1961. Xcallback(subname, sp, gimme, hasargs, numargs)
  1962. Xchar *subname;
  1963. Xint sp;            /* stack pointer after args are pushed */
  1964. Xint gimme;        /* called in array or scalar context */
  1965. Xint hasargs;        /* whether to create a @_ array for routine */
  1966. Xint numargs;        /* how many args are pushed on the stack */
  1967. X{
  1968. X    static ARG myarg[3];    /* fake syntax tree node */
  1969. X    int arglast[3];
  1970. X    
  1971. X    arglast[2] = sp;
  1972. X    sp -= numargs;
  1973. X    arglast[1] = sp--;
  1974. X    arglast[0] = sp;
  1975. X
  1976. X    if (!myarg[0].arg_ptr.arg_str)
  1977. X    myarg[0].arg_ptr.arg_str = str_make("",0);
  1978. X
  1979. X    myarg[1].arg_type = A_WORD;
  1980. X    myarg[1].arg_ptr.arg_stab = stabent(subname, FALSE);
  1981. X
  1982. X    myarg[2].arg_type = hasargs ? A_EXPR : A_NULL;
  1983. X
  1984. X    return do_subr(myarg, gimme, arglast);
  1985. X}
  1986. X
  1987. X#endif                /* HAS_CALLBACK */
  1988. X
  1989. END_OF_FILE
  1990.   if test 23786 -ne `wc -c <'sybperl.c'`; then
  1991.     echo shar: \"'sybperl.c'\" unpacked with wrong size!
  1992.   fi
  1993.   # end of 'sybperl.c'
  1994. fi
  1995. if test ! -d 't' ; then
  1996.     echo shar: Creating directory \"'t'\"
  1997.     mkdir 't'
  1998. fi
  1999. if test -f 't/sbex.pl' -a "${1}" != "-c" ; then 
  2000.   echo shar: Will not clobber existing file \"'t/sbex.pl'\"
  2001. else
  2002.   echo shar: Extracting \"'t/sbex.pl'\" \(4974 characters\)
  2003.   sed "s/^X//" >'t/sbex.pl' <<'END_OF_FILE'
  2004. X#!../sybperl
  2005. X
  2006. X
  2007. X@nul = ('not null','null');
  2008. X@sysdb = ('master', 'model', 'tempdb');
  2009. X
  2010. Xrequire "../lib/sybperl.pl";
  2011. Xrequire "../lib/sybdb.ph";
  2012. X
  2013. Xprint "Sybperl version $SybperlVer\n\n";
  2014. X
  2015. Xprint "This script tests some of sybperl's functions, and prints out\n";
  2016. Xprint "description of the databases that are defined in your Sybase\n";
  2017. Xprint "dataserver.\n\n";
  2018. X
  2019. X
  2020. X$dbproc = &dblogin("sa");    # Login to sybase
  2021. X&dbmsghandle ("message_handler"); # Some user defined error handlers
  2022. X&dberrhandle ("error_handler");
  2023. X
  2024. X$dbproc2 = &dbopen;        # Get a second dbprocess, so that we can select from several
  2025. X                                # chanels simultaneously. We could code things so that this
  2026. X                # feature is unnecessary, but it's good to exercise it.
  2027. X
  2028. X                # First, find out what databases exist:
  2029. X&dbcmd($dbproc, "select name from sysdatabases order by crdate\n");
  2030. X&dbsqlexec($dbproc);
  2031. X&dbresults($dbproc);
  2032. X
  2033. Xdatabase: while((@db = &dbnextrow($dbproc)))
  2034. X{
  2035. X    foreach $nm (@sysdb)
  2036. X    {
  2037. X    if($db[0] =~ /$nm/)
  2038. X    {
  2039. X        print "'$db[0]' is a system database\n";
  2040. X        next database;
  2041. X    }
  2042. X    }
  2043. X    print "Finding user tables in user database $db[0]...";
  2044. X
  2045. X    &dbcmd($dbproc2, "select o.name, u.name, o.id\n"); # 
  2046. X    &dbcmd($dbproc2, "from $db[0].dbo.sysobjects o, $db[0].dbo.sysusers u\n");
  2047. X    &dbcmd($dbproc2, "where o.type = 'U' and u.uid = o.uid\n");
  2048. X    &dbcmd($dbproc2, "order by o.name\n");
  2049. X
  2050. X    &dbsqlexec($dbproc2);
  2051. X    &dbresults($dbproc2);
  2052. X
  2053. X    while((@dat = &dbnextrow($dbproc2)))
  2054. X    {
  2055. X    $tab = join('@', @dat);    # Save the information
  2056. X    push(@tables, $tab);    # for later use...
  2057. X    }
  2058. X    print "Done.\n";
  2059. X
  2060. X    print "Finding user defined datatypes in database $db[0]...\n";
  2061. X
  2062. X    &dbcmd($dbproc2, "select s.length,substring(s.name,1,30),substring(st.name,1,30)\n");
  2063. X    &dbcmd($dbproc2, "from $db[0].dbo.systypes s, $db[0].dbo.systypes st\n");
  2064. X    &dbcmd($dbproc2, "where  st.type = s.type\n");
  2065. X    &dbcmd($dbproc2, "and s.usertype > 100 and st.usertype < 100 and st.usertype != 18\n");
  2066. X    &dbsqlexec($dbproc2);
  2067. X    &dbresults($dbproc2);
  2068. X
  2069. X    while((@dat = &dbnextrow($dbproc2)))
  2070. X    {
  2071. X    print "sp_addtype $dat[1],";
  2072. X    if ($dat[2] =~ /char|binary/)
  2073. X    {
  2074. X        print "'$dat[2]($dat[0])'";
  2075. X    }
  2076. X    else
  2077. X    {
  2078. X        print "$dat[2]";
  2079. X    }
  2080. X    print "\n";
  2081. X
  2082. X    }
  2083. X    print "Done.\n";
  2084. X
  2085. X    print "Now we find the table definition for each user table\nin database $db[0]...\n";
  2086. X
  2087. X    foreach $ln (@tables)        # For each line in the list
  2088. X    {
  2089. X    @tab = split('@',$ln);
  2090. X
  2091. X    &dbcmd($dbproc2, "select Column_name = c.name, \n");
  2092. X    &dbcmd($dbproc2, "       Type = t.name, \n");
  2093. X    &dbcmd($dbproc2, "       Length = c.length, \n");
  2094. X    &dbcmd($dbproc2, "       Nulls = convert(bit, (c.status & 8))\n");
  2095. X    &dbcmd($dbproc2, "from   $db[0].dbo.syscolumns c, $db[0].dbo.systypes t\n");
  2096. X    &dbcmd($dbproc2, "where  c.id = $tab[2]\n");
  2097. X    &dbcmd($dbproc2, "and    c.usertype *= t.usertype\n");
  2098. X    
  2099. X    &dbsqlexec($dbproc2);
  2100. X    &dbresults($dbproc2);
  2101. X
  2102. X    print "\nTABLE $db[0].$tab[1].$tab[0]\n ("; 
  2103. X    $first = 1;
  2104. X    while((@field = &dbnextrow($dbproc2)))
  2105. X    {
  2106. X        print ",\n" if !$first;        # add a , and a \n if not first field in table
  2107. X        
  2108. X        print "\t$field[0] \t$field[1]";
  2109. X        print "($field[2])" if $field[1] =~ /char|bin/;
  2110. X        print " $nul[$field[3]]";
  2111. X
  2112. X        $first = 0 if $first;
  2113. X    }
  2114. X    print " )\n";
  2115. X
  2116. X# now get the indexes...
  2117. X#
  2118. X    print "\nIndexes on $db[0].$tab[0].$tab[1]...\n\n";
  2119. X    &dbuse($dbproc2, $db[0]);
  2120. X    &dbcmd($dbproc2, "sp_helpindex '$tab[1].$tab[0]'\n");
  2121. X
  2122. X    &dbsqlexec($dbproc2);
  2123. X    &dbresults($dbproc2);
  2124. X
  2125. X    while((@field = &dbnextrow($dbproc2)))
  2126. X    {
  2127. X        print "unique " if $field[1] =~ /unique/;
  2128. X        print "clustered " if $field[1] =~ /^clust/;
  2129. X        print "index $field[0]\n";
  2130. X        @col = split(/,/,$field[2]);
  2131. X        print "on $db[0].$tab[1].$tab[0] (";
  2132. X        $first = 1;
  2133. X        foreach $ln1 (@col)
  2134. X        {
  2135. X        print ", " if !$first;
  2136. X        $first = 0;
  2137. X        print "$ln1";
  2138. X        }
  2139. X        print ")\n";
  2140. X    }
  2141. X    print "\nDone.\n";
  2142. X    }
  2143. X    &dbuse($dbproc2, "master");
  2144. X    @tables = ();
  2145. X}
  2146. X
  2147. X&dbexit;
  2148. X
  2149. X
  2150. X# Message and error handlers.
  2151. X
  2152. Xsub message_handler
  2153. X{
  2154. X    local ($db, $message, $state, $severity, $text, $server, $procedure, $line)
  2155. X    = @_;
  2156. X
  2157. X    if ($severity > 0)
  2158. X    {
  2159. X    print ("Sybase message ", $message, ", Severity ", $severity,
  2160. X           ", state ", $state);
  2161. X    print ("\nServer `", $server, "'") if defined ($server);
  2162. X    print ("\nProcedure `", $procedure, "'") if defined ($procedure);
  2163. X    print ("\nLine ", $line) if defined ($line);
  2164. X    print ("\n    ", $text, "\n\n");
  2165. X
  2166. X# &dbstrcpy returns the command buffer.
  2167. X
  2168. X    local ($lineno) = 1;    # 
  2169. X    foreach $row (split (/\n/, &dbstrcpy ($db)))
  2170. X    {
  2171. X        print (sprintf ("%5d", $lineno ++), "> ", $row, "\n");
  2172. X    }
  2173. X    }
  2174. X    elsif ($message == 0)
  2175. X    {
  2176. X    print ($text, "\n");
  2177. X    }
  2178. X    
  2179. X    0;
  2180. X}
  2181. X
  2182. Xsub error_handler {
  2183. X    # Check the error code to see if we should report this.
  2184. X    if ($_[2] != &SYBESMSG) {
  2185. X    local ($db, $severity, $error, $os_error, $error_msg, $os_error_msg)
  2186. X        = @_;
  2187. X    print ("Sybase error: ", $error_msg, "\n");
  2188. X    print ("OS Error: ", $os_error_msg, "\n") if defined ($os_error_msg);
  2189. X    }
  2190. X
  2191. X    &INT_CANCEL;
  2192. X}
  2193. X
  2194. X
  2195. X
  2196. END_OF_FILE
  2197.   if test 4974 -ne `wc -c <'t/sbex.pl'`; then
  2198.     echo shar: \"'t/sbex.pl'\" unpacked with wrong size!
  2199.   fi
  2200.   chmod +x 't/sbex.pl'
  2201.   # end of 't/sbex.pl'
  2202. fi
  2203. echo shar: End of archive 1 \(of 1\).
  2204. cp /dev/null ark1isdone
  2205. MISSING=""
  2206. for I in 1 ; do
  2207.     if test ! -f ark${I}isdone ; then
  2208.     MISSING="${MISSING} ${I}"
  2209.     fi
  2210. done
  2211. if test "${MISSING}" = "" ; then
  2212.     echo You have the archive.
  2213.     rm -f ark[1-9]isdone
  2214. else
  2215.     echo You still must unpack the following archives:
  2216.     echo "        " ${MISSING}
  2217. fi
  2218. exit 0
  2219. exit 0 # Just in case...
  2220.