1.\"- 2.\" Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav 3.\" All rights reserved. 4.\" 5.\" Redistribution and use in source and binary forms, with or without 6.\" modification, are permitted provided that the following conditions 7.\" are met: 8.\" 1. Redistributions of source code must retain the above copyright 9.\" notice, this list of conditions and the following disclaimer. 10.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" notice, this list of conditions and the following disclaimer in the 12.\" documentation and/or other materials provided with the distribution. 13.\" 14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24.\" SUCH DAMAGE. 25.\" 26.\" $FreeBSD: fetch.3,v 1.64 2007/12/18 11:03:26 des Exp $ 27.\" $NetBSD: fetch.3,v 1.1.1.3 2008/10/29 16:18:13 joerg Exp $ 28.\" 29.Dd April 25, 2008 30.Dt FETCH 3 31.Os 32.Sh NAME 33.Nm fetchMakeURL , 34.Nm fetchParseURL , 35.Nm fetchCopyURL , 36.Nm fetchFreeURL , 37.Nm fetchXGetURL , 38.Nm fetchGetURL , 39.Nm fetchPutURL , 40.Nm fetchStatURL , 41.Nm fetchListURL , 42.Nm fetchXGet , 43.Nm fetchGet , 44.Nm fetchPut , 45.Nm fetchStat , 46.Nm fetchList , 47.Nm fetchXGetFile , 48.Nm fetchGetFile , 49.Nm fetchPutFile , 50.Nm fetchStatFile , 51.Nm fetchListFile , 52.Nm fetchXGetHTTP , 53.Nm fetchGetHTTP , 54.Nm fetchPutHTTP , 55.Nm fetchStatHTTP , 56.Nm fetchListHTTP , 57.Nm fetchXGetFTP , 58.Nm fetchGetFTP , 59.Nm fetchPutFTP , 60.Nm fetchStatFTP , 61.Nm fetchListFTP 62.Nm fetchInitURLList , 63.Nm fetchFreeURLList , 64.Nm fetchUnquotePath , 65.Nm fetchUnquoteFilename , 66.Nm fetchStringifyURL , 67.Nm fetch 68.Nd file transfer functions 69.Sh LIBRARY 70.Lb libfetch 71.Sh SYNOPSIS 72.In stdio.h 73.In fetch.h 74.Ft struct url * 75.Fn fetchMakeURL "const char *scheme" "const char *host" "int port" "const char *doc" "const char *user" "const char *pwd" 76.Ft struct url * 77.Fn fetchParseURL "const char *URL" 78.Ft struct url * 79.Fn fetchCopyURL "const struct url *u" 80.Ft void 81.Fn fetchFreeURL "struct url *u" 82.Ft fetchIO * 83.Fn fetchXGetURL "const char *URL" "struct url_stat *us" "const char *flags" 84.Ft fetchIO * 85.Fn fetchGetURL "const char *URL" "const char *flags" 86.Ft fetchIO * 87.Fn fetchPutURL "const char *URL" "const char *flags" 88.Ft int 89.Fn fetchStatURL "const char *URL" "struct url_stat *us" "const char *flags" 90.Ft int 91.Fn fetchListURL "struct url_list *list" "const char *URL" "const char *flags" 92.Ft fetchIO * 93.Fn fetchXGet "struct url *u" "struct url_stat *us" "const char *flags" 94.Ft fetchIO * 95.Fn fetchGet "struct url *u" "const char *flags" 96.Ft fetchIO * 97.Fn fetchPut "struct url *u" "const char *flags" 98.Ft int 99.Fn fetchStat "struct url *u" "struct url_stat *us" "const char *flags" 100.Ft int 101.Fn fetchList "struct url_list *list" "struct url *u" "const char *flags" 102.Ft fetchIO * 103.Fn fetchXGetFile "struct url *u" "struct url_stat *us" "const char *flags" 104.Ft fetchIO * 105.Fn fetchGetFile "struct url *u" "const char *flags" 106.Ft fetchIO * 107.Fn fetchPutFile "struct url *u" "const char *flags" 108.Ft int 109.Fn fetchStatFile "struct url *u" "struct url_stat *us" "const char *flags" 110.Ft int 111.Fn fetchListFile "struct url_list *list" "struct url *u" "const char *flags" 112.Ft fetchIO * 113.Fn fetchXGetHTTP "struct url *u" "struct url_stat *us" "const char *flags" 114.Ft fetchIO * 115.Fn fetchGetHTTP "struct url *u" "const char *flags" 116.Ft fetchIO * 117.Fn fetchPutHTTP "struct url *u" "const char *flags" 118.Ft int 119.Fn fetchStatHTTP "struct url *u" "struct url_stat *us" "const char *flags" 120.Ft int 121.Fn fetchListHTTP "struct url_list *list" "struct url *u" "const char *flags" 122.Ft fetchIO * 123.Fn fetchXGetFTP "struct url *u" "struct url_stat *us" "const char *flags" 124.Ft fetchIO * 125.Fn fetchGetFTP "struct url *u" "const char *flags" 126.Ft fetchIO * 127.Fn fetchPutFTP "struct url *u" "const char *flags" 128.Ft int 129.Fn fetchStatFTP "struct url *u" "struct url_stat *us" "const char *flags" 130.Ft int 131.Fn fetchListFTP "struct url_list *list" "struct url *u" "const char *flags" 132.Ft void 133.Fn fetchInitURLList "struct url_list *ul" 134.Ft void 135.Fn fetchFreeURLList "struct url_list *ul" 136.Ft char * 137.Fn fetchUnquotePath "struct url *u" 138.Ft char * 139.Fn fetchUnquoteFilename "struct url *u" 140.Ft char * 141.Fn fetchStringifyURL "const struct url *u" 142.Sh DESCRIPTION 143These functions implement a high-level library for retrieving and 144uploading files using Uniform Resource Locators (URLs). 145.Pp 146.Fn fetchParseURL 147takes a URL in the form of a null-terminated string and splits it into 148its components function according to the Common Internet Scheme Syntax 149detailed in RFC 1738. 150A regular expression which produces this syntax is: 151.Bd -literal 152 \*[Lt]scheme\*[Gt]:(//(\*[Lt]user\*[Gt](:\*[Lt]pwd\*[Gt])?@)?\*[Lt]host\*[Gt](:\*[Lt]port\*[Gt])?)?/(\*[Lt]document\*[Gt])? 153.Ed 154.Pp 155If the URL does not seem to begin with a scheme name, it is assumed to be a local path. 156Only absolute path names are accepted. 157.Pp 158Note that some components of the URL are not necessarily relevant to 159all URL schemes. 160For instance, the file scheme only needs the 161.Aq scheme 162and 163.Aq document 164components. 165.Fn fetchParseURL 166quotes any unsafe character in the URL automatically. 167This is not done by 168.Fn fetchMakeURL . 169.Fn fetchCopyURL 170copies an existing 171.Vt url 172structure. 173.Pp 174.Fn fetchMakeURL , 175.Fn fetchParseURL , 176and 177.Fn fetchCopyURL 178return a pointer to a 179.Vt url 180structure, which is defined as follows in 181.In fetch.h : 182.Bd -literal 183#define URL_SCHEMELEN 16 184#define URL_USERLEN 256 185#define URL_PWDLEN 256 186#define URL_HOSTLEN 255 187 188struct url { 189 char scheme[URL_SCHEMELEN + 1]; 190 char user[URL_USERLEN + 1]; 191 char pwd[URL_PWDLEN + 1]; 192 char host[URL_HOSTLEN + 1]; 193 int port; 194 char *doc; 195 off_t offset; 196 size_t length; 197}; 198.Ed 199.Pp 200The pointer returned by 201.Fn fetchMakeURL , 202.Fn fetchCopyURL , 203and 204.Fn fetchParseURL 205should be freed using 206.Fn fetchFreeURL . 207.Pp 208.Fn fetchXGetURL , 209.Fn fetchGetURL , 210and 211.Fn fetchPutURL 212constitute the recommended interface to the 213.Nm fetch 214library. 215They examine the URL passed to them to determine the transfer 216method, and call the appropriate lower-level functions to perform the 217actual transfer. 218.Fn fetchXGetURL 219also returns the remote document's metadata in the 220.Vt url_stat 221structure pointed to by the 222.Fa us 223argument. 224.Pp 225The 226.Fa flags 227argument is a string of characters which specify transfer options. 228The 229meaning of the individual flags is scheme-dependent, and is detailed 230in the appropriate section below. 231.Pp 232.Fn fetchStatURL 233attempts to obtain the requested document's metadata and fill in the 234structure pointed to by its second argument. 235The 236.Vt url_stat 237structure is defined as follows in 238.In fetch.h : 239.Bd -literal 240struct url_stat { 241 off_t size; 242 time_t atime; 243 time_t mtime; 244}; 245.Ed 246.Pp 247If the size could not be obtained from the server, the 248.Fa size 249field is set to \-1. 250If the modification time could not be obtained from the server, the 251.Fa mtime 252field is set to the epoch. 253If the access time could not be obtained from the server, the 254.Fa atime 255field is set to the modification time. 256.Pp 257.Fn fetchListURL 258attempts to list the contents of the directory pointed to by the URL provided. 259The pattern can be a simple glob-like expression as hint. 260Callers should not depend on the server to filter names. 261If successful, it appends the list of entries to the 262.Vt url_list 263structure. 264The 265.Vt url_list 266structure is defined as follows in 267.In fetch.h : 268.Bd -literal 269struct url_list { 270 size_t length; 271 size_t alloc_size; 272 struct url *urls; 273}; 274.Ed 275.Pp 276The list should be initialized by calling 277.Fn fetchInitURLList 278and the entries be freed by calling 279.Fn fetchFreeURLList . 280.Pp 281.Fn fetchStringifyURL 282returns the URL as string. 283.Fn fetchUnquotePath 284returns the path name part of the URL with any quoting undone. 285Query arguments and fragment identifiers are not included. 286.Fn fetchUnquoteFilename 287returns the last component of the path name as returned by 288.Fn fetchUnquotePath . 289.Fn fetchStringifyURL , 290.Fn fetchUnquotePath , 291and 292.Fn fetchUnquoteFilename 293return a string that should be deallocated with 294.Fn free 295after use. 296.Pp 297.Fn fetchXGet , 298.Fn fetchGet , 299.Fn fetchPut , 300and 301.Fn fetchStat 302are similar to 303.Fn fetchXGetURL , 304.Fn fetchGetURL , 305.Fn fetchPutURL , 306and 307.Fn fetchStatURL , 308except that they expect a pre-parsed URL in the form of a pointer to 309a 310.Vt struct url 311rather than a string. 312.Pp 313All of the 314.Fn fetchXGetXXX , 315.Fn fetchGetXXX , 316and 317.Fn fetchPutXXX 318functions return a pointer to a stream which can be used to read or 319write data from or to the requested document, respectively. 320Note that 321although the implementation details of the individual access methods 322vary, it can generally be assumed that a stream returned by one of the 323.Fn fetchXGetXXX 324or 325.Fn fetchGetXXX 326functions is read-only, and that a stream returned by one of the 327.Fn fetchPutXXX 328functions is write-only. 329.Sh FILE SCHEME 330.Fn fetchXGetFile , 331.Fn fetchGetFile , 332and 333.Fn fetchPutFile 334provide access to documents which are files in a locally mounted file 335system. 336Only the 337.Aq document 338component of the URL is used. 339.Pp 340.Fn fetchXGetFile 341and 342.Fn fetchGetFile 343do not accept any flags. 344.Pp 345.Fn fetchPutFile 346accepts the 347.Ql a 348(append to file) flag. 349If that flag is specified, the data written to 350the stream returned by 351.Fn fetchPutFile 352will be appended to the previous contents of the file, instead of 353replacing them. 354.Sh FTP SCHEME 355.Fn fetchXGetFTP , 356.Fn fetchGetFTP , 357and 358.Fn fetchPutFTP 359implement the FTP protocol as described in RFC 959. 360.Pp 361By default 362.Nm libfetch 363will attempt to use passive mode first and only fallback to active mode 364if the server reports a syntax error. 365If the 366.Ql a 367(active) flag is specified, a passive connection is not tried and active mode 368is used directly. 369.Pp 370If the 371.Ql l 372(low) flag is specified, data sockets will be allocated in the low (or 373default) port range instead of the high port range (see 374.Xr ip 4 ) . 375.Pp 376If the 377.Ql d 378(direct) flag is specified, 379.Fn fetchXGetFTP , 380.Fn fetchGetFTP , 381and 382.Fn fetchPutFTP 383will use a direct connection even if a proxy server is defined. 384.Pp 385If no user name or password is given, the 386.Nm fetch 387library will attempt an anonymous login, with user name "anonymous" 388and password "anonymous@\*[Lt]hostname\*[Gt]". 389.Sh HTTP SCHEME 390The 391.Fn fetchXGetHTTP , 392.Fn fetchGetHTTP , 393and 394.Fn fetchPutHTTP 395functions implement the HTTP/1.1 protocol. 396With a little luck, there is 397even a chance that they comply with RFC 2616 and RFC 2617. 398.Pp 399If the 400.Ql d 401(direct) flag is specified, 402.Fn fetchXGetHTTP , 403.Fn fetchGetHTTP , 404and 405.Fn fetchPutHTTP 406will use a direct connection even if a proxy server is defined. 407.Pp 408Since there seems to be no good way of implementing the HTTP PUT 409method in a manner consistent with the rest of the 410.Nm fetch 411library, 412.Fn fetchPutHTTP 413is currently unimplemented. 414.Sh AUTHENTICATION 415Apart from setting the appropriate environment variables and 416specifying the user name and password in the URL or the 417.Vt struct url , 418the calling program has the option of defining an authentication 419function with the following prototype: 420.Pp 421.Ft int 422.Fn myAuthMethod "struct url *u" 423.Pp 424The callback function should fill in the 425.Fa user 426and 427.Fa pwd 428fields in the provided 429.Vt struct url 430and return 0 on success, or any other value to indicate failure. 431.Pp 432To register the authentication callback, simply set 433.Va fetchAuthMethod 434to point at it. 435The callback will be used whenever a site requires authentication and 436the appropriate environment variables are not set. 437.Pp 438This interface is experimental and may be subject to change. 439.Sh RETURN VALUES 440.Fn fetchParseURL 441returns a pointer to a 442.Vt struct url 443containing the individual components of the URL. 444If it is 445unable to allocate memory, or the URL is syntactically incorrect, 446.Fn fetchParseURL 447returns a 448.Dv NULL 449pointer. 450.Pp 451The 452.Fn fetchStat 453functions return 0 on success and \-1 on failure. 454.Pp 455All other functions return a stream pointer which may be used to 456access the requested document, or 457.Dv NULL 458if an error occurred. 459.Pp 460The following error codes are defined in 461.In fetch.h : 462.Bl -tag -width 18n 463.It Bq Er FETCH_ABORT 464Operation aborted 465.It Bq Er FETCH_AUTH 466Authentication failed 467.It Bq Er FETCH_DOWN 468Service unavailable 469.It Bq Er FETCH_EXISTS 470File exists 471.It Bq Er FETCH_FULL 472File system full 473.It Bq Er FETCH_INFO 474Informational response 475.It Bq Er FETCH_MEMORY 476Insufficient memory 477.It Bq Er FETCH_MOVED 478File has moved 479.It Bq Er FETCH_NETWORK 480Network error 481.It Bq Er FETCH_OK 482No error 483.It Bq Er FETCH_PROTO 484Protocol error 485.It Bq Er FETCH_RESOLV 486Resolver error 487.It Bq Er FETCH_SERVER 488Server error 489.It Bq Er FETCH_TEMP 490Temporary error 491.It Bq Er FETCH_TIMEOUT 492Operation timed out 493.It Bq Er FETCH_UNAVAIL 494File is not available 495.It Bq Er FETCH_UNKNOWN 496Unknown error 497.It Bq Er FETCH_URL 498Invalid URL 499.El 500.Pp 501The accompanying error message includes a protocol-specific error code 502and message, e.g.\& "File is not available (404 Not Found)" 503.Sh ENVIRONMENT 504.Bl -tag -width ".Ev FETCH_BIND_ADDRESS" 505.It Ev FETCH_BIND_ADDRESS 506Specifies a host name or IP address to which sockets used for outgoing 507connections will be bound. 508.It Ev FTP_LOGIN 509Default FTP login if none was provided in the URL. 510.It Ev FTP_PASSIVE_MODE 511If set to anything but 512.Ql no , 513forces the FTP code to use passive mode. 514.It Ev FTP_PASSWORD 515Default FTP password if the remote server requests one and none was 516provided in the URL. 517.It Ev FTP_PROXY 518URL of the proxy to use for FTP requests. 519The document part is ignored. 520FTP and HTTP proxies are supported; if no scheme is specified, FTP is 521assumed. 522If the proxy is an FTP proxy, 523.Nm libfetch 524will send 525.Ql user@host 526as user name to the proxy, where 527.Ql user 528is the real user name, and 529.Ql host 530is the name of the FTP server. 531.Pp 532If this variable is set to an empty string, no proxy will be used for 533FTP requests, even if the 534.Ev HTTP_PROXY 535variable is set. 536.It Ev ftp_proxy 537Same as 538.Ev FTP_PROXY , 539for compatibility. 540.It Ev HTTP_AUTH 541Specifies HTTP authorization parameters as a colon-separated list of 542items. 543The first and second item are the authorization scheme and realm 544respectively; further items are scheme-dependent. 545Currently, only basic authorization is supported. 546.Pp 547Basic authorization requires two parameters: the user name and 548password, in that order. 549.Pp 550This variable is only used if the server requires authorization and 551no user name or password was specified in the URL. 552.It Ev HTTP_PROXY 553URL of the proxy to use for HTTP requests. 554The document part is ignored. 555Only HTTP proxies are supported for HTTP requests. 556If no port number is specified, the default is 3128. 557.Pp 558Note that this proxy will also be used for FTP documents, unless the 559.Ev FTP_PROXY 560variable is set. 561.It Ev http_proxy 562Same as 563.Ev HTTP_PROXY , 564for compatibility. 565.It Ev HTTP_PROXY_AUTH 566Specifies authorization parameters for the HTTP proxy in the same 567format as the 568.Ev HTTP_AUTH 569variable. 570.Pp 571This variable is used if and only if connected to an HTTP proxy, and 572is ignored if a user and/or a password were specified in the proxy 573URL. 574.It Ev HTTP_REFERER 575Specifies the referrer URL to use for HTTP requests. 576If set to 577.Dq auto , 578the document URL will be used as referrer URL. 579.It Ev HTTP_USER_AGENT 580Specifies the User-Agent string to use for HTTP requests. 581This can be useful when working with HTTP origin or proxy servers that 582differentiate between user agents. 583.It Ev NETRC 584Specifies a file to use instead of 585.Pa ~/.netrc 586to look up login names and passwords for FTP sites. 587See 588.Xr ftp 1 589for a description of the file format. 590This feature is experimental. 591.It Ev NO_PROXY 592Either a single asterisk, which disables the use of proxies 593altogether, or a comma- or whitespace-separated list of hosts for 594which proxies should not be used. 595.It Ev no_proxy 596Same as 597.Ev NO_PROXY , 598for compatibility. 599.El 600.Sh EXAMPLES 601To access a proxy server on 602.Pa proxy.example.com 603port 8080, set the 604.Ev HTTP_PROXY 605environment variable in a manner similar to this: 606.Pp 607.Dl HTTP_PROXY=http://proxy.example.com:8080 608.Pp 609If the proxy server requires authentication, there are 610two options available for passing the authentication data. 611The first method is by using the proxy URL: 612.Pp 613.Dl HTTP_PROXY=http://\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt]@proxy.example.com:8080 614.Pp 615The second method is by using the 616.Ev HTTP_PROXY_AUTH 617environment variable: 618.Bd -literal -offset indent 619HTTP_PROXY=http://proxy.example.com:8080 620HTTP_PROXY_AUTH=basic:*:\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt] 621.Ed 622.Pp 623To disable the use of a proxy for an HTTP server running on the local 624host, define 625.Ev NO_PROXY 626as follows: 627.Bd -literal -offset indent 628NO_PROXY=localhost,127.0.0.1 629.Ed 630.Sh SEE ALSO 631.\" .Xr fetch 1 , 632.\" .Xr ftpio 3 , 633.Xr ftp 1 , 634.Xr ip 4 635.Rs 636.%A J. Postel 637.%A J. K. Reynolds 638.%D October 1985 639.%B File Transfer Protocol 640.%O RFC 959 641.Re 642.Rs 643.%A P. Deutsch 644.%A A. Emtage 645.%A A. Marine 646.%D May 1994 647.%T How to Use Anonymous FTP 648.%O RFC 1635 649.Re 650.Rs 651.%A T. Berners-Lee 652.%A L. Masinter 653.%A M. McCahill 654.%D December 1994 655.%T Uniform Resource Locators (URL) 656.%O RFC 1738 657.Re 658.Rs 659.%A R. Fielding 660.%A J. Gettys 661.%A J. Mogul 662.%A H. Frystyk 663.%A L. Masinter 664.%A P. Leach 665.%A T. Berners-Lee 666.%D January 1999 667.%B Hypertext Transfer Protocol -- HTTP/1.1 668.%O RFC 2616 669.Re 670.Rs 671.%A J. Franks 672.%A P. Hallam-Baker 673.%A J. Hostetler 674.%A S. Lawrence 675.%A P. Leach 676.%A A. Luotonen 677.%A L. Stewart 678.%D June 1999 679.%B HTTP Authentication: Basic and Digest Access Authentication 680.%O RFC 2617 681.Re 682.Sh HISTORY 683The 684.Nm fetch 685library first appeared in 686.Fx 3.0 . 687.Sh AUTHORS 688.An -nosplit 689The 690.Nm fetch 691library was mostly written by 692.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org 693with numerous suggestions from 694.An Jordan K. Hubbard Aq jkh@FreeBSD.org , 695.An Eugene Skepner Aq eu@qub.com 696and other 697.Fx 698developers. 699It replaces the older 700.Nm ftpio 701library written by 702.An Poul-Henning Kamp Aq phk@FreeBSD.org 703and 704.An Jordan K. Hubbard Aq jkh@FreeBSD.org . 705.Pp 706This manual page was written by 707.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org . 708.Sh BUGS 709Some parts of the library are not yet implemented. 710The most notable 711examples of this are 712.Fn fetchPutHTTP 713and FTP proxy support. 714.Pp 715There is no way to select a proxy at run-time other than setting the 716.Ev HTTP_PROXY 717or 718.Ev FTP_PROXY 719environment variables as appropriate. 720.Pp 721.Nm libfetch 722does not understand or obey 305 (Use Proxy) replies. 723.Pp 724Error numbers are unique only within a certain context; the error 725codes used for FTP and HTTP overlap, as do those used for resolver and 726system errors. 727For instance, error code 202 means "Command not 728implemented, superfluous at this site" in an FTP context and 729"Accepted" in an HTTP context. 730.Pp 731.Fn fetchStatFTP 732does not check that the result of an MDTM command is a valid date. 733.Pp 734The man page is incomplete, poorly written and produces badly 735formatted text. 736.Pp 737The error reporting mechanism is unsatisfactory. 738.Pp 739Some parts of the code are not fully reentrant. 740