Fossil SCM

Split the various server implementations out of "main.c" and into a new source file "server.c". This is groundwork for adding SCGI and FastCGI.

drh 2013-08-13 12:51 trunk
Commit bc20a30f4982d827b8a5210a27a6f76a27f3b3af
+2 -545
--- src/main.c
+++ src/main.c
@@ -21,18 +21,11 @@
2121
#include "config.h"
2222
#include "main.h"
2323
#include <string.h>
2424
#include <time.h>
2525
#include <fcntl.h>
26
-#include <sys/types.h>
27
-#include <sys/stat.h>
2826
#include <stdlib.h> /* atexit() */
29
-#if defined(_WIN32)
30
-# include <windows.h>
31
-#else
32
-# include <errno.h> /* errno global */
33
-#endif
3427
#include "zlib.h"
3528
#ifdef FOSSIL_ENABLE_SSL
3629
# include "openssl/opensslv.h"
3730
#endif
3831
#if INTERFACE
@@ -1023,11 +1016,11 @@
10231016
** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
10241017
** environment variables. However, if zAltBase is not NULL then it
10251018
** is the argument to the --baseurl option command-line option and
10261019
** g.zBaseURL and g.zTop is set from that instead.
10271020
*/
1028
-static void set_base_url(const char *zAltBase){
1021
+void set_base_url(const char *zAltBase){
10291022
int i;
10301023
const char *zHost;
10311024
const char *zMode;
10321025
const char *zCur;
10331026
@@ -1085,65 +1078,10 @@
10851078
*/
10861079
NORETURN void fossil_redirect_home(void){
10871080
cgi_redirectf("%s%s", g.zTop, db_get("index-page", "/index"));
10881081
}
10891082
1090
-/*
1091
-** If running as root, chroot to the directory containing the
1092
-** repository zRepo and then drop root privileges. Return the
1093
-** new repository name.
1094
-**
1095
-** zRepo might be a directory itself. In that case chroot into
1096
-** the directory zRepo.
1097
-**
1098
-** Assume the user-id and group-id of the repository, or if zRepo
1099
-** is a directory, of that directory.
1100
-*/
1101
-static char *enter_chroot_jail(char *zRepo){
1102
-#if !defined(_WIN32)
1103
- if( getuid()==0 ){
1104
- int i;
1105
- struct stat sStat;
1106
- Blob dir;
1107
- char *zDir;
1108
-
1109
- file_canonical_name(zRepo, &dir, 0);
1110
- zDir = blob_str(&dir);
1111
- if( file_isdir(zDir)==1 ){
1112
- if( file_chdir(zDir, 1) ){
1113
- fossil_fatal("unable to chroot into %s", zDir);
1114
- }
1115
- zRepo = "/";
1116
- }else{
1117
- for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){}
1118
- if( zDir[i]!='/' ) fossil_panic("bad repository name: %s", zRepo);
1119
- if( i>0 ){
1120
- zDir[i] = 0;
1121
- if( file_chdir(zDir, 1) ){
1122
- fossil_fatal("unable to chroot into %s", zDir);
1123
- }
1124
- zDir[i] = '/';
1125
- }
1126
- zRepo = &zDir[i];
1127
- }
1128
- if( stat(zRepo, &sStat)!=0 ){
1129
- fossil_fatal("cannot stat() repository: %s", zRepo);
1130
- }
1131
- i = setgid(sStat.st_gid);
1132
- i = i || setuid(sStat.st_uid);
1133
- if(i){
1134
- fossil_fatal("setgid/uid() failed with errno %d", errno);
1135
- }
1136
- if( g.db!=0 ){
1137
- db_close(1);
1138
- db_open_repository(zRepo);
1139
- }
1140
- }
1141
-#endif
1142
- return zRepo;
1143
-}
1144
-
11451083
/*
11461084
** Preconditions:
11471085
**
11481086
** * Environment variables are set up according to the CGI standard.
11491087
**
@@ -1162,11 +1100,11 @@
11621100
** $prefix can be determined from its suffix, then the file $prefix is
11631101
** returned as static text.
11641102
**
11651103
** If no suitable webpage is found, try to redirect to zNotFound.
11661104
*/
1167
-static void process_one_web_page(const char *zNotFound, Glob *pFileGlob){
1105
+void process_one_web_page(const char *zNotFound, Glob *pFileGlob){
11681106
const char *zPathInfo;
11691107
char *zPath = NULL;
11701108
int idx;
11711109
int i;
11721110
@@ -1407,491 +1345,10 @@
14071345
/* Return the result.
14081346
*/
14091347
cgi_reply();
14101348
}
14111349
1412
-/* If the CGI program contains one or more lines of the form
1413
-**
1414
-** redirect: repository-filename http://hostname/path/%s
1415
-**
1416
-** then control jumps here. Search each repository for an artifact ID
1417
-** that matches the "name" CGI parameter and for the first match,
1418
-** redirect to the corresponding URL with the "name" CGI parameter
1419
-** inserted. Paint an error page if no match is found.
1420
-**
1421
-** If there is a line of the form:
1422
-**
1423
-** redirect: * URL
1424
-**
1425
-** Then a redirect is made to URL if no match is found. Otherwise a
1426
-** very primitive error message is returned.
1427
-*/
1428
-static void redirect_web_page(int nRedirect, char **azRedirect){
1429
- int i; /* Loop counter */
1430
- const char *zNotFound = 0; /* Not found URL */
1431
- const char *zName = P("name");
1432
- set_base_url(0);
1433
- if( zName==0 ){
1434
- zName = P("SCRIPT_NAME");
1435
- if( zName && zName[0]=='/' ) zName++;
1436
- }
1437
- if( zName && validate16(zName, strlen(zName)) ){
1438
- for(i=0; i<nRedirect; i++){
1439
- if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
1440
- zNotFound = azRedirect[i*2+1];
1441
- continue;
1442
- }
1443
- db_open_repository(azRedirect[i*2]);
1444
- if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){
1445
- cgi_redirectf(azRedirect[i*2+1], zName);
1446
- return;
1447
- }
1448
- db_close(1);
1449
- }
1450
- }
1451
- if( zNotFound ){
1452
- cgi_redirectf(zNotFound, zName);
1453
- }else{
1454
- @ <html>
1455
- @ <head><title>No Such Object</title></head>
1456
- @ <body>
1457
- @ <p>No such object: <b>%h(zName)</b></p>
1458
- @ </body>
1459
- cgi_reply();
1460
- }
1461
-}
1462
-
1463
-/*
1464
-** COMMAND: cgi*
1465
-**
1466
-** Usage: %fossil ?cgi? SCRIPT
1467
-**
1468
-** The SCRIPT argument is the name of a file that is the CGI script
1469
-** that is being run. The command name, "cgi", may be omitted if
1470
-** the GATEWAY_INTERFACE environment variable is set to "CGI" (which
1471
-** should always be the case for CGI scripts run by a webserver.) The
1472
-** SCRIPT file should look something like this:
1473
-**
1474
-** #!/usr/bin/fossil
1475
-** repository: /home/somebody/project.db
1476
-**
1477
-** The second line defines the name of the repository. After locating
1478
-** the repository, fossil will generate a webpage on stdout based on
1479
-** the values of standard CGI environment variables.
1480
-**
1481
-** See also: http, server, winsrv
1482
-*/
1483
-void cmd_cgi(void){
1484
- const char *zFile;
1485
- const char *zNotFound = 0;
1486
- char **azRedirect = 0; /* List of repositories to redirect to */
1487
- int nRedirect = 0; /* Number of entries in azRedirect */
1488
- Glob *pFileGlob = 0; /* Pattern for files */
1489
- Blob config, line, key, value, value2;
1490
- if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){
1491
- zFile = g.argv[2];
1492
- }else{
1493
- zFile = g.argv[1];
1494
- }
1495
- g.httpOut = stdout;
1496
- g.httpIn = stdin;
1497
- fossil_binary_mode(g.httpOut);
1498
- fossil_binary_mode(g.httpIn);
1499
- g.cgiOutput = 1;
1500
- blob_read_from_file(&config, zFile);
1501
- while( blob_line(&config, &line) ){
1502
- if( !blob_token(&line, &key) ) continue;
1503
- if( blob_buffer(&key)[0]=='#' ) continue;
1504
- if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
1505
- g.fDebug = fossil_fopen(blob_str(&value), "ab");
1506
- blob_reset(&value);
1507
- continue;
1508
- }
1509
- if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
1510
- cgi_setenv("HOME", blob_str(&value));
1511
- blob_reset(&value);
1512
- continue;
1513
- }
1514
- if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
1515
- blob_trim(&value);
1516
- db_open_repository(blob_str(&value));
1517
- blob_reset(&value);
1518
- continue;
1519
- }
1520
- if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){
1521
- db_close(1);
1522
- g.zRepositoryName = mprintf("%s", blob_str(&value));
1523
- blob_reset(&value);
1524
- continue;
1525
- }
1526
- if( blob_eq(&key, "notfound:") && blob_token(&line, &value) ){
1527
- zNotFound = mprintf("%s", blob_str(&value));
1528
- blob_reset(&value);
1529
- continue;
1530
- }
1531
- if( blob_eq(&key, "localauth") ){
1532
- g.useLocalauth = 1;
1533
- continue;
1534
- }
1535
- if( blob_eq(&key, "redirect:") && blob_token(&line, &value)
1536
- && blob_token(&line, &value2) ){
1537
- nRedirect++;
1538
- azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*));
1539
- azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value));
1540
- azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2));
1541
- blob_reset(&value);
1542
- blob_reset(&value2);
1543
- continue;
1544
- }
1545
- if( blob_eq(&key, "files:") && blob_token(&line, &value) ){
1546
- pFileGlob = glob_create(blob_str(&value));
1547
- continue;
1548
- }
1549
- }
1550
- blob_reset(&config);
1551
- if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){
1552
- cgi_panic("Unable to find or open the project repository");
1553
- }
1554
- cgi_init();
1555
- if( nRedirect ){
1556
- redirect_web_page(nRedirect, azRedirect);
1557
- }else{
1558
- process_one_web_page(zNotFound, pFileGlob);
1559
- }
1560
-}
1561
-
1562
-/*
1563
-** If g.argv[2] exists then it is either the name of a repository
1564
-** that will be used by a server, or else it is a directory that
1565
-** contains multiple repositories that can be served. If g.argv[2]
1566
-** is a directory, the repositories it contains must be named
1567
-** "*.fossil". If g.argv[2] does not exists, then we must be within
1568
-** a check-out and the repository to be served is the repository of
1569
-** that check-out.
1570
-**
1571
-** Open the repository to be served if it is known. If g.argv[2] is
1572
-** a directory full of repositories, then set g.zRepositoryName to
1573
-** the name of that directory and the specific repository will be
1574
-** opened later by process_one_web_page() based on the content of
1575
-** the PATH_INFO variable.
1576
-**
1577
-** If disallowDir is set, then the directory full of repositories method
1578
-** is disallowed.
1579
-*/
1580
-static void find_server_repository(int disallowDir){
1581
- if( g.argc<3 ){
1582
- db_must_be_within_tree();
1583
- }else if( file_isdir(g.argv[2])==1 ){
1584
- if( disallowDir ){
1585
- fossil_fatal("\"%s\" is a directory, not a repository file", g.argv[2]);
1586
- }else{
1587
- g.zRepositoryName = mprintf("%s", g.argv[2]);
1588
- file_simplify_name(g.zRepositoryName, -1, 0);
1589
- }
1590
- }else{
1591
- db_open_repository(g.argv[2]);
1592
- }
1593
-}
1594
-
1595
-/*
1596
-** undocumented format:
1597
-**
1598
-** fossil http REPOSITORY INFILE OUTFILE IPADDR
1599
-**
1600
-** The argv==6 form is used by the win32 server only.
1601
-**
1602
-** COMMAND: http*
1603
-**
1604
-** Usage: %fossil http REPOSITORY ?OPTIONS?
1605
-**
1606
-** Handle a single HTTP request appearing on stdin. The resulting webpage
1607
-** is delivered on stdout. This method is used to launch an HTTP request
1608
-** handler from inetd, for example. The argument is the name of the
1609
-** repository.
1610
-**
1611
-** If REPOSITORY is a directory that contains one or more repositories,
1612
-** either directly in REPOSITORY itself, or in subdirectories, and
1613
-** with names of the form "*.fossil" then the a prefix of the URL pathname
1614
-** selects from among the various repositories. If the pathname does
1615
-** not select a valid repository and the --notfound option is available,
1616
-** then the server redirects (HTTP code 302) to the URL of --notfound.
1617
-** When REPOSITORY is a directory, the pathname must contain only
1618
-** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
1619
-** and every "." must be surrounded on both sides by alphanumerics or else
1620
-** a 404 error is returned. Static content files in the directory are
1621
-** returned if they match comma-separate GLOB pattern specified by --files
1622
-** and do not match "*.fossil*" and have a well-known suffix.
1623
-**
1624
-** The --host option can be used to specify the hostname for the server.
1625
-** The --https option indicates that the request came from HTTPS rather
1626
-** than HTTP. If --nossl is given, then SSL connections will not be available,
1627
-** thus also no redirecting from http: to https: will take place.
1628
-**
1629
-** If the --localauth option is given, then automatic login is performed
1630
-** for requests coming from localhost, if the "localauth" setting is not
1631
-** enabled.
1632
-**
1633
-** Options:
1634
-** --localauth enable automatic login for local connections
1635
-** --host NAME specify hostname of the server
1636
-** --https signal a request coming in via https
1637
-** --nossl signal that no SSL connections are available
1638
-** --notfound URL use URL as "HTTP 404, object not found" page.
1639
-** --files GLOB comma-separate glob patterns for static file to serve
1640
-** --baseurl URL base URL (useful with reverse proxies)
1641
-**
1642
-** See also: cgi, server, winsrv
1643
-*/
1644
-void cmd_http(void){
1645
- const char *zIpAddr;
1646
- const char *zNotFound;
1647
- const char *zHost;
1648
- const char *zAltBase;
1649
- const char *zFileGlob;
1650
-
1651
- /* The winhttp module passes the --files option as --files-urlenc with
1652
- ** the argument being URL encoded, to avoid wildcard expansion in the
1653
- ** shell. This option is for internal use and is undocumented.
1654
- */
1655
- zFileGlob = find_option("files-urlenc",0,1);
1656
- if( zFileGlob ){
1657
- char *z = mprintf("%s", zFileGlob);
1658
- dehttpize(z);
1659
- zFileGlob = z;
1660
- }else{
1661
- zFileGlob = find_option("files",0,1);
1662
- }
1663
- zNotFound = find_option("notfound", 0, 1);
1664
- g.useLocalauth = find_option("localauth", 0, 0)!=0;
1665
- g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
1666
- zAltBase = find_option("baseurl", 0, 1);
1667
- if( zAltBase ) set_base_url(zAltBase);
1668
- if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
1669
- zHost = find_option("host", 0, 1);
1670
- if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
1671
- g.cgiOutput = 1;
1672
- if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
1673
- fossil_fatal("no repository specified");
1674
- }
1675
- g.fullHttpReply = 1;
1676
- if( g.argc==6 ){
1677
- g.httpIn = fossil_fopen(g.argv[3], "rb");
1678
- g.httpOut = fossil_fopen(g.argv[4], "wb");
1679
- zIpAddr = g.argv[5];
1680
- }else{
1681
- g.httpIn = stdin;
1682
- g.httpOut = stdout;
1683
- zIpAddr = 0;
1684
- }
1685
- find_server_repository(0);
1686
- g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1687
- cgi_handle_http_request(zIpAddr);
1688
- process_one_web_page(zNotFound, glob_create(zFileGlob));
1689
-}
1690
-
1691
-/*
1692
-** Note that the following command is used by ssh:// processing.
1693
-**
1694
-** COMMAND: test-http
1695
-** Works like the http command but gives setup permission to all users.
1696
-*/
1697
-void cmd_test_http(void){
1698
- Th_InitTraceLog();
1699
- login_set_capabilities("sx", 0);
1700
- g.useLocalauth = 1;
1701
- cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
1702
- g.httpIn = stdin;
1703
- g.httpOut = stdout;
1704
- find_server_repository(0);
1705
- g.cgiOutput = 1;
1706
- g.fullHttpReply = 1;
1707
- cgi_handle_http_request(0);
1708
- process_one_web_page(0, 0);
1709
-}
1710
-
1711
-#if !defined(_WIN32)
1712
-#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1713
-/*
1714
-** Search for an executable on the PATH environment variable.
1715
-** Return true (1) if found and false (0) if not found.
1716
-*/
1717
-static int binaryOnPath(const char *zBinary){
1718
- const char *zPath = fossil_getenv("PATH");
1719
- char *zFull;
1720
- int i;
1721
- int bExists;
1722
- while( zPath && zPath[0] ){
1723
- while( zPath[0]==':' ) zPath++;
1724
- for(i=0; zPath[i] && zPath[i]!=':'; i++){}
1725
- zFull = mprintf("%.*s/%s", i, zPath, zBinary);
1726
- bExists = file_access(zFull, X_OK);
1727
- fossil_free(zFull);
1728
- if( bExists==0 ) return 1;
1729
- zPath += i;
1730
- }
1731
- return 0;
1732
-}
1733
-#endif
1734
-#endif
1735
-
1736
-/*
1737
-** COMMAND: server*
1738
-** COMMAND: ui
1739
-**
1740
-** Usage: %fossil server ?OPTIONS? ?REPOSITORY?
1741
-** Or: %fossil ui ?OPTIONS? ?REPOSITORY?
1742
-**
1743
-** Open a socket and begin listening and responding to HTTP requests on
1744
-** TCP port 8080, or on any other TCP port defined by the -P or
1745
-** --port option. The optional argument is the name of the repository.
1746
-** The repository argument may be omitted if the working directory is
1747
-** within an open checkout.
1748
-**
1749
-** The "ui" command automatically starts a web browser after initializing
1750
-** the web server. The "ui" command also binds to 127.0.0.1 and so will
1751
-** only process HTTP traffic from the local machine.
1752
-**
1753
-** The REPOSITORY can be a directory (aka folder) that contains one or
1754
-** more repositories with names ending in ".fossil". In this case, the
1755
-** a prefix of the URL pathname is used to search the directory for an
1756
-** appropriate repository. To thwart mischief, the pathname in the URL must
1757
-** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
1758
-** occur after "/", and every "." must be surrounded on both sides by
1759
-** alphanumerics. Any pathname that does not satisfy these constraints
1760
-** results in a 404 error. Files in REPOSITORY that match the comma-separated
1761
-** list of glob patterns given by --files and that have known suffixes
1762
-** such as ".txt" or ".html" or ".jpeg" and do not match the pattern
1763
-** "*.fossil*" will be served as static content. With the "ui" command,
1764
-** the REPOSITORY can only be a directory if the --notfound option is
1765
-** also present.
1766
-**
1767
-** By default, the "ui" command provides full administrative access without
1768
-** having to log in. This can be disabled by setting turning off the
1769
-** "localauth" setting. Automatic login for the "server" command is available
1770
-** if the --localauth option is present and the "localauth" setting is off
1771
-** and the connection is from localhost. The optional REPOSITORY argument
1772
-** to "ui" may be a directory and will function as "server" if and only if
1773
-** the --notfound option is used.
1774
-**
1775
-** Options:
1776
-** --localauth enable automatic login for requests from localhost
1777
-** --localhost listen on 127.0.0.1 only (always true for "ui")
1778
-** -P|--port TCPPORT listen to request on port TCPPORT
1779
-** --th-trace trace TH1 execution (for debugging purposes)
1780
-** --baseurl URL Use URL as the base (useful for reverse proxies)
1781
-** --notfound URL Redirect
1782
-** --files GLOBLIST Comma-separated list of glob patterns for static files
1783
-**
1784
-** See also: cgi, http, winsrv
1785
-*/
1786
-void cmd_webserver(void){
1787
- int iPort, mxPort; /* Range of TCP ports allowed */
1788
- const char *zPort; /* Value of the --port option */
1789
- const char *zBrowser; /* Name of web browser program */
1790
- char *zBrowserCmd = 0; /* Command to launch the web browser */
1791
- int isUiCmd; /* True if command is "ui", not "server' */
1792
- const char *zNotFound; /* The --notfound option or NULL */
1793
- int flags = 0; /* Server flags */
1794
- const char *zAltBase; /* Argument to the --baseurl option */
1795
- const char *zFileGlob; /* Static content must match this */
1796
- char *zIpAddr = 0; /* Bind to this IP address */
1797
-
1798
-#if defined(_WIN32)
1799
- const char *zStopperFile; /* Name of file used to terminate server */
1800
- zStopperFile = find_option("stopper", 0, 1);
1801
-#endif
1802
-
1803
- zFileGlob = find_option("files", 0, 1);
1804
- g.useLocalauth = find_option("localauth", 0, 0)!=0;
1805
- Th_InitTraceLog();
1806
- zPort = find_option("port", "P", 1);
1807
- zNotFound = find_option("notfound", 0, 1);
1808
- zAltBase = find_option("baseurl", 0, 1);
1809
- if( zAltBase ){
1810
- set_base_url(zAltBase);
1811
- }
1812
- if ( find_option("localhost", 0, 0)!=0 ){
1813
- flags |= HTTP_SERVER_LOCALHOST;
1814
- }
1815
- if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
1816
- isUiCmd = g.argv[1][0]=='u';
1817
- if( isUiCmd ){
1818
- flags |= HTTP_SERVER_LOCALHOST;
1819
- g.useLocalauth = 1;
1820
- }
1821
- find_server_repository(isUiCmd && zNotFound==0);
1822
- if( zPort ){
1823
- int i;
1824
- for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
1825
- if( i>0 ){
1826
- zIpAddr = mprintf("%.*s", i, zPort);
1827
- zPort += i+1;
1828
- }
1829
- iPort = mxPort = atoi(zPort);
1830
- }else{
1831
- iPort = db_get_int("http-port", 8080);
1832
- mxPort = iPort+100;
1833
- }
1834
-#if !defined(_WIN32)
1835
- /* Unix implementation */
1836
- if( isUiCmd ){
1837
-#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1838
- zBrowser = db_get("web-browser", 0);
1839
- if( zBrowser==0 ){
1840
- static const char *const azBrowserProg[] =
1841
- { "xdg-open", "gnome-open", "firefox", "google-chrome" };
1842
- int i;
1843
- zBrowser = "echo";
1844
- for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1845
- if( binaryOnPath(azBrowserProg[i]) ){
1846
- zBrowser = azBrowserProg[i];
1847
- break;
1848
- }
1849
- }
1850
- }
1851
-#else
1852
- zBrowser = db_get("web-browser", "open");
1853
-#endif
1854
- if( zIpAddr ){
1855
- zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
1856
- }else{
1857
- zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1858
- }
1859
- }
1860
- db_close(1);
1861
- if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
1862
- fossil_fatal("unable to listen on TCP socket %d", iPort);
1863
- }
1864
- g.sslNotAvailable = 1;
1865
- g.httpIn = stdin;
1866
- g.httpOut = stdout;
1867
- if( g.fHttpTrace || g.fSqlTrace ){
1868
- fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
1869
- }
1870
- g.cgiOutput = 1;
1871
- find_server_repository(isUiCmd && zNotFound==0);
1872
- g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1873
- cgi_handle_http_request(0);
1874
- process_one_web_page(zNotFound, glob_create(zFileGlob));
1875
-#else
1876
- /* Win32 implementation */
1877
- if( isUiCmd ){
1878
- zBrowser = db_get("web-browser", "start");
1879
- if( zIpAddr ){
1880
- zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
1881
- }else{
1882
- zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1883
- }
1884
- }
1885
- db_close(1);
1886
- if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
1887
- win32_http_server(iPort, mxPort, zBrowserCmd,
1888
- zStopperFile, zNotFound, zFileGlob, zIpAddr, flags);
1889
- }
1890
-#endif
1891
-}
1892
-
18931350
/*
18941351
** COMMAND: test-echo
18951352
**
18961353
** Usage: %fossil test-echo [--hex] ARGS...
18971354
**
18981355
--- src/main.c
+++ src/main.c
@@ -21,18 +21,11 @@
21 #include "config.h"
22 #include "main.h"
23 #include <string.h>
24 #include <time.h>
25 #include <fcntl.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <stdlib.h> /* atexit() */
29 #if defined(_WIN32)
30 # include <windows.h>
31 #else
32 # include <errno.h> /* errno global */
33 #endif
34 #include "zlib.h"
35 #ifdef FOSSIL_ENABLE_SSL
36 # include "openssl/opensslv.h"
37 #endif
38 #if INTERFACE
@@ -1023,11 +1016,11 @@
1023 ** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
1024 ** environment variables. However, if zAltBase is not NULL then it
1025 ** is the argument to the --baseurl option command-line option and
1026 ** g.zBaseURL and g.zTop is set from that instead.
1027 */
1028 static void set_base_url(const char *zAltBase){
1029 int i;
1030 const char *zHost;
1031 const char *zMode;
1032 const char *zCur;
1033
@@ -1085,65 +1078,10 @@
1085 */
1086 NORETURN void fossil_redirect_home(void){
1087 cgi_redirectf("%s%s", g.zTop, db_get("index-page", "/index"));
1088 }
1089
1090 /*
1091 ** If running as root, chroot to the directory containing the
1092 ** repository zRepo and then drop root privileges. Return the
1093 ** new repository name.
1094 **
1095 ** zRepo might be a directory itself. In that case chroot into
1096 ** the directory zRepo.
1097 **
1098 ** Assume the user-id and group-id of the repository, or if zRepo
1099 ** is a directory, of that directory.
1100 */
1101 static char *enter_chroot_jail(char *zRepo){
1102 #if !defined(_WIN32)
1103 if( getuid()==0 ){
1104 int i;
1105 struct stat sStat;
1106 Blob dir;
1107 char *zDir;
1108
1109 file_canonical_name(zRepo, &dir, 0);
1110 zDir = blob_str(&dir);
1111 if( file_isdir(zDir)==1 ){
1112 if( file_chdir(zDir, 1) ){
1113 fossil_fatal("unable to chroot into %s", zDir);
1114 }
1115 zRepo = "/";
1116 }else{
1117 for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){}
1118 if( zDir[i]!='/' ) fossil_panic("bad repository name: %s", zRepo);
1119 if( i>0 ){
1120 zDir[i] = 0;
1121 if( file_chdir(zDir, 1) ){
1122 fossil_fatal("unable to chroot into %s", zDir);
1123 }
1124 zDir[i] = '/';
1125 }
1126 zRepo = &zDir[i];
1127 }
1128 if( stat(zRepo, &sStat)!=0 ){
1129 fossil_fatal("cannot stat() repository: %s", zRepo);
1130 }
1131 i = setgid(sStat.st_gid);
1132 i = i || setuid(sStat.st_uid);
1133 if(i){
1134 fossil_fatal("setgid/uid() failed with errno %d", errno);
1135 }
1136 if( g.db!=0 ){
1137 db_close(1);
1138 db_open_repository(zRepo);
1139 }
1140 }
1141 #endif
1142 return zRepo;
1143 }
1144
1145 /*
1146 ** Preconditions:
1147 **
1148 ** * Environment variables are set up according to the CGI standard.
1149 **
@@ -1162,11 +1100,11 @@
1162 ** $prefix can be determined from its suffix, then the file $prefix is
1163 ** returned as static text.
1164 **
1165 ** If no suitable webpage is found, try to redirect to zNotFound.
1166 */
1167 static void process_one_web_page(const char *zNotFound, Glob *pFileGlob){
1168 const char *zPathInfo;
1169 char *zPath = NULL;
1170 int idx;
1171 int i;
1172
@@ -1407,491 +1345,10 @@
1407 /* Return the result.
1408 */
1409 cgi_reply();
1410 }
1411
1412 /* If the CGI program contains one or more lines of the form
1413 **
1414 ** redirect: repository-filename http://hostname/path/%s
1415 **
1416 ** then control jumps here. Search each repository for an artifact ID
1417 ** that matches the "name" CGI parameter and for the first match,
1418 ** redirect to the corresponding URL with the "name" CGI parameter
1419 ** inserted. Paint an error page if no match is found.
1420 **
1421 ** If there is a line of the form:
1422 **
1423 ** redirect: * URL
1424 **
1425 ** Then a redirect is made to URL if no match is found. Otherwise a
1426 ** very primitive error message is returned.
1427 */
1428 static void redirect_web_page(int nRedirect, char **azRedirect){
1429 int i; /* Loop counter */
1430 const char *zNotFound = 0; /* Not found URL */
1431 const char *zName = P("name");
1432 set_base_url(0);
1433 if( zName==0 ){
1434 zName = P("SCRIPT_NAME");
1435 if( zName && zName[0]=='/' ) zName++;
1436 }
1437 if( zName && validate16(zName, strlen(zName)) ){
1438 for(i=0; i<nRedirect; i++){
1439 if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
1440 zNotFound = azRedirect[i*2+1];
1441 continue;
1442 }
1443 db_open_repository(azRedirect[i*2]);
1444 if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){
1445 cgi_redirectf(azRedirect[i*2+1], zName);
1446 return;
1447 }
1448 db_close(1);
1449 }
1450 }
1451 if( zNotFound ){
1452 cgi_redirectf(zNotFound, zName);
1453 }else{
1454 @ <html>
1455 @ <head><title>No Such Object</title></head>
1456 @ <body>
1457 @ <p>No such object: <b>%h(zName)</b></p>
1458 @ </body>
1459 cgi_reply();
1460 }
1461 }
1462
1463 /*
1464 ** COMMAND: cgi*
1465 **
1466 ** Usage: %fossil ?cgi? SCRIPT
1467 **
1468 ** The SCRIPT argument is the name of a file that is the CGI script
1469 ** that is being run. The command name, "cgi", may be omitted if
1470 ** the GATEWAY_INTERFACE environment variable is set to "CGI" (which
1471 ** should always be the case for CGI scripts run by a webserver.) The
1472 ** SCRIPT file should look something like this:
1473 **
1474 ** #!/usr/bin/fossil
1475 ** repository: /home/somebody/project.db
1476 **
1477 ** The second line defines the name of the repository. After locating
1478 ** the repository, fossil will generate a webpage on stdout based on
1479 ** the values of standard CGI environment variables.
1480 **
1481 ** See also: http, server, winsrv
1482 */
1483 void cmd_cgi(void){
1484 const char *zFile;
1485 const char *zNotFound = 0;
1486 char **azRedirect = 0; /* List of repositories to redirect to */
1487 int nRedirect = 0; /* Number of entries in azRedirect */
1488 Glob *pFileGlob = 0; /* Pattern for files */
1489 Blob config, line, key, value, value2;
1490 if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){
1491 zFile = g.argv[2];
1492 }else{
1493 zFile = g.argv[1];
1494 }
1495 g.httpOut = stdout;
1496 g.httpIn = stdin;
1497 fossil_binary_mode(g.httpOut);
1498 fossil_binary_mode(g.httpIn);
1499 g.cgiOutput = 1;
1500 blob_read_from_file(&config, zFile);
1501 while( blob_line(&config, &line) ){
1502 if( !blob_token(&line, &key) ) continue;
1503 if( blob_buffer(&key)[0]=='#' ) continue;
1504 if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
1505 g.fDebug = fossil_fopen(blob_str(&value), "ab");
1506 blob_reset(&value);
1507 continue;
1508 }
1509 if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
1510 cgi_setenv("HOME", blob_str(&value));
1511 blob_reset(&value);
1512 continue;
1513 }
1514 if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
1515 blob_trim(&value);
1516 db_open_repository(blob_str(&value));
1517 blob_reset(&value);
1518 continue;
1519 }
1520 if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){
1521 db_close(1);
1522 g.zRepositoryName = mprintf("%s", blob_str(&value));
1523 blob_reset(&value);
1524 continue;
1525 }
1526 if( blob_eq(&key, "notfound:") && blob_token(&line, &value) ){
1527 zNotFound = mprintf("%s", blob_str(&value));
1528 blob_reset(&value);
1529 continue;
1530 }
1531 if( blob_eq(&key, "localauth") ){
1532 g.useLocalauth = 1;
1533 continue;
1534 }
1535 if( blob_eq(&key, "redirect:") && blob_token(&line, &value)
1536 && blob_token(&line, &value2) ){
1537 nRedirect++;
1538 azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*));
1539 azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value));
1540 azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2));
1541 blob_reset(&value);
1542 blob_reset(&value2);
1543 continue;
1544 }
1545 if( blob_eq(&key, "files:") && blob_token(&line, &value) ){
1546 pFileGlob = glob_create(blob_str(&value));
1547 continue;
1548 }
1549 }
1550 blob_reset(&config);
1551 if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){
1552 cgi_panic("Unable to find or open the project repository");
1553 }
1554 cgi_init();
1555 if( nRedirect ){
1556 redirect_web_page(nRedirect, azRedirect);
1557 }else{
1558 process_one_web_page(zNotFound, pFileGlob);
1559 }
1560 }
1561
1562 /*
1563 ** If g.argv[2] exists then it is either the name of a repository
1564 ** that will be used by a server, or else it is a directory that
1565 ** contains multiple repositories that can be served. If g.argv[2]
1566 ** is a directory, the repositories it contains must be named
1567 ** "*.fossil". If g.argv[2] does not exists, then we must be within
1568 ** a check-out and the repository to be served is the repository of
1569 ** that check-out.
1570 **
1571 ** Open the repository to be served if it is known. If g.argv[2] is
1572 ** a directory full of repositories, then set g.zRepositoryName to
1573 ** the name of that directory and the specific repository will be
1574 ** opened later by process_one_web_page() based on the content of
1575 ** the PATH_INFO variable.
1576 **
1577 ** If disallowDir is set, then the directory full of repositories method
1578 ** is disallowed.
1579 */
1580 static void find_server_repository(int disallowDir){
1581 if( g.argc<3 ){
1582 db_must_be_within_tree();
1583 }else if( file_isdir(g.argv[2])==1 ){
1584 if( disallowDir ){
1585 fossil_fatal("\"%s\" is a directory, not a repository file", g.argv[2]);
1586 }else{
1587 g.zRepositoryName = mprintf("%s", g.argv[2]);
1588 file_simplify_name(g.zRepositoryName, -1, 0);
1589 }
1590 }else{
1591 db_open_repository(g.argv[2]);
1592 }
1593 }
1594
1595 /*
1596 ** undocumented format:
1597 **
1598 ** fossil http REPOSITORY INFILE OUTFILE IPADDR
1599 **
1600 ** The argv==6 form is used by the win32 server only.
1601 **
1602 ** COMMAND: http*
1603 **
1604 ** Usage: %fossil http REPOSITORY ?OPTIONS?
1605 **
1606 ** Handle a single HTTP request appearing on stdin. The resulting webpage
1607 ** is delivered on stdout. This method is used to launch an HTTP request
1608 ** handler from inetd, for example. The argument is the name of the
1609 ** repository.
1610 **
1611 ** If REPOSITORY is a directory that contains one or more repositories,
1612 ** either directly in REPOSITORY itself, or in subdirectories, and
1613 ** with names of the form "*.fossil" then the a prefix of the URL pathname
1614 ** selects from among the various repositories. If the pathname does
1615 ** not select a valid repository and the --notfound option is available,
1616 ** then the server redirects (HTTP code 302) to the URL of --notfound.
1617 ** When REPOSITORY is a directory, the pathname must contain only
1618 ** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
1619 ** and every "." must be surrounded on both sides by alphanumerics or else
1620 ** a 404 error is returned. Static content files in the directory are
1621 ** returned if they match comma-separate GLOB pattern specified by --files
1622 ** and do not match "*.fossil*" and have a well-known suffix.
1623 **
1624 ** The --host option can be used to specify the hostname for the server.
1625 ** The --https option indicates that the request came from HTTPS rather
1626 ** than HTTP. If --nossl is given, then SSL connections will not be available,
1627 ** thus also no redirecting from http: to https: will take place.
1628 **
1629 ** If the --localauth option is given, then automatic login is performed
1630 ** for requests coming from localhost, if the "localauth" setting is not
1631 ** enabled.
1632 **
1633 ** Options:
1634 ** --localauth enable automatic login for local connections
1635 ** --host NAME specify hostname of the server
1636 ** --https signal a request coming in via https
1637 ** --nossl signal that no SSL connections are available
1638 ** --notfound URL use URL as "HTTP 404, object not found" page.
1639 ** --files GLOB comma-separate glob patterns for static file to serve
1640 ** --baseurl URL base URL (useful with reverse proxies)
1641 **
1642 ** See also: cgi, server, winsrv
1643 */
1644 void cmd_http(void){
1645 const char *zIpAddr;
1646 const char *zNotFound;
1647 const char *zHost;
1648 const char *zAltBase;
1649 const char *zFileGlob;
1650
1651 /* The winhttp module passes the --files option as --files-urlenc with
1652 ** the argument being URL encoded, to avoid wildcard expansion in the
1653 ** shell. This option is for internal use and is undocumented.
1654 */
1655 zFileGlob = find_option("files-urlenc",0,1);
1656 if( zFileGlob ){
1657 char *z = mprintf("%s", zFileGlob);
1658 dehttpize(z);
1659 zFileGlob = z;
1660 }else{
1661 zFileGlob = find_option("files",0,1);
1662 }
1663 zNotFound = find_option("notfound", 0, 1);
1664 g.useLocalauth = find_option("localauth", 0, 0)!=0;
1665 g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
1666 zAltBase = find_option("baseurl", 0, 1);
1667 if( zAltBase ) set_base_url(zAltBase);
1668 if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
1669 zHost = find_option("host", 0, 1);
1670 if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
1671 g.cgiOutput = 1;
1672 if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
1673 fossil_fatal("no repository specified");
1674 }
1675 g.fullHttpReply = 1;
1676 if( g.argc==6 ){
1677 g.httpIn = fossil_fopen(g.argv[3], "rb");
1678 g.httpOut = fossil_fopen(g.argv[4], "wb");
1679 zIpAddr = g.argv[5];
1680 }else{
1681 g.httpIn = stdin;
1682 g.httpOut = stdout;
1683 zIpAddr = 0;
1684 }
1685 find_server_repository(0);
1686 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1687 cgi_handle_http_request(zIpAddr);
1688 process_one_web_page(zNotFound, glob_create(zFileGlob));
1689 }
1690
1691 /*
1692 ** Note that the following command is used by ssh:// processing.
1693 **
1694 ** COMMAND: test-http
1695 ** Works like the http command but gives setup permission to all users.
1696 */
1697 void cmd_test_http(void){
1698 Th_InitTraceLog();
1699 login_set_capabilities("sx", 0);
1700 g.useLocalauth = 1;
1701 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
1702 g.httpIn = stdin;
1703 g.httpOut = stdout;
1704 find_server_repository(0);
1705 g.cgiOutput = 1;
1706 g.fullHttpReply = 1;
1707 cgi_handle_http_request(0);
1708 process_one_web_page(0, 0);
1709 }
1710
1711 #if !defined(_WIN32)
1712 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1713 /*
1714 ** Search for an executable on the PATH environment variable.
1715 ** Return true (1) if found and false (0) if not found.
1716 */
1717 static int binaryOnPath(const char *zBinary){
1718 const char *zPath = fossil_getenv("PATH");
1719 char *zFull;
1720 int i;
1721 int bExists;
1722 while( zPath && zPath[0] ){
1723 while( zPath[0]==':' ) zPath++;
1724 for(i=0; zPath[i] && zPath[i]!=':'; i++){}
1725 zFull = mprintf("%.*s/%s", i, zPath, zBinary);
1726 bExists = file_access(zFull, X_OK);
1727 fossil_free(zFull);
1728 if( bExists==0 ) return 1;
1729 zPath += i;
1730 }
1731 return 0;
1732 }
1733 #endif
1734 #endif
1735
1736 /*
1737 ** COMMAND: server*
1738 ** COMMAND: ui
1739 **
1740 ** Usage: %fossil server ?OPTIONS? ?REPOSITORY?
1741 ** Or: %fossil ui ?OPTIONS? ?REPOSITORY?
1742 **
1743 ** Open a socket and begin listening and responding to HTTP requests on
1744 ** TCP port 8080, or on any other TCP port defined by the -P or
1745 ** --port option. The optional argument is the name of the repository.
1746 ** The repository argument may be omitted if the working directory is
1747 ** within an open checkout.
1748 **
1749 ** The "ui" command automatically starts a web browser after initializing
1750 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
1751 ** only process HTTP traffic from the local machine.
1752 **
1753 ** The REPOSITORY can be a directory (aka folder) that contains one or
1754 ** more repositories with names ending in ".fossil". In this case, the
1755 ** a prefix of the URL pathname is used to search the directory for an
1756 ** appropriate repository. To thwart mischief, the pathname in the URL must
1757 ** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
1758 ** occur after "/", and every "." must be surrounded on both sides by
1759 ** alphanumerics. Any pathname that does not satisfy these constraints
1760 ** results in a 404 error. Files in REPOSITORY that match the comma-separated
1761 ** list of glob patterns given by --files and that have known suffixes
1762 ** such as ".txt" or ".html" or ".jpeg" and do not match the pattern
1763 ** "*.fossil*" will be served as static content. With the "ui" command,
1764 ** the REPOSITORY can only be a directory if the --notfound option is
1765 ** also present.
1766 **
1767 ** By default, the "ui" command provides full administrative access without
1768 ** having to log in. This can be disabled by setting turning off the
1769 ** "localauth" setting. Automatic login for the "server" command is available
1770 ** if the --localauth option is present and the "localauth" setting is off
1771 ** and the connection is from localhost. The optional REPOSITORY argument
1772 ** to "ui" may be a directory and will function as "server" if and only if
1773 ** the --notfound option is used.
1774 **
1775 ** Options:
1776 ** --localauth enable automatic login for requests from localhost
1777 ** --localhost listen on 127.0.0.1 only (always true for "ui")
1778 ** -P|--port TCPPORT listen to request on port TCPPORT
1779 ** --th-trace trace TH1 execution (for debugging purposes)
1780 ** --baseurl URL Use URL as the base (useful for reverse proxies)
1781 ** --notfound URL Redirect
1782 ** --files GLOBLIST Comma-separated list of glob patterns for static files
1783 **
1784 ** See also: cgi, http, winsrv
1785 */
1786 void cmd_webserver(void){
1787 int iPort, mxPort; /* Range of TCP ports allowed */
1788 const char *zPort; /* Value of the --port option */
1789 const char *zBrowser; /* Name of web browser program */
1790 char *zBrowserCmd = 0; /* Command to launch the web browser */
1791 int isUiCmd; /* True if command is "ui", not "server' */
1792 const char *zNotFound; /* The --notfound option or NULL */
1793 int flags = 0; /* Server flags */
1794 const char *zAltBase; /* Argument to the --baseurl option */
1795 const char *zFileGlob; /* Static content must match this */
1796 char *zIpAddr = 0; /* Bind to this IP address */
1797
1798 #if defined(_WIN32)
1799 const char *zStopperFile; /* Name of file used to terminate server */
1800 zStopperFile = find_option("stopper", 0, 1);
1801 #endif
1802
1803 zFileGlob = find_option("files", 0, 1);
1804 g.useLocalauth = find_option("localauth", 0, 0)!=0;
1805 Th_InitTraceLog();
1806 zPort = find_option("port", "P", 1);
1807 zNotFound = find_option("notfound", 0, 1);
1808 zAltBase = find_option("baseurl", 0, 1);
1809 if( zAltBase ){
1810 set_base_url(zAltBase);
1811 }
1812 if ( find_option("localhost", 0, 0)!=0 ){
1813 flags |= HTTP_SERVER_LOCALHOST;
1814 }
1815 if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
1816 isUiCmd = g.argv[1][0]=='u';
1817 if( isUiCmd ){
1818 flags |= HTTP_SERVER_LOCALHOST;
1819 g.useLocalauth = 1;
1820 }
1821 find_server_repository(isUiCmd && zNotFound==0);
1822 if( zPort ){
1823 int i;
1824 for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
1825 if( i>0 ){
1826 zIpAddr = mprintf("%.*s", i, zPort);
1827 zPort += i+1;
1828 }
1829 iPort = mxPort = atoi(zPort);
1830 }else{
1831 iPort = db_get_int("http-port", 8080);
1832 mxPort = iPort+100;
1833 }
1834 #if !defined(_WIN32)
1835 /* Unix implementation */
1836 if( isUiCmd ){
1837 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1838 zBrowser = db_get("web-browser", 0);
1839 if( zBrowser==0 ){
1840 static const char *const azBrowserProg[] =
1841 { "xdg-open", "gnome-open", "firefox", "google-chrome" };
1842 int i;
1843 zBrowser = "echo";
1844 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1845 if( binaryOnPath(azBrowserProg[i]) ){
1846 zBrowser = azBrowserProg[i];
1847 break;
1848 }
1849 }
1850 }
1851 #else
1852 zBrowser = db_get("web-browser", "open");
1853 #endif
1854 if( zIpAddr ){
1855 zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
1856 }else{
1857 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1858 }
1859 }
1860 db_close(1);
1861 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
1862 fossil_fatal("unable to listen on TCP socket %d", iPort);
1863 }
1864 g.sslNotAvailable = 1;
1865 g.httpIn = stdin;
1866 g.httpOut = stdout;
1867 if( g.fHttpTrace || g.fSqlTrace ){
1868 fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
1869 }
1870 g.cgiOutput = 1;
1871 find_server_repository(isUiCmd && zNotFound==0);
1872 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1873 cgi_handle_http_request(0);
1874 process_one_web_page(zNotFound, glob_create(zFileGlob));
1875 #else
1876 /* Win32 implementation */
1877 if( isUiCmd ){
1878 zBrowser = db_get("web-browser", "start");
1879 if( zIpAddr ){
1880 zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
1881 }else{
1882 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1883 }
1884 }
1885 db_close(1);
1886 if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
1887 win32_http_server(iPort, mxPort, zBrowserCmd,
1888 zStopperFile, zNotFound, zFileGlob, zIpAddr, flags);
1889 }
1890 #endif
1891 }
1892
1893 /*
1894 ** COMMAND: test-echo
1895 **
1896 ** Usage: %fossil test-echo [--hex] ARGS...
1897 **
1898
--- src/main.c
+++ src/main.c
@@ -21,18 +21,11 @@
21 #include "config.h"
22 #include "main.h"
23 #include <string.h>
24 #include <time.h>
25 #include <fcntl.h>
 
 
26 #include <stdlib.h> /* atexit() */
 
 
 
 
 
27 #include "zlib.h"
28 #ifdef FOSSIL_ENABLE_SSL
29 # include "openssl/opensslv.h"
30 #endif
31 #if INTERFACE
@@ -1023,11 +1016,11 @@
1016 ** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
1017 ** environment variables. However, if zAltBase is not NULL then it
1018 ** is the argument to the --baseurl option command-line option and
1019 ** g.zBaseURL and g.zTop is set from that instead.
1020 */
1021 void set_base_url(const char *zAltBase){
1022 int i;
1023 const char *zHost;
1024 const char *zMode;
1025 const char *zCur;
1026
@@ -1085,65 +1078,10 @@
1078 */
1079 NORETURN void fossil_redirect_home(void){
1080 cgi_redirectf("%s%s", g.zTop, db_get("index-page", "/index"));
1081 }
1082
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1083 /*
1084 ** Preconditions:
1085 **
1086 ** * Environment variables are set up according to the CGI standard.
1087 **
@@ -1162,11 +1100,11 @@
1100 ** $prefix can be determined from its suffix, then the file $prefix is
1101 ** returned as static text.
1102 **
1103 ** If no suitable webpage is found, try to redirect to zNotFound.
1104 */
1105 void process_one_web_page(const char *zNotFound, Glob *pFileGlob){
1106 const char *zPathInfo;
1107 char *zPath = NULL;
1108 int idx;
1109 int i;
1110
@@ -1407,491 +1345,10 @@
1345 /* Return the result.
1346 */
1347 cgi_reply();
1348 }
1349
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1350 /*
1351 ** COMMAND: test-echo
1352 **
1353 ** Usage: %fossil test-echo [--hex] ARGS...
1354 **
1355
+11 -1
--- src/main.mk
+++ src/main.mk
@@ -88,10 +88,11 @@
8888
$(SRCDIR)/regexp.c \
8989
$(SRCDIR)/report.c \
9090
$(SRCDIR)/rss.c \
9191
$(SRCDIR)/schema.c \
9292
$(SRCDIR)/search.c \
93
+ $(SRCDIR)/server.c \
9394
$(SRCDIR)/setup.c \
9495
$(SRCDIR)/sha1.c \
9596
$(SRCDIR)/shun.c \
9697
$(SRCDIR)/skins.c \
9798
$(SRCDIR)/sqlcmd.c \
@@ -197,10 +198,11 @@
197198
$(OBJDIR)/regexp_.c \
198199
$(OBJDIR)/report_.c \
199200
$(OBJDIR)/rss_.c \
200201
$(OBJDIR)/schema_.c \
201202
$(OBJDIR)/search_.c \
203
+ $(OBJDIR)/server_.c \
202204
$(OBJDIR)/setup_.c \
203205
$(OBJDIR)/sha1_.c \
204206
$(OBJDIR)/shun_.c \
205207
$(OBJDIR)/skins_.c \
206208
$(OBJDIR)/sqlcmd_.c \
@@ -306,10 +308,11 @@
306308
$(OBJDIR)/regexp.o \
307309
$(OBJDIR)/report.o \
308310
$(OBJDIR)/rss.o \
309311
$(OBJDIR)/schema.o \
310312
$(OBJDIR)/search.o \
313
+ $(OBJDIR)/server.o \
311314
$(OBJDIR)/setup.o \
312315
$(OBJDIR)/sha1.o \
313316
$(OBJDIR)/shun.o \
314317
$(OBJDIR)/skins.o \
315318
$(OBJDIR)/sqlcmd.o \
@@ -405,11 +408,11 @@
405408
406409
407410
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
408411
$(OBJDIR)/mkindex $(TRANS_SRC) >$@
409412
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
410
- $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/util_.c:$(OBJDIR)/util.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
413
+ $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/server_.c:$(OBJDIR)/server.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/util_.c:$(OBJDIR)/util.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
411414
touch $(OBJDIR)/headers
412415
$(OBJDIR)/headers: Makefile
413416
$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
414417
Makefile:
415418
$(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -942,10 +945,17 @@
942945
943946
$(OBJDIR)/search.o: $(OBJDIR)/search_.c $(OBJDIR)/search.h $(SRCDIR)/config.h
944947
$(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c
945948
946949
$(OBJDIR)/search.h: $(OBJDIR)/headers
950
+$(OBJDIR)/server_.c: $(SRCDIR)/server.c $(OBJDIR)/translate
951
+ $(OBJDIR)/translate $(SRCDIR)/server.c >$(OBJDIR)/server_.c
952
+
953
+$(OBJDIR)/server.o: $(OBJDIR)/server_.c $(OBJDIR)/server.h $(SRCDIR)/config.h
954
+ $(XTCC) -o $(OBJDIR)/server.o -c $(OBJDIR)/server_.c
955
+
956
+$(OBJDIR)/server.h: $(OBJDIR)/headers
947957
$(OBJDIR)/setup_.c: $(SRCDIR)/setup.c $(OBJDIR)/translate
948958
$(OBJDIR)/translate $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c
949959
950960
$(OBJDIR)/setup.o: $(OBJDIR)/setup_.c $(OBJDIR)/setup.h $(SRCDIR)/config.h
951961
$(XTCC) -o $(OBJDIR)/setup.o -c $(OBJDIR)/setup_.c
952962
--- src/main.mk
+++ src/main.mk
@@ -88,10 +88,11 @@
88 $(SRCDIR)/regexp.c \
89 $(SRCDIR)/report.c \
90 $(SRCDIR)/rss.c \
91 $(SRCDIR)/schema.c \
92 $(SRCDIR)/search.c \
 
93 $(SRCDIR)/setup.c \
94 $(SRCDIR)/sha1.c \
95 $(SRCDIR)/shun.c \
96 $(SRCDIR)/skins.c \
97 $(SRCDIR)/sqlcmd.c \
@@ -197,10 +198,11 @@
197 $(OBJDIR)/regexp_.c \
198 $(OBJDIR)/report_.c \
199 $(OBJDIR)/rss_.c \
200 $(OBJDIR)/schema_.c \
201 $(OBJDIR)/search_.c \
 
202 $(OBJDIR)/setup_.c \
203 $(OBJDIR)/sha1_.c \
204 $(OBJDIR)/shun_.c \
205 $(OBJDIR)/skins_.c \
206 $(OBJDIR)/sqlcmd_.c \
@@ -306,10 +308,11 @@
306 $(OBJDIR)/regexp.o \
307 $(OBJDIR)/report.o \
308 $(OBJDIR)/rss.o \
309 $(OBJDIR)/schema.o \
310 $(OBJDIR)/search.o \
 
311 $(OBJDIR)/setup.o \
312 $(OBJDIR)/sha1.o \
313 $(OBJDIR)/shun.o \
314 $(OBJDIR)/skins.o \
315 $(OBJDIR)/sqlcmd.o \
@@ -405,11 +408,11 @@
405
406
407 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
408 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
409 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
410 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/util_.c:$(OBJDIR)/util.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
411 touch $(OBJDIR)/headers
412 $(OBJDIR)/headers: Makefile
413 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
414 Makefile:
415 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -942,10 +945,17 @@
942
943 $(OBJDIR)/search.o: $(OBJDIR)/search_.c $(OBJDIR)/search.h $(SRCDIR)/config.h
944 $(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c
945
946 $(OBJDIR)/search.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
947 $(OBJDIR)/setup_.c: $(SRCDIR)/setup.c $(OBJDIR)/translate
948 $(OBJDIR)/translate $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c
949
950 $(OBJDIR)/setup.o: $(OBJDIR)/setup_.c $(OBJDIR)/setup.h $(SRCDIR)/config.h
951 $(XTCC) -o $(OBJDIR)/setup.o -c $(OBJDIR)/setup_.c
952
--- src/main.mk
+++ src/main.mk
@@ -88,10 +88,11 @@
88 $(SRCDIR)/regexp.c \
89 $(SRCDIR)/report.c \
90 $(SRCDIR)/rss.c \
91 $(SRCDIR)/schema.c \
92 $(SRCDIR)/search.c \
93 $(SRCDIR)/server.c \
94 $(SRCDIR)/setup.c \
95 $(SRCDIR)/sha1.c \
96 $(SRCDIR)/shun.c \
97 $(SRCDIR)/skins.c \
98 $(SRCDIR)/sqlcmd.c \
@@ -197,10 +198,11 @@
198 $(OBJDIR)/regexp_.c \
199 $(OBJDIR)/report_.c \
200 $(OBJDIR)/rss_.c \
201 $(OBJDIR)/schema_.c \
202 $(OBJDIR)/search_.c \
203 $(OBJDIR)/server_.c \
204 $(OBJDIR)/setup_.c \
205 $(OBJDIR)/sha1_.c \
206 $(OBJDIR)/shun_.c \
207 $(OBJDIR)/skins_.c \
208 $(OBJDIR)/sqlcmd_.c \
@@ -306,10 +308,11 @@
308 $(OBJDIR)/regexp.o \
309 $(OBJDIR)/report.o \
310 $(OBJDIR)/rss.o \
311 $(OBJDIR)/schema.o \
312 $(OBJDIR)/search.o \
313 $(OBJDIR)/server.o \
314 $(OBJDIR)/setup.o \
315 $(OBJDIR)/sha1.o \
316 $(OBJDIR)/shun.o \
317 $(OBJDIR)/skins.o \
318 $(OBJDIR)/sqlcmd.o \
@@ -405,11 +408,11 @@
408
409
410 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
411 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
412 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
413 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/server_.c:$(OBJDIR)/server.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/util_.c:$(OBJDIR)/util.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
414 touch $(OBJDIR)/headers
415 $(OBJDIR)/headers: Makefile
416 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
417 Makefile:
418 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -942,10 +945,17 @@
945
946 $(OBJDIR)/search.o: $(OBJDIR)/search_.c $(OBJDIR)/search.h $(SRCDIR)/config.h
947 $(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c
948
949 $(OBJDIR)/search.h: $(OBJDIR)/headers
950 $(OBJDIR)/server_.c: $(SRCDIR)/server.c $(OBJDIR)/translate
951 $(OBJDIR)/translate $(SRCDIR)/server.c >$(OBJDIR)/server_.c
952
953 $(OBJDIR)/server.o: $(OBJDIR)/server_.c $(OBJDIR)/server.h $(SRCDIR)/config.h
954 $(XTCC) -o $(OBJDIR)/server.o -c $(OBJDIR)/server_.c
955
956 $(OBJDIR)/server.h: $(OBJDIR)/headers
957 $(OBJDIR)/setup_.c: $(SRCDIR)/setup.c $(OBJDIR)/translate
958 $(OBJDIR)/translate $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c
959
960 $(OBJDIR)/setup.o: $(OBJDIR)/setup_.c $(OBJDIR)/setup.h $(SRCDIR)/config.h
961 $(XTCC) -o $(OBJDIR)/setup.o -c $(OBJDIR)/setup_.c
962
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -91,10 +91,11 @@
9191
regexp
9292
report
9393
rss
9494
schema
9595
search
96
+ server
9697
setup
9798
sha1
9899
shun
99100
skins
100101
sqlcmd
101102
102103
ADDED src/server.c
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -91,10 +91,11 @@
91 regexp
92 report
93 rss
94 schema
95 search
 
96 setup
97 sha1
98 shun
99 skins
100 sqlcmd
101
102 DDED src/server.c
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -91,10 +91,11 @@
91 regexp
92 report
93 rss
94 schema
95 search
96 server
97 setup
98 sha1
99 shun
100 skins
101 sqlcmd
102
103 DDED src/server.c
+567
--- a/src/server.c
+++ b/src/server.c
@@ -0,0 +1,567 @@
1
+/*
2
+** Copyright (c) 2006 D. Richard Hipp
3
+**
4
+** This program is free software; you can redistribute it and/or
5
+** modify it under the terms of the Simplified BSD License (also
6
+** known as the "2-Clause License" or "FreeBSD License".)
7
+**
8
+** This program is distributed in the hope that it will be useful,
9
+** but without any warranty; without even the implied warranty of
10
+** merchantability or fitness for a particular purpose.
11
+**
12
+** Author contact information:
13
+** [email protected]
14
+** http://www.hwaci.com/drh/
15
+**
16
+*******************************************************************************
17
+**
18
+** This module contains code to implement CGI, HTTP, SCGI, and FastCGI
19
+** servers.
20
+*/
21
+#include "config.h"
22
+#include "server.h"
23
+#include <sys/types.h>
24
+#include <sys/stat.h>
25
+#if defined(_WIN32)
26
+# include <windows.h>
27
+#else
28
+# include <errno.h> /* errno global */
29
+#endif
30
+
31
+/*
32
+** If g.argv[2] exists then it is either the name of a repository
33
+** that will be used by a server, or else it is a directory that
34
+** contains multiple repositories that can be served. If g.argv[2]
35
+** is a directory, the repositories it contains must be named
36
+** "*.fossil". If g.argv[2] does not exists, then we must be within
37
+** a check-out and the repository to be served is the repository of
38
+** that check-out.
39
+**
40
+** Open the repository to be served if it is known. If g.argv[2] is
41
+** a directory full of repositories, then set g.zRepositoryName to
42
+** the name of that directory and the specific repository will be
43
+** opened later by process_one_web_page() based on the content of
44
+** the PATH_INFO variable.
45
+**
46
+** If disallowDir is set, then the directory full of repositories method
47
+** is disallowed.
48
+*/
49
+static void find_server_repository(int disallowDir){
50
+ if( g.argc<3 ){
51
+ db_must_be_within_tree();
52
+ }else if( file_isdir(g.argv[2])==1 ){
53
+ if( disallowDir ){
54
+ fossil_fatal("\"%s\" is a directory, not a repository file", g.argv[2]);
55
+ }else{
56
+ g.zRepositoryName = mprintf("%s", g.argv[2]);
57
+ file_simplify_name(g.zRepositoryName, -1, 0);
58
+ }
59
+ }else{
60
+ db_open_repository(g.argv[2]);
61
+ }
62
+}
63
+
64
+#if !defined(_WIN32)
65
+#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
66
+/*
67
+** Search for an executable on the PATH environment variable.
68
+** Return true (1) if found and false (0) if not found.
69
+*/
70
+static int binaryOnPath(const char *zBinary){
71
+ const char *zPath = fossil_getenv("PATH");
72
+ char *zFull;
73
+ int i;
74
+ int bExists;
75
+ while( zPath && zPath[0] ){
76
+ while( zPath[0]==':' ) zPath++;
77
+ for(i=0; zPath[i] && zPath[i]!=':'; i++){}
78
+ zFull = mprintf("%.*s/%s", i, zPath, zBinary);
79
+ bExists = file_access(zFull, X_OK);
80
+ fossil_free(zFull);
81
+ if( bExists==0 ) return 1;
82
+ zPath += i;
83
+ }
84
+ return 0;
85
+}
86
+#endif
87
+#endif
88
+
89
+/*
90
+** If running as root, chroot to the directory containing the
91
+** repository zRepo and then drop root privileges. Return the
92
+** new repository name.
93
+**
94
+** zRepo might be a directory itself. In that case chroot into
95
+** the directory zRepo.
96
+**
97
+** Assume the user-id and group-id of the repository, or if zRepo
98
+** is a directory, of that directory.
99
+*/
100
+char *enter_chroot_jail(char *zRepo){
101
+#if !defined(_WIN32)
102
+ if( getuid()==0 ){
103
+ int i;
104
+ struct stat sStat;
105
+ Blob dir;
106
+ char *zDir;
107
+
108
+ file_canonical_name(zRepo, &dir, 0);
109
+ zDir = blob_str(&dir);
110
+ if( file_isdir(zDir)==1 ){
111
+ if( file_chdir(zDir, 1) ){
112
+ fossil_fatal("unable to chroot into %s", zDir);
113
+ }
114
+ zRepo = "/";
115
+ }else{
116
+ for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){}
117
+ if( zDir[i]!='/' ) fossil_panic("bad repository name: %s", zRepo);
118
+ if( i>0 ){
119
+ zDir[i] = 0;
120
+ if( file_chdir(zDir, 1) ){
121
+ fossil_fatal("unable to chroot into %s", zDir);
122
+ }
123
+ zDir[i] = '/';
124
+ }
125
+ zRepo = &zDir[i];
126
+ }
127
+ if( stat(zRepo, &sStat)!=0 ){
128
+ fossil_fatal("cannot stat() repository: %s", zRepo);
129
+ }
130
+ i = setgid(sStat.st_gid);
131
+ i = i || setuid(sStat.st_uid);
132
+ if(i){
133
+ fossil_fatal("setgid/uid() failed with errno %d", errno);
134
+ }
135
+ if( g.db!=0 ){
136
+ db_close(1);
137
+ db_open_repository(zRepo);
138
+ }
139
+ }
140
+#endif
141
+ return zRepo;
142
+}
143
+
144
+/* If the CGI program contains one or more lines of the form
145
+**
146
+** redirect: repository-filename http://hostname/path/%s
147
+**
148
+** then control jumps here. Search each repository for an artifact ID
149
+** that matches the "name" CGI parameter and for the first match,
150
+** redirect to the corresponding URL with the "name" CGI parameter
151
+** inserted. Paint an error page if no match is found.
152
+**
153
+** If there is a line of the form:
154
+**
155
+** redirect: * URL
156
+**
157
+** Then a redirect is made to URL if no match is found. Otherwise a
158
+** very primitive error message is returned.
159
+*/
160
+static void redirect_web_page(int nRedirect, char **azRedirect){
161
+ int i; /* Loop counter */
162
+ const char *zNotFound = 0; /* Not found URL */
163
+ const char *zName = P("name");
164
+ set_base_url(0);
165
+ if( zName==0 ){
166
+ zName = P("SCRIPT_NAME");
167
+ if( zName && zName[0]=='/' ) zName++;
168
+ }
169
+ if( zName && validate16(zName, strlen(zName)) ){
170
+ for(i=0; i<nRedirect; i++){
171
+ if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
172
+ zNotFound = azRedirect[i*2+1];
173
+ continue;
174
+ }
175
+ db_open_repository(azRedirect[i*2]);
176
+ if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){
177
+ cgi_redirectf(azRedirect[i*2+1], zName);
178
+ return;
179
+ }
180
+ db_close(1);
181
+ }
182
+ }
183
+ if( zNotFound ){
184
+ cgi_redirectf(zNotFound, zName);
185
+ }else{
186
+ @ <html>
187
+ @ <head><title>No Such Object</title></head>
188
+ @ <body>
189
+ @ <p>No such object: <b>%h(zName)</b></p>
190
+ @ </body>
191
+ cgi_reply();
192
+ }
193
+}
194
+
195
+/*
196
+** COMMAND: cgi*
197
+**
198
+** Usage: %fossil ?cgi? SCRIPT
199
+**
200
+** The SCRIPT argument is the name of a file that is the CGI script
201
+** that is being run. The command name, "cgi", may be omitted if
202
+** the GATEWAY_INTERFACE environment variable is set to "CGI" (which
203
+** should always be the case for CGI scripts run by a webserver.) The
204
+** SCRIPT file should look something like this:
205
+**
206
+** #!/usr/bin/fossil
207
+** repository: /home/somebody/project.db
208
+**
209
+** The second line defines the name of the repository. After locating
210
+** the repository, fossil will generate a webpage on stdout based on
211
+** the values of standard CGI environment variables.
212
+**
213
+** See also: http, server, winsrv
214
+*/
215
+void cmd_cgi(void){
216
+ const char *zFile;
217
+ const char *zNotFound = 0;
218
+ char **azRedirect = 0; /* List of repositories to redirect to */
219
+ int nRedirect = 0; /* Number of entries in azRedirect */
220
+ Glob *pFileGlob = 0; /* Pattern for files */
221
+ Blob config, line, key, value, value2;
222
+ if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){
223
+ zFile = g.argv[2];
224
+ }else{
225
+ zFile = g.argv[1];
226
+ }
227
+ g.httpOut = stdout;
228
+ g.httpIn = stdin;
229
+ fossil_binary_mode(g.httpOut);
230
+ fossil_binary_mode(g.httpIn);
231
+ g.cgiOutput = 1;
232
+ blob_read_from_file(&config, zFile);
233
+ while( blob_line(&config, &line) ){
234
+ if( !blob_token(&line, &key) ) continue;
235
+ if( blob_buffer(&key)[0]=='#' ) continue;
236
+ if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
237
+ g.fDebug = fossil_fopen(blob_str(&value), "ab");
238
+ blob_reset(&value);
239
+ continue;
240
+ }
241
+ if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
242
+ cgi_setenv("HOME", blob_str(&value));
243
+ blob_reset(&value);
244
+ continue;
245
+ }
246
+ if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
247
+ blob_trim(&value);
248
+ db_open_repository(blob_str(&value));
249
+ blob_reset(&value);
250
+ continue;
251
+ }
252
+ if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){
253
+ db_close(1);
254
+ g.zRepositoryName = mprintf("%s", blob_str(&value));
255
+ blob_reset(&value);
256
+ continue;
257
+ }
258
+ if( blob_eq(&key, "notfound:") && blob_token(&line, &value) ){
259
+ zNotFound = mprintf("%s", blob_str(&value));
260
+ blob_reset(&value);
261
+ continue;
262
+ }
263
+ if( blob_eq(&key, "localauth") ){
264
+ g.useLocalauth = 1;
265
+ continue;
266
+ }
267
+ if( blob_eq(&key, "redirect:") && blob_token(&line, &value)
268
+ && blob_token(&line, &value2) ){
269
+ nRedirect++;
270
+ azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*));
271
+ azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value));
272
+ azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2));
273
+ blob_reset(&value);
274
+ blob_reset(&value2);
275
+ continue;
276
+ }
277
+ if( blob_eq(&key, "files:") && blob_token(&line, &value) ){
278
+ pFileGlob = glob_create(blob_str(&value));
279
+ continue;
280
+ }
281
+ }
282
+ blob_reset(&config);
283
+ if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){
284
+ cgi_panic("Unable to find or open the project repository");
285
+ }
286
+ cgi_init();
287
+ if( nRedirect ){
288
+ redirect_web_page(nRedirect, azRedirect);
289
+ }else{
290
+ process_one_web_page(zNotFound, pFileGlob);
291
+ }
292
+}
293
+
294
+
295
+/*
296
+** undocumented format:
297
+**
298
+** fossil http REPOSITORY INFILE OUTFILE IPADDR
299
+**
300
+** The argv==6 form is used by the win32 server only.
301
+**
302
+** COMMAND: http*
303
+**
304
+** Usage: %fossil http REPOSITORY ?OPTIONS?
305
+**
306
+** Handle a single HTTP request appearing on stdin. The resulting webpage
307
+** is delivered on stdout. This method is used to launch an HTTP request
308
+** handler from inetd, for example. The argument is the name of the
309
+** repository.
310
+**
311
+** If REPOSITORY is a directory that contains one or more repositories,
312
+** either directly in REPOSITORY itself, or in subdirectories, and
313
+** with names of the form "*.fossil" then the a prefix of the URL pathname
314
+** selects from among the various repositories. If the pathname does
315
+** not select a valid repository and the --notfound option is available,
316
+** then the server redirects (HTTP code 302) to the URL of --notfound.
317
+** When REPOSITORY is a directory, the pathname must contain only
318
+** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
319
+** and every "." must be surrounded on both sides by alphanumerics or else
320
+** a 404 error is returned. Static content files in the directory are
321
+** returned if they match comma-separate GLOB pattern specified by --files
322
+** and do not match "*.fossil*" and have a well-known suffix.
323
+**
324
+** The --host option can be used to specify the hostname for the server.
325
+** The --https option indicates that the request came from HTTPS rather
326
+** than HTTP. If --nossl is given, then SSL connections will not be available,
327
+** thus also no redirecting from http: to https: will take place.
328
+**
329
+** If the --localauth option is given, then automatic login is performed
330
+** for requests coming from localhost, if the "localauth" setting is not
331
+** enabled.
332
+**
333
+** Options:
334
+** --localauth enable automatic login for local connections
335
+** --host NAME specify hostname of the server
336
+** --https signal a request coming in via https
337
+** --nossl signal that no SSL connections are available
338
+** --notfound URL use URL as "HTTP 404, object not found" page.
339
+** --files GLOB comma-separate glob patterns for static file to serve
340
+** --baseurl URL base URL (useful with reverse proxies)
341
+**
342
+** See also: cgi, server, winsrv
343
+*/
344
+void cmd_http(void){
345
+ const char *zIpAddr;
346
+ const char *zNotFound;
347
+ const char *zHost;
348
+ const char *zAltBase;
349
+ const char *zFileGlob;
350
+
351
+ /* The winhttp module passes the --files option as --files-urlenc with
352
+ ** the argument being URL encoded, to avoid wildcard expansion in the
353
+ ** shell. This option is for internal use and is undocumented.
354
+ */
355
+ zFileGlob = find_option("files-urlenc",0,1);
356
+ if( zFileGlob ){
357
+ char *z = mprintf("%s", zFileGlob);
358
+ dehttpize(z);
359
+ zFileGlob = z;
360
+ }else{
361
+ zFileGlob = find_option("files",0,1);
362
+ }
363
+ zNotFound = find_option("notfound", 0, 1);
364
+ g.useLocalauth = find_option("localauth", 0, 0)!=0;
365
+ g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
366
+ zAltBase = find_option("baseurl", 0, 1);
367
+ if( zAltBase ) set_base_url(zAltBase);
368
+ if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
369
+ zHost = find_option("host", 0, 1);
370
+ if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
371
+ g.cgiOutput = 1;
372
+ if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
373
+ fossil_fatal("no repository specified");
374
+ }
375
+ g.fullHttpReply = 1;
376
+ if( g.argc==6 ){
377
+ g.httpIn = fossil_fopen(g.argv[3], "rb");
378
+ g.httpOut = fossil_fopen(g.argv[4], "wb");
379
+ zIpAddr = g.argv[5];
380
+ }else{
381
+ g.httpIn = stdin;
382
+ g.httpOut = stdout;
383
+ zIpAddr = 0;
384
+ }
385
+ find_server_repository(0);
386
+ g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
387
+ cgi_handle_http_request(zIpAddr);
388
+ process_one_web_page(zNotFound, glob_create(zFileGlob));
389
+}
390
+
391
+/*
392
+** Note that the following command is used by ssh:// processing.
393
+**
394
+** COMMAND: test-http
395
+** Works like the http command but gives setup permission to all users.
396
+*/
397
+void cmd_test_http(void){
398
+ Th_InitTraceLog();
399
+ login_set_capabilities("sx", 0);
400
+ g.useLocalauth = 1;
401
+ cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
402
+ g.httpIn = stdin;
403
+ g.httpOut = stdout;
404
+ find_server_repository(0);
405
+ g.cgiOutput = 1;
406
+ g.fullHttpReply = 1;
407
+ cgi_handle_http_request(0);
408
+ process_one_web_page(0, 0);
409
+}
410
+
411
+
412
+/*
413
+** COMMAND: server*
414
+** COMMAND: ui
415
+**
416
+** Usage: %fossil server ?OPTIONS? ?REPOSITORY?
417
+** Or: %fossil ui ?OPTIONS? ?REPOSITORY?
418
+**
419
+** Open a socket and begin listening and responding to HTTP requests on
420
+** TCP port 8080, or on any other TCP port defined by the -P or
421
+** --port option. The optional argument is the name of the repository.
422
+** The repository argument may be omitted if the working directory is
423
+** within an open checkout.
424
+**
425
+** The "ui" command automatically starts a web browser after initializing
426
+** the web server. The "ui" command also binds to 127.0.0.1 and so will
427
+** only process HTTP traffic from the local machine.
428
+**
429
+** The REPOSITORY can be a directory (aka folder) that contains one or
430
+** more repositories with names ending in ".fossil". In this case, the
431
+** a prefix of the URL pathname is used to search the directory for an
432
+** appropriate repository. To thwart mischief, the pathname in the URL must
433
+** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
434
+** occur after "/", and every "." must be surrounded on both sides by
435
+** alphanumerics. Any pathname that does not satisfy these constraints
436
+** results in a 404 error. Files in REPOSITORY that match the comma-separated
437
+** list of glob patterns given by --files and that have known suffixes
438
+** such as ".txt" or ".html" or ".jpeg" and do not match the pattern
439
+** "*.fossil*" will be served as static content. With the "ui" command,
440
+** the REPOSITORY can only be a directory if the --notfound option is
441
+** also present.
442
+**
443
+** By default, the "ui" command provides full administrative access without
444
+** having to log in. This can be disabled by setting turning off the
445
+** "localauth" setting. Automatic login for the "server" command is available
446
+** if the --localauth option is present and the "localauth" setting is off
447
+** and the connection is from localhost. The optional REPOSITORY argument
448
+** to "ui" may be a directory and will function as "server" if and only if
449
+** the --notfound option is used.
450
+**
451
+** Options:
452
+** --localauth enable automatic login for requests from localhost
453
+** --localhost listen on 127.0.0.1 only (always true for "ui")
454
+** -P|--port TCPPORT listen to request on port TCPPORT
455
+** --th-trace trace TH1 execution (for debugging purposes)
456
+** --baseurl URL Use URL as the base (useful for reverse proxies)
457
+** --notfound URL Redirect
458
+** --files GLOBLIST Comma-separated list of glob patterns for static files
459
+**
460
+** See also: cgi, http, winsrv
461
+*/
462
+void cmd_webserver(void){
463
+ int iPort, mxPort; /* Range of TCP ports allowed */
464
+ const char *zPort; /* Value of the --port option */
465
+ const char *zBrowser; /* Name of web browser program */
466
+ char *zBrowserCmd = 0; /* Command to launch the web browser */
467
+ int isUiCmd; /* True if command is "ui", not "server' */
468
+ const char *zNotFound; /* The --notfound option or NULL */
469
+ int flags = 0; /* Server flags */
470
+ const char *zAltBase; /* Argument to the --baseurl option */
471
+ const char *zFileGlob; /* Static content must match this */
472
+ char *zIpAddr = 0; /* Bind to this IP address */
473
+
474
+#if defined(_WIN32)
475
+ const char *zStopperFile; /* Name of file used to terminate server */
476
+ zStopperFile = find_option("stopper", 0, 1);
477
+#endif
478
+
479
+ zFileGlob = find_option("files", 0, 1);
480
+ g.useLocalauth = find_option("localauth", 0, 0)!=0;
481
+ Th_InitTraceLog();
482
+ zPort = find_option("port", "P", 1);
483
+ zNotFound = find_option("notfound", 0, 1);
484
+ zAltBase = find_option("baseurl", 0, 1);
485
+ if( zAltBase ){
486
+ set_base_url(zAltBase);
487
+ }
488
+ if ( find_option("localhost", 0, 0)!=0 ){
489
+ flags |= HTTP_SERVER_LOCALHOST;
490
+ }
491
+ if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
492
+ isUiCmd = g.argv[1][0]=='u';
493
+ if( isUiCmd ){
494
+ flags |= HTTP_SERVER_LOCALHOST;
495
+ g.useLocalauth = 1;
496
+ }
497
+ find_server_repository(isUiCmd && zNotFound==0);
498
+ if( zPort ){
499
+ int i;
500
+ for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
501
+ if( i>0 ){
502
+ zIpAddr = mprintf("%.*s", i, zPort);
503
+ zPort += i+1;
504
+ }
505
+ iPort = mxPort = atoi(zPort);
506
+ }else{
507
+ iPort = db_get_int("http-port", 8080);
508
+ mxPort = iPort+100;
509
+ }
510
+#if !defined(_WIN32)
511
+ /* Unix implementation */
512
+ if( isUiCmd ){
513
+#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
514
+ zBrowser = db_get("web-browser", 0);
515
+ if( zBrowser==0 ){
516
+ static const char *const azBrowserProg[] =
517
+ { "xdg-open", "gnome-open", "firefox", "google-chrome" };
518
+ int i;
519
+ zBrowser = "echo";
520
+ for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
521
+ if( binaryOnPath(azBrowserProg[i]) ){
522
+ zBrowser = azBrowserProg[i];
523
+ break;
524
+ }
525
+ }
526
+ }
527
+#else
528
+ zBrowser = db_get("web-browser", "open");
529
+#endif
530
+ if( zIpAddr ){
531
+ zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
532
+ }else{
533
+ zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
534
+ }
535
+ }
536
+ db_close(1);
537
+ if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
538
+ fossil_fatal("unable to listen on TCP socket %d", iPort);
539
+ }
540
+ g.sslNotAvailable = 1;
541
+ g.httpIn = stdin;
542
+ g.httpOut = stdout;
543
+ if( g.fHttpTrace || g.fSqlTrace ){
544
+ fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
545
+ }
546
+ g.cgiOutput = 1;
547
+ find_server_repository(isUiCmd && zNotFound==0);
548
+ g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
549
+ cgi_handle_http_request(0);
550
+ process_one_web_page(zNotFound, glob_create(zFileGlob));
551
+#else
552
+ /* Win32 implementation */
553
+ if( isUiCmd ){
554
+ zBrowser = db_get("web-browser", "start");
555
+ if( zIpAddr ){
556
+ zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
557
+ }else{
558
+ zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
559
+ }
560
+ }
561
+ db_close(1);
562
+ if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
563
+ win32_http_server(iPort, mxPort, zBrowserCmd,
564
+ zStopperFile, zNotFound, zFileGlob, zIpAddr, flags);
565
+ }
566
+#endif
567
+}
--- a/src/server.c
+++ b/src/server.c
@@ -0,0 +1,567 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/server.c
+++ b/src/server.c
@@ -0,0 +1,567 @@
1 /*
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This module contains code to implement CGI, HTTP, SCGI, and FastCGI
19 ** servers.
20 */
21 #include "config.h"
22 #include "server.h"
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #if defined(_WIN32)
26 # include <windows.h>
27 #else
28 # include <errno.h> /* errno global */
29 #endif
30
31 /*
32 ** If g.argv[2] exists then it is either the name of a repository
33 ** that will be used by a server, or else it is a directory that
34 ** contains multiple repositories that can be served. If g.argv[2]
35 ** is a directory, the repositories it contains must be named
36 ** "*.fossil". If g.argv[2] does not exists, then we must be within
37 ** a check-out and the repository to be served is the repository of
38 ** that check-out.
39 **
40 ** Open the repository to be served if it is known. If g.argv[2] is
41 ** a directory full of repositories, then set g.zRepositoryName to
42 ** the name of that directory and the specific repository will be
43 ** opened later by process_one_web_page() based on the content of
44 ** the PATH_INFO variable.
45 **
46 ** If disallowDir is set, then the directory full of repositories method
47 ** is disallowed.
48 */
49 static void find_server_repository(int disallowDir){
50 if( g.argc<3 ){
51 db_must_be_within_tree();
52 }else if( file_isdir(g.argv[2])==1 ){
53 if( disallowDir ){
54 fossil_fatal("\"%s\" is a directory, not a repository file", g.argv[2]);
55 }else{
56 g.zRepositoryName = mprintf("%s", g.argv[2]);
57 file_simplify_name(g.zRepositoryName, -1, 0);
58 }
59 }else{
60 db_open_repository(g.argv[2]);
61 }
62 }
63
64 #if !defined(_WIN32)
65 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
66 /*
67 ** Search for an executable on the PATH environment variable.
68 ** Return true (1) if found and false (0) if not found.
69 */
70 static int binaryOnPath(const char *zBinary){
71 const char *zPath = fossil_getenv("PATH");
72 char *zFull;
73 int i;
74 int bExists;
75 while( zPath && zPath[0] ){
76 while( zPath[0]==':' ) zPath++;
77 for(i=0; zPath[i] && zPath[i]!=':'; i++){}
78 zFull = mprintf("%.*s/%s", i, zPath, zBinary);
79 bExists = file_access(zFull, X_OK);
80 fossil_free(zFull);
81 if( bExists==0 ) return 1;
82 zPath += i;
83 }
84 return 0;
85 }
86 #endif
87 #endif
88
89 /*
90 ** If running as root, chroot to the directory containing the
91 ** repository zRepo and then drop root privileges. Return the
92 ** new repository name.
93 **
94 ** zRepo might be a directory itself. In that case chroot into
95 ** the directory zRepo.
96 **
97 ** Assume the user-id and group-id of the repository, or if zRepo
98 ** is a directory, of that directory.
99 */
100 char *enter_chroot_jail(char *zRepo){
101 #if !defined(_WIN32)
102 if( getuid()==0 ){
103 int i;
104 struct stat sStat;
105 Blob dir;
106 char *zDir;
107
108 file_canonical_name(zRepo, &dir, 0);
109 zDir = blob_str(&dir);
110 if( file_isdir(zDir)==1 ){
111 if( file_chdir(zDir, 1) ){
112 fossil_fatal("unable to chroot into %s", zDir);
113 }
114 zRepo = "/";
115 }else{
116 for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){}
117 if( zDir[i]!='/' ) fossil_panic("bad repository name: %s", zRepo);
118 if( i>0 ){
119 zDir[i] = 0;
120 if( file_chdir(zDir, 1) ){
121 fossil_fatal("unable to chroot into %s", zDir);
122 }
123 zDir[i] = '/';
124 }
125 zRepo = &zDir[i];
126 }
127 if( stat(zRepo, &sStat)!=0 ){
128 fossil_fatal("cannot stat() repository: %s", zRepo);
129 }
130 i = setgid(sStat.st_gid);
131 i = i || setuid(sStat.st_uid);
132 if(i){
133 fossil_fatal("setgid/uid() failed with errno %d", errno);
134 }
135 if( g.db!=0 ){
136 db_close(1);
137 db_open_repository(zRepo);
138 }
139 }
140 #endif
141 return zRepo;
142 }
143
144 /* If the CGI program contains one or more lines of the form
145 **
146 ** redirect: repository-filename http://hostname/path/%s
147 **
148 ** then control jumps here. Search each repository for an artifact ID
149 ** that matches the "name" CGI parameter and for the first match,
150 ** redirect to the corresponding URL with the "name" CGI parameter
151 ** inserted. Paint an error page if no match is found.
152 **
153 ** If there is a line of the form:
154 **
155 ** redirect: * URL
156 **
157 ** Then a redirect is made to URL if no match is found. Otherwise a
158 ** very primitive error message is returned.
159 */
160 static void redirect_web_page(int nRedirect, char **azRedirect){
161 int i; /* Loop counter */
162 const char *zNotFound = 0; /* Not found URL */
163 const char *zName = P("name");
164 set_base_url(0);
165 if( zName==0 ){
166 zName = P("SCRIPT_NAME");
167 if( zName && zName[0]=='/' ) zName++;
168 }
169 if( zName && validate16(zName, strlen(zName)) ){
170 for(i=0; i<nRedirect; i++){
171 if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
172 zNotFound = azRedirect[i*2+1];
173 continue;
174 }
175 db_open_repository(azRedirect[i*2]);
176 if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){
177 cgi_redirectf(azRedirect[i*2+1], zName);
178 return;
179 }
180 db_close(1);
181 }
182 }
183 if( zNotFound ){
184 cgi_redirectf(zNotFound, zName);
185 }else{
186 @ <html>
187 @ <head><title>No Such Object</title></head>
188 @ <body>
189 @ <p>No such object: <b>%h(zName)</b></p>
190 @ </body>
191 cgi_reply();
192 }
193 }
194
195 /*
196 ** COMMAND: cgi*
197 **
198 ** Usage: %fossil ?cgi? SCRIPT
199 **
200 ** The SCRIPT argument is the name of a file that is the CGI script
201 ** that is being run. The command name, "cgi", may be omitted if
202 ** the GATEWAY_INTERFACE environment variable is set to "CGI" (which
203 ** should always be the case for CGI scripts run by a webserver.) The
204 ** SCRIPT file should look something like this:
205 **
206 ** #!/usr/bin/fossil
207 ** repository: /home/somebody/project.db
208 **
209 ** The second line defines the name of the repository. After locating
210 ** the repository, fossil will generate a webpage on stdout based on
211 ** the values of standard CGI environment variables.
212 **
213 ** See also: http, server, winsrv
214 */
215 void cmd_cgi(void){
216 const char *zFile;
217 const char *zNotFound = 0;
218 char **azRedirect = 0; /* List of repositories to redirect to */
219 int nRedirect = 0; /* Number of entries in azRedirect */
220 Glob *pFileGlob = 0; /* Pattern for files */
221 Blob config, line, key, value, value2;
222 if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){
223 zFile = g.argv[2];
224 }else{
225 zFile = g.argv[1];
226 }
227 g.httpOut = stdout;
228 g.httpIn = stdin;
229 fossil_binary_mode(g.httpOut);
230 fossil_binary_mode(g.httpIn);
231 g.cgiOutput = 1;
232 blob_read_from_file(&config, zFile);
233 while( blob_line(&config, &line) ){
234 if( !blob_token(&line, &key) ) continue;
235 if( blob_buffer(&key)[0]=='#' ) continue;
236 if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
237 g.fDebug = fossil_fopen(blob_str(&value), "ab");
238 blob_reset(&value);
239 continue;
240 }
241 if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
242 cgi_setenv("HOME", blob_str(&value));
243 blob_reset(&value);
244 continue;
245 }
246 if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
247 blob_trim(&value);
248 db_open_repository(blob_str(&value));
249 blob_reset(&value);
250 continue;
251 }
252 if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){
253 db_close(1);
254 g.zRepositoryName = mprintf("%s", blob_str(&value));
255 blob_reset(&value);
256 continue;
257 }
258 if( blob_eq(&key, "notfound:") && blob_token(&line, &value) ){
259 zNotFound = mprintf("%s", blob_str(&value));
260 blob_reset(&value);
261 continue;
262 }
263 if( blob_eq(&key, "localauth") ){
264 g.useLocalauth = 1;
265 continue;
266 }
267 if( blob_eq(&key, "redirect:") && blob_token(&line, &value)
268 && blob_token(&line, &value2) ){
269 nRedirect++;
270 azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*));
271 azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value));
272 azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2));
273 blob_reset(&value);
274 blob_reset(&value2);
275 continue;
276 }
277 if( blob_eq(&key, "files:") && blob_token(&line, &value) ){
278 pFileGlob = glob_create(blob_str(&value));
279 continue;
280 }
281 }
282 blob_reset(&config);
283 if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){
284 cgi_panic("Unable to find or open the project repository");
285 }
286 cgi_init();
287 if( nRedirect ){
288 redirect_web_page(nRedirect, azRedirect);
289 }else{
290 process_one_web_page(zNotFound, pFileGlob);
291 }
292 }
293
294
295 /*
296 ** undocumented format:
297 **
298 ** fossil http REPOSITORY INFILE OUTFILE IPADDR
299 **
300 ** The argv==6 form is used by the win32 server only.
301 **
302 ** COMMAND: http*
303 **
304 ** Usage: %fossil http REPOSITORY ?OPTIONS?
305 **
306 ** Handle a single HTTP request appearing on stdin. The resulting webpage
307 ** is delivered on stdout. This method is used to launch an HTTP request
308 ** handler from inetd, for example. The argument is the name of the
309 ** repository.
310 **
311 ** If REPOSITORY is a directory that contains one or more repositories,
312 ** either directly in REPOSITORY itself, or in subdirectories, and
313 ** with names of the form "*.fossil" then the a prefix of the URL pathname
314 ** selects from among the various repositories. If the pathname does
315 ** not select a valid repository and the --notfound option is available,
316 ** then the server redirects (HTTP code 302) to the URL of --notfound.
317 ** When REPOSITORY is a directory, the pathname must contain only
318 ** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
319 ** and every "." must be surrounded on both sides by alphanumerics or else
320 ** a 404 error is returned. Static content files in the directory are
321 ** returned if they match comma-separate GLOB pattern specified by --files
322 ** and do not match "*.fossil*" and have a well-known suffix.
323 **
324 ** The --host option can be used to specify the hostname for the server.
325 ** The --https option indicates that the request came from HTTPS rather
326 ** than HTTP. If --nossl is given, then SSL connections will not be available,
327 ** thus also no redirecting from http: to https: will take place.
328 **
329 ** If the --localauth option is given, then automatic login is performed
330 ** for requests coming from localhost, if the "localauth" setting is not
331 ** enabled.
332 **
333 ** Options:
334 ** --localauth enable automatic login for local connections
335 ** --host NAME specify hostname of the server
336 ** --https signal a request coming in via https
337 ** --nossl signal that no SSL connections are available
338 ** --notfound URL use URL as "HTTP 404, object not found" page.
339 ** --files GLOB comma-separate glob patterns for static file to serve
340 ** --baseurl URL base URL (useful with reverse proxies)
341 **
342 ** See also: cgi, server, winsrv
343 */
344 void cmd_http(void){
345 const char *zIpAddr;
346 const char *zNotFound;
347 const char *zHost;
348 const char *zAltBase;
349 const char *zFileGlob;
350
351 /* The winhttp module passes the --files option as --files-urlenc with
352 ** the argument being URL encoded, to avoid wildcard expansion in the
353 ** shell. This option is for internal use and is undocumented.
354 */
355 zFileGlob = find_option("files-urlenc",0,1);
356 if( zFileGlob ){
357 char *z = mprintf("%s", zFileGlob);
358 dehttpize(z);
359 zFileGlob = z;
360 }else{
361 zFileGlob = find_option("files",0,1);
362 }
363 zNotFound = find_option("notfound", 0, 1);
364 g.useLocalauth = find_option("localauth", 0, 0)!=0;
365 g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
366 zAltBase = find_option("baseurl", 0, 1);
367 if( zAltBase ) set_base_url(zAltBase);
368 if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
369 zHost = find_option("host", 0, 1);
370 if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
371 g.cgiOutput = 1;
372 if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
373 fossil_fatal("no repository specified");
374 }
375 g.fullHttpReply = 1;
376 if( g.argc==6 ){
377 g.httpIn = fossil_fopen(g.argv[3], "rb");
378 g.httpOut = fossil_fopen(g.argv[4], "wb");
379 zIpAddr = g.argv[5];
380 }else{
381 g.httpIn = stdin;
382 g.httpOut = stdout;
383 zIpAddr = 0;
384 }
385 find_server_repository(0);
386 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
387 cgi_handle_http_request(zIpAddr);
388 process_one_web_page(zNotFound, glob_create(zFileGlob));
389 }
390
391 /*
392 ** Note that the following command is used by ssh:// processing.
393 **
394 ** COMMAND: test-http
395 ** Works like the http command but gives setup permission to all users.
396 */
397 void cmd_test_http(void){
398 Th_InitTraceLog();
399 login_set_capabilities("sx", 0);
400 g.useLocalauth = 1;
401 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
402 g.httpIn = stdin;
403 g.httpOut = stdout;
404 find_server_repository(0);
405 g.cgiOutput = 1;
406 g.fullHttpReply = 1;
407 cgi_handle_http_request(0);
408 process_one_web_page(0, 0);
409 }
410
411
412 /*
413 ** COMMAND: server*
414 ** COMMAND: ui
415 **
416 ** Usage: %fossil server ?OPTIONS? ?REPOSITORY?
417 ** Or: %fossil ui ?OPTIONS? ?REPOSITORY?
418 **
419 ** Open a socket and begin listening and responding to HTTP requests on
420 ** TCP port 8080, or on any other TCP port defined by the -P or
421 ** --port option. The optional argument is the name of the repository.
422 ** The repository argument may be omitted if the working directory is
423 ** within an open checkout.
424 **
425 ** The "ui" command automatically starts a web browser after initializing
426 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
427 ** only process HTTP traffic from the local machine.
428 **
429 ** The REPOSITORY can be a directory (aka folder) that contains one or
430 ** more repositories with names ending in ".fossil". In this case, the
431 ** a prefix of the URL pathname is used to search the directory for an
432 ** appropriate repository. To thwart mischief, the pathname in the URL must
433 ** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
434 ** occur after "/", and every "." must be surrounded on both sides by
435 ** alphanumerics. Any pathname that does not satisfy these constraints
436 ** results in a 404 error. Files in REPOSITORY that match the comma-separated
437 ** list of glob patterns given by --files and that have known suffixes
438 ** such as ".txt" or ".html" or ".jpeg" and do not match the pattern
439 ** "*.fossil*" will be served as static content. With the "ui" command,
440 ** the REPOSITORY can only be a directory if the --notfound option is
441 ** also present.
442 **
443 ** By default, the "ui" command provides full administrative access without
444 ** having to log in. This can be disabled by setting turning off the
445 ** "localauth" setting. Automatic login for the "server" command is available
446 ** if the --localauth option is present and the "localauth" setting is off
447 ** and the connection is from localhost. The optional REPOSITORY argument
448 ** to "ui" may be a directory and will function as "server" if and only if
449 ** the --notfound option is used.
450 **
451 ** Options:
452 ** --localauth enable automatic login for requests from localhost
453 ** --localhost listen on 127.0.0.1 only (always true for "ui")
454 ** -P|--port TCPPORT listen to request on port TCPPORT
455 ** --th-trace trace TH1 execution (for debugging purposes)
456 ** --baseurl URL Use URL as the base (useful for reverse proxies)
457 ** --notfound URL Redirect
458 ** --files GLOBLIST Comma-separated list of glob patterns for static files
459 **
460 ** See also: cgi, http, winsrv
461 */
462 void cmd_webserver(void){
463 int iPort, mxPort; /* Range of TCP ports allowed */
464 const char *zPort; /* Value of the --port option */
465 const char *zBrowser; /* Name of web browser program */
466 char *zBrowserCmd = 0; /* Command to launch the web browser */
467 int isUiCmd; /* True if command is "ui", not "server' */
468 const char *zNotFound; /* The --notfound option or NULL */
469 int flags = 0; /* Server flags */
470 const char *zAltBase; /* Argument to the --baseurl option */
471 const char *zFileGlob; /* Static content must match this */
472 char *zIpAddr = 0; /* Bind to this IP address */
473
474 #if defined(_WIN32)
475 const char *zStopperFile; /* Name of file used to terminate server */
476 zStopperFile = find_option("stopper", 0, 1);
477 #endif
478
479 zFileGlob = find_option("files", 0, 1);
480 g.useLocalauth = find_option("localauth", 0, 0)!=0;
481 Th_InitTraceLog();
482 zPort = find_option("port", "P", 1);
483 zNotFound = find_option("notfound", 0, 1);
484 zAltBase = find_option("baseurl", 0, 1);
485 if( zAltBase ){
486 set_base_url(zAltBase);
487 }
488 if ( find_option("localhost", 0, 0)!=0 ){
489 flags |= HTTP_SERVER_LOCALHOST;
490 }
491 if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
492 isUiCmd = g.argv[1][0]=='u';
493 if( isUiCmd ){
494 flags |= HTTP_SERVER_LOCALHOST;
495 g.useLocalauth = 1;
496 }
497 find_server_repository(isUiCmd && zNotFound==0);
498 if( zPort ){
499 int i;
500 for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
501 if( i>0 ){
502 zIpAddr = mprintf("%.*s", i, zPort);
503 zPort += i+1;
504 }
505 iPort = mxPort = atoi(zPort);
506 }else{
507 iPort = db_get_int("http-port", 8080);
508 mxPort = iPort+100;
509 }
510 #if !defined(_WIN32)
511 /* Unix implementation */
512 if( isUiCmd ){
513 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
514 zBrowser = db_get("web-browser", 0);
515 if( zBrowser==0 ){
516 static const char *const azBrowserProg[] =
517 { "xdg-open", "gnome-open", "firefox", "google-chrome" };
518 int i;
519 zBrowser = "echo";
520 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
521 if( binaryOnPath(azBrowserProg[i]) ){
522 zBrowser = azBrowserProg[i];
523 break;
524 }
525 }
526 }
527 #else
528 zBrowser = db_get("web-browser", "open");
529 #endif
530 if( zIpAddr ){
531 zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
532 }else{
533 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
534 }
535 }
536 db_close(1);
537 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
538 fossil_fatal("unable to listen on TCP socket %d", iPort);
539 }
540 g.sslNotAvailable = 1;
541 g.httpIn = stdin;
542 g.httpOut = stdout;
543 if( g.fHttpTrace || g.fSqlTrace ){
544 fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
545 }
546 g.cgiOutput = 1;
547 find_server_repository(isUiCmd && zNotFound==0);
548 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
549 cgi_handle_http_request(0);
550 process_one_web_page(zNotFound, glob_create(zFileGlob));
551 #else
552 /* Win32 implementation */
553 if( isUiCmd ){
554 zBrowser = db_get("web-browser", "start");
555 if( zIpAddr ){
556 zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
557 }else{
558 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
559 }
560 }
561 db_close(1);
562 if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
563 win32_http_server(iPort, mxPort, zBrowserCmd,
564 zStopperFile, zNotFound, zFileGlob, zIpAddr, flags);
565 }
566 #endif
567 }
+10 -4
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,13 +26,13 @@
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2727
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
2828
2929
SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
3030
31
-SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
31
+SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c server_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3232
33
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
33
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\server$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3434
3535
3636
RC=$(DMDIR)\bin\rcc
3737
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
3838
@@ -46,11 +46,11 @@
4646
4747
$(OBJDIR)\fossil.res: $B\win\fossil.rc
4848
$(RC) $(RCFLAGS) -o$@ $**
4949
5050
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51
- +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
51
+ +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search server setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
5252
+echo fossil >> $@
5353
+echo fossil >> $@
5454
+echo $(LIBS) >> $@
5555
+echo. >> $@
5656
+echo fossil >> $@
@@ -566,10 +566,16 @@
566566
$(OBJDIR)\search$O : search_.c search.h
567567
$(TCC) -o$@ -c search_.c
568568
569569
search_.c : $(SRCDIR)\search.c
570570
+translate$E $** > $@
571
+
572
+$(OBJDIR)\server$O : server_.c server.h
573
+ $(TCC) -o$@ -c server_.c
574
+
575
+server_.c : $(SRCDIR)\server.c
576
+ +translate$E $** > $@
571577
572578
$(OBJDIR)\setup$O : setup_.c setup.h
573579
$(TCC) -o$@ -c setup_.c
574580
575581
setup_.c : $(SRCDIR)\setup.c
@@ -754,7 +760,7 @@
754760
755761
zip_.c : $(SRCDIR)\zip.c
756762
+translate$E $** > $@
757763
758764
headers: makeheaders$E page_index.h VERSION.h
759
- +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
765
+ +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h server_.c:server.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
760766
@copy /Y nul: headers
761767
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,13 +26,13 @@
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
30
31 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
32
33 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
34
35
36 RC=$(DMDIR)\bin\rcc
37 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
38
@@ -46,11 +46,11 @@
46
47 $(OBJDIR)\fossil.res: $B\win\fossil.rc
48 $(RC) $(RCFLAGS) -o$@ $**
49
50 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51 +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
52 +echo fossil >> $@
53 +echo fossil >> $@
54 +echo $(LIBS) >> $@
55 +echo. >> $@
56 +echo fossil >> $@
@@ -566,10 +566,16 @@
566 $(OBJDIR)\search$O : search_.c search.h
567 $(TCC) -o$@ -c search_.c
568
569 search_.c : $(SRCDIR)\search.c
570 +translate$E $** > $@
 
 
 
 
 
 
571
572 $(OBJDIR)\setup$O : setup_.c setup.h
573 $(TCC) -o$@ -c setup_.c
574
575 setup_.c : $(SRCDIR)\setup.c
@@ -754,7 +760,7 @@
754
755 zip_.c : $(SRCDIR)\zip.c
756 +translate$E $** > $@
757
758 headers: makeheaders$E page_index.h VERSION.h
759 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
760 @copy /Y nul: headers
761
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,13 +26,13 @@
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
30
31 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c server_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
32
33 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\server$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
34
35
36 RC=$(DMDIR)\bin\rcc
37 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
38
@@ -46,11 +46,11 @@
46
47 $(OBJDIR)\fossil.res: $B\win\fossil.rc
48 $(RC) $(RCFLAGS) -o$@ $**
49
50 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51 +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search server setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
52 +echo fossil >> $@
53 +echo fossil >> $@
54 +echo $(LIBS) >> $@
55 +echo. >> $@
56 +echo fossil >> $@
@@ -566,10 +566,16 @@
566 $(OBJDIR)\search$O : search_.c search.h
567 $(TCC) -o$@ -c search_.c
568
569 search_.c : $(SRCDIR)\search.c
570 +translate$E $** > $@
571
572 $(OBJDIR)\server$O : server_.c server.h
573 $(TCC) -o$@ -c server_.c
574
575 server_.c : $(SRCDIR)\server.c
576 +translate$E $** > $@
577
578 $(OBJDIR)\setup$O : setup_.c setup.h
579 $(TCC) -o$@ -c setup_.c
580
581 setup_.c : $(SRCDIR)\setup.c
@@ -754,7 +760,7 @@
760
761 zip_.c : $(SRCDIR)\zip.c
762 +translate$E $** > $@
763
764 headers: makeheaders$E page_index.h VERSION.h
765 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h server_.c:server.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
766 @copy /Y nul: headers
767
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -319,10 +319,11 @@
319319
$(SRCDIR)/regexp.c \
320320
$(SRCDIR)/report.c \
321321
$(SRCDIR)/rss.c \
322322
$(SRCDIR)/schema.c \
323323
$(SRCDIR)/search.c \
324
+ $(SRCDIR)/server.c \
324325
$(SRCDIR)/setup.c \
325326
$(SRCDIR)/sha1.c \
326327
$(SRCDIR)/shun.c \
327328
$(SRCDIR)/skins.c \
328329
$(SRCDIR)/sqlcmd.c \
@@ -428,10 +429,11 @@
428429
$(OBJDIR)/regexp_.c \
429430
$(OBJDIR)/report_.c \
430431
$(OBJDIR)/rss_.c \
431432
$(OBJDIR)/schema_.c \
432433
$(OBJDIR)/search_.c \
434
+ $(OBJDIR)/server_.c \
433435
$(OBJDIR)/setup_.c \
434436
$(OBJDIR)/sha1_.c \
435437
$(OBJDIR)/shun_.c \
436438
$(OBJDIR)/skins_.c \
437439
$(OBJDIR)/sqlcmd_.c \
@@ -537,10 +539,11 @@
537539
$(OBJDIR)/regexp.o \
538540
$(OBJDIR)/report.o \
539541
$(OBJDIR)/rss.o \
540542
$(OBJDIR)/schema.o \
541543
$(OBJDIR)/search.o \
544
+ $(OBJDIR)/server.o \
542545
$(OBJDIR)/setup.o \
543546
$(OBJDIR)/sha1.o \
544547
$(OBJDIR)/shun.o \
545548
$(OBJDIR)/skins.o \
546549
$(OBJDIR)/sqlcmd.o \
@@ -759,10 +762,11 @@
759762
$(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
760763
$(OBJDIR)/report_.c:$(OBJDIR)/report.h \
761764
$(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
762765
$(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
763766
$(OBJDIR)/search_.c:$(OBJDIR)/search.h \
767
+ $(OBJDIR)/server_.c:$(OBJDIR)/server.h \
764768
$(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
765769
$(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
766770
$(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
767771
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
768772
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
@@ -1406,10 +1410,18 @@
14061410
14071411
$(OBJDIR)/search.o: $(OBJDIR)/search_.c $(OBJDIR)/search.h $(SRCDIR)/config.h
14081412
$(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c
14091413
14101414
$(OBJDIR)/search.h: $(OBJDIR)/headers
1415
+
1416
+$(OBJDIR)/server_.c: $(SRCDIR)/server.c $(OBJDIR)/translate
1417
+ $(TRANSLATE) $(SRCDIR)/server.c >$(OBJDIR)/server_.c
1418
+
1419
+$(OBJDIR)/server.o: $(OBJDIR)/server_.c $(OBJDIR)/server.h $(SRCDIR)/config.h
1420
+ $(XTCC) -o $(OBJDIR)/server.o -c $(OBJDIR)/server_.c
1421
+
1422
+$(OBJDIR)/server.h: $(OBJDIR)/headers
14111423
14121424
$(OBJDIR)/setup_.c: $(SRCDIR)/setup.c $(OBJDIR)/translate
14131425
$(TRANSLATE) $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c
14141426
14151427
$(OBJDIR)/setup.o: $(OBJDIR)/setup_.c $(OBJDIR)/setup.h $(SRCDIR)/config.h
14161428
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -319,10 +319,11 @@
319 $(SRCDIR)/regexp.c \
320 $(SRCDIR)/report.c \
321 $(SRCDIR)/rss.c \
322 $(SRCDIR)/schema.c \
323 $(SRCDIR)/search.c \
 
324 $(SRCDIR)/setup.c \
325 $(SRCDIR)/sha1.c \
326 $(SRCDIR)/shun.c \
327 $(SRCDIR)/skins.c \
328 $(SRCDIR)/sqlcmd.c \
@@ -428,10 +429,11 @@
428 $(OBJDIR)/regexp_.c \
429 $(OBJDIR)/report_.c \
430 $(OBJDIR)/rss_.c \
431 $(OBJDIR)/schema_.c \
432 $(OBJDIR)/search_.c \
 
433 $(OBJDIR)/setup_.c \
434 $(OBJDIR)/sha1_.c \
435 $(OBJDIR)/shun_.c \
436 $(OBJDIR)/skins_.c \
437 $(OBJDIR)/sqlcmd_.c \
@@ -537,10 +539,11 @@
537 $(OBJDIR)/regexp.o \
538 $(OBJDIR)/report.o \
539 $(OBJDIR)/rss.o \
540 $(OBJDIR)/schema.o \
541 $(OBJDIR)/search.o \
 
542 $(OBJDIR)/setup.o \
543 $(OBJDIR)/sha1.o \
544 $(OBJDIR)/shun.o \
545 $(OBJDIR)/skins.o \
546 $(OBJDIR)/sqlcmd.o \
@@ -759,10 +762,11 @@
759 $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
760 $(OBJDIR)/report_.c:$(OBJDIR)/report.h \
761 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
762 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
763 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
 
764 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
765 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
766 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
767 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
768 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
@@ -1406,10 +1410,18 @@
1406
1407 $(OBJDIR)/search.o: $(OBJDIR)/search_.c $(OBJDIR)/search.h $(SRCDIR)/config.h
1408 $(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c
1409
1410 $(OBJDIR)/search.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1411
1412 $(OBJDIR)/setup_.c: $(SRCDIR)/setup.c $(OBJDIR)/translate
1413 $(TRANSLATE) $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c
1414
1415 $(OBJDIR)/setup.o: $(OBJDIR)/setup_.c $(OBJDIR)/setup.h $(SRCDIR)/config.h
1416
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -319,10 +319,11 @@
319 $(SRCDIR)/regexp.c \
320 $(SRCDIR)/report.c \
321 $(SRCDIR)/rss.c \
322 $(SRCDIR)/schema.c \
323 $(SRCDIR)/search.c \
324 $(SRCDIR)/server.c \
325 $(SRCDIR)/setup.c \
326 $(SRCDIR)/sha1.c \
327 $(SRCDIR)/shun.c \
328 $(SRCDIR)/skins.c \
329 $(SRCDIR)/sqlcmd.c \
@@ -428,10 +429,11 @@
429 $(OBJDIR)/regexp_.c \
430 $(OBJDIR)/report_.c \
431 $(OBJDIR)/rss_.c \
432 $(OBJDIR)/schema_.c \
433 $(OBJDIR)/search_.c \
434 $(OBJDIR)/server_.c \
435 $(OBJDIR)/setup_.c \
436 $(OBJDIR)/sha1_.c \
437 $(OBJDIR)/shun_.c \
438 $(OBJDIR)/skins_.c \
439 $(OBJDIR)/sqlcmd_.c \
@@ -537,10 +539,11 @@
539 $(OBJDIR)/regexp.o \
540 $(OBJDIR)/report.o \
541 $(OBJDIR)/rss.o \
542 $(OBJDIR)/schema.o \
543 $(OBJDIR)/search.o \
544 $(OBJDIR)/server.o \
545 $(OBJDIR)/setup.o \
546 $(OBJDIR)/sha1.o \
547 $(OBJDIR)/shun.o \
548 $(OBJDIR)/skins.o \
549 $(OBJDIR)/sqlcmd.o \
@@ -759,10 +762,11 @@
762 $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
763 $(OBJDIR)/report_.c:$(OBJDIR)/report.h \
764 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
765 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
766 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
767 $(OBJDIR)/server_.c:$(OBJDIR)/server.h \
768 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
769 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
770 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
771 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
772 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
@@ -1406,10 +1410,18 @@
1410
1411 $(OBJDIR)/search.o: $(OBJDIR)/search_.c $(OBJDIR)/search.h $(SRCDIR)/config.h
1412 $(XTCC) -o $(OBJDIR)/search.o -c $(OBJDIR)/search_.c
1413
1414 $(OBJDIR)/search.h: $(OBJDIR)/headers
1415
1416 $(OBJDIR)/server_.c: $(SRCDIR)/server.c $(OBJDIR)/translate
1417 $(TRANSLATE) $(SRCDIR)/server.c >$(OBJDIR)/server_.c
1418
1419 $(OBJDIR)/server.o: $(OBJDIR)/server_.c $(OBJDIR)/server.h $(SRCDIR)/config.h
1420 $(XTCC) -o $(OBJDIR)/server.o -c $(OBJDIR)/server_.c
1421
1422 $(OBJDIR)/server.h: $(OBJDIR)/headers
1423
1424 $(OBJDIR)/setup_.c: $(SRCDIR)/setup.c $(OBJDIR)/translate
1425 $(TRANSLATE) $(SRCDIR)/setup.c >$(OBJDIR)/setup_.c
1426
1427 $(OBJDIR)/setup.o: $(OBJDIR)/setup_.c $(OBJDIR)/setup.h $(SRCDIR)/config.h
1428
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -137,10 +137,11 @@
137137
regexp_.c \
138138
report_.c \
139139
rss_.c \
140140
schema_.c \
141141
search_.c \
142
+ server_.c \
142143
setup_.c \
143144
sha1_.c \
144145
shun_.c \
145146
skins_.c \
146147
sqlcmd_.c \
@@ -246,10 +247,11 @@
246247
$(OX)\regexp$O \
247248
$(OX)\report$O \
248249
$(OX)\rss$O \
249250
$(OX)\schema$O \
250251
$(OX)\search$O \
252
+ $(OX)\server$O \
251253
$(OX)\setup$O \
252254
$(OX)\sha1$O \
253255
$(OX)\shell$O \
254256
$(OX)\shun$O \
255257
$(OX)\skins$O \
@@ -373,10 +375,11 @@
373375
echo $(OX)\regexp.obj >> $@
374376
echo $(OX)\report.obj >> $@
375377
echo $(OX)\rss.obj >> $@
376378
echo $(OX)\schema.obj >> $@
377379
echo $(OX)\search.obj >> $@
380
+ echo $(OX)\server.obj >> $@
378381
echo $(OX)\setup.obj >> $@
379382
echo $(OX)\sha1.obj >> $@
380383
echo $(OX)\shell.obj >> $@
381384
echo $(OX)\shun.obj >> $@
382385
echo $(OX)\skins.obj >> $@
@@ -938,10 +941,16 @@
938941
$(OX)\search$O : search_.c search.h
939942
$(TCC) /Fo$@ -c search_.c
940943
941944
search_.c : $(SRCDIR)\search.c
942945
translate$E $** > $@
946
+
947
+$(OX)\server$O : server_.c server.h
948
+ $(TCC) /Fo$@ -c server_.c
949
+
950
+server_.c : $(SRCDIR)\server.c
951
+ translate$E $** > $@
943952
944953
$(OX)\setup$O : setup_.c setup.h
945954
$(TCC) /Fo$@ -c setup_.c
946955
947956
setup_.c : $(SRCDIR)\setup.c
@@ -1204,10 +1213,11 @@
12041213
regexp_.c:regexp.h \
12051214
report_.c:report.h \
12061215
rss_.c:rss.h \
12071216
schema_.c:schema.h \
12081217
search_.c:search.h \
1218
+ server_.c:server.h \
12091219
setup_.c:setup.h \
12101220
sha1_.c:sha1.h \
12111221
shun_.c:shun.h \
12121222
skins_.c:skins.h \
12131223
sqlcmd_.c:sqlcmd.h \
12141224
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -137,10 +137,11 @@
137 regexp_.c \
138 report_.c \
139 rss_.c \
140 schema_.c \
141 search_.c \
 
142 setup_.c \
143 sha1_.c \
144 shun_.c \
145 skins_.c \
146 sqlcmd_.c \
@@ -246,10 +247,11 @@
246 $(OX)\regexp$O \
247 $(OX)\report$O \
248 $(OX)\rss$O \
249 $(OX)\schema$O \
250 $(OX)\search$O \
 
251 $(OX)\setup$O \
252 $(OX)\sha1$O \
253 $(OX)\shell$O \
254 $(OX)\shun$O \
255 $(OX)\skins$O \
@@ -373,10 +375,11 @@
373 echo $(OX)\regexp.obj >> $@
374 echo $(OX)\report.obj >> $@
375 echo $(OX)\rss.obj >> $@
376 echo $(OX)\schema.obj >> $@
377 echo $(OX)\search.obj >> $@
 
378 echo $(OX)\setup.obj >> $@
379 echo $(OX)\sha1.obj >> $@
380 echo $(OX)\shell.obj >> $@
381 echo $(OX)\shun.obj >> $@
382 echo $(OX)\skins.obj >> $@
@@ -938,10 +941,16 @@
938 $(OX)\search$O : search_.c search.h
939 $(TCC) /Fo$@ -c search_.c
940
941 search_.c : $(SRCDIR)\search.c
942 translate$E $** > $@
 
 
 
 
 
 
943
944 $(OX)\setup$O : setup_.c setup.h
945 $(TCC) /Fo$@ -c setup_.c
946
947 setup_.c : $(SRCDIR)\setup.c
@@ -1204,10 +1213,11 @@
1204 regexp_.c:regexp.h \
1205 report_.c:report.h \
1206 rss_.c:rss.h \
1207 schema_.c:schema.h \
1208 search_.c:search.h \
 
1209 setup_.c:setup.h \
1210 sha1_.c:sha1.h \
1211 shun_.c:shun.h \
1212 skins_.c:skins.h \
1213 sqlcmd_.c:sqlcmd.h \
1214
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -137,10 +137,11 @@
137 regexp_.c \
138 report_.c \
139 rss_.c \
140 schema_.c \
141 search_.c \
142 server_.c \
143 setup_.c \
144 sha1_.c \
145 shun_.c \
146 skins_.c \
147 sqlcmd_.c \
@@ -246,10 +247,11 @@
247 $(OX)\regexp$O \
248 $(OX)\report$O \
249 $(OX)\rss$O \
250 $(OX)\schema$O \
251 $(OX)\search$O \
252 $(OX)\server$O \
253 $(OX)\setup$O \
254 $(OX)\sha1$O \
255 $(OX)\shell$O \
256 $(OX)\shun$O \
257 $(OX)\skins$O \
@@ -373,10 +375,11 @@
375 echo $(OX)\regexp.obj >> $@
376 echo $(OX)\report.obj >> $@
377 echo $(OX)\rss.obj >> $@
378 echo $(OX)\schema.obj >> $@
379 echo $(OX)\search.obj >> $@
380 echo $(OX)\server.obj >> $@
381 echo $(OX)\setup.obj >> $@
382 echo $(OX)\sha1.obj >> $@
383 echo $(OX)\shell.obj >> $@
384 echo $(OX)\shun.obj >> $@
385 echo $(OX)\skins.obj >> $@
@@ -938,10 +941,16 @@
941 $(OX)\search$O : search_.c search.h
942 $(TCC) /Fo$@ -c search_.c
943
944 search_.c : $(SRCDIR)\search.c
945 translate$E $** > $@
946
947 $(OX)\server$O : server_.c server.h
948 $(TCC) /Fo$@ -c server_.c
949
950 server_.c : $(SRCDIR)\server.c
951 translate$E $** > $@
952
953 $(OX)\setup$O : setup_.c setup.h
954 $(TCC) /Fo$@ -c setup_.c
955
956 setup_.c : $(SRCDIR)\setup.c
@@ -1204,10 +1213,11 @@
1213 regexp_.c:regexp.h \
1214 report_.c:report.h \
1215 rss_.c:rss.h \
1216 schema_.c:schema.h \
1217 search_.c:search.h \
1218 server_.c:server.h \
1219 setup_.c:setup.h \
1220 sha1_.c:sha1.h \
1221 shun_.c:shun.h \
1222 skins_.c:skins.h \
1223 sqlcmd_.c:sqlcmd.h \
1224

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button