diff options
Diffstat (limited to 'basic_cmds')
-rw-r--r-- | basic_cmds/basic_cmds.xcodeproj/project.pbxproj | 546 | ||||
-rw-r--r-- | basic_cmds/mesg/mesg.1 | 112 | ||||
-rw-r--r-- | basic_cmds/mesg/mesg.c | 116 | ||||
-rw-r--r-- | basic_cmds/uudecode/base64.c | 317 | ||||
-rw-r--r-- | basic_cmds/uudecode/uudecode.1 | 1 | ||||
-rw-r--r-- | basic_cmds/uudecode/uudecode.c | 504 | ||||
-rw-r--r-- | basic_cmds/uuencode/base64.c | 317 | ||||
-rw-r--r-- | basic_cmds/uuencode/uuencode.1 | 192 | ||||
-rw-r--r-- | basic_cmds/uuencode/uuencode.5 | 100 | ||||
-rw-r--r-- | basic_cmds/uuencode/uuencode.c | 226 | ||||
-rw-r--r-- | basic_cmds/write/write.1 | 106 | ||||
-rw-r--r-- | basic_cmds/write/write.c | 332 |
12 files changed, 2869 insertions, 0 deletions
diff --git a/basic_cmds/basic_cmds.xcodeproj/project.pbxproj b/basic_cmds/basic_cmds.xcodeproj/project.pbxproj new file mode 100644 index 0000000..093906e --- /dev/null +++ b/basic_cmds/basic_cmds.xcodeproj/project.pbxproj @@ -0,0 +1,546 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 721D59C60FC5FA20009D810A /* Build All */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 721D59C90FC5FA4E009D810A /* Build configuration list for PBXAggregateTarget "Build All" */; + buildPhases = ( + ); + dependencies = ( + 721D59D50FC5FB18009D810A /* PBXTargetDependency */, + 721D59D30FC5FB18009D810A /* PBXTargetDependency */, + 721D59D10FC5FB18009D810A /* PBXTargetDependency */, + 721D59CF0FC5FB18009D810A /* PBXTargetDependency */, + ); + name = "Build All"; + productName = "Build All"; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 721D59850FC5F414009D810A /* mesg.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D59840FC5F414009D810A /* mesg.c */; }; + 721D598D0FC5F49F009D810A /* mesg.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D59830FC5F414009D810A /* mesg.1 */; }; + 721D59920FC5F53E009D810A /* write.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D59900FC5F533009D810A /* write.c */; }; + 721D59940FC5F566009D810A /* write.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D598F0FC5F533009D810A /* write.1 */; }; + 721D599C0FC5F593009D810A /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D599A0FC5F593009D810A /* base64.c */; }; + 721D599D0FC5F593009D810A /* uudecode.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D599B0FC5F593009D810A /* uudecode.c */; }; + 721D59A10FC5F5C3009D810A /* uudecode.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D599F0FC5F5A8009D810A /* uudecode.1 */; }; + 721D59B30FC5F6D9009D810A /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D59AF0FC5F6D9009D810A /* base64.c */; }; + 721D59B40FC5F6D9009D810A /* uuencode.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D59B20FC5F6D9009D810A /* uuencode.c */; }; + 721D59B60FC5F6F4009D810A /* uuencode.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D59B00FC5F6D9009D810A /* uuencode.1 */; }; + 721D59B70FC5F6F4009D810A /* uuencode.5 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D59B10FC5F6D9009D810A /* uuencode.5 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 721D59CE0FC5FB18009D810A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 721D59560FC5F325009D810A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 721D597C0FC5F36F009D810A; + remoteInfo = write; + }; + 721D59D00FC5FB18009D810A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 721D59560FC5F325009D810A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 721D59730FC5F347009D810A; + remoteInfo = mesg; + }; + 721D59D20FC5FB18009D810A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 721D59560FC5F325009D810A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 721D596C0FC5F33E009D810A; + remoteInfo = uudecode; + }; + 721D59D40FC5FB18009D810A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 721D59560FC5F325009D810A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 721D59630FC5F336009D810A; + remoteInfo = uuencode; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 721D598C0FC5F43F009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + 721D598D0FC5F49F009D810A /* mesg.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 721D59980FC5F56F009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + 721D59940FC5F566009D810A /* write.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 721D59A40FC5F5CA009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + 721D59A10FC5F5C3009D810A /* uudecode.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 721D59BC0FC5F70F009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + 721D59B60FC5F6F4009D810A /* uuencode.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 721D59CD0FC5FA9D009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man5; + dstSubfolderSpec = 0; + files = ( + 721D59B70FC5F6F4009D810A /* uuencode.5 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 721D59640FC5F336009D810A /* uuencode */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = uuencode; sourceTree = BUILT_PRODUCTS_DIR; }; + 721D596D0FC5F33E009D810A /* uudecode */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = uudecode; sourceTree = BUILT_PRODUCTS_DIR; }; + 721D59740FC5F347009D810A /* mesg */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mesg; sourceTree = BUILT_PRODUCTS_DIR; }; + 721D597D0FC5F370009D810A /* write */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = write; sourceTree = BUILT_PRODUCTS_DIR; }; + 721D59830FC5F414009D810A /* mesg.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = mesg.1; sourceTree = "<group>"; }; + 721D59840FC5F414009D810A /* mesg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mesg.c; sourceTree = "<group>"; }; + 721D598F0FC5F533009D810A /* write.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = write.1; sourceTree = "<group>"; }; + 721D59900FC5F533009D810A /* write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = write.c; sourceTree = "<group>"; }; + 721D599A0FC5F593009D810A /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = "<group>"; }; + 721D599B0FC5F593009D810A /* uudecode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uudecode.c; sourceTree = "<group>"; }; + 721D599F0FC5F5A8009D810A /* uudecode.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = uudecode.1; sourceTree = "<group>"; }; + 721D59AF0FC5F6D9009D810A /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = "<group>"; }; + 721D59B00FC5F6D9009D810A /* uuencode.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = uuencode.1; sourceTree = "<group>"; }; + 721D59B10FC5F6D9009D810A /* uuencode.5 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = uuencode.5; sourceTree = "<group>"; }; + 721D59B20FC5F6D9009D810A /* uuencode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uuencode.c; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 721D59620FC5F336009D810A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D596B0FC5F33E009D810A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D59720FC5F347009D810A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D597B0FC5F36F009D810A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 721D59540FC5F325009D810A = { + isa = PBXGroup; + children = ( + 721D59A70FC5F613009D810A /* uuencode */, + 721D59970FC5F56F009D810A /* uudecode */, + 721D59810FC5F38E009D810A /* mesg */, + 721D598E0FC5F4AC009D810A /* write */, + 721D59650FC5F336009D810A /* Products */, + ); + sourceTree = "<group>"; + }; + 721D59650FC5F336009D810A /* Products */ = { + isa = PBXGroup; + children = ( + 721D59640FC5F336009D810A /* uuencode */, + 721D596D0FC5F33E009D810A /* uudecode */, + 721D59740FC5F347009D810A /* mesg */, + 721D597D0FC5F370009D810A /* write */, + ); + name = Products; + sourceTree = "<group>"; + }; + 721D59810FC5F38E009D810A /* mesg */ = { + isa = PBXGroup; + children = ( + 721D59830FC5F414009D810A /* mesg.1 */, + 721D59840FC5F414009D810A /* mesg.c */, + ); + path = mesg; + sourceTree = "<group>"; + }; + 721D598E0FC5F4AC009D810A /* write */ = { + isa = PBXGroup; + children = ( + 721D598F0FC5F533009D810A /* write.1 */, + 721D59900FC5F533009D810A /* write.c */, + ); + path = write; + sourceTree = "<group>"; + }; + 721D59970FC5F56F009D810A /* uudecode */ = { + isa = PBXGroup; + children = ( + 721D599A0FC5F593009D810A /* base64.c */, + 721D599F0FC5F5A8009D810A /* uudecode.1 */, + 721D599B0FC5F593009D810A /* uudecode.c */, + ); + path = uudecode; + sourceTree = "<group>"; + }; + 721D59A70FC5F613009D810A /* uuencode */ = { + isa = PBXGroup; + children = ( + 721D59AF0FC5F6D9009D810A /* base64.c */, + 721D59B00FC5F6D9009D810A /* uuencode.1 */, + 721D59B10FC5F6D9009D810A /* uuencode.5 */, + 721D59B20FC5F6D9009D810A /* uuencode.c */, + ); + path = uuencode; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 721D59630FC5F336009D810A /* uuencode */ = { + isa = PBXNativeTarget; + buildConfigurationList = 721D59690FC5F337009D810A /* Build configuration list for PBXNativeTarget "uuencode" */; + buildPhases = ( + 721D59610FC5F336009D810A /* Sources */, + 721D59620FC5F336009D810A /* Frameworks */, + 721D59BC0FC5F70F009D810A /* CopyFiles */, + 721D59CD0FC5FA9D009D810A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = uuencode; + productName = uuencode; + productReference = 721D59640FC5F336009D810A /* uuencode */; + productType = "com.apple.product-type.tool"; + }; + 721D596C0FC5F33E009D810A /* uudecode */ = { + isa = PBXNativeTarget; + buildConfigurationList = 721D59780FC5F348009D810A /* Build configuration list for PBXNativeTarget "uudecode" */; + buildPhases = ( + 721D596A0FC5F33E009D810A /* Sources */, + 721D596B0FC5F33E009D810A /* Frameworks */, + 721D59A40FC5F5CA009D810A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = uudecode; + productName = uudecode; + productReference = 721D596D0FC5F33E009D810A /* uudecode */; + productType = "com.apple.product-type.tool"; + }; + 721D59730FC5F347009D810A /* mesg */ = { + isa = PBXNativeTarget; + buildConfigurationList = 721D59790FC5F348009D810A /* Build configuration list for PBXNativeTarget "mesg" */; + buildPhases = ( + 721D59710FC5F347009D810A /* Sources */, + 721D59720FC5F347009D810A /* Frameworks */, + 721D598C0FC5F43F009D810A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = mesg; + productName = mesg; + productReference = 721D59740FC5F347009D810A /* mesg */; + productType = "com.apple.product-type.tool"; + }; + 721D597C0FC5F36F009D810A /* write */ = { + isa = PBXNativeTarget; + buildConfigurationList = 721D59820FC5F38E009D810A /* Build configuration list for PBXNativeTarget "write" */; + buildPhases = ( + 721D597A0FC5F36F009D810A /* Sources */, + 721D597B0FC5F36F009D810A /* Frameworks */, + 721D59980FC5F56F009D810A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = write; + productName = write; + productReference = 721D597D0FC5F370009D810A /* write */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 721D59560FC5F325009D810A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + }; + buildConfigurationList = 721D59590FC5F325009D810A /* Build configuration list for PBXProject "basic_cmds" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 721D59540FC5F325009D810A; + productRefGroup = 721D59650FC5F336009D810A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 721D59C60FC5FA20009D810A /* Build All */, + 721D59630FC5F336009D810A /* uuencode */, + 721D596C0FC5F33E009D810A /* uudecode */, + 721D59730FC5F347009D810A /* mesg */, + 721D597C0FC5F36F009D810A /* write */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 721D59610FC5F336009D810A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 721D59B30FC5F6D9009D810A /* base64.c in Sources */, + 721D59B40FC5F6D9009D810A /* uuencode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D596A0FC5F33E009D810A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 721D599C0FC5F593009D810A /* base64.c in Sources */, + 721D599D0FC5F593009D810A /* uudecode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D59710FC5F347009D810A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 721D59850FC5F414009D810A /* mesg.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D597A0FC5F36F009D810A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 721D59920FC5F53E009D810A /* write.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 721D59CF0FC5FB18009D810A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 721D597C0FC5F36F009D810A /* write */; + targetProxy = 721D59CE0FC5FB18009D810A /* PBXContainerItemProxy */; + }; + 721D59D10FC5FB18009D810A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 721D59730FC5F347009D810A /* mesg */; + targetProxy = 721D59D00FC5FB18009D810A /* PBXContainerItemProxy */; + }; + 721D59D30FC5FB18009D810A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 721D596C0FC5F33E009D810A /* uudecode */; + targetProxy = 721D59D20FC5FB18009D810A /* PBXContainerItemProxy */; + }; + 721D59D50FC5FB18009D810A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 721D59630FC5F336009D810A /* uuencode */; + targetProxy = 721D59D40FC5FB18009D810A /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 721D59580FC5F325009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)"; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + INSTALL_MODE_FLAG = "gou-w,a+rX"; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + USE_HEADERMAP = NO; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_BUILDER = "$(USER)"; + VERSION_INFO_FILE = "$(PRODUCT_NAME)_vers.c"; + VERSION_INFO_PREFIX = __; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59680FC5F337009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = uuencode; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59700FC5F33F009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = uudecode; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59770FC5F348009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = mesg; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59800FC5F370009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_GROUP = tty; + INSTALL_MODE_FLAG = "gou-w,a+rX,g+s"; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = write; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59C80FC5FA20009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + PRODUCT_NAME = basic_cmds; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 721D59590FC5F325009D810A /* Build configuration list for PBXProject "basic_cmds" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59580FC5F325009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59690FC5F337009D810A /* Build configuration list for PBXNativeTarget "uuencode" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59680FC5F337009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59780FC5F348009D810A /* Build configuration list for PBXNativeTarget "uudecode" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59700FC5F33F009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59790FC5F348009D810A /* Build configuration list for PBXNativeTarget "mesg" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59770FC5F348009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59820FC5F38E009D810A /* Build configuration list for PBXNativeTarget "write" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59800FC5F370009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59C90FC5FA4E009D810A /* Build configuration list for PBXAggregateTarget "Build All" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59C80FC5FA20009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 721D59560FC5F325009D810A /* Project object */; +} diff --git a/basic_cmds/mesg/mesg.1 b/basic_cmds/mesg/mesg.1 new file mode 100644 index 0000000..de2f7a4 --- /dev/null +++ b/basic_cmds/mesg/mesg.1 @@ -0,0 +1,112 @@ +.\" Copyright (c) 1987, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)mesg.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD: src/usr.bin/mesg/mesg.1,v 1.10 2002/07/25 05:16:49 tjr Exp $ +.\" +.Dd May 5, 2002 +.Dt MESG 1 +.Os +.Sh NAME +.Nm mesg +.Nd display (do not display) messages from other users +.Sh SYNOPSIS +.Nm +.Op Cm n | Cm y +.Sh DESCRIPTION +The +.Nm +utility is invoked by a user to control write access others +have to a terminal device. +Write access is allowed by default, and programs such as +.Xr talk 1 +and +.Xr write 1 +may display messages on the terminal. +.Pp +The first terminal device in the sequence of devices associated with standard +input, standard output and standard error is affected. +.Pp +Options available: +.Bl -tag -width flag +.It Cm n +Disallows messages. +.It Cm y +Permits messages to be displayed. +.El +.Pp +If no arguments are given, +.Nm +displays the present message status to the standard output. +.Sh EXAMPLES +Disallow messages from other users to the current terminal: +.Pp +.Dl "mesg n" +.Pp +Allow messages from other users to +.Pa ttyp1 +(assuming you are also logged in on that terminal): +.Pp +.Dl "mesg y </dev/ttyp1" +.Sh DIAGNOSTICS +The +.Nm +utility exits with one of the following values: +.Bl -tag -width flag -compact -offset indent +.Pp +.It Li "\ 0" +Messages are allowed. +.It Li "\ 1" +Messages are not allowed. +.It Li ">1" +An error has occurred. +.El +.Sh COMPATIBILITY +Previous versions of the +.Nm +utility wrote the message status to the standard error output and +affected the terminal attached to standard error without first trying the +standard input or output devices. +.Sh SEE ALSO +.Xr biff 1 , +.Xr talk 1 , +.Xr wall 1 , +.Xr write 1 +.Sh STANDARDS +The +.Nm +utility conforms to +.St -p1003.1-2001 . +.Sh HISTORY +A +.Nm +command appeared in +.At v1 . diff --git a/basic_cmds/mesg/mesg.c b/basic_cmds/mesg/mesg.c new file mode 100644 index 0000000..b66980b --- /dev/null +++ b/basic_cmds/mesg/mesg.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1987, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)mesg.c 8.2 (Berkeley) 1/21/94"; +#endif +#endif /* not lint */ +#include <sys/cdefs.h> +__RCSID("$FreeBSD: src/usr.bin/mesg/mesg.c,v 1.8 2002/09/04 23:29:04 dwmalone Exp $"); + +#include <sys/types.h> +#include <sys/stat.h> + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static void usage(void); + +int +main(int argc, char *argv[]) +{ + struct stat sb; + char *tty; + int ch; + + while ((ch = getopt(argc, argv, "")) != -1) + switch (ch) { + case '?': + default: + usage(); + } +// argc -= optind; + argv += optind; + + if ((tty = ttyname(STDIN_FILENO)) == NULL && + (tty = ttyname(STDOUT_FILENO)) == NULL && + (tty = ttyname(STDERR_FILENO)) == NULL) + err(2, "ttyname"); + if (stat(tty, &sb) < 0) + err(2, "%s", tty); + + if (*argv == NULL) { + if (sb.st_mode & S_IWGRP) { + (void)puts("is y"); + exit(0); + } + (void)puts("is n"); + exit(1); + } + + switch (*argv[0]) { + case 'y': + if (chmod(tty, sb.st_mode | S_IWGRP) < 0) + err(2, "%s", tty); + exit(0); + case 'n': + if (chmod(tty, sb.st_mode & ~S_IWGRP) < 0) + err(2, "%s", tty); + exit(1); + } + + usage(); + return(0); +} + +static void +usage(void) +{ + (void)fprintf(stderr, "usage: mesg [y | n]\n"); + exit(2); +} diff --git a/basic_cmds/uudecode/base64.c b/basic_cmds/uudecode/base64.c new file mode 100644 index 0000000..b537171 --- /dev/null +++ b/basic_cmds/uudecode/base64.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if !defined(LINT) && !defined(CODECENTER) +#include <sys/cdefs.h> +__unused static char rcsid[] = "$FreeBSD: src/lib/libc/net/base64.c,v 1.4 1999/11/04 04:30:43 ache Exp $"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/basic_cmds/uudecode/uudecode.1 b/basic_cmds/uudecode/uudecode.1 new file mode 100644 index 0000000..ace1742 --- /dev/null +++ b/basic_cmds/uudecode/uudecode.1 @@ -0,0 +1 @@ +.so man1/uuencode.1 diff --git a/basic_cmds/uudecode/uudecode.c b/basic_cmds/uudecode/uudecode.c new file mode 100644 index 0000000..4831cab --- /dev/null +++ b/basic_cmds/uudecode/uudecode.c @@ -0,0 +1,504 @@ +/*- + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)uudecode.c 8.2 (Berkeley) 4/2/94"; +#endif /* not lint */ +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: head/usr.bin/uudecode/uudecode.c 214010 2010-10-18 05:44:11Z edwin $"); + +/* + * uudecode [file ...] + * + * create the specified file, decoding as you go. + * used with uuencode. + */ +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <netinet/in.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <libgen.h> +#include <pwd.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static const char *infile, *outfile; +static FILE *infp, *outfp; +static int base64, cflag, iflag, oflag, pflag, rflag, sflag; + +static void usage(void); +static int decode(void); +static int decode2(void); +static int uu_decode(void); +static int base64_decode(void); + +int +main(int argc, char *argv[]) +{ + int rval, ch; + + if (strcmp(basename(argv[0]), "b64decode") == 0) + base64 = 1; + + while ((ch = getopt(argc, argv, "cimo:prs")) != -1) { + switch (ch) { + case 'c': + if (oflag || rflag) + usage(); + cflag = 1; /* multiple uudecode'd files */ + break; + case 'i': + iflag = 1; /* ask before override files */ + break; + case 'm': + base64 = 1; + break; + case 'o': + if (cflag || pflag || rflag || sflag) + usage(); + oflag = 1; /* output to the specified file */ + sflag = 1; /* do not strip pathnames for output */ + outfile = optarg; /* set the output filename */ + break; + case 'p': + if (oflag) + usage(); + pflag = 1; /* print output to stdout */ + break; + case 'r': + if (cflag || oflag) + usage(); + rflag = 1; /* decode raw data */ + break; + case 's': + if (oflag) + usage(); + sflag = 1; /* do not strip pathnames for output */ + break; + default: + usage(); + } + } +// argc -= optind; + argv += optind; + + if (*argv != NULL) { + rval = 0; + do { + infp = fopen(infile = *argv, "r"); + if (infp == NULL) { + warn("%s", *argv); + rval = 1; + continue; + } + rval |= decode(); + fclose(infp); + } while (*++argv); + } else { + infile = "stdin"; + infp = stdin; + rval = decode(); + } + exit(rval); +} + +static int +decode(void) +{ + int r, v; + + if (rflag) { + /* relaxed alternative to decode2() */ + outfile = "/dev/stdout"; + outfp = stdout; + if (base64) + return (base64_decode()); + else + return (uu_decode()); + } + v = decode2(); + if (v == EOF) { + warnx("%s: missing or bad \"begin\" line", infile); + return (1); + } + for (r = v; cflag; r |= v) { + v = decode2(); + if (v == EOF) + break; + } + return (r); +} + +static int +decode2(void) +{ + int flags, fd, mode; + size_t n, m; + char *p, *q = NULL, *orig_outfile = NULL; + void *handle; + struct passwd *pw; + struct stat st; + char buf[MAXPATHLEN + 1]; + + base64 = 0; + /* search for header line */ + for (;;) { + if (fgets(buf, sizeof(buf), infp) == NULL) + return (EOF); + p = buf; + if (strncmp(p, "begin-base64 ", 13) == 0) { + base64 = 1; + p += 13; + } else if (strncmp(p, "begin ", 6) == 0) + p += 6; + else + continue; + /* p points to mode */ + q = strchr(p, ' '); + if (q == NULL) + continue; + *q++ = '\0'; + /* q points to filename */ + n = strlen(q); + while (n > 0 && (q[n-1] == '\n' || q[n-1] == '\r')) + q[--n] = '\0'; + /* found valid header? */ + if (n > 0) + break; + } + orig_outfile = q; + handle = setmode(p); + if (handle == NULL) { + warnx("%s: unable to parse file mode", infile); + return (1); + } + mode = getmode(handle, 0); + free(handle); + + if (sflag) { + /* don't strip, so try ~user/file expansion */ + p = NULL; + pw = NULL; + if (*q == '~') + p = strchr(q, '/'); + if (p != NULL) { + *p = '\0'; + pw = getpwnam(q + 1); + *p = '/'; + } + if (pw != NULL) { + n = strlen(pw->pw_dir); + if (buf + n > p) { + /* make room */ + m = strlen(p); + if (sizeof(buf) < n + m) { + warnx("%s: bad output filename", + infile); + return (1); + } + p = memmove(buf + n, p, m); + } + q = memcpy(p - n, pw->pw_dir, n); + } + } else { + /* strip down to leaf name */ + p = strrchr(q, '/'); + if (p != NULL) + q = p + 1; + } + if (!oflag) { + outfile = q ? strdup(q) : q; + } + + /* POSIX says "/dev/stdout" is a 'magic cookie' not a special file. */ + if (pflag || (strcmp(oflag ? outfile : orig_outfile, "/dev/stdout") == 0)) { + outfp = stdout; + } else { + char pwd[MAXPATHLEN] = ""; + char targetpath[MAXPATHLEN]; + flags = O_WRONLY | O_CREAT | O_EXCL; + if (lstat(outfile, &st) == 0) { + if (iflag && !S_ISFIFO(st.st_mode)) { + warnc(EEXIST, "%s: %s", infile, outfile); + return (0); + } + + flags = O_RDWR; + switch (st.st_mode & S_IFMT) { + case S_IFREG: + flags |= O_NOFOLLOW | O_TRUNC; + break; + case S_IFLNK: + if (NULL == realpath(".", pwd)) { + warn("Unable to get realpath for ."); + return (1); + } + flags |= O_CREAT; // for dangling symlinks + break; + case S_IFDIR: + warnc(EISDIR, "%s: %s", infile, outfile); + return (1); + case S_IFIFO: + flags &= ~O_EXCL; + break; + default: + if (oflag) { + /* trust command-line names */ + flags &= ~O_EXCL; + break; + } + warnc(EEXIST, "%s: %s", infile, outfile); + return (1); + } + } else if (errno != ENOENT) { + warn("%s: %s", infile, outfile); + return (1); + } + fd = open(outfile, flags, mode); + if (fd < 0) { + warn("%s: %s", infile, outfile); + return (1); + } + if (pwd[0]) { + if (-1 != fcntl(fd, F_GETPATH, targetpath)) { + if (strstr(targetpath, pwd) != targetpath) { + warnx("Target path %s is not based at %s", targetpath, pwd); + close(fd); + return (1); + } + ftruncate(fd, 0); + } else { + close(fd); + warn("Unable to get path for target: %s", outfile); + return (1); + } + } + if ((outfp = fdopen(fd, "w")) == NULL) { + warn("%s: %s", infile, outfile); + close(fd); + return (1); + } + if (fchmod(fileno(outfp), mode) && (EPERM != errno)) { + warn("%s: %s", infile, outfile); + close(fd); + return 1; + } + } + if (base64) + return (base64_decode()); + else + return (uu_decode()); +} + +static int +uugetline(char *buf, size_t size) +{ + + if (fgets(buf, size, infp) != NULL) + return (2); + if (rflag) + return (0); + warnx("%s: %s: short file", infile, outfile); + return (1); +} + +static int +checkend(const char *ptr, const char *end, const char *msg) +{ + size_t n; + + n = strlen(end); + if (strncmp(ptr, end, n) != 0 || + strspn(ptr + n, " \t\r\n") != strlen(ptr + n)) { + warnx("%s: %s: %s", infile, outfile, msg); + return (1); + } + if (fclose(outfp) != 0) { + warn("%s: %s", infile, outfile); + return (1); + } + return (0); +} + +static int +uu_decode(void) +{ + int i, ch; + char *p; + char buf[MAXPATHLEN+1]; + + /* for each input line */ + for (;;) { + switch (uugetline(buf, sizeof(buf))) { + case 0: + return (0); + case 1: + return (1); + } + +#define DEC(c) (((c) - ' ') & 077) /* single character decode */ +#define IS_DEC(c) ( (((c) - ' ') >= 0) && (((c) - ' ') <= 077 + 1) ) + +#define OUT_OF_RANGE do { \ + warnx("%s: %s: character out of range: [%d-%d]", \ + infile, outfile, 1 + ' ', 077 + ' ' + 1); \ + return (1); \ +} while (0) + + /* + * `i' is used to avoid writing out all the characters + * at the end of the file. + */ + p = buf; + if ((i = DEC(*p)) <= 0) + break; + for (++p; i > 0; p += 4, i -= 3) + if (i >= 3) { + if (!(IS_DEC(*p) && IS_DEC(*(p + 1)) && + IS_DEC(*(p + 2)) && IS_DEC(*(p + 3)))) + OUT_OF_RANGE; + + ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; + putc(ch, outfp); + ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; + putc(ch, outfp); + ch = DEC(p[2]) << 6 | DEC(p[3]); + putc(ch, outfp); + } else { + if (i >= 1) { + if (!(IS_DEC(*p) && IS_DEC(*(p + 1)))) + OUT_OF_RANGE; + ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; + putc(ch, outfp); + } + if (i >= 2) { + if (!(IS_DEC(*(p + 1)) && + IS_DEC(*(p + 2)))) + OUT_OF_RANGE; + + ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; + putc(ch, outfp); + } + if (i >= 3) { + if (!(IS_DEC(*(p + 2)) && + IS_DEC(*(p + 3)))) + OUT_OF_RANGE; + ch = DEC(p[2]) << 6 | DEC(p[3]); + putc(ch, outfp); + } + } + } + switch (uugetline(buf, sizeof(buf))) { + case 0: + return (0); + case 1: + return (1); + default: + return (checkend(buf, "end", "no \"end\" line")); + } +} + +static int +base64_decode(void) +{ + int n, count, count4; + char inbuf[MAXPATHLEN + 1], *p; + unsigned char outbuf[MAXPATHLEN * 4]; + char leftover[MAXPATHLEN + 1]; + + leftover[0] = '\0'; + for (;;) { + strcpy(inbuf, leftover); + switch (uugetline(inbuf + strlen(inbuf), + sizeof(inbuf) - strlen(inbuf))) { + case 0: + return (0); + case 1: + return (1); + } + + count = 0; + count4 = -1; + p = inbuf; + while (*p != '\0') { + /* + * Base64 encoded strings have the following + * characters in them: A-Z, a-z, 0-9 and +, / and = + */ + if (isalnum(*p) || *p == '+' || *p == '/' || *p == '=') + count++; + if (count % 4 == 0) + count4 = p - inbuf; + p++; + } + + strcpy(leftover, inbuf + count4 + 1); + inbuf[count4 + 1] = 0; + + n = b64_pton(inbuf, outbuf, sizeof(outbuf)); + + if (n < 0) + break; + fwrite(outbuf, 1, n, outfp); + } + return (checkend(inbuf, "====", "error decoding base64 input stream")); +} + +static void +usage(void) +{ + + (void)fprintf(stderr, + "usage: uudecode [-cimprs] [file ...]\n" + " uudecode [-i] -o output_file [file]\n" + " b64decode [-cimprs] [file ...]\n" + " b64decode [-i] -o output_file [file]\n"); + exit(1); +} diff --git a/basic_cmds/uuencode/base64.c b/basic_cmds/uuencode/base64.c new file mode 100644 index 0000000..b537171 --- /dev/null +++ b/basic_cmds/uuencode/base64.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if !defined(LINT) && !defined(CODECENTER) +#include <sys/cdefs.h> +__unused static char rcsid[] = "$FreeBSD: src/lib/libc/net/base64.c,v 1.4 1999/11/04 04:30:43 ache Exp $"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/basic_cmds/uuencode/uuencode.1 b/basic_cmds/uuencode/uuencode.1 new file mode 100644 index 0000000..20a8bf4 --- /dev/null +++ b/basic_cmds/uuencode/uuencode.1 @@ -0,0 +1,192 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)uuencode.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD: src/usr.bin/uuencode/uuencode.1,v 1.9.2.6 2002/04/27 01:55:11 jmallett Exp $ +.\" +.Dd January 27, 2002 +.Dt UUENCODE 1 +.Os +.Sh NAME +.Nm uudecode , +.Nm uuencode +.Nd encode/decode a binary file +.Sh SYNOPSIS +.Nm uuencode +.Op Fl m +.Op Fl o Ar output_file +.Op Ar file +.Ar name +.Nm uudecode +.Op Fl cips +.Op Ar +.Nm uudecode +.Op Fl i +.Fl o Ar output_file +.Op Ar file +.Sh DESCRIPTION +The +.Nm uuencode +and +.Nm uudecode +utilities are used to transmit binary files over transmission mediums +that do not support other than simple +.Tn ASCII +data. +.Pp +The +.Nm uuencode +utility reads +.Ar file +(or by default the standard input) and writes an encoded version +to the standard output, or +.Ar output_file +if one has been specified. +The encoding uses only printing +.Tn ASCII +characters and includes the +mode of the file and the operand +.Ar name +for use by +.Nm uudecode . +.Pp +The +.Nm uudecode +utility transforms +.Em uuencoded +files (or by default, the standard input) into the original form. +The resulting file is named either +.Ar name +or (depending on options passed to +.Nm uudecode ) +.Ar output_file +and will have the mode of the original file except that setuid +and execute bits are not retained. +The +.Nm uudecode +utility ignores any leading and trailing lines. +.Pp +The following options are available for +.Nm uuencode : +.Bl -tag -width ident +.It Fl m +Use the Base64 method of encoding, rather than the traditional +.Nm uuencode +algorithm. +.It Fl o Ar output_file +Output to +.Ar output_file +instead of standard output. +.El +.Pp +The following options are available for +.Nm uudecode : +.Bl -tag -width ident +.It Fl c +Decode more than one uuencode'd file from +.Ar file +if possible. +.It Fl i +Do not overwrite files. +.It Fl o Ar output_file +Output to +.Ar output_file +instead of any pathname contained in the input data. +.It Fl p +Decode +.Ar file +and write output to standard output. +.It Fl s +Do not strip output pathname to base filename. +By default +.Nm uudecode +deletes any prefix ending with the last slash '/' for security +purpose. +.El +.Sh EXAMPLES +The following example packages up a source tree, compresses it, +uuencodes it and mails it to a user on another system. +When +.Nm uudecode +is run on the target system, the file ``src_tree.tar.Z'' will be +created which may then be uncompressed and extracted into the original +tree. +.Pp +.Bd -literal -offset indent -compact +tar cf \- src_tree \&| compress \&| +uuencode src_tree.tar.Z \&| mail sys1!sys2!user +.Ed +.Pp +The following example unpack all uuencode'd +files from your mailbox into your current working directory. +.Pp +.Bd -literal -offset indent -compact +uudecode -c < $MAIL +.Ed +.Pp +The following example extract a compress'ed tar +archive from your mailbox +.Pp +.Bd -literal -offset indent -compact +uudecode -o /dev/stdout < $MAIL | zcat | tar xfv - +.Ed +.Sh LEGACY DESCRIPTION +In legacy operation, +.Nm uudecode +masks file modes with 0666, +preventing the creation of executable files. +.Pp +.Nm uudecode +cannot change the mode of a created file +which is not owned by the current user (unless that user is root). +In legacy operation, +.Xr fchmod 2 +allows the mode to be changed. +.Pp +For more information about legacy mode, see +.Xr compat 5 . +.Sh SEE ALSO +.Xr basename 1 , +.Xr compress 1 , +.Xr mail 1 , +.Xr uucp 1 , +.Xr fchmod 2 , +.Xr uuencode 5 +.Sh BUGS +Files encoded using the traditional algorithm are expanded by 35% +(3 bytes become 4, plus control information). +.Sh HISTORY +The +.Nm uudecode +and +.Nm uuencode +utilities appeared in +.Bx 4.0 . diff --git a/basic_cmds/uuencode/uuencode.5 b/basic_cmds/uuencode/uuencode.5 new file mode 100644 index 0000000..3914dad --- /dev/null +++ b/basic_cmds/uuencode/uuencode.5 @@ -0,0 +1,100 @@ +.TH uuencode 5 "May, 2001" "Apple Computer, Inc." +.SH NAME +uuencode file format +.NM uuencode +.ND description of the uuencode file format +.SH DESCRIPTION + +The +.XR uuencode 1 +command generates files in a format that allows them to be successfully +transferred by systems which strip the high bit from an 8-bit byte. +.XR uudecode 1 +decodes uuencoded files. + +.PP +The uuencode file format consists of three sections: header, body, and trailer. +The header is a line is of the form: + +.PP +begin 644 "filename.ext" + +.PP +where "644" is a +.XR chmod 1 +-format permissions byte for the file and "filename.ext" is the name of +the encoded file. + +.PP +The body section is the encoded representation of the source file. Three +bytes of input file data are encoded into four bytes of output data. +.PP +The 24 input bits are divided up into four pieces of six bits +each. The integer value 32 (the ASCII value for the space character) is +added to each of these pieces to move them outside of the range of control +characters. To avoid using the space character in the encoding, pieces with +value zero are encoded using backquote (ASCII value 96) instead of zero. The +resulting character is one of the this set (ASCII values 96,33-95): + +.DQ `!"#$%&'()*+,-./012356789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ + +.PP +A line itself contains three segments: a length character (encoded using +the "add a space" algorithm described above), the body of the line, +typically (although not required to be) 60 output characters long, +representing 45 input bytes, and (of course) a linefeed. The length +character specifies the number of valid input bytes on the line (so, for +a line which is 60 encoded bytes, the length value would be 45). +Decoding programs should decode no further than the specified length on +a single line. + +.PP +The trailer, which must exist, consists of a single backquote +("`", ASCII 96) character on a line by itself, directly followed by +.DQ end +on a line by itself. + +.PP +.DQ .uue +is the canonical filename extension for uuencoded files. + +.SH BUGS +uudecode does not read all permutations of the file format described in +this man page. + +.PP +Ancient versions of uuencode used a space character (ASCII 32) in the +encoding to represent zero. Many (arguably broken) mailers and transport +agents stripped, rewrapped, or otherwise mangled this format, so the space +was later changed to the backquote, ASCII 96. Decoders may attempt to +read the older format if they wish, though it's unlikely to be encountered +in practice at this point in time. + +.PP +The uuencode encoding method is highly ASCII-centric. In particular, the +character set used doesn't work well on EBCDIC-based systems. (EBCDIC, +generally used by IBM mainframes, is an old alternative character encoding; +most computers use ASCII instead). + +.PP +Many variants of uuencode on various platforms generate different forms +of line checksums, using to represent the checksum one or more encoded +characters after the last counted character in a line. Because these +formats are different and impossible to distinguish (with certainty), +such characters should be ignored by decoding implementations. + +.PP +The uuencode encoding format has no provisions for segmented files. +Writers of segmenting utilities should be careful to avoid using +character sequences that may naturally occur in the encoding (such +as sequences of dashes ("---")) to divide sections. + +.SH SEE ALSO +The MIME Base64 encoding (documented in RFC 2045) is a consistent, +cross-platform-savvy message encoding which should be used in place of +UUEncode wherever possible. + +.PP +The Unix-Hater's Handbook (IDG, 1994) identifies the folly of the +older zero-encoded-as-space versions of uuencode. + diff --git a/basic_cmds/uuencode/uuencode.c b/basic_cmds/uuencode/uuencode.c new file mode 100644 index 0000000..bb528a6 --- /dev/null +++ b/basic_cmds/uuencode/uuencode.c @@ -0,0 +1,226 @@ +/*- + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#include <sys/cdefs.h> +__unused static const char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)uuencode.c 8.2 (Berkeley) 4/2/94"; +#endif +__unused static const char rcsid[] = + "$FreeBSD: src/usr.bin/uuencode/uuencode.c,v 1.4.2.4 2002/06/17 05:01:46 jmallett Exp $"; +#endif /* not lint */ + +/* + * uuencode [input] output + * + * Encode a file so it can be mailed to a remote system. + */ +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <netinet/in.h> + +#include <err.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +int b64_ntop __P((u_char const *, size_t, char *, size_t)); +int b64_pton __P((char const *, u_char *, size_t)); +void encode(void); +void base64_encode(void); +static void usage(void); + +FILE *output; +int mode; +char **av; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct stat sb; + int base64; + char ch; + char *outfile; + + base64 = 0; + outfile = NULL; + + while ((ch = getopt(argc, argv, "mo:")) != -1) { + switch (ch) { + case 'm': + base64 = 1; + break; + case 'o': + outfile = optarg; + break; + case '?': + default: + usage(); + } + } + argv += optind; + argc -= optind; + + switch(argc) { + case 2: /* optional first argument is input file */ + if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb)) + err(1, "%s", *argv); +#define RWX (S_IRWXU|S_IRWXG|S_IRWXO) + mode = sb.st_mode & RWX; + ++argv; + break; + case 1: +#define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) + mode = RW & ~umask(RW); + break; + case 0: + default: + usage(); + } + + av = argv; + + if (outfile != NULL) { + output = fopen(outfile, "w+"); + if (output == NULL) + err(1, "unable to open %s for output", outfile); + } else + output = stdout; + if (base64) + base64_encode(); + else + encode(); + if (ferror(output)) + errx(1, "write error"); + exit(0); +} + +/* ENC is the basic 1 character encoding function to make a char printing */ +#define ENC(c) ((c) ? ((c) & 077) + ' ': '`') + +/* + * Copy from in to out, encoding in base64 as you go along. + */ +void +base64_encode() +{ + /* + * Output must fit into 80 columns, chunks come in 4, leave 1. + */ +#define GROUPS ((80 / 4) - 1) + unsigned char buf[3]; + char buf2[sizeof(buf) * 2 + 1]; + size_t n; + int rv, sequence; + + sequence = 0; + + fprintf(output, "begin-base64 %o %s\n", mode, *av); + while ((n = fread(buf, 1, sizeof(buf), stdin))) { + ++sequence; + rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0]))); + if (rv == -1) + errx(1, "b64_ntop: error encoding base64"); + fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n"); + } + if (sequence % GROUPS) + fprintf(output, "\n"); + fprintf(output, "====\n"); +} + +/* + * Copy from in to out, encoding as you go along. + */ +void +encode() +{ + register int ch, n; + register char *p; + char buf[80]; + + (void)fprintf(output, "begin %o %s\n", mode, *av); + while ((n = fread(buf, 1, 45, stdin))) { + ch = ENC(n); + if (fputc(ch, output) == EOF) + break; + for (p = buf; n > 0; n -= 3, p += 3) { + /* Pad with nulls if not a multiple of 3. */ + if (n < 3) { + p[2] = '\0'; + if (n < 2) + p[1] = '\0'; + } + ch = *p >> 2; + ch = ENC(ch); + if (fputc(ch, output) == EOF) + break; + ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017); + ch = ENC(ch); + if (fputc(ch, output) == EOF) + break; + ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); + ch = ENC(ch); + if (fputc(ch, output) == EOF) + break; + ch = p[2] & 077; + ch = ENC(ch); + if (fputc(ch, output) == EOF) + break; + } + if (fputc('\n', output) == EOF) + break; + } + if (ferror(stdin)) + errx(1, "read error"); + (void)fprintf(output, "%c\nend\n", ENC('\0')); +} + +static void +usage() +{ + (void)fprintf(stderr,"usage: uuencode [-m] [-o outfile] [infile] remotefile\n"); + exit(1); +} diff --git a/basic_cmds/write/write.1 b/basic_cmds/write/write.1 new file mode 100644 index 0000000..c7c2df1 --- /dev/null +++ b/basic_cmds/write/write.1 @@ -0,0 +1,106 @@ +.\" Copyright (c) 1989, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)write.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD: src/usr.bin/write/write.1,v 1.10 2002/04/20 12:18:12 charnier Exp $ +.\" +.Dd June 6, 1993 +.Dt WRITE 1 +.Os +.Sh NAME +.Nm write +.Nd send a message to another user +.Sh SYNOPSIS +.Nm +.Ar user +.Op Ar ttyname +.Sh DESCRIPTION +The +.Nm +utility allows you to communicate with other users, by copying lines from +your terminal to theirs. +.Pp +When you run the +.Nm +command, the user you are writing to gets a message of the form: +.Pp +.Dl Message from yourname@yourhost on yourtty at hh:mm ... +.Pp +Any further lines you enter will be copied to the specified user's +terminal. +If the other user wants to reply, they must run +.Nm +as well. +.Pp +When you are done, type an end-of-file or interrupt character. +The other user will see the message +.Ql EOF +indicating that the +conversation is over. +.Pp +You can prevent people (other than the super-user) from writing to you +with the +.Xr mesg 1 +command. +.Pp +If the user you want to write to is logged in on more than one terminal, +you can specify which terminal to write to by specifying the terminal +name as the second operand to the +.Nm +command. +Alternatively, you can let +.Nm +select one of the terminals \- it will pick the one with the shortest +idle time. +This is so that if the user is logged in at work and also dialed up from +home, the message will go to the right place. +.Pp +The traditional protocol for writing to someone is that the string +.Ql \-o , +either at the end of a line or on a line by itself, means that it's the +other person's turn to talk. +The string +.Ql oo +means that the person believes the conversation to be +over. +.Sh SEE ALSO +.Xr mesg 1 , +.Xr talk 1 , +.Xr wall 1 , +.Xr who 1 +.Sh HISTORY +A +.Nm +command appeared in +.At v1 . diff --git a/basic_cmds/write/write.c b/basic_cmds/write/write.c new file mode 100644 index 0000000..e3f2255 --- /dev/null +++ b/basic_cmds/write/write.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +__unused static const char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)write.c 8.1 (Berkeley) 6/6/93"; +#endif +#endif + +__RCSID("$FreeBSD: src/usr.bin/write/write.c,v 1.17 2002/09/04 23:29:09 dwmalone Exp $"); + +#include <sys/param.h> +#include <sys/signal.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <sys/time.h> +#include <ctype.h> +#include <err.h> +#include <locale.h> +#include <paths.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <utmpx.h> + +void done(int); +void do_write(char *, char *, uid_t); +static void usage(void); +int term_chk(char *, int *, time_t *, int); +void wr_fputs(unsigned char *s); +void search_utmp(char *, char *, char *, uid_t); +int utmp_chk(char *, char *); + +int +main(int argc, char **argv) +{ + char *cp; + time_t atime; + uid_t myuid; + int msgsok, myttyfd; + char tty[MAXPATHLEN], *mytty; + + (void)setlocale(LC_CTYPE, ""); + + while (getopt(argc, argv, "") != -1) + usage(); + argc -= optind; + argv += optind; + + /* check that sender has write enabled */ + if (isatty(fileno(stdin))) + myttyfd = fileno(stdin); + else if (isatty(fileno(stdout))) + myttyfd = fileno(stdout); + else if (isatty(fileno(stderr))) + myttyfd = fileno(stderr); + else + myttyfd=-1; + if(myttyfd == -1) + mytty = "tty??"; + else + { + if (!(mytty = ttyname(myttyfd))) + errx(1, "can't find your tty's name"); + if ((cp = rindex(mytty, '/'))) + mytty = cp + 1; + if (term_chk(mytty, &msgsok, &atime, 1)) + exit(1); + if (!msgsok) + errx(1, "you have write permission turned off"); + } + myuid = getuid(); + + /* check args */ + switch (argc) { + case 1: + search_utmp(argv[0], tty, mytty, myuid); + do_write(tty, mytty, myuid); + break; + case 2: + if (!strncmp(argv[1], _PATH_DEV, strlen(_PATH_DEV))) + argv[1] += strlen(_PATH_DEV); + if (utmp_chk(argv[0], argv[1])) + errx(1, "%s is not logged in on %s", argv[0], argv[1]); + if (term_chk(argv[1], &msgsok, &atime, 1)) + exit(1); + if (myuid && !msgsok) + errx(1, "%s has messages disabled on %s", argv[0], argv[1]); + do_write(argv[1], mytty, myuid); + break; + default: + usage(); + } + done(0); + return (0); +} + +static void +usage(void) +{ + (void)fprintf(stderr, "usage: write user [tty]\n"); + exit(1); +} + +/* + * utmp_chk - checks that the given user is actually logged in on + * the given tty + */ +int +utmp_chk(char *user, char *tty) +{ + struct utmpx *u; + + setutxent(); + while((u = getutxent()) != NULL) + if(strncmp(u->ut_line, tty, sizeof(u->ut_line)) == 0) { + if(u->ut_type == USER_PROCESS && + strncmp(u->ut_user, user, sizeof(u->ut_user)) == 0) { + endutxent(); + return 0; + } + break; + } + endutxent(); + return 1; +} + +/* + * search_utmp - search utmp for the "best" terminal to write to + * + * Ignores terminals with messages disabled, and of the rest, returns + * the one with the most recent access time. Returns as value the number + * of the user's terminals with messages enabled, or -1 if the user is + * not logged in at all. + * + * Special case for writing to yourself - ignore the terminal you're + * writing from, unless that's the only terminal with messages enabled. + */ +void +search_utmp(char *user, char *tty, char *mytty, uid_t myuid) +{ + struct utmpx ux, *u; + time_t bestatime, atime; + int nloggedttys, nttys, msgsok, user_is_me; + char atty[sizeof(ux.ut_line) + 1]; + + nloggedttys = nttys = 0; + bestatime = 0; + user_is_me = 0; + setutxent(); + while ((u = getutxent()) != NULL) { + if (u->ut_type != USER_PROCESS) + continue; + if (strncmp(user, u->ut_user, sizeof(u->ut_user)) == 0) { + ++nloggedttys; + (void)strlcpy(atty, u->ut_line, sizeof(atty)); + if (term_chk(atty, &msgsok, &atime, 0)) + continue; /* bad term? skip */ + if (myuid && !msgsok) + continue; /* skip ttys with msgs off */ + if (strcmp(atty, mytty) == 0) { + user_is_me = 1; + continue; /* don't write to yourself */ + } + ++nttys; + if (atime > bestatime) { + bestatime = atime; + (void)strcpy(tty, atty); + } + } + } + + endutxent(); + if (nloggedttys == 0) + errx(1, "%s is not logged in", user); + if (nttys == 0) { + if (user_is_me) { /* ok, so write to yourself! */ + (void)strcpy(tty, mytty); + return; + } + errx(1, "%s has messages disabled", user); + } else if (nttys > 1) { + warnx("%s is logged in more than once; writing to %s", user, tty); + } +} + +/* + * term_chk - check that a terminal exists, and get the message bit + * and the access time + */ +int +term_chk(char *tty, int *msgsokP, time_t *atimeP, int showerror) +{ + struct stat s; + char path[MAXPATHLEN]; + + (void)snprintf(path, sizeof(path), "%s%s", _PATH_DEV, tty); + if (stat(path, &s) < 0) { + if (showerror) + warn("%s", path); + return(1); + } + *msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */ + *atimeP = s.st_atime; + return(0); +} + +/* + * do_write - actually make the connection + */ +void +do_write(char *tty, char *mytty, uid_t myuid) +{ + const char *login; + char *nows; + struct passwd *pwd; + time_t now; + char path[MAXPATHLEN], host[MAXHOSTNAMELEN], line[512]; + + /* Determine our login name before the we reopen() stdout */ + if ((login = getlogin()) == NULL) { + if ((pwd = getpwuid(myuid))) + login = pwd->pw_name; + else + login = "???"; + } + + (void)snprintf(path, sizeof(path), "%s%s", _PATH_DEV, tty); + if ((freopen(path, "w", stdout)) == NULL) + err(1, "%s", path); + + (void)signal(SIGINT, done); + (void)signal(SIGHUP, done); + + /* print greeting */ + if (gethostname(host, sizeof(host)) < 0) + (void)strcpy(host, "???"); + now = time((time_t *)NULL); + nows = ctime(&now); + nows[16] = '\0'; + (void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n", + login, host, mytty, nows + 11); + + while (fgets(line, sizeof(line), stdin) != NULL) + wr_fputs((unsigned char *)line); +} + +/* + * done - cleanup and exit + */ +void +done(int n) +{ + (void)printf("EOF\r\n"); + exit(0); +} + +/* + * wr_fputs - like fputs(), but makes control characters visible and + * turns \n into \r\n + */ +void +wr_fputs(unsigned char *s) +{ + +#define PUTC(c) if (putchar(c) == EOF) err(1, NULL); + + for (; *s != '\0'; ++s) { + if (*s == '\n') { + PUTC('\r'); + } else if (((*s & 0x80) && *s < 0xA0) || + /* disable upper controls */ + (!isprint(*s) && !isspace(*s) && + *s != '\a' && *s != '\b') + ) { + if (*s & 0x80) { + *s &= ~0x80; + PUTC('M'); + PUTC('-'); + } + if (iscntrl(*s)) { + *s ^= 0x40; + PUTC('^'); + } + } + PUTC(*s); + } + return; +#undef PUTC +} |