Fossil SCM
Change --unix-socket to --socket-name. Add --socket-mode and --socket-owner. Mostly working, accept that --socket-owner seemingly has no effect, even though the fchown() return 0. There is currently a debugging printf() in that line of code. This is an experimental check-in.
Commit
9f71e5cc027f656bd263c6bf7fde53381e5186f7a49ef2231b9bc451672c8200
Parent
7fc2902126d43f8…
3 files changed
+40
-17
+64
+38
-9
+40
-17
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -2477,11 +2477,11 @@ | ||
| 2477 | 2477 | #define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */ |
| 2478 | 2478 | #define HTTP_SERVER_HAD_REPOSITORY 0x0004 /* Was the repository open? */ |
| 2479 | 2479 | #define HTTP_SERVER_HAD_CHECKOUT 0x0008 /* Was a checkout open? */ |
| 2480 | 2480 | #define HTTP_SERVER_REPOLIST 0x0010 /* Allow repo listing */ |
| 2481 | 2481 | #define HTTP_SERVER_NOFORK 0x0020 /* Do not call fork() */ |
| 2482 | -#define HTTP_SERVER_UNIXDOMAINSOCK 0x0040 /* Use a unix-domain socket */ | |
| 2482 | +#define HTTP_SERVER_UNIXSOCKET 0x0040 /* Use a unix-domain socket */ | |
| 2483 | 2483 | |
| 2484 | 2484 | #endif /* INTERFACE */ |
| 2485 | 2485 | |
| 2486 | 2486 | /* |
| 2487 | 2487 | ** Maximum number of child processes that we can have running |
| @@ -2524,23 +2524,46 @@ | ||
| 2524 | 2524 | int opt = 1; /* setsockopt flag */ |
| 2525 | 2525 | int rc; /* Result code from system calls */ |
| 2526 | 2526 | int iPort = mnPort; /* Port to try to use */ |
| 2527 | 2527 | |
| 2528 | 2528 | while( iPort<=mxPort ){ |
| 2529 | - if( flags & HTTP_SERVER_UNIXDOMAINSOCK ){ | |
| 2529 | + if( flags & HTTP_SERVER_UNIXSOCKET ){ | |
| 2530 | + /* Initialize a Unix socket named g.zSockName */ | |
| 2531 | + assert( g.zSockName!=0 ); | |
| 2530 | 2532 | memset(&uxaddr, 0, sizeof(uxaddr)); |
| 2531 | - if( strlen(zIpAddr)>sizeof(uxaddr.sun_path) ){ | |
| 2532 | - fossil_fatal("name of unix-domain socket too big: %s\n" | |
| 2533 | - "max size: %d\n", zIpAddr, (int)sizeof(uxaddr.sun_path)); | |
| 2533 | + if( strlen(g.zSockName)>sizeof(uxaddr.sun_path) ){ | |
| 2534 | + fossil_fatal("name of unix socket too big: %s\nmax size: %d\n", | |
| 2535 | + g.zSockName, (int)sizeof(uxaddr.sun_path)); | |
| 2534 | 2536 | } |
| 2535 | - if( unlink(zIpAddr)==-1 && errno!=ENOENT ){ | |
| 2536 | - fossil_fatal("Cannot remove existing file at %s\n", zIpAddr); | |
| 2537 | + if( file_isdir(g.zSockName, ExtFILE)!=0 ){ | |
| 2538 | + if( !file_issocket(g.zSockName) ){ | |
| 2539 | + fossil_fatal("cannot name socket \"%s\" because another object" | |
| 2540 | + " with that name already exists", g.zSockName); | |
| 2541 | + }else{ | |
| 2542 | + unlink(g.zSockName); | |
| 2543 | + } | |
| 2537 | 2544 | } |
| 2538 | 2545 | uxaddr.sun_family = AF_UNIX; |
| 2539 | - strncpy(uxaddr.sun_path, zIpAddr, sizeof(uxaddr.sun_path)-1); | |
| 2546 | + strncpy(uxaddr.sun_path, g.zSockName, sizeof(uxaddr.sun_path)-1); | |
| 2540 | 2547 | listener = socket(AF_UNIX, SOCK_STREAM, 0); |
| 2548 | + if( listener<0 ){ | |
| 2549 | + fossil_fatal("unable to create a unix socket named %s", | |
| 2550 | + g.zSockName); | |
| 2551 | + } | |
| 2552 | + /* Set the access permission for the new socket. Default to 0660. | |
| 2553 | + ** But use an alternative specified by --socket-mode if available */ | |
| 2554 | + if( g.zSockMode ){ | |
| 2555 | + file_set_mode(g.zSockName, listener, g.zSockMode, 0); | |
| 2556 | + }else{ | |
| 2557 | + file_set_mode(g.zSockName, listener, "0660", 1); | |
| 2558 | + } | |
| 2559 | + /* Set the owner of the socket if requested by --socket-owner */ | |
| 2560 | + if( g.zSockOwner ){ | |
| 2561 | + file_set_owner(g.zSockName, listener, g.zSockOwner); | |
| 2562 | + } | |
| 2541 | 2563 | }else{ |
| 2564 | + /* Initialize a TCP/IP socket on port iPort */ | |
| 2542 | 2565 | memset(&inaddr, 0, sizeof(inaddr)); |
| 2543 | 2566 | inaddr.sin_family = AF_INET; |
| 2544 | 2567 | if( zIpAddr ){ |
| 2545 | 2568 | inaddr.sin_addr.s_addr = inet_addr(zIpAddr); |
| 2546 | 2569 | if( inaddr.sin_addr.s_addr == INADDR_NONE ){ |
| @@ -2551,20 +2574,20 @@ | ||
| 2551 | 2574 | }else{ |
| 2552 | 2575 | inaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 2553 | 2576 | } |
| 2554 | 2577 | inaddr.sin_port = htons(iPort); |
| 2555 | 2578 | listener = socket(AF_INET, SOCK_STREAM, 0); |
| 2556 | - } | |
| 2557 | - if( listener<0 ){ | |
| 2558 | - iPort++; | |
| 2559 | - continue; | |
| 2579 | + if( listener<0 ){ | |
| 2580 | + iPort++; | |
| 2581 | + continue; | |
| 2582 | + } | |
| 2560 | 2583 | } |
| 2561 | 2584 | |
| 2562 | 2585 | /* if we can't terminate nicely, at least allow the socket to be reused */ |
| 2563 | 2586 | setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); |
| 2564 | 2587 | |
| 2565 | - if( flags & HTTP_SERVER_UNIXDOMAINSOCK ){ | |
| 2588 | + if( flags & HTTP_SERVER_UNIXSOCKET ){ | |
| 2566 | 2589 | rc = bind(listener, (struct sockaddr*)&uxaddr, sizeof(uxaddr)); |
| 2567 | 2590 | }else{ |
| 2568 | 2591 | rc = bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr)); |
| 2569 | 2592 | } |
| 2570 | 2593 | if( rc<0 ){ |
| @@ -2573,32 +2596,32 @@ | ||
| 2573 | 2596 | continue; |
| 2574 | 2597 | } |
| 2575 | 2598 | break; |
| 2576 | 2599 | } |
| 2577 | 2600 | if( iPort>mxPort ){ |
| 2578 | - if( flags & HTTP_SERVER_UNIXDOMAINSOCK ){ | |
| 2579 | - fossil_fatal("unable to listen on unix-domain socket %s", zIpAddr); | |
| 2601 | + if( flags & HTTP_SERVER_UNIXSOCKET ){ | |
| 2602 | + fossil_fatal("unable to listen on unix socket %s", zIpAddr); | |
| 2580 | 2603 | }else if( mnPort==mxPort ){ |
| 2581 | 2604 | fossil_fatal("unable to open listening socket on port %d", mnPort); |
| 2582 | 2605 | }else{ |
| 2583 | 2606 | fossil_fatal("unable to open listening socket on any" |
| 2584 | 2607 | " port in the range %d..%d", mnPort, mxPort); |
| 2585 | 2608 | } |
| 2586 | 2609 | } |
| 2587 | 2610 | if( iPort>mxPort ) return 1; |
| 2588 | 2611 | listen(listener,10); |
| 2589 | - if( flags & HTTP_SERVER_UNIXDOMAINSOCK ){ | |
| 2612 | + if( flags & HTTP_SERVER_UNIXSOCKET ){ | |
| 2590 | 2613 | fossil_print("Listening for %s requests on unix-domain socket %s\n", |
| 2591 | 2614 | (flags & HTTP_SERVER_SCGI)!=0 ? "SCGI" : |
| 2592 | 2615 | g.httpUseSSL?"TLS-encrypted HTTPS":"HTTP", zIpAddr); |
| 2593 | 2616 | }else{ |
| 2594 | 2617 | fossil_print("Listening for %s requests on TCP port %d\n", |
| 2595 | 2618 | (flags & HTTP_SERVER_SCGI)!=0 ? "SCGI" : |
| 2596 | 2619 | g.httpUseSSL?"TLS-encrypted HTTPS":"HTTP", iPort); |
| 2597 | 2620 | } |
| 2598 | 2621 | fflush(stdout); |
| 2599 | - if( zBrowser && (flags & HTTP_SERVER_UNIXDOMAINSOCK)==0 ){ | |
| 2622 | + if( zBrowser && (flags & HTTP_SERVER_UNIXSOCKET)==0 ){ | |
| 2600 | 2623 | assert( strstr(zBrowser,"%d")!=0 ); |
| 2601 | 2624 | zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort); |
| 2602 | 2625 | #if defined(__CYGWIN__) |
| 2603 | 2626 | /* On Cygwin, we can do better than "echo" */ |
| 2604 | 2627 | if( fossil_strncmp(zBrowser, "echo ", 5)==0 ){ |
| 2605 | 2628 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -2477,11 +2477,11 @@ | |
| 2477 | #define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */ |
| 2478 | #define HTTP_SERVER_HAD_REPOSITORY 0x0004 /* Was the repository open? */ |
| 2479 | #define HTTP_SERVER_HAD_CHECKOUT 0x0008 /* Was a checkout open? */ |
| 2480 | #define HTTP_SERVER_REPOLIST 0x0010 /* Allow repo listing */ |
| 2481 | #define HTTP_SERVER_NOFORK 0x0020 /* Do not call fork() */ |
| 2482 | #define HTTP_SERVER_UNIXDOMAINSOCK 0x0040 /* Use a unix-domain socket */ |
| 2483 | |
| 2484 | #endif /* INTERFACE */ |
| 2485 | |
| 2486 | /* |
| 2487 | ** Maximum number of child processes that we can have running |
| @@ -2524,23 +2524,46 @@ | |
| 2524 | int opt = 1; /* setsockopt flag */ |
| 2525 | int rc; /* Result code from system calls */ |
| 2526 | int iPort = mnPort; /* Port to try to use */ |
| 2527 | |
| 2528 | while( iPort<=mxPort ){ |
| 2529 | if( flags & HTTP_SERVER_UNIXDOMAINSOCK ){ |
| 2530 | memset(&uxaddr, 0, sizeof(uxaddr)); |
| 2531 | if( strlen(zIpAddr)>sizeof(uxaddr.sun_path) ){ |
| 2532 | fossil_fatal("name of unix-domain socket too big: %s\n" |
| 2533 | "max size: %d\n", zIpAddr, (int)sizeof(uxaddr.sun_path)); |
| 2534 | } |
| 2535 | if( unlink(zIpAddr)==-1 && errno!=ENOENT ){ |
| 2536 | fossil_fatal("Cannot remove existing file at %s\n", zIpAddr); |
| 2537 | } |
| 2538 | uxaddr.sun_family = AF_UNIX; |
| 2539 | strncpy(uxaddr.sun_path, zIpAddr, sizeof(uxaddr.sun_path)-1); |
| 2540 | listener = socket(AF_UNIX, SOCK_STREAM, 0); |
| 2541 | }else{ |
| 2542 | memset(&inaddr, 0, sizeof(inaddr)); |
| 2543 | inaddr.sin_family = AF_INET; |
| 2544 | if( zIpAddr ){ |
| 2545 | inaddr.sin_addr.s_addr = inet_addr(zIpAddr); |
| 2546 | if( inaddr.sin_addr.s_addr == INADDR_NONE ){ |
| @@ -2551,20 +2574,20 @@ | |
| 2551 | }else{ |
| 2552 | inaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 2553 | } |
| 2554 | inaddr.sin_port = htons(iPort); |
| 2555 | listener = socket(AF_INET, SOCK_STREAM, 0); |
| 2556 | } |
| 2557 | if( listener<0 ){ |
| 2558 | iPort++; |
| 2559 | continue; |
| 2560 | } |
| 2561 | |
| 2562 | /* if we can't terminate nicely, at least allow the socket to be reused */ |
| 2563 | setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); |
| 2564 | |
| 2565 | if( flags & HTTP_SERVER_UNIXDOMAINSOCK ){ |
| 2566 | rc = bind(listener, (struct sockaddr*)&uxaddr, sizeof(uxaddr)); |
| 2567 | }else{ |
| 2568 | rc = bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr)); |
| 2569 | } |
| 2570 | if( rc<0 ){ |
| @@ -2573,32 +2596,32 @@ | |
| 2573 | continue; |
| 2574 | } |
| 2575 | break; |
| 2576 | } |
| 2577 | if( iPort>mxPort ){ |
| 2578 | if( flags & HTTP_SERVER_UNIXDOMAINSOCK ){ |
| 2579 | fossil_fatal("unable to listen on unix-domain socket %s", zIpAddr); |
| 2580 | }else if( mnPort==mxPort ){ |
| 2581 | fossil_fatal("unable to open listening socket on port %d", mnPort); |
| 2582 | }else{ |
| 2583 | fossil_fatal("unable to open listening socket on any" |
| 2584 | " port in the range %d..%d", mnPort, mxPort); |
| 2585 | } |
| 2586 | } |
| 2587 | if( iPort>mxPort ) return 1; |
| 2588 | listen(listener,10); |
| 2589 | if( flags & HTTP_SERVER_UNIXDOMAINSOCK ){ |
| 2590 | fossil_print("Listening for %s requests on unix-domain socket %s\n", |
| 2591 | (flags & HTTP_SERVER_SCGI)!=0 ? "SCGI" : |
| 2592 | g.httpUseSSL?"TLS-encrypted HTTPS":"HTTP", zIpAddr); |
| 2593 | }else{ |
| 2594 | fossil_print("Listening for %s requests on TCP port %d\n", |
| 2595 | (flags & HTTP_SERVER_SCGI)!=0 ? "SCGI" : |
| 2596 | g.httpUseSSL?"TLS-encrypted HTTPS":"HTTP", iPort); |
| 2597 | } |
| 2598 | fflush(stdout); |
| 2599 | if( zBrowser && (flags & HTTP_SERVER_UNIXDOMAINSOCK)==0 ){ |
| 2600 | assert( strstr(zBrowser,"%d")!=0 ); |
| 2601 | zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort); |
| 2602 | #if defined(__CYGWIN__) |
| 2603 | /* On Cygwin, we can do better than "echo" */ |
| 2604 | if( fossil_strncmp(zBrowser, "echo ", 5)==0 ){ |
| 2605 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -2477,11 +2477,11 @@ | |
| 2477 | #define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */ |
| 2478 | #define HTTP_SERVER_HAD_REPOSITORY 0x0004 /* Was the repository open? */ |
| 2479 | #define HTTP_SERVER_HAD_CHECKOUT 0x0008 /* Was a checkout open? */ |
| 2480 | #define HTTP_SERVER_REPOLIST 0x0010 /* Allow repo listing */ |
| 2481 | #define HTTP_SERVER_NOFORK 0x0020 /* Do not call fork() */ |
| 2482 | #define HTTP_SERVER_UNIXSOCKET 0x0040 /* Use a unix-domain socket */ |
| 2483 | |
| 2484 | #endif /* INTERFACE */ |
| 2485 | |
| 2486 | /* |
| 2487 | ** Maximum number of child processes that we can have running |
| @@ -2524,23 +2524,46 @@ | |
| 2524 | int opt = 1; /* setsockopt flag */ |
| 2525 | int rc; /* Result code from system calls */ |
| 2526 | int iPort = mnPort; /* Port to try to use */ |
| 2527 | |
| 2528 | while( iPort<=mxPort ){ |
| 2529 | if( flags & HTTP_SERVER_UNIXSOCKET ){ |
| 2530 | /* Initialize a Unix socket named g.zSockName */ |
| 2531 | assert( g.zSockName!=0 ); |
| 2532 | memset(&uxaddr, 0, sizeof(uxaddr)); |
| 2533 | if( strlen(g.zSockName)>sizeof(uxaddr.sun_path) ){ |
| 2534 | fossil_fatal("name of unix socket too big: %s\nmax size: %d\n", |
| 2535 | g.zSockName, (int)sizeof(uxaddr.sun_path)); |
| 2536 | } |
| 2537 | if( file_isdir(g.zSockName, ExtFILE)!=0 ){ |
| 2538 | if( !file_issocket(g.zSockName) ){ |
| 2539 | fossil_fatal("cannot name socket \"%s\" because another object" |
| 2540 | " with that name already exists", g.zSockName); |
| 2541 | }else{ |
| 2542 | unlink(g.zSockName); |
| 2543 | } |
| 2544 | } |
| 2545 | uxaddr.sun_family = AF_UNIX; |
| 2546 | strncpy(uxaddr.sun_path, g.zSockName, sizeof(uxaddr.sun_path)-1); |
| 2547 | listener = socket(AF_UNIX, SOCK_STREAM, 0); |
| 2548 | if( listener<0 ){ |
| 2549 | fossil_fatal("unable to create a unix socket named %s", |
| 2550 | g.zSockName); |
| 2551 | } |
| 2552 | /* Set the access permission for the new socket. Default to 0660. |
| 2553 | ** But use an alternative specified by --socket-mode if available */ |
| 2554 | if( g.zSockMode ){ |
| 2555 | file_set_mode(g.zSockName, listener, g.zSockMode, 0); |
| 2556 | }else{ |
| 2557 | file_set_mode(g.zSockName, listener, "0660", 1); |
| 2558 | } |
| 2559 | /* Set the owner of the socket if requested by --socket-owner */ |
| 2560 | if( g.zSockOwner ){ |
| 2561 | file_set_owner(g.zSockName, listener, g.zSockOwner); |
| 2562 | } |
| 2563 | }else{ |
| 2564 | /* Initialize a TCP/IP socket on port iPort */ |
| 2565 | memset(&inaddr, 0, sizeof(inaddr)); |
| 2566 | inaddr.sin_family = AF_INET; |
| 2567 | if( zIpAddr ){ |
| 2568 | inaddr.sin_addr.s_addr = inet_addr(zIpAddr); |
| 2569 | if( inaddr.sin_addr.s_addr == INADDR_NONE ){ |
| @@ -2551,20 +2574,20 @@ | |
| 2574 | }else{ |
| 2575 | inaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 2576 | } |
| 2577 | inaddr.sin_port = htons(iPort); |
| 2578 | listener = socket(AF_INET, SOCK_STREAM, 0); |
| 2579 | if( listener<0 ){ |
| 2580 | iPort++; |
| 2581 | continue; |
| 2582 | } |
| 2583 | } |
| 2584 | |
| 2585 | /* if we can't terminate nicely, at least allow the socket to be reused */ |
| 2586 | setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); |
| 2587 | |
| 2588 | if( flags & HTTP_SERVER_UNIXSOCKET ){ |
| 2589 | rc = bind(listener, (struct sockaddr*)&uxaddr, sizeof(uxaddr)); |
| 2590 | }else{ |
| 2591 | rc = bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr)); |
| 2592 | } |
| 2593 | if( rc<0 ){ |
| @@ -2573,32 +2596,32 @@ | |
| 2596 | continue; |
| 2597 | } |
| 2598 | break; |
| 2599 | } |
| 2600 | if( iPort>mxPort ){ |
| 2601 | if( flags & HTTP_SERVER_UNIXSOCKET ){ |
| 2602 | fossil_fatal("unable to listen on unix socket %s", zIpAddr); |
| 2603 | }else if( mnPort==mxPort ){ |
| 2604 | fossil_fatal("unable to open listening socket on port %d", mnPort); |
| 2605 | }else{ |
| 2606 | fossil_fatal("unable to open listening socket on any" |
| 2607 | " port in the range %d..%d", mnPort, mxPort); |
| 2608 | } |
| 2609 | } |
| 2610 | if( iPort>mxPort ) return 1; |
| 2611 | listen(listener,10); |
| 2612 | if( flags & HTTP_SERVER_UNIXSOCKET ){ |
| 2613 | fossil_print("Listening for %s requests on unix-domain socket %s\n", |
| 2614 | (flags & HTTP_SERVER_SCGI)!=0 ? "SCGI" : |
| 2615 | g.httpUseSSL?"TLS-encrypted HTTPS":"HTTP", zIpAddr); |
| 2616 | }else{ |
| 2617 | fossil_print("Listening for %s requests on TCP port %d\n", |
| 2618 | (flags & HTTP_SERVER_SCGI)!=0 ? "SCGI" : |
| 2619 | g.httpUseSSL?"TLS-encrypted HTTPS":"HTTP", iPort); |
| 2620 | } |
| 2621 | fflush(stdout); |
| 2622 | if( zBrowser && (flags & HTTP_SERVER_UNIXSOCKET)==0 ){ |
| 2623 | assert( strstr(zBrowser,"%d")!=0 ); |
| 2624 | zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort); |
| 2625 | #if defined(__CYGWIN__) |
| 2626 | /* On Cygwin, we can do better than "echo" */ |
| 2627 | if( fossil_strncmp(zBrowser, "echo ", 5)==0 ){ |
| 2628 |
+64
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -34,10 +34,12 @@ | ||
| 34 | 34 | # include <direct.h> |
| 35 | 35 | # include <windows.h> |
| 36 | 36 | # include <sys/utime.h> |
| 37 | 37 | #else |
| 38 | 38 | # include <sys/time.h> |
| 39 | +# include <pwd.h> | |
| 40 | +# include <grp.h> | |
| 39 | 41 | #endif |
| 40 | 42 | |
| 41 | 43 | #if INTERFACE |
| 42 | 44 | |
| 43 | 45 | /* Many APIs take an eFType argument which must be one of ExtFILE, RepoFILE, |
| @@ -229,10 +231,20 @@ | ||
| 229 | 231 | ** for directories, devices, fifos, symlinks, etc. |
| 230 | 232 | */ |
| 231 | 233 | int file_isfile(const char *zFilename, int eFType){ |
| 232 | 234 | return getStat(zFilename, eFType) ? 0 : S_ISREG(fx.fileStat.st_mode); |
| 233 | 235 | } |
| 236 | + | |
| 237 | +/* | |
| 238 | +** Return TRUE if zFilename is a socket. | |
| 239 | +*/ | |
| 240 | +int file_issocket(const char *zFilename){ | |
| 241 | + if( getStat(zFilename, ExtFILE) ){ | |
| 242 | + return 0; /* stat() failed. Return false. */ | |
| 243 | + } | |
| 244 | + return S_ISSOCK(fx.fileStat.st_mode); | |
| 245 | +} | |
| 234 | 246 | |
| 235 | 247 | /* |
| 236 | 248 | ** Create a symbolic link named zLinkFile that points to zTargetFile. |
| 237 | 249 | ** |
| 238 | 250 | ** If allow-symlinks is off, create an ordinary file named zLinkFile |
| @@ -713,10 +725,61 @@ | ||
| 713 | 725 | file_set_mtime(zFile, iMTime); |
| 714 | 726 | iMTime = file_mtime(zFile, RepoFILE); |
| 715 | 727 | zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime); |
| 716 | 728 | fossil_print("Set mtime of \"%s\" to %s (%lld)\n", zFile, zDate, iMTime); |
| 717 | 729 | } |
| 730 | + | |
| 731 | +/* | |
| 732 | +** Change access permissions on a file. | |
| 733 | +*/ | |
| 734 | +void file_set_mode(const char *zFN, int fd, const char *zMode, int bNoErr){ | |
| 735 | + mode_t m; | |
| 736 | + char *zEnd = 0; | |
| 737 | + m = strtol(zMode, &zEnd, 0); | |
| 738 | + if( (zEnd[0] || fchmod(fd, m)) && !bNoErr ){ | |
| 739 | + fossil_fatal("cannot change permissions on %s to \"%s\"", | |
| 740 | + zFN, zMode); | |
| 741 | + } | |
| 742 | +} | |
| 743 | + | |
| 744 | +/* Change the owner of a file to zOwner. zOwner can be of the form | |
| 745 | +** USER:GROUP. | |
| 746 | +*/ | |
| 747 | +void file_set_owner(const char *zFN, int fd, const char *zOwner){ | |
| 748 | + const char *zGrp; | |
| 749 | + const char *zUsr = zOwner; | |
| 750 | + struct passwd *pw; | |
| 751 | + struct group *grp; | |
| 752 | + uid_t uid = -1; | |
| 753 | + gid_t gid = -1; | |
| 754 | + zGrp = strchr(zUsr, ':'); | |
| 755 | + if( zGrp ){ | |
| 756 | + int n = (int)(zGrp - zUsr); | |
| 757 | + zUsr = fossil_strndup(zUsr, n); | |
| 758 | + zGrp++; | |
| 759 | + } | |
| 760 | + pw = getpwnam(zUsr); | |
| 761 | + if( pw==0 ){ | |
| 762 | + fossil_fatal("no such user: \"%s\"", zUsr); | |
| 763 | + } | |
| 764 | + uid = pw->pw_uid; | |
| 765 | + if( zGrp ){ | |
| 766 | + grp = getgrnam(zGrp); | |
| 767 | + if( grp==0 ){ | |
| 768 | + fossil_fatal("no such group: \"%s\"", zGrp); | |
| 769 | + } | |
| 770 | + gid = grp->gr_gid; | |
| 771 | + } | |
| 772 | +printf("fd=%d zFN=%s uid=%d gid=%d\n", (int)fd, zFN, (int)uid, (int)gid); | |
| 773 | + if( fchown(fd, uid, gid) ){ | |
| 774 | + fossil_fatal("cannot change ownership of %s to %s",zFN, zOwner); | |
| 775 | + } | |
| 776 | + if( zOwner!=zUsr ){ | |
| 777 | + fossil_free((char*)zUsr); | |
| 778 | + } | |
| 779 | +} | |
| 780 | + | |
| 718 | 781 | |
| 719 | 782 | /* |
| 720 | 783 | ** Delete a file. |
| 721 | 784 | ** |
| 722 | 785 | ** If zFilename is a symbolic link, then it is the link itself that is |
| @@ -1514,10 +1577,11 @@ | ||
| 1514 | 1577 | fossil_free(z); |
| 1515 | 1578 | fossil_print(" file_mtime(ExtFILE) = %s\n", zBuf); |
| 1516 | 1579 | fossil_print(" file_mode(ExtFILE) = 0%o\n", file_mode(zPath,ExtFILE)); |
| 1517 | 1580 | fossil_print(" file_isfile(ExtFILE) = %d\n", file_isfile(zPath,ExtFILE)); |
| 1518 | 1581 | fossil_print(" file_isdir(ExtFILE) = %d\n", file_isdir(zPath,ExtFILE)); |
| 1582 | + fossil_print(" file_issocket() = %d\n", file_issocket(zPath)); | |
| 1519 | 1583 | if( reset ) resetStat(); |
| 1520 | 1584 | sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zPath,RepoFILE)); |
| 1521 | 1585 | fossil_print(" file_size(RepoFILE) = %s\n", zBuf); |
| 1522 | 1586 | iMtime = file_mtime(zPath,RepoFILE); |
| 1523 | 1587 | z = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMtime); |
| 1524 | 1588 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -34,10 +34,12 @@ | |
| 34 | # include <direct.h> |
| 35 | # include <windows.h> |
| 36 | # include <sys/utime.h> |
| 37 | #else |
| 38 | # include <sys/time.h> |
| 39 | #endif |
| 40 | |
| 41 | #if INTERFACE |
| 42 | |
| 43 | /* Many APIs take an eFType argument which must be one of ExtFILE, RepoFILE, |
| @@ -229,10 +231,20 @@ | |
| 229 | ** for directories, devices, fifos, symlinks, etc. |
| 230 | */ |
| 231 | int file_isfile(const char *zFilename, int eFType){ |
| 232 | return getStat(zFilename, eFType) ? 0 : S_ISREG(fx.fileStat.st_mode); |
| 233 | } |
| 234 | |
| 235 | /* |
| 236 | ** Create a symbolic link named zLinkFile that points to zTargetFile. |
| 237 | ** |
| 238 | ** If allow-symlinks is off, create an ordinary file named zLinkFile |
| @@ -713,10 +725,61 @@ | |
| 713 | file_set_mtime(zFile, iMTime); |
| 714 | iMTime = file_mtime(zFile, RepoFILE); |
| 715 | zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime); |
| 716 | fossil_print("Set mtime of \"%s\" to %s (%lld)\n", zFile, zDate, iMTime); |
| 717 | } |
| 718 | |
| 719 | /* |
| 720 | ** Delete a file. |
| 721 | ** |
| 722 | ** If zFilename is a symbolic link, then it is the link itself that is |
| @@ -1514,10 +1577,11 @@ | |
| 1514 | fossil_free(z); |
| 1515 | fossil_print(" file_mtime(ExtFILE) = %s\n", zBuf); |
| 1516 | fossil_print(" file_mode(ExtFILE) = 0%o\n", file_mode(zPath,ExtFILE)); |
| 1517 | fossil_print(" file_isfile(ExtFILE) = %d\n", file_isfile(zPath,ExtFILE)); |
| 1518 | fossil_print(" file_isdir(ExtFILE) = %d\n", file_isdir(zPath,ExtFILE)); |
| 1519 | if( reset ) resetStat(); |
| 1520 | sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zPath,RepoFILE)); |
| 1521 | fossil_print(" file_size(RepoFILE) = %s\n", zBuf); |
| 1522 | iMtime = file_mtime(zPath,RepoFILE); |
| 1523 | z = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMtime); |
| 1524 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -34,10 +34,12 @@ | |
| 34 | # include <direct.h> |
| 35 | # include <windows.h> |
| 36 | # include <sys/utime.h> |
| 37 | #else |
| 38 | # include <sys/time.h> |
| 39 | # include <pwd.h> |
| 40 | # include <grp.h> |
| 41 | #endif |
| 42 | |
| 43 | #if INTERFACE |
| 44 | |
| 45 | /* Many APIs take an eFType argument which must be one of ExtFILE, RepoFILE, |
| @@ -229,10 +231,20 @@ | |
| 231 | ** for directories, devices, fifos, symlinks, etc. |
| 232 | */ |
| 233 | int file_isfile(const char *zFilename, int eFType){ |
| 234 | return getStat(zFilename, eFType) ? 0 : S_ISREG(fx.fileStat.st_mode); |
| 235 | } |
| 236 | |
| 237 | /* |
| 238 | ** Return TRUE if zFilename is a socket. |
| 239 | */ |
| 240 | int file_issocket(const char *zFilename){ |
| 241 | if( getStat(zFilename, ExtFILE) ){ |
| 242 | return 0; /* stat() failed. Return false. */ |
| 243 | } |
| 244 | return S_ISSOCK(fx.fileStat.st_mode); |
| 245 | } |
| 246 | |
| 247 | /* |
| 248 | ** Create a symbolic link named zLinkFile that points to zTargetFile. |
| 249 | ** |
| 250 | ** If allow-symlinks is off, create an ordinary file named zLinkFile |
| @@ -713,10 +725,61 @@ | |
| 725 | file_set_mtime(zFile, iMTime); |
| 726 | iMTime = file_mtime(zFile, RepoFILE); |
| 727 | zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime); |
| 728 | fossil_print("Set mtime of \"%s\" to %s (%lld)\n", zFile, zDate, iMTime); |
| 729 | } |
| 730 | |
| 731 | /* |
| 732 | ** Change access permissions on a file. |
| 733 | */ |
| 734 | void file_set_mode(const char *zFN, int fd, const char *zMode, int bNoErr){ |
| 735 | mode_t m; |
| 736 | char *zEnd = 0; |
| 737 | m = strtol(zMode, &zEnd, 0); |
| 738 | if( (zEnd[0] || fchmod(fd, m)) && !bNoErr ){ |
| 739 | fossil_fatal("cannot change permissions on %s to \"%s\"", |
| 740 | zFN, zMode); |
| 741 | } |
| 742 | } |
| 743 | |
| 744 | /* Change the owner of a file to zOwner. zOwner can be of the form |
| 745 | ** USER:GROUP. |
| 746 | */ |
| 747 | void file_set_owner(const char *zFN, int fd, const char *zOwner){ |
| 748 | const char *zGrp; |
| 749 | const char *zUsr = zOwner; |
| 750 | struct passwd *pw; |
| 751 | struct group *grp; |
| 752 | uid_t uid = -1; |
| 753 | gid_t gid = -1; |
| 754 | zGrp = strchr(zUsr, ':'); |
| 755 | if( zGrp ){ |
| 756 | int n = (int)(zGrp - zUsr); |
| 757 | zUsr = fossil_strndup(zUsr, n); |
| 758 | zGrp++; |
| 759 | } |
| 760 | pw = getpwnam(zUsr); |
| 761 | if( pw==0 ){ |
| 762 | fossil_fatal("no such user: \"%s\"", zUsr); |
| 763 | } |
| 764 | uid = pw->pw_uid; |
| 765 | if( zGrp ){ |
| 766 | grp = getgrnam(zGrp); |
| 767 | if( grp==0 ){ |
| 768 | fossil_fatal("no such group: \"%s\"", zGrp); |
| 769 | } |
| 770 | gid = grp->gr_gid; |
| 771 | } |
| 772 | printf("fd=%d zFN=%s uid=%d gid=%d\n", (int)fd, zFN, (int)uid, (int)gid); |
| 773 | if( fchown(fd, uid, gid) ){ |
| 774 | fossil_fatal("cannot change ownership of %s to %s",zFN, zOwner); |
| 775 | } |
| 776 | if( zOwner!=zUsr ){ |
| 777 | fossil_free((char*)zUsr); |
| 778 | } |
| 779 | } |
| 780 | |
| 781 | |
| 782 | /* |
| 783 | ** Delete a file. |
| 784 | ** |
| 785 | ** If zFilename is a symbolic link, then it is the link itself that is |
| @@ -1514,10 +1577,11 @@ | |
| 1577 | fossil_free(z); |
| 1578 | fossil_print(" file_mtime(ExtFILE) = %s\n", zBuf); |
| 1579 | fossil_print(" file_mode(ExtFILE) = 0%o\n", file_mode(zPath,ExtFILE)); |
| 1580 | fossil_print(" file_isfile(ExtFILE) = %d\n", file_isfile(zPath,ExtFILE)); |
| 1581 | fossil_print(" file_isdir(ExtFILE) = %d\n", file_isdir(zPath,ExtFILE)); |
| 1582 | fossil_print(" file_issocket() = %d\n", file_issocket(zPath)); |
| 1583 | if( reset ) resetStat(); |
| 1584 | sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zPath,RepoFILE)); |
| 1585 | fossil_print(" file_size(RepoFILE) = %s\n", zBuf); |
| 1586 | iMtime = file_mtime(zPath,RepoFILE); |
| 1587 | z = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMtime); |
| 1588 |
+38
-9
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -238,10 +238,13 @@ | ||
| 238 | 238 | int noPswd; /* Logged in without password (on 127.0.0.1) */ |
| 239 | 239 | int userUid; /* Integer user id */ |
| 240 | 240 | int isHuman; /* True if access by a human, not a spider or bot */ |
| 241 | 241 | int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be |
| 242 | 242 | ** accessed through get_comment_format(). */ |
| 243 | + const char *zSockName; /* Name of the unix-domain socket file */ | |
| 244 | + const char *zSockMode; /* File permissions for unix-domain socket */ | |
| 245 | + const char *zSockOwner; /* Owner, or owner:group for unix-domain socket */ | |
| 243 | 246 | |
| 244 | 247 | /* Information used to populate the RCVFROM table */ |
| 245 | 248 | int rcvid; /* The rcvid. 0 if not yet defined. */ |
| 246 | 249 | char *zIpAddr; /* The remote IP address */ |
| 247 | 250 | char *zNonce; /* The nonce used for login */ |
| @@ -391,10 +394,15 @@ | ||
| 391 | 394 | unloadTcl(g.interp, &g.tcl); |
| 392 | 395 | #endif |
| 393 | 396 | #ifdef FOSSIL_ENABLE_JSON |
| 394 | 397 | cson_value_free(g.json.gc.v); |
| 395 | 398 | memset(&g.json, 0, sizeof(g.json)); |
| 399 | +#endif | |
| 400 | +#if !defined(_WIN32) | |
| 401 | + if( g.zSockName && file_issocket(g.zSockName) ){ | |
| 402 | + unlink(g.zSockName); | |
| 403 | + } | |
| 396 | 404 | #endif |
| 397 | 405 | free(g.zErrMsg); |
| 398 | 406 | if(g.db){ |
| 399 | 407 | db_close(0); |
| 400 | 408 | } |
| @@ -1507,30 +1515,44 @@ | ||
| 1507 | 1515 | if( getuid()==0 ){ |
| 1508 | 1516 | int i; |
| 1509 | 1517 | struct stat sStat; |
| 1510 | 1518 | Blob dir; |
| 1511 | 1519 | char *zDir; |
| 1520 | + size_t nDir; | |
| 1512 | 1521 | if( g.db!=0 ){ |
| 1513 | 1522 | db_close(1); |
| 1514 | 1523 | } |
| 1515 | 1524 | |
| 1516 | 1525 | file_canonical_name(zRepo, &dir, 0); |
| 1517 | 1526 | zDir = blob_str(&dir); |
| 1527 | + nDir = blob_size(&dir); | |
| 1518 | 1528 | if( !noJail ){ |
| 1519 | 1529 | if( file_isdir(zDir, ExtFILE)==1 ){ |
| 1530 | + /* Translate the repository name to the new root */ | |
| 1520 | 1531 | if( g.zRepositoryName ){ |
| 1521 | - size_t n = strlen(zDir); | |
| 1522 | 1532 | Blob repo; |
| 1523 | 1533 | file_canonical_name(g.zRepositoryName, &repo, 0); |
| 1524 | 1534 | zRepo = blob_str(&repo); |
| 1525 | - if( strncmp(zRepo, zDir, n)!=0 ){ | |
| 1535 | + if( strncmp(zRepo, zDir, nDir)!=0 ){ | |
| 1526 | 1536 | fossil_fatal("repo %s not under chroot dir %s", zRepo, zDir); |
| 1527 | 1537 | } |
| 1528 | - zRepo += n; | |
| 1538 | + zRepo += nDir; | |
| 1529 | 1539 | if( *zRepo == '\0' ) zRepo = "/"; |
| 1530 | 1540 | }else { |
| 1531 | 1541 | zRepo = "/"; |
| 1542 | + } | |
| 1543 | + /* If a unix socket is defined, try to translate its name into | |
| 1544 | + ** the new root so that it can be delete by atexit(). If unable, | |
| 1545 | + ** just zero out the socket name. */ | |
| 1546 | + if( g.zSockName ){ | |
| 1547 | + if( strncmp(g.zSockName, zDir, nDir)==0 | |
| 1548 | + && g.zSockName[nDir]=='/' | |
| 1549 | + ){ | |
| 1550 | + g.zSockName += nDir; | |
| 1551 | + }else{ | |
| 1552 | + g.zSockName = 0; | |
| 1553 | + } | |
| 1532 | 1554 | } |
| 1533 | 1555 | if( file_chdir(zDir, 1) ){ |
| 1534 | 1556 | fossil_panic("unable to chroot into %s", zDir); |
| 1535 | 1557 | } |
| 1536 | 1558 | }else{ |
| @@ -3185,13 +3207,18 @@ | ||
| 3185 | 3207 | ** -P|--port [IP:]PORT Listen on the given IP (optional) and port |
| 3186 | 3208 | ** --repolist If REPOSITORY is dir, URL "/" lists repos |
| 3187 | 3209 | ** --scgi Accept SCGI rather than HTTP |
| 3188 | 3210 | ** --skin LABEL Use override skin LABEL, or the site's default skin if |
| 3189 | 3211 | ** LABEL is an empty string. |
| 3212 | +** --socket-mode MODE File permissions to set for the unix socket created | |
| 3213 | +** by the --socket-name option. | |
| 3214 | +** --socket-name NAME Use a unix-domain socket called NAME instead of a | |
| 3215 | +** TCP/IP socket. | |
| 3216 | +** --socket-owner USR Try to set the owner of the unix socket to USR. | |
| 3217 | +** USR can be of the form USER:GROUP to set both | |
| 3218 | +** user and group. | |
| 3190 | 3219 | ** --th-trace Trace TH1 execution (for debugging purposes) |
| 3191 | -** --unix-socket NAME Listen on unix-domain socket NAME rather than on a | |
| 3192 | -** TCP/IP port. | |
| 3193 | 3220 | ** --usepidkey Use saved encryption key from parent process. This is |
| 3194 | 3221 | ** only necessary when using SEE on Windows or Linux. |
| 3195 | 3222 | ** |
| 3196 | 3223 | ** See also: [[cgi]], [[http]], [[winsrv]] |
| 3197 | 3224 | */ |
| @@ -3285,22 +3312,24 @@ | ||
| 3285 | 3312 | g.zMainMenuFile = find_option("mainmenu",0,1); |
| 3286 | 3313 | if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){ |
| 3287 | 3314 | fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile); |
| 3288 | 3315 | } |
| 3289 | 3316 | if( find_option("acme",0,0)!=0 ) g.fAllowACME = 1; |
| 3290 | - zIpAddr = (char*)find_option("unix-socket",0,1); | |
| 3291 | - if( zIpAddr ){ | |
| 3317 | + g.zSockMode = find_option("socket-mode",0,1); | |
| 3318 | + g.zSockName = find_option("socket-name",0,1); | |
| 3319 | + g.zSockOwner = find_option("socket-owner",0,1); | |
| 3320 | + if( g.zSockName ){ | |
| 3292 | 3321 | #if defined(_WIN32) |
| 3293 | 3322 | fossil_fatal("unix sockets are not supported on Windows"); |
| 3294 | 3323 | #endif |
| 3295 | 3324 | if( zPort ){ |
| 3296 | 3325 | fossil_fatal("cannot specify a port number for a unix socket"); |
| 3297 | 3326 | } |
| 3298 | 3327 | if( isUiCmd && !fNoBrowser ){ |
| 3299 | 3328 | fossil_fatal("cannot start a web-browser on a unix socket"); |
| 3300 | 3329 | } |
| 3301 | - flags |= HTTP_SERVER_UNIXDOMAINSOCK; | |
| 3330 | + flags |= HTTP_SERVER_UNIXSOCKET; | |
| 3302 | 3331 | } |
| 3303 | 3332 | |
| 3304 | 3333 | /* Undocumented option: --debug-nofork |
| 3305 | 3334 | ** |
| 3306 | 3335 | ** This sets the HTTP_SERVER_NOFORK flag, which causes only the |
| @@ -3467,11 +3496,11 @@ | ||
| 3467 | 3496 | } |
| 3468 | 3497 | if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; |
| 3469 | 3498 | if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; |
| 3470 | 3499 | db_close(1); |
| 3471 | 3500 | #if !defined(_WIN32) |
| 3472 | - if( getpid()==1 ){ | |
| 3501 | + if( 1 ){ | |
| 3473 | 3502 | /* Modern kernels suppress SIGTERM to PID 1 to prevent root from |
| 3474 | 3503 | ** rebooting the system by nuking the init system. The only way |
| 3475 | 3504 | ** Fossil becomes that PID 1 is when it's running solo in a Linux |
| 3476 | 3505 | ** container or similar, so we do want to exit immediately, to |
| 3477 | 3506 | ** allow the container to shut down quickly. |
| 3478 | 3507 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -238,10 +238,13 @@ | |
| 238 | int noPswd; /* Logged in without password (on 127.0.0.1) */ |
| 239 | int userUid; /* Integer user id */ |
| 240 | int isHuman; /* True if access by a human, not a spider or bot */ |
| 241 | int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be |
| 242 | ** accessed through get_comment_format(). */ |
| 243 | |
| 244 | /* Information used to populate the RCVFROM table */ |
| 245 | int rcvid; /* The rcvid. 0 if not yet defined. */ |
| 246 | char *zIpAddr; /* The remote IP address */ |
| 247 | char *zNonce; /* The nonce used for login */ |
| @@ -391,10 +394,15 @@ | |
| 391 | unloadTcl(g.interp, &g.tcl); |
| 392 | #endif |
| 393 | #ifdef FOSSIL_ENABLE_JSON |
| 394 | cson_value_free(g.json.gc.v); |
| 395 | memset(&g.json, 0, sizeof(g.json)); |
| 396 | #endif |
| 397 | free(g.zErrMsg); |
| 398 | if(g.db){ |
| 399 | db_close(0); |
| 400 | } |
| @@ -1507,30 +1515,44 @@ | |
| 1507 | if( getuid()==0 ){ |
| 1508 | int i; |
| 1509 | struct stat sStat; |
| 1510 | Blob dir; |
| 1511 | char *zDir; |
| 1512 | if( g.db!=0 ){ |
| 1513 | db_close(1); |
| 1514 | } |
| 1515 | |
| 1516 | file_canonical_name(zRepo, &dir, 0); |
| 1517 | zDir = blob_str(&dir); |
| 1518 | if( !noJail ){ |
| 1519 | if( file_isdir(zDir, ExtFILE)==1 ){ |
| 1520 | if( g.zRepositoryName ){ |
| 1521 | size_t n = strlen(zDir); |
| 1522 | Blob repo; |
| 1523 | file_canonical_name(g.zRepositoryName, &repo, 0); |
| 1524 | zRepo = blob_str(&repo); |
| 1525 | if( strncmp(zRepo, zDir, n)!=0 ){ |
| 1526 | fossil_fatal("repo %s not under chroot dir %s", zRepo, zDir); |
| 1527 | } |
| 1528 | zRepo += n; |
| 1529 | if( *zRepo == '\0' ) zRepo = "/"; |
| 1530 | }else { |
| 1531 | zRepo = "/"; |
| 1532 | } |
| 1533 | if( file_chdir(zDir, 1) ){ |
| 1534 | fossil_panic("unable to chroot into %s", zDir); |
| 1535 | } |
| 1536 | }else{ |
| @@ -3185,13 +3207,18 @@ | |
| 3185 | ** -P|--port [IP:]PORT Listen on the given IP (optional) and port |
| 3186 | ** --repolist If REPOSITORY is dir, URL "/" lists repos |
| 3187 | ** --scgi Accept SCGI rather than HTTP |
| 3188 | ** --skin LABEL Use override skin LABEL, or the site's default skin if |
| 3189 | ** LABEL is an empty string. |
| 3190 | ** --th-trace Trace TH1 execution (for debugging purposes) |
| 3191 | ** --unix-socket NAME Listen on unix-domain socket NAME rather than on a |
| 3192 | ** TCP/IP port. |
| 3193 | ** --usepidkey Use saved encryption key from parent process. This is |
| 3194 | ** only necessary when using SEE on Windows or Linux. |
| 3195 | ** |
| 3196 | ** See also: [[cgi]], [[http]], [[winsrv]] |
| 3197 | */ |
| @@ -3285,22 +3312,24 @@ | |
| 3285 | g.zMainMenuFile = find_option("mainmenu",0,1); |
| 3286 | if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){ |
| 3287 | fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile); |
| 3288 | } |
| 3289 | if( find_option("acme",0,0)!=0 ) g.fAllowACME = 1; |
| 3290 | zIpAddr = (char*)find_option("unix-socket",0,1); |
| 3291 | if( zIpAddr ){ |
| 3292 | #if defined(_WIN32) |
| 3293 | fossil_fatal("unix sockets are not supported on Windows"); |
| 3294 | #endif |
| 3295 | if( zPort ){ |
| 3296 | fossil_fatal("cannot specify a port number for a unix socket"); |
| 3297 | } |
| 3298 | if( isUiCmd && !fNoBrowser ){ |
| 3299 | fossil_fatal("cannot start a web-browser on a unix socket"); |
| 3300 | } |
| 3301 | flags |= HTTP_SERVER_UNIXDOMAINSOCK; |
| 3302 | } |
| 3303 | |
| 3304 | /* Undocumented option: --debug-nofork |
| 3305 | ** |
| 3306 | ** This sets the HTTP_SERVER_NOFORK flag, which causes only the |
| @@ -3467,11 +3496,11 @@ | |
| 3467 | } |
| 3468 | if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; |
| 3469 | if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; |
| 3470 | db_close(1); |
| 3471 | #if !defined(_WIN32) |
| 3472 | if( getpid()==1 ){ |
| 3473 | /* Modern kernels suppress SIGTERM to PID 1 to prevent root from |
| 3474 | ** rebooting the system by nuking the init system. The only way |
| 3475 | ** Fossil becomes that PID 1 is when it's running solo in a Linux |
| 3476 | ** container or similar, so we do want to exit immediately, to |
| 3477 | ** allow the container to shut down quickly. |
| 3478 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -238,10 +238,13 @@ | |
| 238 | int noPswd; /* Logged in without password (on 127.0.0.1) */ |
| 239 | int userUid; /* Integer user id */ |
| 240 | int isHuman; /* True if access by a human, not a spider or bot */ |
| 241 | int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be |
| 242 | ** accessed through get_comment_format(). */ |
| 243 | const char *zSockName; /* Name of the unix-domain socket file */ |
| 244 | const char *zSockMode; /* File permissions for unix-domain socket */ |
| 245 | const char *zSockOwner; /* Owner, or owner:group for unix-domain socket */ |
| 246 | |
| 247 | /* Information used to populate the RCVFROM table */ |
| 248 | int rcvid; /* The rcvid. 0 if not yet defined. */ |
| 249 | char *zIpAddr; /* The remote IP address */ |
| 250 | char *zNonce; /* The nonce used for login */ |
| @@ -391,10 +394,15 @@ | |
| 394 | unloadTcl(g.interp, &g.tcl); |
| 395 | #endif |
| 396 | #ifdef FOSSIL_ENABLE_JSON |
| 397 | cson_value_free(g.json.gc.v); |
| 398 | memset(&g.json, 0, sizeof(g.json)); |
| 399 | #endif |
| 400 | #if !defined(_WIN32) |
| 401 | if( g.zSockName && file_issocket(g.zSockName) ){ |
| 402 | unlink(g.zSockName); |
| 403 | } |
| 404 | #endif |
| 405 | free(g.zErrMsg); |
| 406 | if(g.db){ |
| 407 | db_close(0); |
| 408 | } |
| @@ -1507,30 +1515,44 @@ | |
| 1515 | if( getuid()==0 ){ |
| 1516 | int i; |
| 1517 | struct stat sStat; |
| 1518 | Blob dir; |
| 1519 | char *zDir; |
| 1520 | size_t nDir; |
| 1521 | if( g.db!=0 ){ |
| 1522 | db_close(1); |
| 1523 | } |
| 1524 | |
| 1525 | file_canonical_name(zRepo, &dir, 0); |
| 1526 | zDir = blob_str(&dir); |
| 1527 | nDir = blob_size(&dir); |
| 1528 | if( !noJail ){ |
| 1529 | if( file_isdir(zDir, ExtFILE)==1 ){ |
| 1530 | /* Translate the repository name to the new root */ |
| 1531 | if( g.zRepositoryName ){ |
| 1532 | Blob repo; |
| 1533 | file_canonical_name(g.zRepositoryName, &repo, 0); |
| 1534 | zRepo = blob_str(&repo); |
| 1535 | if( strncmp(zRepo, zDir, nDir)!=0 ){ |
| 1536 | fossil_fatal("repo %s not under chroot dir %s", zRepo, zDir); |
| 1537 | } |
| 1538 | zRepo += nDir; |
| 1539 | if( *zRepo == '\0' ) zRepo = "/"; |
| 1540 | }else { |
| 1541 | zRepo = "/"; |
| 1542 | } |
| 1543 | /* If a unix socket is defined, try to translate its name into |
| 1544 | ** the new root so that it can be delete by atexit(). If unable, |
| 1545 | ** just zero out the socket name. */ |
| 1546 | if( g.zSockName ){ |
| 1547 | if( strncmp(g.zSockName, zDir, nDir)==0 |
| 1548 | && g.zSockName[nDir]=='/' |
| 1549 | ){ |
| 1550 | g.zSockName += nDir; |
| 1551 | }else{ |
| 1552 | g.zSockName = 0; |
| 1553 | } |
| 1554 | } |
| 1555 | if( file_chdir(zDir, 1) ){ |
| 1556 | fossil_panic("unable to chroot into %s", zDir); |
| 1557 | } |
| 1558 | }else{ |
| @@ -3185,13 +3207,18 @@ | |
| 3207 | ** -P|--port [IP:]PORT Listen on the given IP (optional) and port |
| 3208 | ** --repolist If REPOSITORY is dir, URL "/" lists repos |
| 3209 | ** --scgi Accept SCGI rather than HTTP |
| 3210 | ** --skin LABEL Use override skin LABEL, or the site's default skin if |
| 3211 | ** LABEL is an empty string. |
| 3212 | ** --socket-mode MODE File permissions to set for the unix socket created |
| 3213 | ** by the --socket-name option. |
| 3214 | ** --socket-name NAME Use a unix-domain socket called NAME instead of a |
| 3215 | ** TCP/IP socket. |
| 3216 | ** --socket-owner USR Try to set the owner of the unix socket to USR. |
| 3217 | ** USR can be of the form USER:GROUP to set both |
| 3218 | ** user and group. |
| 3219 | ** --th-trace Trace TH1 execution (for debugging purposes) |
| 3220 | ** --usepidkey Use saved encryption key from parent process. This is |
| 3221 | ** only necessary when using SEE on Windows or Linux. |
| 3222 | ** |
| 3223 | ** See also: [[cgi]], [[http]], [[winsrv]] |
| 3224 | */ |
| @@ -3285,22 +3312,24 @@ | |
| 3312 | g.zMainMenuFile = find_option("mainmenu",0,1); |
| 3313 | if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){ |
| 3314 | fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile); |
| 3315 | } |
| 3316 | if( find_option("acme",0,0)!=0 ) g.fAllowACME = 1; |
| 3317 | g.zSockMode = find_option("socket-mode",0,1); |
| 3318 | g.zSockName = find_option("socket-name",0,1); |
| 3319 | g.zSockOwner = find_option("socket-owner",0,1); |
| 3320 | if( g.zSockName ){ |
| 3321 | #if defined(_WIN32) |
| 3322 | fossil_fatal("unix sockets are not supported on Windows"); |
| 3323 | #endif |
| 3324 | if( zPort ){ |
| 3325 | fossil_fatal("cannot specify a port number for a unix socket"); |
| 3326 | } |
| 3327 | if( isUiCmd && !fNoBrowser ){ |
| 3328 | fossil_fatal("cannot start a web-browser on a unix socket"); |
| 3329 | } |
| 3330 | flags |= HTTP_SERVER_UNIXSOCKET; |
| 3331 | } |
| 3332 | |
| 3333 | /* Undocumented option: --debug-nofork |
| 3334 | ** |
| 3335 | ** This sets the HTTP_SERVER_NOFORK flag, which causes only the |
| @@ -3467,11 +3496,11 @@ | |
| 3496 | } |
| 3497 | if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; |
| 3498 | if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; |
| 3499 | db_close(1); |
| 3500 | #if !defined(_WIN32) |
| 3501 | if( 1 ){ |
| 3502 | /* Modern kernels suppress SIGTERM to PID 1 to prevent root from |
| 3503 | ** rebooting the system by nuking the init system. The only way |
| 3504 | ** Fossil becomes that PID 1 is when it's running solo in a Linux |
| 3505 | ** container or similar, so we do want to exit immediately, to |
| 3506 | ** allow the container to shut down quickly. |
| 3507 |