From be3e64e5ea637c5d98fb9f450a36a9d2f40450e9 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Thu, 5 Jun 2014 11:49:05 -0700 Subject: [PATCH 01/10] Remove fishd.cpp source, docs, and target from Makefile and Xcode project --- Makefile.in | 20 +- doc_src/fishd.txt | 33 - fish.xcodeproj/project.pbxproj | 123 --- .../xcshareddata/xcschemes/fishd.xcscheme | 86 -- fishd.cpp | 971 ------------------ 5 files changed, 1 insertion(+), 1232 deletions(-) delete mode 100644 doc_src/fishd.txt delete mode 100644 fish.xcodeproj/xcshareddata/xcschemes/fishd.xcscheme delete mode 100644 fishd.cpp diff --git a/Makefile.in b/Makefile.in index f2761e963..3d68a01db 100644 --- a/Makefile.in +++ b/Makefile.in @@ -111,14 +111,6 @@ BUILTIN_FILES := builtin_set.cpp builtin_commandline.cpp \ FISH_TESTS_OBJS := $(FISH_OBJS) fish_tests.o -# -# All objects that the system needs to build fishd -# - -FISHD_OBJS := fishd.o env_universal_common.o wutil.o print_help.o \ - common.o utf8.o fish_version.o - - # # All objects needed to build mimedb # @@ -181,7 +173,7 @@ FUNCTIONS_DIR_FILES := $(wildcard share/functions/*.fish) # Programs to install # -PROGRAMS := fish mimedb fishd fish_indent +PROGRAMS := fish mimedb fish_indent # # Manual pages to install @@ -688,14 +680,6 @@ fish: $(FISH_OBJS) fish.o $(CXX) $(CXXFLAGS) $(LDFLAGS_FISH) $(FISH_OBJS) fish.o $(LIBS) -o $@ -# -# Build the fishd program. -# - -fishd: $(FISHD_OBJS) - $(CXX) $(CXXFLAGS) $(LDFLAGS) $(FISHD_OBJS) $(LIBS) -o $@ - - # # Build the fish_tests program. # @@ -842,8 +826,6 @@ fish.o: highlight.h env.h color.h builtin.h function.h event.h wutil.h fish.o: sanity.h proc.h parse_tree.h tokenizer.h parse_constants.h parser.h fish.o: expand.h intern.h exec.h output.h screen.h history.h path.h input.h fish.o: input_common.h fish_version.h -fishd.o: config.h signal.h fallback.h util.h common.h wutil.h -fishd.o: env_universal_common.h env.h path.h print_help.h fish_version.h fish_indent.o: config.h fallback.h signal.h util.h common.h wutil.h fish_indent.o: tokenizer.h print_help.h parser_keywords.h fish_version.h fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h diff --git a/doc_src/fishd.txt b/doc_src/fishd.txt deleted file mode 100644 index 0eb3088a4..000000000 --- a/doc_src/fishd.txt +++ /dev/null @@ -1,33 +0,0 @@ -\section fishd fishd - universal variable daemon - -\subsection fishd-synopsis Synopsis - fishd [(-h|--help|-v|--version)] - -\subsection fishd-description Description - -The \c fishd daemon is used to load, save and distribute universal -variable information. \c fish automatically connects to \c fishd via a socket -on startup. - -\c fishd is started and stopped automatically. - -The following options are available if starting \c fishd manually: - -- -h or --help displays this help message and then exits -- -v or --version displays the current fish version and then exits - -\subsection fishd-files Files - -- \c ~/.config/fish/fishd.MACHINE_ID - permanent storage location for universal - variable data. \c MACHINE_ID is generally based on the machine's MAC address. - - The data is stored as a set of \c set and \c set_export commands such as - would be parsed by fishd. The file must always be stored in YAML format. - If an instance of fishd is running (which is generally the case), manual - modifications to \c ~/.fishd.MACHINE_ID will be lost. Do NOT edit this file manually! - -- \c /tmp/fishd.socket.USERNAME - the socket which fishd uses to communicate -with all clients. - -- /tmp/fishd.log.USERNAME - the fishd log file - diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj index 762d73c21..aecda2bd7 100644 --- a/fish.xcodeproj/project.pbxproj +++ b/fish.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ ); dependencies = ( D07D265715E33B86009E43F6 /* PBXTargetDependency */, - D07D265915E33B86009E43F6 /* PBXTargetDependency */, D07D265D15E33B86009E43F6 /* PBXTargetDependency */, D0A56500168D257900AF6161 /* PBXTargetDependency */, ); @@ -47,7 +46,6 @@ ); dependencies = ( D0F01A1315AA36280034B3B1 /* PBXTargetDependency */, - D0F01A1515AA362E0034B3B1 /* PBXTargetDependency */, D0F01A1715AA36300034B3B1 /* PBXTargetDependency */, D0A564EF168D09C000AF6161 /* PBXTargetDependency */, ); @@ -59,7 +57,6 @@ /* Begin PBXBuildFile section */ D00F63F119137E9D00FCCDEC /* fish_version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D00F63F019137E9D00FCCDEC /* fish_version.cpp */; }; D00F63F219137E9D00FCCDEC /* fish_version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D00F63F019137E9D00FCCDEC /* fish_version.cpp */; }; - D00F63F31914C5F800FCCDEC /* fish_version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D00F63F019137E9D00FCCDEC /* fish_version.cpp */; }; D01A2D24169B736200767098 /* man1 in Copy Files */ = {isa = PBXBuildFile; fileRef = D01A2D23169B730A00767098 /* man1 */; }; D01A2D25169B737700767098 /* man1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = D01A2D23169B730A00767098 /* man1 */; }; D031890C15E36E4600D9CC39 /* base in Resources */ = {isa = PBXBuildFile; fileRef = D031890915E36D9800D9CC39 /* base */; }; @@ -120,7 +117,6 @@ D0A56501168D258300AF6161 /* man in Copy Files */ = {isa = PBXBuildFile; fileRef = D0A564F1168D0BAB00AF6161 /* man */; }; D0C52F371765284C00BFAB82 /* parse_tree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C52F351765284C00BFAB82 /* parse_tree.cpp */; }; D0C9733818DE5449002D7C81 /* utf8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C9733718DE5449002D7C81 /* utf8.cpp */; }; - D0C9733918DE5449002D7C81 /* utf8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C9733718DE5449002D7C81 /* utf8.cpp */; }; D0CBD587159EF0E10024809C /* launch_fish.scpt in Resources */ = {isa = PBXBuildFile; fileRef = D0CBD586159EF0E10024809C /* launch_fish.scpt */; }; D0D02A67159837AD008E62BD /* complete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853713B3ACEE0099B651 /* complete.cpp */; }; D0D02A69159837B2008E62BD /* env.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853A13B3ACEE0099B651 /* env.cpp */; }; @@ -158,12 +154,6 @@ D0D02A89159839DF008E62BD /* fish.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854213B3ACEE0099B651 /* fish.cpp */; }; D0D02A8D15983CFA008E62BD /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8C15983CFA008E62BD /* libncurses.dylib */; }; D0D02A8F15983D8F008E62BD /* parser_keywords.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855313B3ACEE0099B651 /* parser_keywords.cpp */; }; - D0D02AC215985F3F008E62BD /* fishd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854313B3ACEE0099B651 /* fishd.cpp */; }; - D0D02AC315985F43008E62BD /* env_universal_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */; }; - D0D02AC415985F4D008E62BD /* wutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0856113B3ACEE0099B651 /* wutil.cpp */; }; - D0D02AC515985F5B008E62BD /* print_help.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855613B3ACEE0099B651 /* print_help.cpp */; }; - D0D02AC615985F65008E62BD /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853613B3ACEE0099B651 /* common.cpp */; }; - D0D02AC715985F9D008E62BD /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8C15983CFA008E62BD /* libncurses.dylib */; }; D0D02AD615986492008E62BD /* fish_indent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853F13B3ACEE0099B651 /* fish_indent.cpp */; }; D0D02AD715986498008E62BD /* print_help.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855613B3ACEE0099B651 /* print_help.cpp */; }; D0D02AD81598649E008E62BD /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853613B3ACEE0099B651 /* common.cpp */; }; @@ -174,7 +164,6 @@ D0D2694915983772005D9B9C /* function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854413B3ACEE0099B651 /* function.cpp */; }; D0D2694A15983779005D9B9C /* builtin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853513B3ACEE0099B651 /* builtin.cpp */; }; D0F019F115A977140034B3B1 /* fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D2693C159835CA005D9B9C /* fish */; }; - D0F019F215A977270034B3B1 /* fishd in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D02ABC15985EF9008E62BD /* fishd */; }; D0F019F315A977290034B3B1 /* fish_indent in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D02AD01598642A008E62BD /* fish_indent */; }; D0F019F815A977AB0034B3B1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0CBD580159EE48F0024809C /* config.fish */; }; D0F019FD15A977CA0034B3B1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0C4FD9415A7D7EE00212EF1 /* config.fish */; }; @@ -198,13 +187,6 @@ remoteGlobalIDString = D0D2693B159835CA005D9B9C; remoteInfo = fish_shell; }; - D07D265A15E33B86009E43F6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D0A084F213B3AC130099B651 /* Project object */; - proxyType = 1; - remoteGlobalIDString = D0D02ABB15985EF9008E62BD; - remoteInfo = fishd; - }; D07D265E15E33B86009E43F6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D0A084F213B3AC130099B651 /* Project object */; @@ -233,13 +215,6 @@ remoteGlobalIDString = D0D2693B159835CA005D9B9C; remoteInfo = fish_shell; }; - D0F01A1415AA362E0034B3B1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D0A084F213B3AC130099B651 /* Project object */; - proxyType = 1; - remoteGlobalIDString = D0D02ABB15985EF9008E62BD; - remoteInfo = fishd; - }; D0F01A1615AA36300034B3B1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D0A084F213B3AC130099B651 /* Project object */; @@ -325,7 +300,6 @@ dstSubfolderSpec = 1; files = ( D0F019F115A977140034B3B1 /* fish in CopyFiles */, - D0F019F215A977270034B3B1 /* fishd in CopyFiles */, D0F019F315A977290034B3B1 /* fish_indent in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; @@ -486,7 +460,6 @@ D0D02A8C15983CFA008E62BD /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = usr/lib/libncurses.dylib; sourceTree = SDKROOT; }; D0D02A9A15985A75008E62BD /* fish.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fish.app; sourceTree = BUILT_PRODUCTS_DIR; }; D0D02AA915985C0C008E62BD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = osx/Info.plist; sourceTree = ""; }; - D0D02ABC15985EF9008E62BD /* fishd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fishd; sourceTree = BUILT_PRODUCTS_DIR; }; D0D02AD01598642A008E62BD /* fish_indent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fish_indent; sourceTree = BUILT_PRODUCTS_DIR; }; D0D02AFA159871B2008E62BD /* osx_fish_launcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = osx_fish_launcher.m; path = osx/osx_fish_launcher.m; sourceTree = ""; }; D0D2693C159835CA005D9B9C /* fish */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fish; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -506,14 +479,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - D0D02AB915985EF9008E62BD /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D0D02AC715985F9D008E62BD /* libncurses.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; D0D02ACD1598642A008E62BD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -746,7 +711,6 @@ children = ( D0D2693C159835CA005D9B9C /* fish */, D0D02A9A15985A75008E62BD /* fish.app */, - D0D02ABC15985EF9008E62BD /* fishd */, D0D02AD01598642A008E62BD /* fish_indent */, D08A328D17B4455100F3A533 /* fish_tests */, ); @@ -816,22 +780,6 @@ productReference = D0D02A9A15985A75008E62BD /* fish.app */; productType = "com.apple.product-type.application"; }; - D0D02ABB15985EF9008E62BD /* fishd */ = { - isa = PBXNativeTarget; - buildConfigurationList = D0D02ABF15985EFA008E62BD /* Build configuration list for PBXNativeTarget "fishd" */; - buildPhases = ( - D0D02AB815985EF9008E62BD /* Sources */, - D0D02AB915985EF9008E62BD /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = fishd; - productName = fishd; - productReference = D0D02ABC15985EF9008E62BD /* fishd */; - productType = "com.apple.product-type.tool"; - }; D0D02ACF1598642A008E62BD /* fish_indent */ = { isa = PBXNativeTarget; buildConfigurationList = D0D02AD31598642A008E62BD /* Build configuration list for PBXNativeTarget "fish_indent" */; @@ -888,7 +836,6 @@ D0F019EC15A976F30034B3B1 /* base */, D0D02A9915985A75008E62BD /* fish.app */, D0D2693B159835CA005D9B9C /* fish_shell */, - D0D02ABB15985EF9008E62BD /* fishd */, D0D02ACF1598642A008E62BD /* fish_indent */, D08A328C17B4455100F3A533 /* fish_tests */, D0A564E6168CFDD800AF6161 /* man_pages */, @@ -1115,20 +1062,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - D0D02AB815985EF9008E62BD /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D00F63F31914C5F800FCCDEC /* fish_version.cpp in Sources */, - D0D02AC215985F3F008E62BD /* fishd.cpp in Sources */, - D0D02AC315985F43008E62BD /* env_universal_common.cpp in Sources */, - D0C9733918DE5449002D7C81 /* utf8.cpp in Sources */, - D0D02AC415985F4D008E62BD /* wutil.cpp in Sources */, - D0D02AC515985F5B008E62BD /* print_help.cpp in Sources */, - D0D02AC615985F65008E62BD /* common.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; D0D02ACC1598642A008E62BD /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1214,11 +1147,6 @@ target = D0D2693B159835CA005D9B9C /* fish_shell */; targetProxy = D07D265815E33B86009E43F6 /* PBXContainerItemProxy */; }; - D07D265915E33B86009E43F6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = D0D02ABB15985EF9008E62BD /* fishd */; - targetProxy = D07D265A15E33B86009E43F6 /* PBXContainerItemProxy */; - }; D07D265D15E33B86009E43F6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = D0D02ACF1598642A008E62BD /* fish_indent */; @@ -1239,11 +1167,6 @@ target = D0D2693B159835CA005D9B9C /* fish_shell */; targetProxy = D0F01A1215AA36280034B3B1 /* PBXContainerItemProxy */; }; - D0F01A1515AA362E0034B3B1 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = D0D02ABB15985EF9008E62BD /* fishd */; - targetProxy = D0F01A1415AA362E0034B3B1 /* PBXContainerItemProxy */; - }; D0F01A1715AA36300034B3B1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = D0D02ACF1598642A008E62BD /* fish_indent */; @@ -1328,18 +1251,6 @@ }; name = "Release_C++11"; }; - D007FDDF17136EAA00A52BE6 /* Release_C++11 */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = "Release_C++11"; - }; D007FDE017136EAA00A52BE6 /* Release_C++11 */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1596,30 +1507,6 @@ }; name = Release; }; - D0D02AC015985EFA008E62BD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - D0D02AC115985EFA008E62BD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; D0D02AD41598642A008E62BD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1755,16 +1642,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - D0D02ABF15985EFA008E62BD /* Build configuration list for PBXNativeTarget "fishd" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D0D02AC015985EFA008E62BD /* Debug */, - D0D02AC115985EFA008E62BD /* Release */, - D007FDDF17136EAA00A52BE6 /* Release_C++11 */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; D0D02AD31598642A008E62BD /* Build configuration list for PBXNativeTarget "fish_indent" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/fish.xcodeproj/xcshareddata/xcschemes/fishd.xcscheme b/fish.xcodeproj/xcshareddata/xcschemes/fishd.xcscheme deleted file mode 100644 index a2741de25..000000000 --- a/fish.xcodeproj/xcshareddata/xcschemes/fishd.xcscheme +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/fishd.cpp b/fishd.cpp deleted file mode 100644 index 4bb80b50c..000000000 --- a/fishd.cpp +++ /dev/null @@ -1,971 +0,0 @@ -/** \file fishd.c - -The universal variable server. fishd is automatically started by fish -if a fishd server isn't already running. fishd reads any saved -variables from ~/.fishd, and takes care of communication between fish -instances. When no clients are running, fishd will automatically shut -down and save. - -\section fishd-commands Commands - -Fishd works by sending and receiving commands. Each command is ended -with a newline. These are the commands supported by fishd: - -
set KEY:VALUE
-set_export KEY:VALUE
-
- -These commands update the value of a variable. The only difference -between the two is that set_export-variables should be -exported to children of the process using them. When sending messages, -all values below 32 or above 127 must be escaped using C-style -backslash escapes. This means that the over the wire protocol is -ASCII. However, any conforming reader must also accept non-ascii -characters and interpret them as UTF-8. Lines containing invalid UTF-8 -escape sequences must be ignored entirely. - -
erase KEY
-
- -Erase the variable with the specified name. - -
barrier
-barrier_reply
-
- -A \c barrier command will result in a barrier_reply being added to -the end of the senders queue of unsent messages. These commands are -used to synchronize clients, since once the reply for a barrier -message returns, the sender can know that any updates available at the -time the original barrier request was sent have been received. - -*/ - -#include "config.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_GETOPT_H -#include -#endif - -#include -#include -#include -#include - -#include "fallback.h" -#include "util.h" - -#include "common.h" -#include "wutil.h" -#include "env_universal_common.h" -#include "path.h" -#include "print_help.h" -#include "fish_version.h" - -#ifndef HOST_NAME_MAX -/** - Maximum length of hostname return. It is ok if this is too short, - getting the actual hostname is not critical, so long as the string - is unique in the filesystem namespace. - */ -#define HOST_NAME_MAX 255 -#endif - -/** - Maximum length of socket filename -*/ -#ifndef UNIX_PATH_MAX -#define UNIX_PATH_MAX 100 -#endif - -/** - Fallback if MSG_DONTWAIT isn't defined. That's actually prerry bad, - and may lead to strange fishd behaviour, but at least it should - work most of the time. -*/ -#ifndef MSG_DONTWAIT -#define MSG_DONTWAIT 0 -#endif - -/** - Small greeting to show that fishd is running -*/ -#define GREETING "# Fish universal variable daemon\n" - -/** - Small not about not editing ~/.fishd manually. Inserted at the top of all .fishd files. -*/ -#define SAVE_MSG "# This file is automatically generated by the fishd universal variable daemon.\n# Do NOT edit it directly, your changes will be overwritten.\n" - -/** - The name of the save file. The machine identifier is appended to this. -*/ -#define FILE "fishd." - -/** - Maximum length of hostname. Longer hostnames are truncated -*/ -#define HOSTNAME_LEN 32 - -/** - The string to append to the socket name to name the lockfile -*/ -#define LOCKPOSTFIX ".lock" - -/** - The timeout in seconds on the lockfile for critical section -*/ -#define LOCKTIMEOUT 1 - -/** - Getopt short switches for fishd -*/ -#define GETOPT_STRING "hv" - -/** - The list of connections to clients -*/ -typedef std::list connection_list_t; -static connection_list_t connections; - -/** - The socket to accept new clients on -*/ -static int sock; - -/** - Set to one when fishd should save and exit -*/ -static int quit=0; - -/** - Constructs the fish socket filename -*/ -static std::string get_socket_filename(void) -{ - const char *dir = getenv("FISHD_SOCKET_DIR"); - char *uname = getenv("USER"); - - if (dir == NULL) - { - dir = "/tmp"; - } - - if (uname == NULL) - { - const struct passwd *pw = getpwuid(getuid()); - uname = pw->pw_name; - } - - std::string name; - name.reserve(strlen(dir)+ strlen(uname)+ strlen(SOCK_FILENAME) + 1); - name.append(dir); - name.push_back('/'); - name.append(SOCK_FILENAME); - name.append(uname); - - if (name.size() >= UNIX_PATH_MAX) - { - debug(1, L"Filename too long: '%s'", name.c_str()); - exit(EXIT_FAILURE); - } - return name; -} - -/** - Signal handler for the term signal. -*/ -static void handle_term(int signal) -{ - quit=1; -} - - -/** - Writes a pseudo-random number (between one and maxlen) of pseudo-random - digits into str. - str must point to an allocated buffer of size of at least maxlen chars. - Returns the number of digits written. - Since the randomness in part depends on machine time it has _some_ extra - strength but still not enough for use in concurrent locking schemes on a - single machine because gettimeofday may not return a different value on - consecutive calls when: - a) the OS does not support fine enough resolution - b) the OS is running on an SMP machine. - Additionally, gettimeofday errors are ignored. - Excludes chars other than digits since ANSI C only guarantees that digits - are consecutive. - */ -static void sprint_rand_digits(char *str, int maxlen) -{ - int i, max; - struct timeval tv; - - /* - Seed the pseudo-random generator based on time - this assumes - that consecutive calls to gettimeofday will return different values - and ignores errors returned by gettimeofday. - Cast to unsigned so that wrapping occurs on overflow as per ANSI C. - */ - static bool seeded = false; - if (! seeded) - { - (void)gettimeofday(&tv, NULL); - unsigned long long seed = tv.tv_sec + tv.tv_usec * 1000000ULL; - srand((unsigned int)seed); - seeded = true; - } - max = (int)(1 + (maxlen - 1) * (rand() / (RAND_MAX + 1.0))); - for (i = 0; i < max; i++) - { - str[i] = '0' + 10 * (rand() / (RAND_MAX + 1.0)); - } - str[i] = 0; -} - - - -/** - Generate a filename unique in an NFS namespace by creating a copy of str and - appending .{hostname}.{pid} to it. If gethostname() fails then a pseudo- - random string is substituted for {hostname} - the randomness of the string - should be strong enough across different machines. The main assumption - though is that gethostname will not fail and this is just a "safe enough" - fallback. - The memory returned should be freed using free(). - */ -static std::string gen_unique_nfs_filename(const std::string &filename) -{ - char hostname[HOST_NAME_MAX + 1]; - char pid_str[256]; - snprintf(pid_str, sizeof pid_str, "%ld", (long)getpid()); - - if (gethostname(hostname, sizeof hostname) != 0) - { - sprint_rand_digits(hostname, HOST_NAME_MAX); - } - - std::string newname(filename); - newname.push_back('.'); - newname.append(hostname); - newname.push_back('.'); - newname.append(pid_str); - return newname; -} - -/** - The number of milliseconds to wait between polls when attempting to acquire - a lockfile - */ -#define LOCKPOLLINTERVAL 10 - -/** - Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL - milliseconds between polls and timing out after timeout seconds, - thereafter forcibly attempting to obtain the lock if force is non-zero. - Returns 1 on success, 0 on failure. - To release the lock the lockfile must be unlinked. - A unique temporary file named by appending characters to the lockfile name - is used; any pre-existing file of the same name is subject to deletion. - */ -static int acquire_lock_file(const std::string &lockfile_str, const int timeout, int force) -{ - int fd, timed_out = 0; - int ret = 0; /* early exit returns failure */ - struct timespec pollint; - struct timeval start, end; - double elapsed; - struct stat statbuf; - const char * const lockfile = lockfile_str.c_str(); - - /* - (Re)create a unique file and check that it has one only link. - */ - const std::string linkfile_str = gen_unique_nfs_filename(lockfile); - const char * const linkfile = linkfile_str.c_str(); - (void)unlink(linkfile); - /* OK to not use CLO_EXEC here because fishd is single threaded */ - if ((fd = open(linkfile, O_CREAT|O_RDONLY, 0600)) == -1) - { - debug(1, L"acquire_lock_file: open: %s", strerror(errno)); - goto done; - } - /* - Don't need to check exit status of close on read-only file descriptors - */ - close(fd); - if (stat(linkfile, &statbuf) != 0) - { - debug(1, L"acquire_lock_file: stat: %s", strerror(errno)); - goto done; - } - if (statbuf.st_nlink != 1) - { - debug(1, L"acquire_lock_file: number of hardlinks on unique " - L"tmpfile is %d instead of 1.", (int)statbuf.st_nlink); - goto done; - } - if (gettimeofday(&start, NULL) != 0) - { - debug(1, L"acquire_lock_file: gettimeofday: %s", strerror(errno)); - goto done; - } - end = start; - pollint.tv_sec = 0; - pollint.tv_nsec = LOCKPOLLINTERVAL * 1000000; - do - { - /* - Try to create a hard link to the unique file from the - lockfile. This will only succeed if the lockfile does not - already exist. It is guaranteed to provide race-free - semantics over NFS which the alternative of calling - open(O_EXCL|O_CREAT) on the lockfile is not. The lock - succeeds if the call to link returns 0 or the link count on - the unique file increases to 2. - */ - if (link(linkfile, lockfile) == 0 || - (stat(linkfile, &statbuf) == 0 && - statbuf.st_nlink == 2)) - { - /* Successful lock */ - ret = 1; - break; - } - elapsed = end.tv_sec + end.tv_usec/1000000.0 - - (start.tv_sec + start.tv_usec/1000000.0); - /* - The check for elapsed < 0 is to deal with the unlikely event - that after the loop is entered the system time is set forward - past the loop's end time. This would otherwise result in a - (practically) infinite loop. - */ - if (timed_out || elapsed >= timeout || elapsed < 0) - { - if (timed_out == 0 && force) - { - /* - Timed out and force was specified - attempt to - remove stale lock and try a final time - */ - (void)unlink(lockfile); - timed_out = 1; - continue; - } - else - { - /* - Timed out and final try was unsuccessful or - force was not specified - */ - debug(1, L"acquire_lock_file: timed out " - L"trying to obtain lockfile %s using " - L"linkfile %s", lockfile, linkfile); - break; - } - } - nanosleep(&pollint, NULL); - } - while (gettimeofday(&end, NULL) == 0); -done: - /* The linkfile is not needed once the lockfile has been created */ - (void)unlink(linkfile); - return ret; -} - -/** - Acquire the lock for the socket - Returns the name of the lock file if successful or - NULL if unable to obtain lock. - The returned string must be free()d after unlink()ing the file to release - the lock -*/ -static bool acquire_socket_lock(const std::string &sock_name, std::string *out_lockfile_name) -{ - bool success = false; - std::string lockfile; - lockfile.reserve(sock_name.size() + strlen(LOCKPOSTFIX)); - lockfile = sock_name; - lockfile.append(LOCKPOSTFIX); - if (acquire_lock_file(lockfile, LOCKTIMEOUT, 1)) - { - out_lockfile_name->swap(lockfile); - success = true; - } - return success; -} - -/** - Connects to the fish socket and starts listening for connections -*/ -static int get_socket(void) -{ - // Cygwin has random problems involving sockets. When using Cygwin, - // allow 20 attempts at making socket correctly. -#ifdef __CYGWIN__ - int attempts = 0; -repeat: - attempts += 1; -#endif - - int s, len, doexit = 0; - int exitcode = EXIT_FAILURE; - struct sockaddr_un local; - const std::string sock_name = get_socket_filename(); - - /* - Start critical section protected by lock - */ - std::string lockfile; - if (! acquire_socket_lock(sock_name, &lockfile)) - { - debug(0, L"Unable to obtain lock on socket, exiting"); - exit(EXIT_FAILURE); - } - debug(4, L"Acquired lockfile: %s", lockfile.c_str()); - - local.sun_family = AF_UNIX; - strcpy(local.sun_path, sock_name.c_str()); - len = sizeof(local); - - debug(1, L"Connect to socket at %s", sock_name.c_str()); - - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - { - wperror(L"socket"); - doexit = 1; - goto unlock; - } - - /* - First check whether the socket has been opened by another fishd; - if so, exit with success status - */ - if (connect(s, (struct sockaddr *)&local, len) == 0) - { - debug(1, L"Socket already exists, exiting"); - doexit = 1; - exitcode = 0; - goto unlock; - } - - unlink(local.sun_path); - if (bind(s, (struct sockaddr *)&local, len) == -1) - { - wperror(L"bind"); - doexit = 1; - goto unlock; - } - - if (make_fd_nonblocking(s) != 0) - { - wperror(L"fcntl"); - close(s); - doexit = 1; - } - else if (listen(s, 64) == -1) - { - wperror(L"listen"); - doexit = 1; - } - -unlock: - (void)unlink(lockfile.c_str()); - debug(4, L"Released lockfile: %s", lockfile.c_str()); - /* - End critical section protected by lock - */ - - if (doexit) - { - // If Cygwin, only allow normal quit when made lots of attempts. -#ifdef __CYGWIN__ - if (exitcode && attempts < 20) goto repeat; -#endif - exit_without_destructors(exitcode); - } - - return s; -} - -/** - Event handler. Broadcasts updates to all clients. -*/ -static void broadcast(fish_message_type_t type, const wchar_t *key, const wchar_t *val) -{ - message_t *msg; - - if (connections.empty()) - return; - - msg = create_message(type, key, val); - - /* - Don't merge these loops, or try_send_all can free the message - prematurely - */ - - for (connection_list_t::iterator iter = connections.begin(); iter != connections.end(); ++iter) - { - msg->count++; - iter->unsent.push(msg); - } - - for (connection_list_t::iterator iter = connections.begin(); iter != connections.end(); ++iter) - { - try_send_all(&*iter); - } -} - -/** - Make program into a creature of the night. -*/ -static void daemonize() -{ - /* - Fork, and let parent exit - */ - switch (fork()) - { - case -1: - debug(0, L"Could not put fishd in background. Quitting"); - wperror(L"fork"); - exit(1); - - case 0: - { - /* Ordinarily there's very limited things we will do after fork, due to multithreading. But fishd is safe because it's single threaded. So don't die in is_forked_child. */ - setup_fork_guards(); - - /* - Make fishd ignore the HUP and PIPE signals. - */ - struct sigaction act; - sigemptyset(& act.sa_mask); - act.sa_flags=0; - act.sa_handler=SIG_IGN; - sigaction(SIGHUP, &act, 0); - sigaction(SIGPIPE, &act, 0); - - /* - Make fishd save and exit on the TERM signal. - */ - sigfillset(& act.sa_mask); - act.sa_flags=0; - act.sa_handler=&handle_term; - sigaction(SIGTERM, &act, 0); - break; - - } - - default: - { - debug(0, L"Parent process exiting (This is normal)"); - exit(0); - } - } - - /* - Put ourself in our own process group - */ - setsid(); - - /* - Close stdin and stdout. We only use stderr, anyway. - */ - close(0); - close(1); - -} - -/** - Get environment variable value. -*/ -static env_var_t fishd_env_get(const char *key) -{ - const char *env = getenv(key); - if (env != NULL) - { - return env_var_t(str2wcstring(env)); - } - else - { - const wcstring wkey = str2wcstring(key); - return env_universal_common_get(wkey); - } -} - -/** - Get the configuration directory. The resulting string needs to be - free'd. This is mostly the same code as path_get_config(), but had - to be rewritten to avoid dragging in additional library - dependencies. -*/ -static wcstring fishd_get_config() -{ - bool done = false; - wcstring result; - - env_var_t xdg_dir = fishd_env_get("XDG_CONFIG_HOME"); - if (! xdg_dir.missing_or_empty()) - { - result = xdg_dir; - append_path_component(result, L"/fish"); - if (!create_directory(result)) - { - done = true; - } - } - else - { - env_var_t home = fishd_env_get("HOME"); - if (! home.missing_or_empty()) - { - result = home; - append_path_component(result, L"/.config/fish"); - if (!create_directory(result)) - { - done = 1; - } - } - } - - if (! done) - { - /* Bad juju */ - debug(0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access.")); - result.clear(); - } - - return result; -} - -/** - Load or save all variables -*/ -static bool load_or_save_variables_at_path(bool save, const std::string &path) -{ - bool result = false; - - debug(4, L"Open file for %s: '%s'", - save?"saving":"loading", - path.c_str()); - - /* OK to not use CLO_EXEC here because fishd is single threaded */ - int fd = open(path.c_str(), save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600); - if (fd >= 0) - { - /* Success */ - result = true; - connection_t c(fd); - - if (save) - { - /* Save to the file */ - write_loop(c.fd, SAVE_MSG, strlen(SAVE_MSG)); - enqueue_all(&c); - } - else - { - /* Read from the file */ - read_message(&c); - } - - connection_destroy(&c); - } - return result; -} - - -static std::string get_variables_file_path(const std::string &dir, const std::string &identifier) -{ - std::string name; - name.append(dir); - name.append("/"); - name.append(FILE); - name.append(identifier); - return name; -} - - -static bool load_or_save_variables(bool save) -{ - const wcstring wdir = fishd_get_config(); - const std::string dir = wcs2string(wdir); - if (dir.empty()) - return false; - - const std::string machine_id = get_machine_identifier(); - const std::string machine_id_path = get_variables_file_path(dir, machine_id); - bool success = load_or_save_variables_at_path(save, machine_id_path); - if (! success && ! save && errno == ENOENT) - { - /* We failed to load, because the file was not found. Older fish used the hostname only. Try *moving* the filename based on the hostname into place; if that succeeds try again. Silently "upgraded." */ - std::string hostname_id; - if (get_hostname_identifier(&hostname_id) && hostname_id != machine_id) - { - std::string hostname_path = get_variables_file_path(dir, hostname_id); - if (0 == rename(hostname_path.c_str(), machine_id_path.c_str())) - { - /* We renamed - try again */ - success = load_or_save_variables_at_path(save, machine_id_path); - } - } - } - return success; -} - -/** - Load variables from disk -*/ -static void load() -{ - load_or_save_variables(false /* load, not save */); -} - -/** - Save variables to disk -*/ -static void save() -{ - load_or_save_variables(true /* save, not load */); -} - -/** - Do all sorts of boring initialization. -*/ -static void init() -{ - - sock = get_socket(); - daemonize(); - env_universal_common_init(&broadcast); - - load(); -} - -/** - Main function for fishd -*/ -int main(int argc, char ** argv) -{ - int child_socket; - struct sockaddr_un remote; - socklen_t t; - uid_t sock_euid; - gid_t sock_egid; - int max_fd; - int update_count=0; - - fd_set read_fd, write_fd; - - set_main_thread(); - setup_fork_guards(); - - program_name=L"fishd"; - wsetlocale(LC_ALL, L""); - - /* - Parse options - */ - while (1) - { - static struct option - long_options[] = - { - { - "help", no_argument, 0, 'h' - } - , - { - "version", no_argument, 0, 'v' - } - , - { - 0, 0, 0, 0 - } - } - ; - - int opt_index = 0; - - int opt = getopt_long(argc, - argv, - GETOPT_STRING, - long_options, - &opt_index); - - if (opt == -1) - break; - - switch (opt) - { - case 0: - break; - - case 'h': - print_help(argv[0], 1); - exit(0); - - case 'v': - debug(0, L"%ls, version %s\n", program_name, get_fish_version()); - exit(0); - - case '?': - return 1; - - } - } - - init(); - while (1) - { - int res; - - t = sizeof(remote); - - FD_ZERO(&read_fd); - FD_ZERO(&write_fd); - FD_SET(sock, &read_fd); - max_fd = sock+1; - for (connection_list_t::const_iterator iter = connections.begin(); iter != connections.end(); ++iter) - { - const connection_t &c = *iter; - FD_SET(c.fd, &read_fd); - max_fd = maxi(max_fd, c.fd+1); - - if (! c.unsent.empty()) - { - FD_SET(c.fd, &write_fd); - } - } - - while (1) - { - res=select(max_fd, &read_fd, &write_fd, 0, 0); - - if (quit) - { - save(); - exit(0); - } - - if (res != -1) - break; - - if (errno != EINTR) - { - wperror(L"select"); - exit(1); - } - } - - if (FD_ISSET(sock, &read_fd)) - { - if ((child_socket = - accept(sock, - (struct sockaddr *)&remote, - &t)) == -1) - { - wperror(L"accept"); - exit(1); - } - else - { - debug(4, L"Connected with new child on fd %d", child_socket); - - if (((getpeereid(child_socket, &sock_euid, &sock_egid) != 0) || sock_euid != geteuid())) - { - debug(1, L"Wrong credentials for child on fd %d", child_socket); - close(child_socket); - } - else if (make_fd_nonblocking(child_socket) != 0) - { - wperror(L"fcntl"); - close(child_socket); - } - else - { - connections.push_front(connection_t(child_socket)); - connection_t &newc = connections.front(); - send(newc.fd, GREETING, strlen(GREETING), MSG_DONTWAIT); - enqueue_all(&newc); - } - } - } - - for (connection_list_t::iterator iter = connections.begin(); iter != connections.end(); ++iter) - { - if (FD_ISSET(iter->fd, &write_fd)) - { - try_send_all(&*iter); - } - } - - for (connection_list_t::iterator iter = connections.begin(); iter != connections.end(); ++iter) - { - if (FD_ISSET(iter->fd, &read_fd)) - { - read_message(&*iter); - - /* - Occasionally we save during normal use, so that we - won't lose everything on a system crash - */ - update_count++; - if (update_count >= 64) - { - save(); - update_count = 0; - } - } - } - - for (connection_list_t::iterator iter = connections.begin(); iter != connections.end();) - { - if (iter->killme) - { - debug(4, L"Close connection %d", iter->fd); - - while (! iter->unsent.empty()) - { - message_t *msg = iter->unsent.front(); - iter->unsent.pop(); - msg->count--; - if (! msg->count) - free(msg); - } - - connection_destroy(&*iter); - iter = connections.erase(iter); - } - else - { - ++iter; - } - } - - if (connections.empty()) - { - debug(0, L"No more clients. Quitting"); - save(); - break; - } - - } -} - From ecf56606dca7b06abb0779f16be94d50537b7efa Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 6 Jun 2014 10:34:42 -0700 Subject: [PATCH 02/10] Remove large parts of fishd interaction, including env_universal_server --- common.cpp | 2 +- env.cpp | 53 +------ env_universal.cpp | 395 ++-------------------------------------------- env_universal.h | 5 +- input_common.cpp | 17 +- 5 files changed, 14 insertions(+), 458 deletions(-) diff --git a/common.cpp b/common.cpp index a9c579493..9e4fb50d9 100644 --- a/common.cpp +++ b/common.cpp @@ -2129,7 +2129,7 @@ static pid_t initial_foreground_process_group = -1; bool is_forked_child(void) { - /* Just bail if nobody's called setup_fork_guards - e.g. fishd */ + /* Just bail if nobody's called setup_fork_guards, e.g. some of our tools */ if (! initial_pid) return false; bool is_child_of_fork = (getpid() != initial_pid); diff --git a/env.cpp b/env.cpp index 086f181ab..69e0dd114 100644 --- a/env.cpp +++ b/env.cpp @@ -57,12 +57,6 @@ #include "complete.h" #include "fish_version.h" -/** Command used to start fishd */ -#define FISHD_CMD L"fishd ^ /dev/null" - -// Version for easier debugging -//#define FISHD_CMD L"fishd" - /** Value denoting a null string */ #define ENV_NULL L"\x1d" @@ -219,43 +213,6 @@ env_node_t *env_node_t::next_scope_to_search(void) return this->new_scope ? global_env : this->next; } - -/** - When fishd isn't started, this function is provided to - env_universal as a callback, it tries to start up fishd. It's - implementation is a bit of a hack, since it evaluates a bit of - shellscript, and it might be used at times when that might not be - the best idea. -*/ -static void start_fishd() -{ - struct passwd *pw = getpwuid(getuid()); - - debug(3, L"Spawning new copy of fishd"); - - if (!pw) - { - debug(0, _(L"Could not get user information")); - return; - } - - wcstring cmd = format_string(FISHD_CMD, pw->pw_name); - - /* Prefer the fishd in __fish_bin_dir, if exists */ - const env_var_t bin_dir = env_get_string(L"__fish_bin_dir"); - if (! bin_dir.missing_or_empty()) - { - wcstring path = bin_dir + L"/fishd"; - if (waccess(path, X_OK) == 0) - { - /* The path command just looks like 'fishd', so insert the bin path to make it absolute */ - cmd.insert(0, bin_dir + L"/"); - } - } - parser_t &parser = parser_t::principal_parser(); - parser.eval(cmd, io_chain_t(), TOP); -} - /** Return the current umask value. */ @@ -604,15 +561,7 @@ void env_init(const struct config_paths_t *paths /* or NULL */) env_set(L"version", version.c_str(), ENV_GLOBAL); env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL); - const env_var_t fishd_dir_wstr = env_get_string(L"FISHD_SOCKET_DIR"); - const env_var_t user_dir_wstr = env_get_string(L"USER"); - - wchar_t * fishd_dir = fishd_dir_wstr.missing()?NULL:const_cast(fishd_dir_wstr.c_str()); - wchar_t * user_dir = user_dir_wstr.missing()?NULL:const_cast(user_dir_wstr.c_str()); - - env_universal_init(fishd_dir , user_dir , - &start_fishd, - &universal_callback); + env_universal_init(universal_callback); /* Set up SHLVL variable diff --git a/env_universal.cpp b/env_universal.cpp index 920139dda..2d2bf304d 100644 --- a/env_universal.cpp +++ b/env_universal.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -40,31 +39,11 @@ #include "env_universal.h" #include "env.h" -/** - Maximum number of times to try to get a new fishd socket -*/ - -#define RECONNECT_COUNT 32 - - -connection_t env_universal_server(-1); /** Set to true after initialization has been performed */ static bool s_env_univeral_inited = false; - -/** - The number of attempts to start fishd -*/ -static int get_socket_count = 0; - -#define DEFAULT_RETRY_COUNT 15 -#define DEFAULT_RETRY_DELAY 0.2 - -static wchar_t * path; -static wchar_t *user; -static void (*start_fishd)(); static void (*external_callback)(fish_message_type_t type, const wchar_t *name, const wchar_t *val); /** @@ -74,133 +53,6 @@ static int barrier_reply = 0; void env_universal_barrier(); -static int is_dead() -{ - return env_universal_server.fd < 0; -} - -static int try_get_socket_once(void) -{ - int s; - - wchar_t *wdir; - wchar_t *wuname; - char *dir = 0; - - wdir = path; - wuname = user; - uid_t seuid; - gid_t segid; - - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - { - wperror(L"socket"); - return -1; - } - - if (wdir) - dir = wcs2str(wdir); - else - dir = strdup("/tmp"); - - std::string uname; - if (wuname) - { - uname = wcs2string(wuname); - } - else - { - struct passwd *pw = getpwuid(getuid()); - if (pw && pw->pw_name) - { - uname = pw->pw_name; - } - } - - std::string name; - name.reserve(strlen(dir) + uname.size() + strlen(SOCK_FILENAME) + 2); - name.append(dir); - name.append("/"); - name.append(SOCK_FILENAME); - name.append(uname); - - free(dir); - - debug(3, L"Connect to socket %s at fd %d", name.c_str(), s); - - struct sockaddr_un local = {}; - local.sun_family = AF_UNIX; - strncpy(local.sun_path, name.c_str(), (sizeof local.sun_path) - 1); - - if (connect(s, (struct sockaddr *)&local, sizeof local) == -1) - { - close(s); - - /* If it fails on first try, it's probably no serious error, but fishd hasn't been launched yet. - This happens (at least) on the first concurrent session. */ - if (get_socket_count > 1) - wperror(L"connect"); - - return -1; - } - - if ((getpeereid(s, &seuid, &segid) != 0) || seuid != geteuid()) - { - debug(1, L"Wrong credentials for socket %s at fd %d", name.c_str(), s); - close(s); - return -1; - } - - if ((make_fd_nonblocking(s) != 0) || (fcntl(s, F_SETFD, FD_CLOEXEC) != 0)) - { - wperror(L"fcntl"); - close(s); - - return -1; - } - - debug(3, L"Connected to fd %d", s); - - return s; -} - -/** - Get a socket for reading from the server -*/ -static int get_socket(void) -{ - get_socket_count++; - - int s = try_get_socket_once(); - if (s < 0) - { - if (start_fishd) - { - debug(2, L"Could not connect to socket %d, starting fishd", s); - - start_fishd(); - - for (size_t i=0; s < 0 && i < DEFAULT_RETRY_COUNT; i++) - { - if (i > 0) - { - // Wait before next try - usleep((useconds_t)(DEFAULT_RETRY_DELAY * 1E6)); - } - s = try_get_socket_once(); - } - } - } - - if (s < 0) - { - debug(1, L"Could not connect to universal variable server, already tried manual restart (or no command supplied). You will not be able to share variable values between fish sessions. Is fish properly installed?"); - return -1; - } - - return s; -} - /** Callback function used whenever a new fishd message is recieved */ @@ -217,151 +69,19 @@ static void callback(fish_message_type_t type, const wchar_t *name, const wchar_ } } -/** - Make sure the connection is healthy. If not, close it, and try to - establish a new connection. -*/ -static void check_connection(void) +void env_universal_init(void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val)) { - if (! s_env_univeral_inited) - return; - - if (env_universal_server.killme) - { - debug(3, L"Lost connection to universal variable server."); - - if (close(env_universal_server.fd)) - { - wperror(L"close"); - } - - env_universal_server.fd = -1; - env_universal_server.killme=0; - env_universal_server.input.clear(); - env_universal_read_all(); - } -} - -/** - Remove all universal variables. -*/ -static void env_universal_remove_all() -{ - size_t i; - wcstring_list_t lst; - env_universal_common_get_names(lst, true, true); - for (i=0; i= RECONNECT_COUNT) - return; - - debug(3, L"Get new fishd connection"); - - s_env_univeral_inited = false; - env_universal_server.buffer_consumed = 0; - env_universal_server.read_buffer.clear(); - env_universal_server.fd = get_socket(); + external_callback = cb; + env_universal_common_init(&callback); s_env_univeral_inited = true; - if (env_universal_server.fd >= 0) - { - env_universal_remove_all(); - env_universal_barrier(); - } -} - -void env_universal_init(wchar_t * p, - wchar_t *u, - void (*sf)(), - void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val)) -{ - if (! synchronizes_via_fishd()) - { - external_callback = cb; - env_universal_common_init(&callback); - s_env_univeral_inited = true; - } - else - { - path=p; - user=u; - start_fishd=sf; - external_callback = cb; - - env_universal_server.fd = get_socket(); - env_universal_common_init(&callback); - env_universal_read_all(); - s_env_univeral_inited = true; - if (env_universal_server.fd >= 0) - { - env_universal_barrier(); - } - } } void env_universal_destroy() { - /* - Go into blocking mode and send all data before exiting - */ - if (env_universal_server.fd >= 0) - { - if (fcntl(env_universal_server.fd, F_SETFL, 0) != 0) - { - wperror(L"fcntl"); - } - try_send_all(&env_universal_server); - } - - connection_destroy(&env_universal_server); - env_universal_server.fd =-1; s_env_univeral_inited = false; } -/** - Read all available messages from the server. -*/ -int env_universal_read_all() -{ - if (! s_env_univeral_inited) - return 0; - - if (env_universal_server.fd == -1) - { - reconnect(); - if (env_universal_server.fd == -1) - return 0; - } - - if (env_universal_server.fd != -1) - { - read_message(&env_universal_server); - check_connection(); - return 1; - } - else - { - debug(2, L"No connection to universal variable server"); - return 0; - } -} - env_var_t env_universal_get(const wcstring &name) { if (!s_env_univeral_inited) @@ -382,69 +102,7 @@ void env_universal_barrier() { ASSERT_IS_MAIN_THREAD(); UNIVERSAL_LOG("BARRIER"); - message_t *msg; - fd_set fds; - - if (! synchronizes_via_fishd()) - { - env_universal_common_sync(); - return; - } - - if (!s_env_univeral_inited || is_dead()) - return; - - barrier_reply = 0; - - /* - Create barrier request - */ - msg= create_message(BARRIER, 0, 0); - msg->count=1; - env_universal_server.unsent.push(msg); - - /* - Wait until barrier request has been sent - */ - debug(3, L"Create barrier"); - while (1) - { - try_send_all(&env_universal_server); - check_connection(); - - if (env_universal_server.unsent.empty()) - break; - - if (env_universal_server.fd == -1) - { - reconnect(); - debug(2, L"barrier interrupted, exiting"); - return; - } - - FD_ZERO(&fds); - FD_SET(env_universal_server.fd, &fds); - select(env_universal_server.fd+1, 0, &fds, 0, 0); - } - - /* - Wait for barrier reply - */ - debug(3, L"Sent barrier request"); - while (!barrier_reply) - { - if (env_universal_server.fd == -1) - { - reconnect(); - debug(2, L"barrier interrupted, exiting (2)"); - return; - } - FD_ZERO(&fds); - FD_SET(env_universal_server.fd, &fds); - select(env_universal_server.fd+1, &fds, 0, 0, 0); - env_universal_read_all(); - } - debug(3, L"End barrier"); + env_universal_common_sync(); } @@ -454,28 +112,9 @@ void env_universal_set(const wcstring &name, const wcstring &value, bool exportv return; debug(3, L"env_universal_set( \"%ls\", \"%ls\" )", name.c_str(), value.c_str()); - - if (! synchronizes_via_fishd() || is_dead()) - { - env_universal_common_set(name.c_str(), value.c_str(), exportv); - env_universal_barrier(); - } - else - { - message_t *msg = create_message(exportv?SET_EXPORT:SET, - name.c_str(), - value.c_str()); - - if (!msg) - { - debug(1, L"Could not create universal variable message"); - return; - } - - msg->count=1; - env_universal_server.unsent.push(msg); - env_universal_barrier(); - } + + env_universal_common_set(name.c_str(), value.c_str(), exportv); + env_universal_barrier(); } int env_universal_remove(const wchar_t *name) @@ -487,24 +126,10 @@ int env_universal_remove(const wchar_t *name) CHECK(name, 1); - wcstring name_str = name; + const wcstring name_str = name; + // TODO: shouldn't have to call get() here, should just have remove return success res = env_universal_common_get(name_str).missing(); - debug(3, - L"env_universal_remove( \"%ls\" )", - name); - - if (! synchronizes_via_fishd() || is_dead()) - { - env_universal_common_remove(name_str); - } - else - { - message_t *msg = create_message(ERASE, name, 0); - msg->count=1; - env_universal_server.unsent.push(msg); - env_universal_barrier(); - } - + env_universal_common_remove(name_str); return res; } diff --git a/env_universal.h b/env_universal.h index a77efb1f5..7710999a9 100644 --- a/env_universal.h +++ b/env_universal.h @@ -18,10 +18,7 @@ extern connection_t env_universal_server; /** Initialize the envuni library */ -void env_universal_init(wchar_t * p, - wchar_t *u, - void (*sf)(), - void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val)); +void env_universal_init(void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val)); /** Free memory used by envuni */ diff --git a/input_common.cpp b/input_common.cpp index 1252dc0d4..e63931243 100644 --- a/input_common.cpp +++ b/input_common.cpp @@ -102,11 +102,6 @@ static wint_t readb() FD_ZERO(&fdset); FD_SET(0, &fdset); - if (env_universal_server.fd > 0) - { - FD_SET(env_universal_server.fd, &fdset); - fd_max = maxi(fd_max, env_universal_server.fd); - } if (ioport > 0) { FD_SET(ioport, &fdset); @@ -174,17 +169,7 @@ static wint_t readb() /* Assume we loop unless we see a character in stdin */ do_loop = true; - if (env_universal_server.fd > 0 && FD_ISSET(env_universal_server.fd, &fdset)) - { - debug(3, L"Wake up on universal variable event"); - env_universal_read_all(); - if (has_lookahead()) - { - return lookahead_pop(); - } - } - - /* Check to see if we want a barrier */ + /* Check to see if we want a universal variable barrier */ bool barrier_from_poll = notifier.poll(); bool barrier_from_readability = false; if (notifier_fd > 0 && FD_ISSET(notifier_fd, &fdset)) From ef646f0f7823e7be6f290297d1dac15f303d1947 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 9 Jun 2014 12:07:40 -0700 Subject: [PATCH 03/10] Removal of more fishd artifacts and headers --- env.cpp | 7 --- env_universal.cpp | 16 +----- env_universal_common.cpp | 94 +--------------------------------- env_universal_common.h | 33 ++---------- fish.xcodeproj/project.pbxproj | 2 - 5 files changed, 8 insertions(+), 144 deletions(-) diff --git a/env.cpp b/env.cpp index 69e0dd114..21e0adee1 100644 --- a/env.cpp +++ b/env.cpp @@ -345,13 +345,6 @@ static void universal_callback(fish_message_type_t type, str=L"SET"; break; } - - case ERASE: - { - str=L"ERASE"; - break; - } - default: break; } diff --git a/env_universal.cpp b/env_universal.cpp index 2d2bf304d..eb23aff18 100644 --- a/env_universal.cpp +++ b/env_universal.cpp @@ -46,11 +46,6 @@ static bool s_env_univeral_inited = false; static void (*external_callback)(fish_message_type_t type, const wchar_t *name, const wchar_t *val); -/** - Flag set to 1 when a barrier reply is recieved -*/ -static int barrier_reply = 0; - void env_universal_barrier(); /** @@ -58,15 +53,8 @@ void env_universal_barrier(); */ static void callback(fish_message_type_t type, const wchar_t *name, const wchar_t *val) { - if (type == BARRIER_REPLY) - { - barrier_reply = 1; - } - else - { - if (external_callback) - external_callback(type, name, val); - } + if (external_callback) + external_callback(type, name, val); } void env_universal_init(void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val)) diff --git a/env_universal_common.cpp b/env_universal_common.cpp index 0b73782d4..baf94a19f 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -7,32 +7,12 @@ */ #include "config.h" +#include "env_universal_common.h" -#include -#include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #ifdef HAVE_SYS_SELECT_H #include @@ -44,7 +24,6 @@ #include "common.h" #include "wutil.h" #include "utf8.h" -#include "env_universal_common.h" #include "path.h" #include "iothread.h" @@ -477,24 +456,6 @@ message_t *create_message(fish_message_type_t type, break; } - case ERASE: - { - set_body(msg, ERASE_MBS, " ", key, "\n", NULL); - break; - } - - case BARRIER: - { - set_body(msg, BARRIER_MBS, "\n", NULL); - break; - } - - case BARRIER_REPLY: - { - set_body(msg, BARRIER_REPLY_MBS, "\n", NULL); - break; - } - default: { debug(0, L"create_message: Unknown message type"); @@ -540,20 +501,6 @@ connection_t::connection_t(int input_fd) : { } -void connection_destroy(connection_t *c) -{ - /* - A connection need not always be open - we only try to close it - if it is open. - */ - if (c->fd >= 0) - { - if (close(c->fd)) - { - wperror(L"close"); - } - } -} env_universal_t::env_universal_t(const wcstring &path) : explicit_vars_path(path), tried_renaming(false), last_read_file(kInvalidFileID) { @@ -1201,45 +1148,6 @@ void env_universal_t::parse_message_internal(wchar_t *msg, connection_t *src, ca debug(1, PARSE_ERR, msg); } } - else if (match(msg, ERASE_STR)) - { - wchar_t *name, *tmp; - - name = msg+wcslen(ERASE_STR); - while (wcschr(L"\t ", *name)) - name++; - - tmp = name; - while (iswalnum(*tmp) || *tmp == L'_') - tmp++; - - *tmp = 0; - - if (!wcslen(name)) - { - debug(1, PARSE_ERR, msg); - } - - this->remove_internal(name, false); - if (callbacks != NULL) - { - callbacks->push_back(callback_data_t(ERASE, name, wcstring())); - } - } - else if (match(msg, BARRIER_STR)) - { - message_t *msg = create_message(BARRIER_REPLY, 0, 0); - msg->count = 1; - src->unsent.push(msg); - try_send_all(src); - } - else if (match(msg, BARRIER_REPLY_STR)) - { - if (callbacks != NULL) - { - callbacks->push_back(callback_data_t(BARRIER_REPLY, wcstring(), wcstring())); - } - } else { debug(1, PARSE_ERR, msg); diff --git a/env_universal_common.h b/env_universal_common.h index 1dcf6ed43..19e56986e 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -5,6 +5,7 @@ #include #include #include +#include "wutil.h" #include "util.h" #include "env.h" @@ -19,40 +20,16 @@ #define SET_EXPORT_STR L"SET_EXPORT" /** - The erase command -*/ -#define ERASE_STR L"ERASE" - -/** - The barrier command -*/ -#define BARRIER_STR L"BARRIER" - -/** - The barrier_reply command -*/ -#define BARRIER_REPLY_STR L"BARRIER_REPLY" - - -/** - The filename to use for univeral variables. The username is appended -*/ -#define SOCK_FILENAME "fishd.socket." - -/** - The different types of commands that can be sent between client/server + The different types of messages found in the fishd file */ typedef enum { SET, - SET_EXPORT, - ERASE, - BARRIER, - BARRIER_REPLY, + SET_EXPORT } fish_message_type_t; /** - The size of the buffer used for reading from the socket + The size of the buffer used for reading from the file */ #define ENV_UNIVERSAL_BUFFER_SIZE 1024 @@ -67,7 +44,7 @@ typedef struct int count; /** - Message body. The message must be allocated using enough memory to actually contain the message. + Message body. */ std::string body; diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj index aecda2bd7..32ba442b3 100644 --- a/fish.xcodeproj/project.pbxproj +++ b/fish.xcodeproj/project.pbxproj @@ -406,7 +406,6 @@ D0A0853F13B3ACEE0099B651 /* fish_indent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_indent.cpp; sourceTree = ""; }; D0A0854113B3ACEE0099B651 /* fish_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_tests.cpp; sourceTree = ""; }; D0A0854213B3ACEE0099B651 /* fish.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish.cpp; sourceTree = ""; }; - D0A0854313B3ACEE0099B651 /* fishd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fishd.cpp; sourceTree = ""; }; D0A0854413B3ACEE0099B651 /* function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = function.cpp; sourceTree = ""; }; D0A0854713B3ACEE0099B651 /* highlight.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = highlight.cpp; sourceTree = ""; }; D0A0854813B3ACEE0099B651 /* history.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = history.cpp; sourceTree = ""; }; @@ -600,7 +599,6 @@ D0A0853F13B3ACEE0099B651 /* fish_indent.cpp */, D0A0854113B3ACEE0099B651 /* fish_tests.cpp */, D0A0854213B3ACEE0099B651 /* fish.cpp */, - D0A0854313B3ACEE0099B651 /* fishd.cpp */, D00F63F019137E9D00FCCDEC /* fish_version.cpp */, D0A0851113B3ACEE0099B651 /* highlight.h */, D0A0854713B3ACEE0099B651 /* highlight.cpp */, From 11c156251250dec94960aa267739c958cfdb3e04 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 9 Jun 2014 12:57:44 -0700 Subject: [PATCH 04/10] Remove connection_t usage from write_to_fd --- builtin_set.cpp | 2 +- common.cpp | 6 +- common.h | 2 +- env_universal_common.cpp | 126 ++++++++++++++++++++++++++++++++------- env_universal_common.h | 2 +- 5 files changed, 112 insertions(+), 26 deletions(-) diff --git a/builtin_set.cpp b/builtin_set.cpp index 633416497..598d6c402 100644 --- a/builtin_set.cpp +++ b/builtin_set.cpp @@ -428,7 +428,7 @@ static int builtin_set(parser_t &parser, wchar_t **argv) int slice=0; int i; - wchar_t *bad_char; + const wchar_t *bad_char = NULL; /* Parse options to obtain the requested operation and the modifiers */ diff --git a/common.cpp b/common.cpp index 9e4fb50d9..81d7b8396 100644 --- a/common.cpp +++ b/common.cpp @@ -486,17 +486,17 @@ void append_format(wcstring &str, const wchar_t *format, ...) va_end(va); } -wchar_t *wcsvarname(const wchar_t *str) +const wchar_t *wcsvarname(const wchar_t *str) { while (*str) { if ((!iswalnum(*str)) && (*str != L'_')) { - return (wchar_t *)str; + return str; } str++; } - return 0; + return NULL; } const wchar_t *wcsfuncname(const wchar_t *str) diff --git a/common.h b/common.h index 188215093..ca4c83371 100644 --- a/common.h +++ b/common.h @@ -650,7 +650,7 @@ char **wcsv2strv(const wchar_t * const *in); \return null if this is a valid name, and a pointer to the first invalid character otherwise */ -wchar_t *wcsvarname(const wchar_t *str); +const wchar_t *wcsvarname(const wchar_t *str); /** diff --git a/env_universal_common.cpp b/env_universal_common.cpp index baf94a19f..1fe2c4665 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -42,21 +42,6 @@ */ #define SET_EXPORT_MBS "SET_EXPORT" -/** - Non-wide version of the erase command -*/ -#define ERASE_MBS "ERASE" - -/** - Non-wide version of the barrier command -*/ -#define BARRIER_MBS "BARRIER" - -/** - Non-wide version of the barrier_reply command -*/ -#define BARRIER_REPLY_MBS "BARRIER_REPLY" - /** Error message */ @@ -409,6 +394,72 @@ void set_body(message_t *msg, ...) va_end(arg_list); } +/* Converts input to UTF-8 and appends it to receiver, using storage as temp storage */ +static bool append_utf8(const wcstring &input, std::string *receiver, std::string *storage) +{ + bool result = false; + if (wchar_to_utf8_string(input, storage)) + { + receiver->append(*storage); + result = true; + } + return result; +} + +/* Creates a file entry like "SET fish_color_cwd:FF0". Appends the result to *result (as UTF8). Returns true on success. storage may be used for temporary storage, to avoid allocations */ +static bool append_file_entry(fish_message_type_t type, const wcstring &key_in, const wcstring &val_in, std::string *result, std::string *storage) +{ + assert(storage != NULL); + assert(result != NULL); + + // Record the length on entry, in case we need to back up + bool success = true; + const size_t result_length_on_entry = result->size(); + + // Append header like "SET " + result->append(type==SET ? SET_MBS : SET_EXPORT_MBS); + result->push_back(' '); + + // Append variable name like "fish_color_cwd" + if (wcsvarname(key_in.c_str())) + { + debug(0, L"Illegal variable name: '%ls'", key_in.c_str()); + success = false; + } + if (success && ! append_utf8(key_in, result, storage)) + { + debug(0, L"Could not convert %ls to narrow character string", key_in.c_str()); + success = false; + } + + // Append ":" + if (success) + { + result->push_back(':'); + } + + // Append value + if (success && ! append_utf8(full_escape(val_in.c_str()), result, storage)) + { + debug(0, L"Could not convert %ls to narrow character string", val_in.c_str()); + success = false; + } + + // Append newline + if (success) + { + result->push_back('\n'); + } + + // Don't modify result on failure. It's sufficient to simply resize it since all we ever did was append to it. + if (! success) + { + result->resize(result_length_on_entry); + } + + return success; +} + /* Returns an instance of message_t allocated via new */ message_t *create_message(fish_message_type_t type, const wchar_t *key_in, @@ -614,6 +665,7 @@ void env_universal_t::enqueue_all_internal(connection_t *c) const message_t *msg = create_message(entry.exportv ? SET_EXPORT : SET, key.c_str(), entry.val.c_str()); msg->count=1; c->unsent.push(msg); + fprintf(stderr, "%s", msg->body.c_str()); } try_send_all(c); } @@ -689,18 +741,52 @@ bool env_universal_t::load_from_path(const wcstring &path, callback_data_list_t return result; } -void env_universal_t::write_to_fd(int fd) +/* Writes our state to the fd. path is provided only for error reporting */ +bool env_universal_t::write_to_fd(int fd, const wcstring &path) { ASSERT_IS_LOCKED(lock); assert(fd >= 0); - connection_t conn(fd); + bool success = true; + + // Stuff we output to fd + std::string contents; + + // Temporary storage + std::string storage; + + // Write the save message. If this fails, we don't bother complaining. write_loop(fd, SAVE_MSG, strlen(SAVE_MSG)); - this->enqueue_all_internal(&conn); + + var_table_t::const_iterator iter = vars.begin(); + while (iter != vars.end()) + { + // Append the entry. Note that append_file_entry may fail, but that only affects one variable; soldier on. + const wcstring &key = iter->first; + const var_entry_t &entry = iter->second; + append_file_entry(entry.exportv ? SET_EXPORT : SET, key, entry.val, &contents, &storage); + + // Go to next + ++iter; + + // Flush if this is the last iteration or we exceed a page + if (iter == vars.end() || contents.size() >= 4096) + { + if (write_loop(fd, contents.data(), contents.size()) < 0) + { + int err = errno; + report_error(err, L"Unable to write to universal variables file '%ls'", path.c_str()); + success = false; + break; + } + contents.clear(); + } + } /* Since we just wrote out this file, it matches our internal state; pretend we read from it */ this->last_read_file = file_id_for_fd(fd); - /* Do not destroy the connection; we don't close the file */ + /* We don't close the file */ + return success; } bool env_universal_t::move_new_vars_file_into_place(const wcstring &src, const wcstring &dst) @@ -985,7 +1071,7 @@ bool env_universal_t::sync(callback_data_list_t *callbacks) if (success) { assert(private_fd >= 0); - this->write_to_fd(private_fd); + success = this->write_to_fd(private_fd, private_file_path); } if (success) diff --git a/env_universal_common.h b/env_universal_common.h index 19e56986e..083f7fbf6 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -209,7 +209,7 @@ class env_universal_t /* Functions concerned with saving */ bool open_and_acquire_lock(const wcstring &path, int *out_fd); bool open_temporary_file(const wcstring &directory, wcstring *out_path, int *out_fd); - void write_to_fd(int fd); + bool write_to_fd(int fd, const wcstring &path); bool move_new_vars_file_into_place(const wcstring &src, const wcstring &dst); /* File id from which we last read */ From 17c2d76c5ec935ab320badee834260bd3a5a4340 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 9 Jun 2014 16:41:10 -0700 Subject: [PATCH 05/10] Removed connection_t and associated functions --- env_universal.h | 5 - env_universal_common.cpp | 390 ++++----------------------------------- env_universal_common.h | 102 +--------- 3 files changed, 41 insertions(+), 456 deletions(-) diff --git a/env_universal.h b/env_universal.h index 7710999a9..7e2e69909 100644 --- a/env_universal.h +++ b/env_universal.h @@ -10,11 +10,6 @@ #include "env_universal_common.h" #include "env.h" -/** - Data about the universal variable server. -*/ -extern connection_t env_universal_server; - /** Initialize the envuni library */ diff --git a/env_universal_common.cpp b/env_universal_common.cpp index 1fe2c4665..4df44ad83 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -47,21 +47,6 @@ */ #define PARSE_ERR L"Unable to parse universal variable message: '%ls'" -/** - ERROR string for internal buffered reader -*/ -#define ENV_UNIVERSAL_ERROR 0x100 - -/** - EAGAIN string for internal buffered reader -*/ -#define ENV_UNIVERSAL_AGAIN 0x101 - -/** - EOF string for internal buffered reader -*/ -#define ENV_UNIVERSAL_EOF 0x102 - /** Small note about not editing ~/.fishd manually. Inserted at the top of all .fishd files. */ #define SAVE_MSG "# This file is automatically generated by the fish.\n# Do NOT edit it directly, your changes will be overwritten.\n" @@ -120,83 +105,11 @@ static void post_callbacks(const callback_data_list_t &callbacks) } } -/* UTF <-> wchar conversions. These return a string allocated with malloc. These call sites could be cleaned up substantially to eliminate the dependence on malloc. */ -static wchar_t *utf2wcs(const char *input) -{ - wchar_t *result = NULL; - wcstring converted; - if (utf8_to_wchar_string(input, &converted)) - { - result = wcsdup(converted.c_str()); - } - return result; -} - -static char *wcs2utf(const wchar_t *input) -{ - char *result = NULL; - std::string converted; - if (wchar_to_utf8_string(input, &converted)) - { - result = strdup(converted.c_str()); - } - return result; -} - void env_universal_common_init(void (*cb)(fish_message_type_t type, const wchar_t *key, const wchar_t *val)) { callback = cb; } -void read_message(connection_t *conn) -{ - callback_data_list_t callbacks; - default_universal_vars().read_message(conn, &callbacks); - post_callbacks(callbacks); -} - -/** - Read one byte of date form the specified connection - */ -static int read_byte(connection_t *src) -{ - - if (src->buffer_consumed >= src->read_buffer.size()) - { - char local[ENV_UNIVERSAL_BUFFER_SIZE]; - - ssize_t res = read(src->fd, local, sizeof local); - -// debug(4, L"Read chunk '%.*s'", res, src->buffer ); - - if (res < 0) - { - - if (errno == EAGAIN || - errno == EINTR) - { - return ENV_UNIVERSAL_AGAIN; - } - - return ENV_UNIVERSAL_ERROR; - - } - else if (res == 0) - { - return ENV_UNIVERSAL_EOF; - } - else - { - src->read_buffer.clear(); - src->read_buffer.insert(src->read_buffer.begin(), local, local + res); - src->buffer_consumed = 0; - } - } - - return src->read_buffer.at(src->buffer_consumed++); - -} - /** Remove variable with specified name */ @@ -259,80 +172,6 @@ static void report_error(int err_code, const wchar_t *err_format, ...) fwprintf(stderr, L"%s\n", strerror(err_code)); } -/** - Attempt to send the specified message to the specified file descriptor - - \return 1 on sucess, 0 if the message could not be sent without blocking and -1 on error -*/ -static int try_send(message_t *msg, - int fd) -{ - - debug(3, - L"before write of %d chars to fd %d", msg->body.size(), fd); - - ssize_t res = write(fd, msg->body.c_str(), msg->body.size()); - - if (res != -1) - { - debug(4, L"Wrote message '%s'", msg->body.c_str()); - } - else - { - debug(4, L"Failed to write message '%s'", msg->body.c_str()); - } - - if (res == -1) - { - switch (errno) - { - case EAGAIN: - return 0; - - default: - debug(2, - L"Error while sending universal variable message to fd %d. Closing connection", - fd); - if (debug_level > 2) - wperror(L"write"); - - return -1; - } - } - msg->count--; - - if (!msg->count) - { - delete msg; - } - return 1; -} - -void try_send_all(connection_t *c) -{ - /* debug( 3, - L"Send all updates to connection on fd %d", - c->fd );*/ - while (!c->unsent.empty()) - { - switch (try_send(c->unsent.front(), c->fd)) - { - case 1: - c->unsent.pop(); - break; - - case 0: - debug(4, - L"Socket full, send rest later"); - return; - - case -1: - c->killme = 1; - return; - } - } -} - /* The universal variable format has some funny escaping requirements; here we try to be safe */ static bool is_universal_safe_to_encode_directly(wchar_t c) { @@ -372,28 +211,6 @@ static wcstring full_escape(const wchar_t *in) return out; } -/* Sets the body of a message to the null-terminated list of null terminated const char *. */ -void set_body(message_t *msg, ...) -{ - /* Start by counting the length of all the strings */ - size_t body_len = 0; - const char *arg; - va_list arg_list; - va_start(arg_list, msg); - while ((arg = va_arg(arg_list, const char *)) != NULL) - body_len += strlen(arg); - va_end(arg_list); - - /* Reserve that length in the string */ - msg->body.reserve(body_len + 1); //+1 for trailing NULL? Do I need that? - - /* Set the string contents */ - va_start(arg_list, msg); - while ((arg = va_arg(arg_list, const char *)) != NULL) - msg->body.append(arg); - va_end(arg_list); -} - /* Converts input to UTF-8 and appends it to receiver, using storage as temp storage */ static bool append_utf8(const wcstring &input, std::string *receiver, std::string *storage) { @@ -460,66 +277,6 @@ static bool append_file_entry(fish_message_type_t type, const wcstring &key_in, return success; } -/* Returns an instance of message_t allocated via new */ -message_t *create_message(fish_message_type_t type, - const wchar_t *key_in, - const wchar_t *val_in) -{ - char *key = NULL; - - // debug( 4, L"Crete message of type %d", type ); - - if (key_in) - { - if (wcsvarname(key_in)) - { - debug(0, L"Illegal variable name: '%ls'", key_in); - return NULL; - } - - key = wcs2utf(key_in); - if (!key) - { - debug(0, - L"Could not convert %ls to narrow character string", - key_in); - return NULL; - } - } - - message_t *msg = new message_t; - msg->count = 0; - - switch (type) - { - case SET: - case SET_EXPORT: - { - if (!val_in) - { - val_in=L""; - } - - wcstring esc = full_escape(val_in); - char *val = wcs2utf(esc.c_str()); - set_body(msg, (type==SET?SET_MBS:SET_EXPORT_MBS), " ", key, ":", val, "\n", NULL); - free(val); - break; - } - - default: - { - debug(0, L"create_message: Unknown message type"); - } - } - - free(key); - - // debug( 4, L"Message body is '%s'", msg->body ); - - return msg; -} - /** Put exported or unexported variables in a string list */ @@ -540,19 +297,6 @@ bool env_universal_common_get_export(const wcstring &name) return default_universal_vars().get_export(name); } -void enqueue_all(connection_t *c) -{ - default_universal_vars().enqueue_all(c); -} - -connection_t::connection_t(int input_fd) : - fd(input_fd), - killme(false), - buffer_consumed(0) -{ -} - - env_universal_t::env_universal_t(const wcstring &path) : explicit_vars_path(path), tried_renaming(false), last_read_file(kInvalidFileID) { VOMIT_ON_FAILURE(pthread_mutex_init(&lock, NULL)); @@ -653,28 +397,6 @@ wcstring_list_t env_universal_t::get_names(bool show_exported, bool show_unexpor return result; } -void env_universal_t::enqueue_all_internal(connection_t *c) const -{ - ASSERT_IS_LOCKED(lock); - var_table_t::const_iterator iter; - for (iter = vars.begin(); iter != vars.end(); ++iter) - { - const wcstring &key = iter->first; - const var_entry_t &entry = iter->second; - - message_t *msg = create_message(entry.exportv ? SET_EXPORT : SET, key.c_str(), entry.val.c_str()); - msg->count=1; - c->unsent.push(msg); - fprintf(stderr, "%s", msg->body.c_str()); - } - try_send_all(c); -} - -void env_universal_t::enqueue_all(connection_t *c) const -{ - scoped_lock locker(lock); - enqueue_all_internal(c); -} void env_universal_t::erase_unmodified_values() { @@ -710,9 +432,8 @@ void env_universal_t::load_from_fd(int fd, callback_data_list_t *callbacks) { /* Unmodified values are sourced from the file. Since we are about to read a different file, erase them */ this->erase_unmodified_values(); - connection_t c(fd); - /* Read from the file. Do not destroy the connection; the caller is responsible for closing the fd. */ - this->read_message_internal(&c, callbacks); + /* Read from the file. */ + this->read_message_internal(fd, callbacks); last_read_file = current_file; } } @@ -1109,94 +830,61 @@ bool env_universal_t::sync(callback_data_list_t *callbacks) return success; } -void env_universal_t::read_message_internal(connection_t *src, callback_data_list_t *callbacks) +void env_universal_t::read_message_internal(int fd, callback_data_list_t *callbacks) { ASSERT_IS_LOCKED(lock); - while (1) + + // The line we construct (and then parse) + std::string line; + wcstring wide_line; + for (;;) { - - int ib = read_byte(src); - char b; - - switch (ib) + // Read into a buffer. Note this is NOT null-terminated! + char buffer[1024]; + ssize_t amt = read_loop(fd, buffer, sizeof buffer); + if (amt <= 0) { - case ENV_UNIVERSAL_AGAIN: + break; + } + + // Walk over it by lines. The contents of an unterminated line will be left in 'line' for the next iteration. + size_t line_start = 0; + while (line_start < sizeof buffer) + { + // Run until we hit a newline + size_t cursor = line_start; + while (cursor < sizeof buffer && buffer[cursor] != '\n') { - return; + cursor++; } - - case ENV_UNIVERSAL_ERROR: + + // Copy over what we read + line.append(buffer + line_start, cursor - line_start); + + // Process it if it's a newline (which is true if we are before the end of the buffer) + if (cursor < sizeof buffer && ! line.empty()) { - debug(2, L"Read error on fd %d, set killme flag", src->fd); - if (debug_level > 2) - wperror(L"read"); - src->killme = 1; - return; - } - - case ENV_UNIVERSAL_EOF: - { - src->killme = 1; - debug(3, L"Fd %d has reached eof, set killme flag", src->fd); - if (! src->input.empty()) + if (utf8_to_wchar_string(line, &wide_line)) { - char c = 0; - src->input.push_back(c); - debug(1, - L"Universal variable connection closed while reading command. Partial command recieved: '%s'", - &src->input.at(0)); + wchar_t *tmp = wcsdup(wide_line.c_str()); + this->parse_message_internal(tmp, callbacks); + free(tmp); } - return; - } - } - - b = (char)ib; - - if (b == '\n') - { - wchar_t *msg; - - b = 0; - src->input.push_back(b); - - msg = utf2wcs(&src->input.at(0)); - - /* - Before calling parse_message, we must empty reset - everything, since the callback function could - potentially call read_message. - */ - src->input.clear(); - - if (msg) - { - this->parse_message_internal(msg, src, callbacks); - } - else - { - debug(0, _(L"Could not convert message '%s' to wide character string"), &src->input.at(0)); + line.clear(); } - free(msg); - - } - else - { - src->input.push_back(b); + // Skip over the newline (or skip past the end) + line_start = cursor + 1; } } -} - -void env_universal_t::read_message(connection_t *src, callback_data_list_t *callbacks) -{ - scoped_lock locker(lock); - return read_message_internal(src, callbacks); + + // We make no effort to handle an unterminated last line } /** Parse message msg */ -void env_universal_t::parse_message_internal(wchar_t *msg, connection_t *src, callback_data_list_t *callbacks) +void env_universal_t::parse_message_internal(wchar_t *msg, callback_data_list_t *callbacks) { ASSERT_IS_LOCKED(lock); diff --git a/env_universal_common.h b/env_universal_common.h index 083f7fbf6..a802f81f0 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -33,85 +33,6 @@ typedef enum */ #define ENV_UNIVERSAL_BUFFER_SIZE 1024 -/** - A struct representing a message to be sent between client and server -*/ -typedef struct -{ - /** - Number of queues that contain this message. Once this reaches zero, the message should be deleted - */ - int count; - - /** - Message body. - */ - std::string body; - -} message_t; - -typedef std::queue message_queue_t; - -/** - This struct represents a connection between a universal variable server/client -*/ -class connection_t -{ -private: - /* No assignment */ - connection_t &operator=(const connection_t &); - -public: - - /** - The file descriptor this socket lives on - */ - int fd; - - /** - Queue of unsent messages - */ - std::queue unsent; - - /** - Set to one when this connection should be killed - */ - bool killme; - /** - The input string. Input from the socket goes here. When a - newline is encountered, the buffer is parsed and cleared. - */ - std::vector input; - - /** - The read buffer. - */ - std::vector read_buffer; - - /** - Number of bytes that have already been consumed. - */ - size_t buffer_consumed; - - /* Constructor */ - connection_t(int input_fd); -}; - -/** - Read all available messages on this connection -*/ -void read_message(connection_t *); - -/** - Send as many messages as possible without blocking to the connection -*/ -void try_send_all(connection_t *c); - -/** - Create a messge with the specified properties -*/ -message_t *create_message(fish_message_type_t type, const wchar_t *key, const wchar_t *val); - /** Init the library */ @@ -169,18 +90,6 @@ bool env_universal_common_get_export(const wcstring &name); /** Synchronizes all changse: writes everything out, reads stuff in */ void env_universal_common_sync(); -/** - Add messages about all existing variables to the specified connection -*/ -void enqueue_all(connection_t *c); - -/** - Close and destroy the specified connection struct. This frees - allstructures allocated by the connection, such as ques of unsent - messages. -*/ -void connection_destroy(connection_t *c); - typedef std::vector callback_data_list_t; /** Class representing universal variables */ @@ -201,7 +110,7 @@ class env_universal_t void load_from_fd(int fd, callback_data_list_t *callbacks); void erase_unmodified_values(); - void parse_message_internal(wchar_t *msg, connection_t *src, callback_data_list_t *callbacks); + void parse_message_internal(wchar_t *msg, callback_data_list_t *callbacks); void set_internal(const wcstring &key, const wcstring &val, bool exportv, bool overwrite); void remove_internal(const wcstring &name, bool overwrite); @@ -215,8 +124,7 @@ class env_universal_t /* File id from which we last read */ file_id_t last_read_file; - void read_message_internal(connection_t *src, callback_data_list_t *callbacks); - void enqueue_all_internal(connection_t *c) const; + void read_message_internal(int fd, callback_data_list_t *callbacks); public: env_universal_t(const wcstring &path); @@ -237,17 +145,11 @@ public: /* Gets variable names */ wcstring_list_t get_names(bool show_exported, bool show_unexported) const; - /* Writes variables to the connection */ - void enqueue_all(connection_t *c) const; - /** Loads variables at the correct path */ bool load(); /** Reads and writes variables at the correct path. Returns true if modified variables were written. */ bool sync(callback_data_list_t *callbacks); - - /* Internal use */ - void read_message(connection_t *src, callback_data_list_t *callbacks); }; /** The "universal notifier" is an object responsible for broadcasting and receiving universal variable change notifications. These notifications do not contain the change, but merely indicate that the uvar file has changed. It is up to the uvar subsystem to re-read the file. From 735195e8ea99d747e92a71b9b0233948e5de60fa Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 13 Jun 2014 15:15:11 -0700 Subject: [PATCH 06/10] Teach env_universal_remove to directly report whether the variable was successfully removed. --- env.cpp | 2 +- env_universal.cpp | 14 +++----------- env_universal.h | 4 ++-- env_universal_common.cpp | 18 +++++++----------- env_universal_common.h | 16 +++++----------- 5 files changed, 18 insertions(+), 36 deletions(-) diff --git a/env.cpp b/env.cpp index 21e0adee1..106af3b46 100644 --- a/env.cpp +++ b/env.cpp @@ -917,7 +917,7 @@ int env_remove(const wcstring &key, int var_mode) !(var_mode & ENV_GLOBAL) && !(var_mode & ENV_LOCAL)) { - erased = ! env_universal_remove(key.c_str()); + erased = env_universal_remove(key); } react_to_variable_change(key); diff --git a/env_universal.cpp b/env_universal.cpp index eb23aff18..a9c812e6a 100644 --- a/env_universal.cpp +++ b/env_universal.cpp @@ -105,20 +105,12 @@ void env_universal_set(const wcstring &name, const wcstring &value, bool exportv env_universal_barrier(); } -int env_universal_remove(const wchar_t *name) +bool env_universal_remove(const wcstring &name) { - int res; - if (!s_env_univeral_inited) - return 1; + return false; - CHECK(name, 1); - - const wcstring name_str = name; - // TODO: shouldn't have to call get() here, should just have remove return success - res = env_universal_common_get(name_str).missing(); - env_universal_common_remove(name_str); - return res; + return env_universal_common_remove(name); } void env_universal_get_names(wcstring_list_t &lst, diff --git a/env_universal.h b/env_universal.h index 7e2e69909..5c15c86db 100644 --- a/env_universal.h +++ b/env_universal.h @@ -37,9 +37,9 @@ void env_universal_set(const wcstring &name, const wcstring &val, bool exportv); /** Erase a universal variable - \return zero if the variable existed, and non-zero if the variable did not exist + \return true if the variable existed, and false if the variable did not exist */ -int env_universal_remove(const wchar_t *name); +bool env_universal_remove(const wcstring &name); /** Read all available messages from the server. diff --git a/env_universal_common.cpp b/env_universal_common.cpp index 4df44ad83..843cfc327 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -113,9 +113,9 @@ void env_universal_common_init(void (*cb)(fish_message_type_t type, const wchar_ /** Remove variable with specified name */ -void env_universal_common_remove(const wcstring &name) +bool env_universal_common_remove(const wcstring &name) { - default_universal_vars().remove(name); + return default_universal_vars().remove(name); } /** @@ -359,25 +359,21 @@ void env_universal_t::set(const wcstring &key, const wcstring &val, bool exportv this->set_internal(key, val, exportv, true /* overwrite */); } -void env_universal_t::remove_internal(const wcstring &key, bool overwrite) +bool env_universal_t::remove_internal(const wcstring &key) { ASSERT_IS_LOCKED(lock); - if (! overwrite && this->modified.find(key) != modified.end()) - { - /* This value has been modified and we're not overwriting it. Skip it. */ - return; - } size_t erased = this->vars.erase(key); - if (erased > 0 && overwrite) + if (erased > 0) { this->modified.insert(key); } + return erased > 0; } -void env_universal_t::remove(const wcstring &key) +bool env_universal_t::remove(const wcstring &key) { scoped_lock locker(lock); - this->remove_internal(key, true); + return this->remove_internal(key); } wcstring_list_t env_universal_t::get_names(bool show_exported, bool show_unexported) const diff --git a/env_universal_common.h b/env_universal_common.h index a802f81f0..ced45994f 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -60,15 +60,9 @@ void env_universal_common_get_names(wcstring_list_t &lst, void env_universal_common_set(const wchar_t *key, const wchar_t *val, bool exportv); /** - Remove the specified variable. - - This function operate agains the local copy of all universal - variables, it does not communicate with any other process. - - Do not call this function. Create a message to do it. This function - is only to be used when fishd is dead. + Remove the specified variable. Returns true if it was removed, false if it was not found. */ -void env_universal_common_remove(const wcstring &key); +bool env_universal_common_remove(const wcstring &key); /** Get the value of the variable with the specified name @@ -113,7 +107,7 @@ class env_universal_t void parse_message_internal(wchar_t *msg, callback_data_list_t *callbacks); void set_internal(const wcstring &key, const wcstring &val, bool exportv, bool overwrite); - void remove_internal(const wcstring &name, bool overwrite); + bool remove_internal(const wcstring &name); /* Functions concerned with saving */ bool open_and_acquire_lock(const wcstring &path, int *out_fd); @@ -139,8 +133,8 @@ public: /* Sets a variable */ void set(const wcstring &key, const wcstring &val, bool exportv); - /* Removes a variable */ - void remove(const wcstring &name); + /* Removes a variable. Returns true if it was found, false if not. */ + bool remove(const wcstring &name); /* Gets variable names */ wcstring_list_t get_names(bool show_exported, bool show_unexported) const; From 84faa60c4efa47aad89c7733881b5765f42c8403 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 13 Jun 2014 15:35:37 -0700 Subject: [PATCH 07/10] Fix Linux build of env_universal_common --- env_universal_common.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/env_universal_common.cpp b/env_universal_common.cpp index 843cfc327..60411b46e 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -9,10 +9,12 @@ #include "env_universal_common.h" +#include #include -#include - +#include #include +#include +#include #ifdef HAVE_SYS_SELECT_H #include From 6277a2e4a4a9557290018d885c0b34d244a84dbc Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 15 Jun 2014 17:30:50 -0700 Subject: [PATCH 08/10] Migrate global functions out of env_universal. Have env operate directly on an env_universal_t. --- env.cpp | 141 ++++++++++++++++++++------------------- env.h | 9 +-- env_universal.cpp | 85 ----------------------- env_universal.h | 52 --------------- env_universal_common.cpp | 88 ++++++++---------------- env_universal_common.h | 79 +++++----------------- fish.cpp | 2 - fish_tests.cpp | 1 - 8 files changed, 118 insertions(+), 339 deletions(-) diff --git a/env.cpp b/env.cpp index 106af3b46..0b262f11b 100644 --- a/env.cpp +++ b/env.cpp @@ -50,6 +50,7 @@ #include "reader.h" #include "parser.h" #include "env_universal.h" +#include "env_universal_common.h" #include "input.h" #include "event.h" #include "path.h" @@ -129,6 +130,13 @@ static env_node_t *top = NULL; /** Bottom node on the function stack */ static env_node_t *global_env = NULL; +/** Universal variables global instance. Initialized in env_init. */ +static env_universal_t *s_universal_variables = NULL; + +/* Getter for universal variables */ +static env_universal_t *uvars() { + return s_universal_variables; +} /** Table for global variables @@ -331,9 +339,7 @@ static void react_to_variable_change(const wcstring &key) Universal variable callback function. This function makes sure the proper events are triggered when an event occurs. */ -static void universal_callback(fish_message_type_t type, - const wchar_t *name, - const wchar_t *val) +static void universal_callback(fish_message_type_t type, const wchar_t *name, const wchar_t *val) { const wchar_t *str = NULL; @@ -554,7 +560,9 @@ void env_init(const struct config_paths_t *paths /* or NULL */) env_set(L"version", version.c_str(), ENV_GLOBAL); env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL); - env_universal_init(universal_callback); + /* Set up universal variables. The empty string means to use the deafult path. */ + assert(s_universal_variables == NULL); + s_universal_variables = new env_universal_t(L""); /* Set up SHLVL variable @@ -586,32 +594,6 @@ void env_init(const struct config_paths_t *paths /* or NULL */) env_set(FISH_BIND_MODE_VAR, DEFAULT_BIND_MODE, ENV_GLOBAL); } -void env_destroy() -{ - env_universal_destroy(); - - while (&top->env != global) - { - env_pop(); - } - - env_read_only.clear(); - env_electric.clear(); - - var_table_t::iterator iter; - for (iter = global->begin(); iter != global->end(); ++iter) - { - const var_entry_t &entry = iter->second; - if (entry.exportv) - { - mark_changed_exported(); - break; - } - } - - delete top; -} - /** Search all visible scopes in order for the specified key. Return the first scope in which it was found. @@ -688,23 +670,32 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode) if (var_mode & ENV_UNIVERSAL) { - bool exportv; + const bool old_export = uvars() && uvars()->get_export(key); + bool new_export; if (var_mode & ENV_EXPORT) { // export - exportv = true; + new_export = true; } else if (var_mode & ENV_UNEXPORT) { // unexport - exportv = false; + new_export = false; } else { // not changing the export - exportv = env_universal_get_export(key); + new_export = old_export; + } + if (uvars()) + { + uvars()->set(key, val, new_export); + env_universal_barrier(); + if (old_export || new_export) + { + mark_changed_exported(); + } } - env_universal_set(key, val, exportv); is_universal = 1; } @@ -753,7 +744,7 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode) env_universal_barrier(); } - if (! env_universal_get(key).missing()) + if (uvars() && ! uvars()->get(key).missing()) { bool exportv; if (var_mode & ENV_EXPORT) @@ -766,10 +757,11 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode) } else { - exportv = env_universal_get_export(key); + exportv = uvars()->get_export(key); } - env_universal_set(key, val, exportv); + uvars()->set(key, val, exportv); + env_universal_barrier(); is_universal = 1; done = 1; @@ -817,7 +809,6 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode) if (has_changed_old || has_changed_new) mark_changed_exported(); } - } if (!is_universal) @@ -917,7 +908,7 @@ int env_remove(const wcstring &key, int var_mode) !(var_mode & ENV_GLOBAL) && !(var_mode & ENV_LOCAL)) { - erased = env_universal_remove(key); + erased = uvars() && uvars()->remove(key); } react_to_variable_change(key); @@ -1000,16 +991,12 @@ env_var_t env_get_string(const wcstring &key) env_universal_barrier(); } - env_var_t item = env_universal_get(key); - - if (item.missing() || (wcscmp(item.c_str(), ENV_NULL)==0)) + env_var_t env_var = uvars() ? uvars()->get(key) : env_var_t::missing_var(); + if (env_var == ENV_NULL) { - return env_var_t::missing_var(); - } - else - { - return item; + env_var = env_var_t::missing_var(); } + return env_var; } } @@ -1079,15 +1066,15 @@ bool env_exist(const wchar_t *key, int mode) env_universal_barrier(); } - if (! env_universal_get(key).missing()) + if (uvars() && ! uvars()->get(key).missing()) { if (mode & ENV_EXPORT) { - return env_universal_get_export(key) == 1; + return uvars()->get_export(key); } else if (mode & ENV_UNEXPORT) { - return env_universal_get_export(key) == 0; + return ! uvars()->get_export(key); } return 1; @@ -1254,13 +1241,9 @@ wcstring_list_t env_get_names(int flags) } - if (show_universal) + if (show_universal && uvars()) { - - wcstring_list_t uni_list; - env_universal_get_names(uni_list, - show_exported, - show_unexported); + const wcstring_list_t uni_list = uvars()->get_names(show_exported, show_unexported); names.insert(uni_list.begin(), uni_list.end()); } @@ -1340,18 +1323,20 @@ static void update_export_array_if_necessary(bool recalc) get_exported(top, vals); - wcstring_list_t uni; - env_universal_get_names(uni, 1, 0); - for (i=0; iget_names(true, false); + for (i=0; i(key, val)); + const wcstring &key = uni.at(i); + const env_var_t val = uvars()->get(key); + + if (! val.missing() && val != ENV_NULL) + { + // Note that std::map::insert does NOT overwrite a value already in the map, + // which we depend on here + vals.insert(std::pair(key, val)); + } } } @@ -1385,6 +1370,28 @@ env_vars_snapshot_t::env_vars_snapshot_t(const wchar_t * const *keys) } } + +void env_universal_barrier() +{ + ASSERT_IS_MAIN_THREAD(); + if (uvars()) + { + callback_data_list_t changes; + bool changed = uvars()->sync(&changes); + if (changed) + { + universal_notifier_t::default_notifier().post_notification(); + } + + /* Post callbacks */ + for (size_t i=0; i < changes.size(); i++) + { + const callback_data_t &data = changes.at(i); + universal_callback(data.type, data.key.c_str(), data.val.c_str()); + } + } +} + env_vars_snapshot_t::env_vars_snapshot_t() { } /* The "current" variables are not a snapshot at all, but instead trampoline to env_get_string, etc. We identify the current snapshot based on pointer values. */ diff --git a/env.h b/env.h index 7898a1253..d1a40f7de 100644 --- a/env.h +++ b/env.h @@ -68,12 +68,6 @@ struct config_paths_t */ void env_init(const struct config_paths_t *paths = NULL); -/** - Destroy environment variable data -*/ -void env_destroy(); - - /** Set the value of the environment variable whose name matches key to val. @@ -205,6 +199,9 @@ void env_push(bool new_scope); */ void env_pop(); +/** Synchronizes all universal variable changes: writes everything out, reads stuff in */ +void env_universal_barrier(); + /** Returns an array containing all exported variables in a format suitable for execv. */ const char * const * env_export_arr(bool recalc); diff --git a/env_universal.cpp b/env_universal.cpp index a9c812e6a..fa6e6b5d6 100644 --- a/env_universal.cpp +++ b/env_universal.cpp @@ -40,88 +40,3 @@ #include "env.h" -/** - Set to true after initialization has been performed -*/ -static bool s_env_univeral_inited = false; -static void (*external_callback)(fish_message_type_t type, const wchar_t *name, const wchar_t *val); - -void env_universal_barrier(); - -/** - Callback function used whenever a new fishd message is recieved -*/ -static void callback(fish_message_type_t type, const wchar_t *name, const wchar_t *val) -{ - if (external_callback) - external_callback(type, name, val); -} - -void env_universal_init(void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val)) -{ - external_callback = cb; - env_universal_common_init(&callback); - s_env_univeral_inited = true; -} - -void env_universal_destroy() -{ - s_env_univeral_inited = false; -} - - -env_var_t env_universal_get(const wcstring &name) -{ - if (!s_env_univeral_inited) - return env_var_t::missing_var(); - - return env_universal_common_get(name); -} - -bool env_universal_get_export(const wcstring &name) -{ - if (!s_env_univeral_inited) - return false; - - return env_universal_common_get_export(name); -} - -void env_universal_barrier() -{ - ASSERT_IS_MAIN_THREAD(); - UNIVERSAL_LOG("BARRIER"); - env_universal_common_sync(); -} - - -void env_universal_set(const wcstring &name, const wcstring &value, bool exportv) -{ - if (!s_env_univeral_inited) - return; - - debug(3, L"env_universal_set( \"%ls\", \"%ls\" )", name.c_str(), value.c_str()); - - env_universal_common_set(name.c_str(), value.c_str(), exportv); - env_universal_barrier(); -} - -bool env_universal_remove(const wcstring &name) -{ - if (!s_env_univeral_inited) - return false; - - return env_universal_common_remove(name); -} - -void env_universal_get_names(wcstring_list_t &lst, - bool show_exported, - bool show_unexported) -{ - if (!s_env_univeral_inited) - return; - - env_universal_common_get_names(lst, - show_exported, - show_unexported); -} - diff --git a/env_universal.h b/env_universal.h index 5c15c86db..c84ab8b6f 100644 --- a/env_universal.h +++ b/env_universal.h @@ -10,56 +10,4 @@ #include "env_universal_common.h" #include "env.h" -/** - Initialize the envuni library -*/ -void env_universal_init(void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val)); -/** - Free memory used by envuni -*/ -void env_universal_destroy(); - -/** - Get the value of a universal variable -*/ -env_var_t env_universal_get(const wcstring &name); - -/** - Get the export flag of the variable with the specified - name. Returns 0 if the variable doesn't exist. -*/ -bool env_universal_get_export(const wcstring &name); - -/** - Set the value of a universal variable -*/ -void env_universal_set(const wcstring &name, const wcstring &val, bool exportv); -/** - Erase a universal variable - - \return true if the variable existed, and false if the variable did not exist -*/ -bool env_universal_remove(const wcstring &name); - -/** - Read all available messages from the server. -*/ -int env_universal_read_all(); - -/** - Get the names of all universal variables - - \param l the list to insert the names into - \param show_exported whether exported variables should be shown - \param show_unexported whether unexported variables should be shown -*/ -void env_universal_get_names(wcstring_list_t &list, - bool show_exported, - bool show_unexported); - -/** - Synchronize with fishd -*/ -void env_universal_barrier(); - #endif diff --git a/env_universal_common.cpp b/env_universal_common.cpp index 60411b46e..ce4f4f9a6 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -34,6 +34,17 @@ #include #endif +/** + The set command +*/ +#define SET_STR L"SET" + +/** + The set_export command +*/ +#define SET_EXPORT_STR L"SET_EXPORT" + + /** Non-wide version of the set command */ @@ -76,37 +87,10 @@ static env_universal_t &default_universal_vars() return s_default_vars; } -/** - Callback function, should be called on all events -*/ -struct callback_data_t -{ - fish_message_type_t type; - wcstring key; - wcstring val; - - callback_data_t(fish_message_type_t t, const wcstring &k, const wcstring &v) : type(t), key(k), val(v) - { - } -}; - static void (*callback)(fish_message_type_t type, const wchar_t *key, const wchar_t *val); -/* Post callbacks that we have determined in this list. We do this here, instead of at the point where we determined that the values changed, because we determine those under a lock, and reentrancy would cause a deadlock */ -static void post_callbacks(const callback_data_list_t &callbacks) -{ - if (callback != NULL) - { - for (size_t i=0; i < callbacks.size(); i++) - { - const callback_data_t &data = callbacks.at(i); - callback(data.type, data.key.c_str(), data.val.c_str()); - } - } -} - void env_universal_common_init(void (*cb)(fish_message_type_t type, const wchar_t *key, const wchar_t *val)) { callback = cb; @@ -148,18 +132,6 @@ void env_universal_common_set(const wchar_t *key, const wchar_t *val, bool expor } } -void env_universal_common_sync() -{ - assert(! synchronizes_via_fishd()); - callback_data_list_t callbacks; - bool changed = default_universal_vars().sync(&callbacks); - if (changed) - { - universal_notifier_t::default_notifier().post_notification(); - } - post_callbacks(callbacks); -} - static void report_error(int err_code, const wchar_t *err_format, ...) { va_list va; @@ -279,17 +251,14 @@ static bool append_file_entry(fish_message_type_t type, const wcstring &key_in, return success; } -/** - Put exported or unexported variables in a string list -*/ -void env_universal_common_get_names(wcstring_list_t &lst, bool show_exported, bool show_unexported) +wcstring_list_t env_universal_get_names(bool show_exported, bool show_unexported) { - const wcstring_list_t names = default_universal_vars().get_names(show_exported, show_unexported); - lst.insert(lst.end(), names.begin(), names.end()); + return default_universal_vars().get_names(show_exported, show_unexported); + } -env_var_t env_universal_common_get(const wcstring &name) +env_var_t env_universal_get(const wcstring &name) { return default_universal_vars().get(name); } @@ -531,8 +500,7 @@ static env_var_t fishd_env_get(const char *key) } else { - const wcstring wkey = str2wcstring(key); - return env_universal_common_get(wkey); + return env_var_t::missing_var(); } } @@ -725,6 +693,7 @@ bool env_universal_t::open_and_acquire_lock(const wcstring &path, int *out_fd) /* Returns true if modified variables were written, false if not. (There may still be variable changes due to other processes on a false return). */ bool env_universal_t::sync(callback_data_list_t *callbacks) { + UNIVERSAL_LOG("sync"); scoped_lock locker(lock); /* Our saving strategy: @@ -844,14 +813,15 @@ void env_universal_t::read_message_internal(int fd, callback_data_list_t *callba { break; } + const size_t bufflen = (size_t)amt; // Walk over it by lines. The contents of an unterminated line will be left in 'line' for the next iteration. size_t line_start = 0; - while (line_start < sizeof buffer) + while (line_start < amt) { // Run until we hit a newline size_t cursor = line_start; - while (cursor < sizeof buffer && buffer[cursor] != '\n') + while (cursor < bufflen && buffer[cursor] != '\n') { cursor++; } @@ -860,13 +830,11 @@ void env_universal_t::read_message_internal(int fd, callback_data_list_t *callba line.append(buffer + line_start, cursor - line_start); // Process it if it's a newline (which is true if we are before the end of the buffer) - if (cursor < sizeof buffer && ! line.empty()) + if (cursor < bufflen && ! line.empty()) { if (utf8_to_wchar_string(line, &wide_line)) { - wchar_t *tmp = wcsdup(wide_line.c_str()); - this->parse_message_internal(tmp, callbacks); - free(tmp); + this->parse_message_internal(wide_line, callbacks); } line.clear(); } @@ -882,9 +850,10 @@ void env_universal_t::read_message_internal(int fd, callback_data_list_t *callba /** Parse message msg */ -void env_universal_t::parse_message_internal(wchar_t *msg, callback_data_list_t *callbacks) +void env_universal_t::parse_message_internal(const wcstring &msgstr, callback_data_list_t *callbacks) { ASSERT_IS_LOCKED(lock); + const wchar_t *msg = msgstr.c_str(); // debug( 3, L"parse_message( %ls );", msg ); @@ -893,11 +862,11 @@ void env_universal_t::parse_message_internal(wchar_t *msg, callback_data_list_t if (match(msg, SET_STR) || match(msg, SET_EXPORT_STR)) { - wchar_t *name, *tmp; + const wchar_t *name, *tmp; bool exportv = match(msg, SET_EXPORT_STR); name = msg+(exportv?wcslen(SET_EXPORT_STR):wcslen(SET_STR)); - while (wcschr(L"\t ", *name)) + while (name[0] == L'\t' || name[0] == L' ') name++; tmp = wcschr(name, L':'); @@ -1516,11 +1485,6 @@ class universal_notifier_null_t : public universal_notifier_t static universal_notifier_t::notifier_strategy_t fetch_default_strategy_from_environment() { - if (synchronizes_via_fishd()) - { - return universal_notifier_t::strategy_null; - } - universal_notifier_t::notifier_strategy_t result = universal_notifier_t::strategy_default; const struct diff --git a/env_universal_common.h b/env_universal_common.h index ced45994f..c827716e1 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -9,16 +9,6 @@ #include "util.h" #include "env.h" -/** - The set command -*/ -#define SET_STR L"SET" - -/** - The set_export command -*/ -#define SET_EXPORT_STR L"SET_EXPORT" - /** The different types of messages found in the fishd file */ @@ -33,59 +23,22 @@ typedef enum */ #define ENV_UNIVERSAL_BUFFER_SIZE 1024 -/** - Init the library -*/ -void env_universal_common_init(void (*cb)(fish_message_type_t type, const wchar_t *key, const wchar_t *val)); - -/** - Add all variable names to the specified list - - This function operate agains the local copy of all universal - variables, it does not communicate with any other process. -*/ -void env_universal_common_get_names(wcstring_list_t &lst, - bool show_exported, - bool show_unexported); - -/** - Perform the specified variable assignment. - - This function operate agains the local copy of all universal - variables, it does not communicate with any other process. - - Do not call this function. Create a message to do it. This function - is only to be used when fishd is dead. -*/ -void env_universal_common_set(const wchar_t *key, const wchar_t *val, bool exportv); - -/** - Remove the specified variable. Returns true if it was removed, false if it was not found. -*/ -bool env_universal_common_remove(const wcstring &key); - -/** - Get the value of the variable with the specified name - - This function operate agains the local copy of all universal - variables, it does not communicate with any other process. -*/ -env_var_t env_universal_common_get(const wcstring &name); - -/** - Get the export flag of the variable with the specified - name. Returns false if the variable doesn't exist. - - This function operate agains the local copy of all universal - variables, it does not communicate with any other process. -*/ -bool env_universal_common_get_export(const wcstring &name); - -/** Synchronizes all changse: writes everything out, reads stuff in */ -void env_universal_common_sync(); - typedef std::vector callback_data_list_t; +/** + Callback data, reflecting a change in universal variables +*/ +struct callback_data_t +{ + fish_message_type_t type; + wcstring key; + wcstring val; + + callback_data_t(fish_message_type_t t, const wcstring &k, const wcstring &v) : type(t), key(k), val(v) + { + } +}; + /** Class representing universal variables */ class env_universal_t { @@ -104,7 +57,7 @@ class env_universal_t void load_from_fd(int fd, callback_data_list_t *callbacks); void erase_unmodified_values(); - void parse_message_internal(wchar_t *msg, callback_data_list_t *callbacks); + void parse_message_internal(const wcstring &msg, callback_data_list_t *callbacks); void set_internal(const wcstring &key, const wcstring &val, bool exportv, bool overwrite); bool remove_internal(const wcstring &name); @@ -216,8 +169,6 @@ public: std::string get_machine_identifier(); bool get_hostname_identifier(std::string *result); -/* Temporary */ -bool synchronizes_via_fishd(); bool universal_log_enabled(); #define UNIVERSAL_LOG(x) if (universal_log_enabled()) fprintf(stderr, "UNIVERSAL LOG: %s\n", x) diff --git a/fish.cpp b/fish.cpp index 12d70092c..9f9b2ed2c 100644 --- a/fish.cpp +++ b/fish.cpp @@ -540,8 +540,6 @@ int main(int argc, char **argv) wutil_destroy(); event_destroy(); - env_destroy(); - if (g_log_forks) printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count); diff --git a/fish_tests.cpp b/fish_tests.cpp index 8fd773d52..939dafb48 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -3469,7 +3469,6 @@ int main(int argc, char **argv) // say( L"Testing performance" ); // perf_complete(); - env_destroy(); reader_destroy(); builtin_destroy(); wutil_destroy(); From 3513ce3ac0de4a4cf9ebb5d273a19c8aaaa9b942 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 16 Jun 2014 12:25:33 -0700 Subject: [PATCH 09/10] Universal variable callbacks should only be announced for changed values, not every value. Also support erase notifications. --- env.cpp | 7 +++ env_universal_common.cpp | 126 ++++++++++++++++++++++++++++----------- env_universal_common.h | 15 +++-- fish_tests.cpp | 62 ++++++++++++++++++- 4 files changed, 168 insertions(+), 42 deletions(-) diff --git a/env.cpp b/env.cpp index 0b262f11b..9f057848a 100644 --- a/env.cpp +++ b/env.cpp @@ -351,6 +351,13 @@ static void universal_callback(fish_message_type_t type, const wchar_t *name, co str=L"SET"; break; } + + case ERASE: + { + str=L"ERASE"; + break; + } + default: break; } diff --git a/env_universal_common.cpp b/env_universal_common.cpp index ce4f4f9a6..49d26cdc1 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -364,25 +364,76 @@ wcstring_list_t env_universal_t::get_names(bool show_exported, bool show_unexpor return result; } - -void env_universal_t::erase_unmodified_values() +/* Given a variable table, generate callbacks representing the difference between our vars and the new vars */ +void env_universal_t::generate_callbacks(const var_table_t &new_vars, callback_data_list_t *callbacks) const { - /* Delete all non-modified keys. */ - var_table_t::iterator iter = vars.begin(); - while (iter != vars.end()) + assert(callbacks != NULL); + + /* Construct callbacks for erased values */ + for (var_table_t::const_iterator iter = this->vars.begin(); iter != this->vars.end(); ++iter) { const wcstring &key = iter->first; - if (modified.find(key) == modified.end()) + + /* Skip modified values */ + if (this->modified.find(key) != this->modified.end()) { - // Unmodified key. Erase the old value. - vars.erase(iter++); + continue; + } + + /* If the value is not present in new_vars, it has been erased */ + if (new_vars.find(key) == new_vars.end()) + { + callbacks->push_back(callback_data_t(ERASE, key, L"")); + } + } + + /* Construct callbacks for newly inserted or changed values */ + for (var_table_t::const_iterator iter = new_vars.begin(); iter != new_vars.end(); ++iter) + { + const wcstring &key = iter->first; + + /* Skip modified values */ + if (this->modified.find(key) != this->modified.end()) + { + continue; + } + + /* See if the value has changed */ + const var_entry_t &new_entry = iter->second; + var_table_t::const_iterator existing = this->vars.find(key); + if (existing == this->vars.end() || existing->second.exportv != new_entry.exportv || existing->second.val != new_entry.val) + { + /* Value has changed */ + callbacks->push_back(callback_data_t(new_entry.exportv ? SET_EXPORT : SET, key, new_entry.val)); + } + } +} + + +void env_universal_t::acquire_variables(var_table_t *vars_to_acquire) +{ + /* Copy modified values from existing vars to vars_to_acquire */ + for (std::set::iterator iter = this->modified.begin(); iter != this->modified.end(); ++iter) + { + const wcstring &key = *iter; + var_table_t::iterator src_iter = this->vars.find(key); + if (src_iter == this->vars.end()) + { + /* The value has been deleted. */ + vars_to_acquire->erase(key); } else { - // Modified key, retain the value. - ++iter; + /* The value has been modified. Copy it over. Note we can destructively modify the source entry in vars since we are about to get rid of this->vars entirely. */ + var_entry_t &src = src_iter->second; + var_entry_t &dst = (*vars_to_acquire)[key]; + dst.val.swap(src.val); + dst.exportv = src.exportv; } } + + /* We have constructed all the callbacks and updated vars_to_acquire. Acquire it! */ + this->vars.swap(*vars_to_acquire); } void env_universal_t::load_from_fd(int fd, callback_data_list_t *callbacks) @@ -397,10 +448,18 @@ void env_universal_t::load_from_fd(int fd, callback_data_list_t *callbacks) } else { - /* Unmodified values are sourced from the file. Since we are about to read a different file, erase them */ - this->erase_unmodified_values(); - /* Read from the file. */ - this->read_message_internal(fd, callbacks); + /* Read a variables table from the file. */ + var_table_t new_vars = this->read_message_internal(fd); + + /* Announce changes */ + if (callbacks != NULL) + { + this->generate_callbacks(new_vars, callbacks); + } + + /* Acquire the new variables */ + this->acquire_variables(&new_vars); + last_read_file = current_file; } } @@ -416,7 +475,6 @@ bool env_universal_t::load_from_path(const wcstring &path, callback_data_list_t return true; } - /* OK to not use CLO_EXEC here because fishd is single threaded */ bool result = false; int fd = wopen_cloexec(path, O_RDONLY); if (fd >= 0) @@ -721,13 +779,6 @@ bool env_universal_t::sync(callback_data_list_t *callbacks) return false; } -#if 0 - for (std::set::iterator iter = modified.begin(); iter != modified.end(); ++iter) - { - fprintf(stderr, "Modified %ls\n", iter->c_str()); - } -#endif - const wcstring directory = wdirname(vars_path); bool success = true; int vars_fd = -1; @@ -797,9 +848,12 @@ bool env_universal_t::sync(callback_data_list_t *callbacks) return success; } -void env_universal_t::read_message_internal(int fd, callback_data_list_t *callbacks) +var_table_t env_universal_t::read_message_internal(int fd) { - ASSERT_IS_LOCKED(lock); + var_table_t result; + + // Temp value used to avoid repeated allocations + wcstring storage; // The line we construct (and then parse) std::string line; @@ -834,7 +888,7 @@ void env_universal_t::read_message_internal(int fd, callback_data_list_t *callba { if (utf8_to_wchar_string(line, &wide_line)) { - this->parse_message_internal(wide_line, callbacks); + env_universal_t::parse_message_internal(wide_line, &result, &storage); } line.clear(); } @@ -845,14 +899,14 @@ void env_universal_t::read_message_internal(int fd, callback_data_list_t *callba } // We make no effort to handle an unterminated last line + return result; } /** Parse message msg */ -void env_universal_t::parse_message_internal(const wcstring &msgstr, callback_data_list_t *callbacks) +void env_universal_t::parse_message_internal(const wcstring &msgstr, var_table_t *vars, wcstring *storage) { - ASSERT_IS_LOCKED(lock); const wchar_t *msg = msgstr.c_str(); // debug( 3, L"parse_message( %ls );", msg ); @@ -860,10 +914,12 @@ void env_universal_t::parse_message_internal(const wcstring &msgstr, callback_da if (msg[0] == L'#') return; - if (match(msg, SET_STR) || match(msg, SET_EXPORT_STR)) + bool is_set_export = match(msg, SET_EXPORT_STR); + bool is_set = ! is_set_export && match(msg, SET_STR); + if (is_set || is_set_export) { const wchar_t *name, *tmp; - bool exportv = match(msg, SET_EXPORT_STR); + const bool exportv = is_set_export; name = msg+(exportv?wcslen(SET_EXPORT_STR):wcslen(SET_STR)); while (name[0] == L'\t' || name[0] == L' ') @@ -872,16 +928,16 @@ void env_universal_t::parse_message_internal(const wcstring &msgstr, callback_da tmp = wcschr(name, L':'); if (tmp) { - const wcstring key(name, tmp - name); + /* Use 'storage' to hold our key to avoid allocations */ + storage->assign(name, tmp - name); + const wcstring &key = *storage; wcstring val; if (unescape_string(tmp + 1, &val, 0)) { - this->set_internal(key, val, exportv, false); - if (callbacks != NULL) - { - callbacks->push_back(callback_data_t(exportv ? SET_EXPORT:SET, key, val)); - } + var_entry_t &entry = (*vars)[key]; + entry.exportv = exportv; + entry.val.swap(val); //acquire the value } } else diff --git a/env_universal_common.h b/env_universal_common.h index c827716e1..207e4dba9 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -15,7 +15,8 @@ typedef enum { SET, - SET_EXPORT + SET_EXPORT, + ERASE } fish_message_type_t; /** @@ -55,9 +56,6 @@ class env_universal_t bool tried_renaming; bool load_from_path(const wcstring &path, callback_data_list_t *callbacks); void load_from_fd(int fd, callback_data_list_t *callbacks); - void erase_unmodified_values(); - - void parse_message_internal(const wcstring &msg, callback_data_list_t *callbacks); void set_internal(const wcstring &key, const wcstring &val, bool exportv, bool overwrite); bool remove_internal(const wcstring &name); @@ -71,7 +69,14 @@ class env_universal_t /* File id from which we last read */ file_id_t last_read_file; - void read_message_internal(int fd, callback_data_list_t *callbacks); + /* Given a variable table, generate callbacks representing the difference between our vars and the new vars */ + void generate_callbacks(const var_table_t &new_vars, callback_data_list_t *callbacks) const; + + /* Given a variable table, copy unmodified values into self. May destructively modified vars_to_acquire. */ + void acquire_variables(var_table_t *vars_to_acquire); + + static void parse_message_internal(const wcstring &msg, var_table_t *vars, wcstring *storage); + static var_table_t read_message_internal(int fd); public: env_universal_t(const wcstring &path); diff --git a/fish_tests.cpp b/fish_tests.cpp index 939dafb48..b29f7124a 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -2255,10 +2255,67 @@ static void test_universal() } } - if (system("rm -Rf /tmp/fish_uvars_test")) err(L"rrm failed"); + if (system("rm -Rf /tmp/fish_uvars_test")) err(L"rm failed"); putc('\n', stderr); } +static bool callback_data_less_than(const callback_data_t &a, const callback_data_t &b) { + return a.key < b.key; +} + +static void test_universal_callbacks() +{ + say(L"Testing universal callbacks"); + if (system("mkdir -p /tmp/fish_uvars_test/")) err(L"mkdir failed"); + env_universal_t uvars1(UVARS_TEST_PATH); + env_universal_t uvars2(UVARS_TEST_PATH); + + /* Put some variables into both */ + uvars1.set(L"alpha", L"1", false); + uvars1.set(L"beta", L"1", false); + uvars1.set(L"delta", L"1", false); + uvars1.set(L"epsilon", L"1", false); + uvars1.set(L"lambda", L"1", false); + uvars1.set(L"kappa", L"1", false); + uvars1.set(L"omicron", L"1", false); + + uvars1.sync(NULL); + uvars2.sync(NULL); + + /* Change uvars1 */ + uvars1.set(L"alpha", L"2", false); //changes value + uvars1.set(L"beta", L"1", true); //changes export + uvars1.remove(L"delta"); //erases value + uvars1.set(L"epsilon", L"1", false); //changes nothing + uvars1.sync(NULL); + + /* Change uvars2. It should treat its value as correct and ignore changes from uvars1. */ + uvars2.set(L"lambda", L"1", false); //same value + uvars2.set(L"kappa", L"2", false); //different value + + /* Now see what uvars2 sees */ + callback_data_list_t callbacks; + uvars2.sync(&callbacks); + + /* Sort them to get them in a predictable order */ + std::sort(callbacks.begin(), callbacks.end(), callback_data_less_than); + + /* Should see exactly two changes */ + do_test(callbacks.size() == 3); + do_test(callbacks.at(0).type == SET); + do_test(callbacks.at(0).key == L"alpha"); + do_test(callbacks.at(0).val == L"2"); + do_test(callbacks.at(1).type == SET_EXPORT); + do_test(callbacks.at(1).key == L"beta"); + do_test(callbacks.at(1).val == L"1"); + do_test(callbacks.at(2).type == ERASE); + do_test(callbacks.at(2).key == L"delta"); + do_test(callbacks.at(2).val == L""); + + + if (system("rm -Rf /tmp/fish_uvars_test")) err(L"rm failed"); +} + bool poll_notifier(universal_notifier_t *note) { bool result = false; @@ -3449,7 +3506,8 @@ int main(int argc, char **argv) if (should_test_function("complete")) test_complete(); if (should_test_function("input")) test_input(); if (should_test_function("universal")) test_universal(); - if (should_test_function("universal_notifiers")) test_universal_notifiers(); + if (should_test_function("universal")) test_universal_callbacks(); + if (should_test_function("notifiers")) test_universal_notifiers(); if (should_test_function("completion_insertions")) test_completion_insertions(); if (should_test_function("autosuggestion_combining")) test_autosuggestion_combining(); if (should_test_function("autosuggest_suggest_special")) test_autosuggest_suggest_special(); From ee8e9c0291b2c7525a8470765bd88166b25e9b6b Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 18 Jun 2014 10:14:35 -0700 Subject: [PATCH 10/10] Remove env_universal.h and env_universal.cpp from project --- Makefile.in | 61 ++++++++++++++++------------------ env.cpp | 1 - env_universal.cpp | 42 ----------------------- env_universal.h | 13 -------- fish.xcodeproj/project.pbxproj | 8 ----- input_common.cpp | 7 ++-- parser.cpp | 1 - 7 files changed, 33 insertions(+), 100 deletions(-) delete mode 100644 env_universal.cpp delete mode 100644 env_universal.h diff --git a/Makefile.in b/Makefile.in index 3d68a01db..d808471ae 100644 --- a/Makefile.in +++ b/Makefile.in @@ -86,7 +86,7 @@ COMMON_FILES := util.cpp fallback.cpp FISH_OBJS := function.o builtin.o complete.o env.o exec.o expand.o \ highlight.o history.o kill.o parser.o proc.o reader.o sanity.o \ tokenizer.o wildcard.o wgetopt.o wutil.o input.o output.o intern.o \ - env_universal.o env_universal_common.o input_common.o event.o \ + env_universal_common.o input_common.o event.o \ signal.o io.o parse_util.o common.o screen.o path.o autoload.o \ parser_keywords.o iothread.o color.o postfork.o \ builtin_test.o parse_tree.o parse_productions.o parse_execution.o \ @@ -708,8 +708,8 @@ fish_indent: $(FISH_INDENT_OBJS) # Neat little program to show output from terminal # -key_reader: key_reader.o input_common.o common.o env_universal.o env_universal_common.o wutil.o iothread.o utf8.o - $(CXX) $(CXXFLAGS) $(LDFLAGS_FISH) key_reader.o input_common.o common.o env_universal.o env_universal_common.o wutil.o iothread.o utf8.o $(LIBS) -o $@ +key_reader: key_reader.o input_common.o common.o env_universal_common.o wutil.o iothread.o utf8.o + $(CXX) $(CXXFLAGS) $(LDFLAGS_FISH) key_reader.o input_common.o common.o env_universal_common.o wutil.o iothread.o utf8.o $(LIBS) -o $@ # @@ -760,6 +760,14 @@ clean: autoload.o: config.h autoload.h common.h util.h lru.h wutil.h signal.h env.h autoload.o: exec.h proc.h io.h parse_tree.h tokenizer.h parse_constants.h +builtin.o: config.h signal.h fallback.h util.h wutil.h common.h builtin.h +builtin.o: io.h function.h event.h complete.h proc.h parse_tree.h tokenizer.h +builtin.o: parse_constants.h parser.h reader.h highlight.h env.h color.h +builtin.o: wgetopt.h sanity.h wildcard.h expand.h input_common.h input.h +builtin.o: intern.h exec.h parse_util.h autoload.h lru.h parser_keywords.h +builtin.o: path.h history.h builtin_set.cpp builtin_commandline.cpp +builtin.o: builtin_complete.cpp builtin_ulimit.cpp builtin_jobs.cpp +builtin.o: builtin_set_color.cpp output.h screen.h builtin_printf.cpp builtin_commandline.o: config.h signal.h fallback.h util.h wutil.h common.h builtin_commandline.o: builtin.h io.h wgetopt.h reader.h complete.h builtin_commandline.o: highlight.h env.h color.h proc.h parse_tree.h @@ -770,23 +778,15 @@ builtin_complete.o: config.h signal.h fallback.h util.h wutil.h common.h builtin_complete.o: builtin.h io.h complete.h wgetopt.h parser.h proc.h builtin_complete.o: parse_tree.h tokenizer.h parse_constants.h event.h builtin_complete.o: function.h reader.h highlight.h env.h color.h -builtin.o: config.h signal.h fallback.h util.h wutil.h common.h builtin.h -builtin.o: io.h function.h event.h complete.h proc.h parse_tree.h tokenizer.h -builtin.o: parse_constants.h parser.h reader.h highlight.h env.h color.h -builtin.o: wgetopt.h sanity.h wildcard.h expand.h input_common.h input.h -builtin.o: intern.h exec.h parse_util.h autoload.h lru.h parser_keywords.h -builtin.o: path.h history.h builtin_set.cpp builtin_commandline.cpp -builtin.o: builtin_complete.cpp builtin_ulimit.cpp builtin_jobs.cpp -builtin.o: builtin_set_color.cpp output.h screen.h builtin_printf.cpp builtin_jobs.o: config.h fallback.h signal.h util.h wutil.h common.h builtin_jobs.o: builtin.h io.h proc.h parse_tree.h tokenizer.h builtin_jobs.o: parse_constants.h parser.h event.h function.h wgetopt.h builtin_printf.o: common.h util.h -builtin_set_color.o: config.h builtin.h util.h io.h common.h color.h output.h -builtin_set_color.o: screen.h highlight.h env.h builtin_set.o: config.h signal.h fallback.h util.h wutil.h common.h builtin.h builtin_set.o: io.h env.h expand.h parse_constants.h wgetopt.h proc.h builtin_set.o: parse_tree.h tokenizer.h parser.h event.h function.h +builtin_set_color.o: config.h builtin.h util.h io.h common.h color.h output.h +builtin_set_color.o: screen.h highlight.h env.h builtin_test.o: config.h common.h util.h builtin.h io.h wutil.h proc.h builtin_test.o: signal.h parse_tree.h tokenizer.h parse_constants.h builtin_ulimit.o: config.h fallback.h signal.h util.h builtin.h io.h common.h @@ -803,12 +803,11 @@ complete.o: parse_util.h autoload.h lru.h parser_keywords.h path.h iothread.h env.o: config.h signal.h fallback.h util.h wutil.h common.h proc.h io.h env.o: parse_tree.h tokenizer.h parse_constants.h env.h sanity.h expand.h env.o: history.h reader.h complete.h highlight.h color.h parser.h event.h -env.o: function.h env_universal.h env_universal_common.h input.h -env.o: input_common.h path.h fish_version.h -env_universal_common.o: config.h signal.h fallback.h util.h common.h wutil.h -env_universal_common.o: utf8.h env_universal_common.h env.h -env_universal.o: config.h signal.h fallback.h util.h common.h wutil.h -env_universal.o: env_universal_common.h env.h env_universal.h +env.o: function.h env_universal_common.h input.h input_common.h path.h +env.o: fish_version.h +env_universal_common.o: config.h env_universal_common.h wutil.h common.h +env_universal_common.o: util.h env.h fallback.h signal.h utf8.h path.h +env_universal_common.o: iothread.h event.o: config.h signal.h fallback.h util.h wutil.h common.h function.h event.o: event.h input_common.h proc.h io.h parse_tree.h tokenizer.h event.o: parse_constants.h parser.h @@ -833,7 +832,7 @@ fish_tests.o: parse_tree.h tokenizer.h parse_constants.h reader.h complete.h fish_tests.o: highlight.h env.h color.h builtin.h function.h event.h fish_tests.o: autoload.h lru.h wutil.h expand.h parser.h output.h screen.h fish_tests.o: exec.h path.h history.h iothread.h postfork.h parse_util.h -fish_tests.o: pager.h input.h input_common.h utf8.h +fish_tests.o: pager.h input.h input_common.h utf8.h env_universal_common.h fish_version.o: fish_version.h function.o: config.h signal.h wutil.h common.h util.h fallback.h function.h function.o: event.h proc.h io.h parse_tree.h tokenizer.h parse_constants.h @@ -848,13 +847,12 @@ history.o: config.h fallback.h signal.h util.h sanity.h tokenizer.h common.h history.o: reader.h io.h complete.h highlight.h env.h color.h parse_tree.h history.o: parse_constants.h wutil.h history.h intern.h path.h autoload.h history.o: lru.h iothread.h -input_common.o: config.h fallback.h signal.h util.h common.h wutil.h -input_common.o: input_common.h env_universal.h env_universal_common.h env.h -input_common.o: iothread.h input.o: config.h signal.h fallback.h util.h wutil.h common.h reader.h io.h input.o: complete.h highlight.h env.h color.h proc.h parse_tree.h tokenizer.h input.o: parse_constants.h sanity.h input_common.h input.h parser.h event.h input.o: function.h expand.h output.h screen.h intern.h +input_common.o: config.h fallback.h signal.h util.h common.h wutil.h +input_common.o: input_common.h iothread.h intern.o: config.h fallback.h signal.h util.h wutil.h common.h intern.h io.o: config.h fallback.h signal.h util.h wutil.h common.h exec.h proc.h io.h io.o: parse_tree.h tokenizer.h parse_constants.h @@ -876,14 +874,6 @@ parse_execution.o: expand.h builtin.h parser.h event.h function.h reader.h parse_execution.o: highlight.h env.h color.h wutil.h exec.h path.h parse_productions.o: parse_productions.h parse_tree.h config.h util.h parse_productions.o: common.h tokenizer.h parse_constants.h -parser.o: config.h signal.h fallback.h util.h common.h wutil.h proc.h io.h -parser.o: parse_tree.h tokenizer.h parse_constants.h parser.h event.h -parser.o: function.h parser_keywords.h exec.h wildcard.h expand.h complete.h -parser.o: builtin.h env.h reader.h highlight.h color.h sanity.h -parser.o: env_universal.h env_universal_common.h intern.h parse_util.h -parser.o: autoload.h lru.h path.h parse_execution.h -parser_keywords.o: config.h fallback.h signal.h common.h util.h -parser_keywords.o: parser_keywords.h parse_tree.o: parse_productions.h parse_tree.h config.h util.h common.h parse_tree.o: tokenizer.h parse_constants.h fallback.h signal.h wutil.h parse_tree.o: proc.h io.h @@ -891,6 +881,13 @@ parse_util.o: config.h fallback.h signal.h util.h wutil.h common.h parse_util.o: tokenizer.h parse_util.h autoload.h lru.h parse_tree.h parse_util.o: parse_constants.h expand.h intern.h exec.h proc.h io.h env.h parse_util.o: wildcard.h complete.h parser.h event.h function.h builtin.h +parser.o: config.h signal.h fallback.h util.h common.h wutil.h proc.h io.h +parser.o: parse_tree.h tokenizer.h parse_constants.h parser.h event.h +parser.o: function.h parser_keywords.h exec.h wildcard.h expand.h complete.h +parser.o: builtin.h env.h reader.h highlight.h color.h sanity.h intern.h +parser.o: parse_util.h autoload.h lru.h path.h parse_execution.h +parser_keywords.o: config.h fallback.h signal.h common.h util.h +parser_keywords.o: parser_keywords.h path.o: config.h fallback.h signal.h util.h common.h env.h wutil.h path.h path.o: expand.h parse_constants.h postfork.o: signal.h postfork.h config.h common.h util.h proc.h io.h @@ -923,9 +920,9 @@ wildcard.o: config.h fallback.h signal.h util.h wutil.h common.h complete.h wildcard.o: wildcard.h expand.h parse_constants.h reader.h io.h highlight.h wildcard.o: env.h color.h exec.h proc.h parse_tree.h tokenizer.h wutil.o: config.h fallback.h signal.h util.h common.h wutil.h -xdgmimealias.o: xdgmimealias.h xdgmime.h xdgmimeint.h xdgmime.o: xdgmime.h xdgmimeint.h xdgmimeglob.h xdgmimemagic.h xdgmimealias.h xdgmime.o: xdgmimeparent.h +xdgmimealias.o: xdgmimealias.h xdgmime.h xdgmimeint.h xdgmimeglob.o: xdgmimeglob.h xdgmime.h xdgmimeint.h xdgmimeint.o: xdgmimeint.h xdgmime.h xdgmimemagic.o: xdgmimemagic.h xdgmime.h xdgmimeint.h diff --git a/env.cpp b/env.cpp index 9f057848a..43a342887 100644 --- a/env.cpp +++ b/env.cpp @@ -49,7 +49,6 @@ #include "history.h" #include "reader.h" #include "parser.h" -#include "env_universal.h" #include "env_universal_common.h" #include "input.h" #include "event.h" diff --git a/env_universal.cpp b/env_universal.cpp deleted file mode 100644 index fa6e6b5d6..000000000 --- a/env_universal.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "config.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if HAVE_NCURSES_H -#include -#else -#include -#endif - -#if HAVE_TERM_H -#include -#elif HAVE_NCURSES_TERM_H -#include -#endif - -#ifdef HAVE_SYS_SELECT_H -#include -#endif - -#include - -#include "fallback.h" -#include "util.h" - -#include "common.h" -#include "wutil.h" -#include "env_universal_common.h" -#include "env_universal.h" -#include "env.h" - - diff --git a/env_universal.h b/env_universal.h deleted file mode 100644 index c84ab8b6f..000000000 --- a/env_universal.h +++ /dev/null @@ -1,13 +0,0 @@ -/** \file env_universal.h - Universal variable client library. -*/ - -#ifndef ENV_UNIVERSAL_H -#define ENV_UNIVERSAL_H - -#include - -#include "env_universal_common.h" -#include "env.h" - -#endif diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj index 32ba442b3..0ed1dcd7e 100644 --- a/fish.xcodeproj/project.pbxproj +++ b/fish.xcodeproj/project.pbxproj @@ -97,7 +97,6 @@ D08A32A917B446A300F3A533 /* color.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0B6B0FE14E88BA400AD6C10 /* color.cpp */; }; D08A32AA17B446A300F3A533 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853613B3ACEE0099B651 /* common.cpp */; }; D08A32AB17B446A300F3A533 /* env_universal_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */; }; - D08A32AC17B446A300F3A533 /* env_universal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853913B3ACEE0099B651 /* env_universal.cpp */; }; D08A32AD17B446A300F3A533 /* event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853B13B3ACEE0099B651 /* event.cpp */; }; D08A32AE17B446A300F3A533 /* input_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854913B3ACEE0099B651 /* input_common.cpp */; }; D08A32AF17B446A300F3A533 /* intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854B13B3ACEE0099B651 /* intern.cpp */; }; @@ -136,7 +135,6 @@ D0D02A7715983875008E62BD /* input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854A13B3ACEE0099B651 /* input.cpp */; }; D0D02A781598387E008E62BD /* output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855113B3ACEE0099B651 /* output.cpp */; }; D0D02A7915983888008E62BD /* intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854B13B3ACEE0099B651 /* intern.cpp */; }; - D0D02A7A15983916008E62BD /* env_universal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853913B3ACEE0099B651 /* env_universal.cpp */; }; D0D02A7B15983928008E62BD /* env_universal_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */; }; D0D02A7C159839D5008E62BD /* autoload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C6FCC914CFA4B0004CE8AD /* autoload.cpp */; }; D0D02A7D159839D5008E62BD /* builtin_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0F3373A1506DE3C00ECEFC0 /* builtin_test.cpp */; }; @@ -350,7 +348,6 @@ D0A0850513B3ACEE0099B651 /* complete.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = complete.h; sourceTree = ""; }; D0A0850613B3ACEE0099B651 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; D0A0850713B3ACEE0099B651 /* env_universal_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = env_universal_common.h; sourceTree = ""; }; - D0A0850813B3ACEE0099B651 /* env_universal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = env_universal.h; sourceTree = ""; }; D0A0850913B3ACEE0099B651 /* env.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = env.h; sourceTree = ""; }; D0A0850A13B3ACEE0099B651 /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = ""; }; D0A0850B13B3ACEE0099B651 /* exec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exec.h; sourceTree = ""; }; @@ -397,7 +394,6 @@ D0A0853613B3ACEE0099B651 /* common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = common.cpp; sourceTree = ""; }; D0A0853713B3ACEE0099B651 /* complete.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = complete.cpp; sourceTree = ""; }; D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env_universal_common.cpp; sourceTree = ""; }; - D0A0853913B3ACEE0099B651 /* env_universal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env_universal.cpp; sourceTree = ""; }; D0A0853A13B3ACEE0099B651 /* env.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env.cpp; sourceTree = ""; }; D0A0853B13B3ACEE0099B651 /* event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = event.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; D0A0853C13B3ACEE0099B651 /* exec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exec.cpp; sourceTree = ""; }; @@ -575,8 +571,6 @@ D0A0850613B3ACEE0099B651 /* config.h */, D0A0850713B3ACEE0099B651 /* env_universal_common.h */, D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */, - D0A0850813B3ACEE0099B651 /* env_universal.h */, - D0A0853913B3ACEE0099B651 /* env_universal.cpp */, D0A0850913B3ACEE0099B651 /* env.h */, D0A0853A13B3ACEE0099B651 /* env.cpp */, D0A0850A13B3ACEE0099B651 /* event.h */, @@ -1025,7 +1019,6 @@ D08A32A917B446A300F3A533 /* color.cpp in Sources */, D08A32AA17B446A300F3A533 /* common.cpp in Sources */, D08A32AB17B446A300F3A533 /* env_universal_common.cpp in Sources */, - D08A32AC17B446A300F3A533 /* env_universal.cpp in Sources */, D08A32AD17B446A300F3A533 /* event.cpp in Sources */, D08A32AE17B446A300F3A533 /* input_common.cpp in Sources */, D08A32AF17B446A300F3A533 /* intern.cpp in Sources */, @@ -1115,7 +1108,6 @@ D0D02A7715983875008E62BD /* input.cpp in Sources */, D0D02A781598387E008E62BD /* output.cpp in Sources */, D0D02A7915983888008E62BD /* intern.cpp in Sources */, - D0D02A7A15983916008E62BD /* env_universal.cpp in Sources */, D0D02A7B15983928008E62BD /* env_universal_common.cpp in Sources */, D032388B1849D1980032CF2C /* pager.cpp in Sources */, D0D02A89159839DF008E62BD /* fish.cpp in Sources */, diff --git a/input_common.cpp b/input_common.cpp index e63931243..513fd8e36 100644 --- a/input_common.cpp +++ b/input_common.cpp @@ -16,6 +16,7 @@ Implementation file for the low level input library #include #include #include +#include #ifdef HAVE_SYS_SELECT_H #include #endif @@ -26,7 +27,7 @@ Implementation file for the low level input library #include "common.h" #include "wutil.h" #include "input_common.h" -#include "env_universal.h" +#include "env_universal_common.h" #include "iothread.h" /** @@ -37,9 +38,9 @@ Implementation file for the low level input library #define WAIT_ON_ESCAPE 10 /** Characters that have been read and returned by the sequence matching code */ -static std::stack > lookahead_list; +static std::stack > lookahead_list; -/* Queue of pairs of (function pointer, argument) to be invoked */ +/* Queue of pairs of (function pointer, argument) to be invoked. Expected to be mostly empty. */ typedef std::pair callback_info_t; typedef std::queue > callback_queue_t; static callback_queue_t callback_queue; diff --git a/parser.cpp b/parser.cpp index 773cde6b7..3740f1fbe 100644 --- a/parser.cpp +++ b/parser.cpp @@ -37,7 +37,6 @@ The fish parser. Contains functions for parsing and evaluating code. #include "expand.h" #include "reader.h" #include "sanity.h" -#include "env_universal.h" #include "event.h" #include "intern.h" #include "parse_util.h"