Index: head/bin/dd/conv_tab.c =================================================================== --- head/bin/dd/conv_tab.c (revision 241776) +++ head/bin/dd/conv_tab.c (revision 241777) @@ -1,284 +1,289 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Keith Muller of the University of California, San Diego and Lance * Visser of Convex Computer Corporation. * * 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. * 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 #if 0 static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include +#include + +#include "dd.h" +#include "extern.h" + /* * There are currently six tables: * * ebcdic -> ascii 32V conv=oldascii * ascii -> ebcdic 32V conv=oldebcdic * ascii -> ibm ebcdic 32V conv=oldibm * * ebcdic -> ascii POSIX/S5 conv=ascii * ascii -> ebcdic POSIX/S5 conv=ebcdic * ascii -> ibm ebcdic POSIX/S5 conv=ibm * * Other tables are built from these if multiple conversions are being * done. * * Tables used for conversions to/from IBM and EBCDIC to support an extension * to POSIX P1003.2/D11. The tables referencing POSIX contain data extracted * from tables 4-3 and 4-4 in P1003.2/Draft 11. The historic tables were * constructed by running against a file with all possible byte values. * * More information can be obtained in "Correspondences of 8-Bit and Hollerith * Codes for Computer Environments-A USASI Tutorial", Communications of the * ACM, Volume 11, Number 11, November 1968, pp. 783-789. */ u_char casetab[256]; /* EBCDIC to ASCII -- 32V compatible. */ const u_char e2a_32V[] = { 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */ 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */ 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */ 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */ 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */ 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */ 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */ 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */ 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */ 0247, 0250, 0133, 0056, 0074, 0050, 0053, 0041, /* 0110 */ 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */ 0260, 0261, 0135, 0044, 0052, 0051, 0073, 0136, /* 0130 */ 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */ 0270, 0271, 0174, 0054, 0045, 0137, 0076, 0077, /* 0150 */ 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */ 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */ 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */ 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */ 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */ 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320, /* 0230 */ 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */ 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327, /* 0250 */ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, /* 0270 */ 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */ 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */ 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */ 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */ 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */ 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */ 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ }; /* ASCII to EBCDIC -- 32V compatible. */ const u_char a2e_32V[] = { 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155, /* 0130 */ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ 0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007, /* 0170 */ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ }; /* ASCII to IBM EBCDIC -- 32V compatible. */ const u_char a2ibm_32V[] = { 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ }; /* EBCDIC to ASCII -- POSIX and System V compatible. */ const u_char e2a_POSIX[] = { 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */ 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */ 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */ 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */ 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */ 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */ 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */ 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */ 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */ 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174, /* 0110 */ 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */ 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176, /* 0130 */ 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */ 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077, /* 0150 */ 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */ 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */ 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */ 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */ 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */ 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320, /* 0230 */ 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */ 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327, /* 0250 */ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */ 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347, /* 0270 */ 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */ 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */ 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */ 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */ 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */ 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */ 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ }; /* ASCII to EBCDIC -- POSIX and System V compatible. */ const u_char a2e_POSIX[] = { 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ 0347, 0350, 0351, 0255, 0340, 0275, 0232, 0155, /* 0130 */ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ 0247, 0250, 0251, 0300, 0117, 0320, 0137, 0007, /* 0170 */ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ 0216, 0217, 0220, 0152, 0233, 0234, 0235, 0236, /* 0310 */ 0237, 0240, 0252, 0253, 0254, 0112, 0256, 0257, /* 0320 */ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ 0270, 0271, 0272, 0273, 0274, 0241, 0276, 0277, /* 0340 */ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ }; /* ASCII to IBM EBCDIC -- POSIX and System V compatible. */ const u_char a2ibm_POSIX[] = { 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ }; Index: head/libexec/rpc.rusersd/Makefile =================================================================== --- head/libexec/rpc.rusersd/Makefile (revision 241776) +++ head/libexec/rpc.rusersd/Makefile (revision 241777) @@ -1,15 +1,15 @@ # $FreeBSD$ PROG = rpc.rusersd -SRCS = rusersd.c rusers_proc.c +SRCS = rusersd.c rusers_proc.c extern.h MAN = rpc.rusersd.8 DPADD= ${LIBRPCSVC} ${LIBUTIL} LDADD= -lrpcsvc -lutil #.if exists(/usr/X11R6/include/X11/extensions/xidle.h) #CFLAGS+= -DXIDLE #LDADD+= -L/usr/X11R6/lib -lXext -lX11 #.endif .include Index: head/libexec/rpc.rusersd/extern.h =================================================================== --- head/libexec/rpc.rusersd/extern.h (nonexistent) +++ head/libexec/rpc.rusersd/extern.h (revision 241777) @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 1993, John Brezak + * 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. + * + * $FreeBSD$ + */ + +extern int from_inetd; + +void rusers_service(struct svc_req *, SVCXPRT *); Property changes on: head/libexec/rpc.rusersd/extern.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/libexec/rpc.rusersd/rusers_proc.c =================================================================== --- head/libexec/rpc.rusersd/rusers_proc.c (revision 241776) +++ head/libexec/rpc.rusersd/rusers_proc.c (revision 241777) @@ -1,338 +1,336 @@ /*- * Copyright (c) 1993, John Brezak * 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 static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #ifdef DEBUG #include #endif #include #include #include #include #include #include #include #ifdef XIDLE #include #include #include #endif #include +#include "extern.h" + #ifndef _PATH_DEV #define _PATH_DEV "/dev" #endif static utmpidle utmp_idle[MAXUSERS]; static utmp old_utmp[MAXUSERS]; static struct utmpx utmp_list[MAXUSERS]; - -extern int from_inetd; - -void rusers_service(struct svc_req *, SVCXPRT *); #ifdef XIDLE static Display *dpy; static jmp_buf openAbort; static void abortOpen(void) { longjmp (openAbort, 1); } XqueryIdle(char *display) { int first_event, first_error; Time IdleTime; (void) signal (SIGALRM, abortOpen); (void) alarm ((unsigned) 10); if (!setjmp (openAbort)) { if (!(dpy= XOpenDisplay(display))) { syslog(LOG_ERR, "Cannot open display %s", display); return(-1); } if (XidleQueryExtension(dpy, &first_event, &first_error)) { if (!XGetIdleTime(dpy, &IdleTime)) { syslog(LOG_ERR, "%s: unable to get idle time", display); return(-1); } } else { syslog(LOG_ERR, "%s: Xidle extension not loaded", display); return(-1); } XCloseDisplay(dpy); } else { syslog(LOG_ERR, "%s: server grabbed for over 10 seconds", display); return(-1); } (void) signal (SIGALRM, SIG_DFL); (void) alarm ((unsigned) 0); IdleTime /= 1000; return((IdleTime + 30) / 60); } #endif static u_int getidle(const char *tty, const char *display __unused) { struct stat st; char ttyname[PATH_MAX]; time_t now; u_long idle; /* * If this is an X terminal or console, then try the * XIdle extension */ #ifdef XIDLE if (display && *display && (idle = XqueryIdle(display)) >= 0) return(idle); #endif idle = 0; if (*tty == 'X') { u_long kbd_idle, mouse_idle; #if !defined(__FreeBSD__) kbd_idle = getidle("kbd", NULL); #else kbd_idle = getidle("vga", NULL); #endif mouse_idle = getidle("mouse", NULL); idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle; } else { sprintf(ttyname, "%s/%s", _PATH_DEV, tty); if (stat(ttyname, &st) < 0) { #ifdef DEBUG printf("%s: %s\n", ttyname, strerror(errno)); #endif return(-1); } time(&now); #ifdef DEBUG printf("%s: now=%d atime=%d\n", ttyname, now, st.st_atime); #endif idle = now - st.st_atime; idle = (idle + 30) / 60; /* secs->mins */ } return(idle); } static utmpidlearr * do_names_2(void) { static utmpidlearr ut; struct utmpx *usr; int nusers = 0; memset(&ut, 0, sizeof(ut)); ut.utmpidlearr_val = &utmp_idle[0]; setutxent(); while ((usr = getutxent()) != NULL && nusers < MAXUSERS) { if (usr->ut_type != USER_PROCESS) continue; memcpy(&utmp_list[nusers], usr, sizeof(*usr)); utmp_idle[nusers].ui_utmp.ut_time = usr->ut_tv.tv_sec; utmp_idle[nusers].ui_idle = getidle(usr->ut_line, usr->ut_host); utmp_idle[nusers].ui_utmp.ut_line = utmp_list[nusers].ut_line; utmp_idle[nusers].ui_utmp.ut_name = utmp_list[nusers].ut_user; utmp_idle[nusers].ui_utmp.ut_host = utmp_list[nusers].ut_host; nusers++; } endutxent(); ut.utmpidlearr_len = nusers; return(&ut); } static int * rusers_num(void *argp __unused, struct svc_req *rqstp __unused) { static int num_users = 0; struct utmpx *usr; setutxent(); while ((usr = getutxent()) != NULL) { if (usr->ut_type != USER_PROCESS) continue; num_users++; } endutxent(); return(&num_users); } static utmparr * do_names_1(void) { utmpidlearr *utidle; static utmparr ut; unsigned int i; bzero((char *)&ut, sizeof(ut)); utidle = do_names_2(); if (utidle) { ut.utmparr_len = utidle->utmpidlearr_len; ut.utmparr_val = &old_utmp[0]; for (i = 0; i < ut.utmparr_len; i++) bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i], sizeof(old_utmp[0])); } return(&ut); } utmpidlearr * rusersproc_names_2_svc(void *argp __unused, struct svc_req *rqstp __unused) { return (do_names_2()); } utmpidlearr * rusersproc_allnames_2_svc(void *argp __unused, struct svc_req *rqstp __unused) { return (do_names_2()); } utmparr * rusersproc_names_1_svc(void *argp __unused, struct svc_req *rqstp __unused) { return (do_names_1()); } utmparr * rusersproc_allnames_1_svc(void *argp __unused, struct svc_req *rqstp __unused) { return (do_names_1()); } typedef void *(*rusersproc_t)(void *, struct svc_req *); void rusers_service(struct svc_req *rqstp, SVCXPRT *transp) { union { int fill; } argument; char *result; xdrproc_t xdr_argument, xdr_result; rusersproc_t local; switch (rqstp->rq_proc) { case NULLPROC: (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); goto leave; case RUSERSPROC_NUM: xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_int; local = (rusersproc_t)rusers_num; break; case RUSERSPROC_NAMES: xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_utmpidlearr; switch (rqstp->rq_vers) { case RUSERSVERS_ORIG: local = (rusersproc_t)rusersproc_names_1_svc; break; case RUSERSVERS_IDLE: local = (rusersproc_t)rusersproc_names_2_svc; break; default: svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); goto leave; /*NOTREACHED*/ } break; case RUSERSPROC_ALLNAMES: xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_utmpidlearr; switch (rqstp->rq_vers) { case RUSERSVERS_ORIG: local = (rusersproc_t)rusersproc_allnames_1_svc; break; case RUSERSVERS_IDLE: local = (rusersproc_t)rusersproc_allnames_2_svc; break; default: svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); goto leave; /*NOTREACHED*/ } break; default: svcerr_noproc(transp); goto leave; } bzero(&argument, sizeof(argument)); if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) { svcerr_decode(transp); goto leave; } result = (*local)(&argument, rqstp); if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { svcerr_systemerr(transp); } if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, &argument)) { syslog(LOG_ERR, "unable to free arguments"); exit(1); } leave: if (from_inetd) exit(0); } Index: head/libexec/rpc.rusersd/rusersd.c =================================================================== --- head/libexec/rpc.rusersd/rusersd.c (revision 241776) +++ head/libexec/rpc.rusersd/rusersd.c (revision 241777) @@ -1,116 +1,116 @@ /*- * Copyright (c) 1993, John Brezak * 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 static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include -extern void rusers_service(struct svc_req *, SVCXPRT *); +#include "extern.h" int from_inetd = 1; static void cleanup(int sig __unused) { (void) rpcb_unset(RUSERSPROG, RUSERSVERS_IDLE, NULL); (void) rpcb_unset(RUSERSPROG, RUSERSVERS_ORIG, NULL); exit(0); } int main(int argc __unused, char *argv[] __unused) { SVCXPRT *transp = NULL; /* Keep compiler happy. */ int ok; struct sockaddr_storage from; socklen_t fromlen; /* * See if inetd started us */ fromlen = sizeof(from); if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) { from_inetd = 0; } if (!from_inetd) { daemon(0, 0); (void) rpcb_unset(RUSERSPROG, RUSERSVERS_IDLE, NULL); (void) rpcb_unset(RUSERSPROG, RUSERSVERS_ORIG, NULL); (void) signal(SIGINT, cleanup); (void) signal(SIGTERM, cleanup); (void) signal(SIGHUP, cleanup); } openlog("rpc.rusersd", LOG_CONS|LOG_PID, LOG_DAEMON); if (from_inetd) { transp = svc_tli_create(0, NULL, NULL, 0, 0); if (transp == NULL) { syslog(LOG_ERR, "cannot create udp service."); exit(1); } ok = svc_reg(transp, RUSERSPROG, RUSERSVERS_IDLE, rusers_service, NULL); } else ok = svc_create(rusers_service, RUSERSPROG, RUSERSVERS_IDLE, "udp"); if (!ok) { syslog(LOG_ERR, "unable to register (RUSERSPROG, RUSERSVERS_IDLE, %s)", (!from_inetd)?"udp":"(inetd)"); exit(1); } if (from_inetd) ok = svc_reg(transp, RUSERSPROG, RUSERSVERS_ORIG, rusers_service, NULL); else ok = svc_create(rusers_service, RUSERSPROG, RUSERSVERS_ORIG, "udp"); if (!ok) { syslog(LOG_ERR, "unable to register (RUSERSPROG, RUSERSVERS_ORIG, %s)", (!from_inetd)?"udp":"(inetd)"); exit(1); } svc_run(); syslog(LOG_ERR, "svc_run returned"); exit(1); } Index: head/libexec/talkd/announce.c =================================================================== --- head/libexec/talkd/announce.c (revision 241776) +++ head/libexec/talkd/announce.c (revision 241777) @@ -1,171 +1,169 @@ /* * 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 #if 0 static char sccsid[] = "@(#)announce.c 8.3 (Berkeley) 4/28/95"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ttymsg.h" #include "extern.h" -extern char hostname[]; - /* * Announce an invitation to talk. */ /* * See if the user is accepting messages. If so, announce that * a talk is requested. */ int announce(CTL_MSG *request, const char *remote_machine) { char full_tty[32]; struct stat stbuf; (void)snprintf(full_tty, sizeof(full_tty), "%s%s", _PATH_DEV, request->r_tty); if (stat(full_tty, &stbuf) < 0 || (stbuf.st_mode&020) == 0) return (PERMISSION_DENIED); return (print_mesg(request->r_tty, request, remote_machine)); } #define max(a,b) ( (a) > (b) ? (a) : (b) ) #define N_LINES 5 #define N_CHARS 256 /* * Build a block of characters containing the message. * It is sent blank filled and in a single block to * try to keep the message in one piece if the recipient * in vi at the time */ int print_mesg(const char *tty, CTL_MSG *request, const char *remote_machine) { struct timeval now; time_t clock_sec; struct tm *localclock; struct iovec iovec; char line_buf[N_LINES][N_CHARS]; int sizes[N_LINES]; char big_buf[N_LINES*N_CHARS]; char *bptr, *lptr, *vis_user; int i, j, max_size; i = 0; max_size = 0; gettimeofday(&now, NULL); clock_sec = now.tv_sec; localclock = localtime(&clock_sec); (void)snprintf(line_buf[i], N_CHARS, " "); sizes[i] = strlen(line_buf[i]); max_size = max(max_size, sizes[i]); i++; (void)snprintf(line_buf[i], N_CHARS, "Message from Talk_Daemon@%s at %d:%02d on %d/%.2d/%.2d ...", hostname, localclock->tm_hour , localclock->tm_min, localclock->tm_year + 1900, localclock->tm_mon + 1, localclock->tm_mday); sizes[i] = strlen(line_buf[i]); max_size = max(max_size, sizes[i]); i++; vis_user = malloc(strlen(request->l_name) * 4 + 1); strvis(vis_user, request->l_name, VIS_CSTYLE); (void)snprintf(line_buf[i], N_CHARS, "talk: connection requested by %s@%s", vis_user, remote_machine); sizes[i] = strlen(line_buf[i]); max_size = max(max_size, sizes[i]); i++; (void)snprintf(line_buf[i], N_CHARS, "talk: respond with: talk %s@%s", vis_user, remote_machine); sizes[i] = strlen(line_buf[i]); max_size = max(max_size, sizes[i]); i++; (void)snprintf(line_buf[i], N_CHARS, " "); sizes[i] = strlen(line_buf[i]); max_size = max(max_size, sizes[i]); i++; bptr = big_buf; *bptr++ = '\007'; /* send something to wake them up */ *bptr++ = '\r'; /* add a \r in case of raw mode */ *bptr++ = '\n'; for (i = 0; i < N_LINES; i++) { /* copy the line into the big buffer */ lptr = line_buf[i]; while (*lptr != '\0') *(bptr++) = *(lptr++); /* pad out the rest of the lines with blanks */ for (j = sizes[i]; j < max_size + 2; j++) *(bptr++) = ' '; *(bptr++) = '\r'; /* add a \r in case of raw mode */ *(bptr++) = '\n'; } *bptr = '\0'; iovec.iov_base = big_buf; iovec.iov_len = bptr - big_buf; /* * we choose a timeout of RING_WAIT-5 seconds so that we don't * stack up processes trying to write messages to a tty * that is permanently blocked. */ if (ttymsg(&iovec, 1, tty, RING_WAIT - 5) != NULL) return (FAILED); return (SUCCESS); } Index: head/libexec/talkd/extern.h =================================================================== --- head/libexec/talkd/extern.h (revision 241776) +++ head/libexec/talkd/extern.h (revision 241777) @@ -1,40 +1,43 @@ /* * Copyright (c) 2002 M. Warner Losh. 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. * * 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. * * $FreeBSD$ */ +extern int debug; +extern char hostname[]; + int announce(CTL_MSG *, const char *); int delete_invite(u_int32_t); void do_announce(CTL_MSG *, CTL_RESPONSE *); CTL_MSG *find_match(CTL_MSG *request); CTL_MSG *find_request(CTL_MSG *request); int find_user(const char *name, char *tty); void insert_table(CTL_MSG *, CTL_RESPONSE *); int new_id(void); int print_mesg(const char *, CTL_MSG *, const char *); void print_request(const char *, CTL_MSG *); void print_response(const char *, CTL_RESPONSE *); void process_request(CTL_MSG *mp, CTL_RESPONSE *rp); void timeout(int sig); Index: head/libexec/talkd/process.c =================================================================== --- head/libexec/talkd/process.c (revision 241776) +++ head/libexec/talkd/process.c (revision 241777) @@ -1,227 +1,225 @@ /* * 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 #if 0 static char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ /* * process.c handles the requests, which can be of three types: * ANNOUNCE - announce to a user that a talk is wanted * LEAVE_INVITE - insert the request into the table * LOOK_UP - look up to see if a request is waiting in * in the table for the local user * DELETE - delete invitation */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "extern.h" -extern int debug; - void process_request(CTL_MSG *mp, CTL_RESPONSE *rp) { CTL_MSG *ptr; char *s; rp->vers = TALK_VERSION; rp->type = mp->type; rp->id_num = htonl(0); if (mp->vers != TALK_VERSION) { syslog(LOG_WARNING, "bad protocol version %d", mp->vers); rp->answer = BADVERSION; return; } mp->id_num = ntohl(mp->id_num); mp->addr.sa_family = ntohs(mp->addr.sa_family); if (mp->addr.sa_family != AF_INET) { syslog(LOG_WARNING, "bad address, family %d", mp->addr.sa_family); rp->answer = BADADDR; return; } mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family); if (mp->ctl_addr.sa_family != AF_INET) { syslog(LOG_WARNING, "bad control address, family %d", mp->ctl_addr.sa_family); rp->answer = BADCTLADDR; return; } for (s = mp->l_name; *s; s++) if (!isprint(*s)) { syslog(LOG_NOTICE, "illegal user name. Aborting"); rp->answer = FAILED; return; } mp->pid = ntohl(mp->pid); if (debug) print_request("process_request", mp); switch (mp->type) { case ANNOUNCE: do_announce(mp, rp); break; case LEAVE_INVITE: ptr = find_request(mp); if (ptr != (CTL_MSG *)0) { rp->id_num = htonl(ptr->id_num); rp->answer = SUCCESS; } else insert_table(mp, rp); break; case LOOK_UP: ptr = find_match(mp); if (ptr != (CTL_MSG *)0) { rp->id_num = htonl(ptr->id_num); rp->addr = ptr->addr; rp->addr.sa_family = htons(ptr->addr.sa_family); rp->answer = SUCCESS; } else rp->answer = NOT_HERE; break; case DELETE: rp->answer = delete_invite(mp->id_num); break; default: rp->answer = UNKNOWN_REQUEST; break; } if (debug) print_response("process_request", rp); } void do_announce(CTL_MSG *mp, CTL_RESPONSE *rp) { struct hostent *hp; CTL_MSG *ptr; int result; /* see if the user is logged */ result = find_user(mp->r_name, mp->r_tty); if (result != SUCCESS) { rp->answer = result; return; } #define satosin(sa) ((struct sockaddr_in *)(void *)(sa)) hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr, sizeof (struct in_addr), AF_INET); if (hp == (struct hostent *)0) { rp->answer = MACHINE_UNKNOWN; return; } ptr = find_request(mp); if (ptr == (CTL_MSG *) 0) { insert_table(mp, rp); rp->answer = announce(mp, hp->h_name); return; } if (mp->id_num > ptr->id_num) { /* * This is an explicit re-announce, so update the id_num * field to avoid duplicates and re-announce the talk. */ ptr->id_num = new_id(); rp->id_num = htonl(ptr->id_num); rp->answer = announce(mp, hp->h_name); } else { /* a duplicated request, so ignore it */ rp->id_num = htonl(ptr->id_num); rp->answer = SUCCESS; } } /* * Search utmp for the local user */ int find_user(const char *name, char *tty) { struct utmpx *ut; int status; struct stat statb; time_t best = 0; char ftty[sizeof(_PATH_DEV) - 1 + sizeof(ut->ut_line)]; setutxent(); status = NOT_HERE; (void) strcpy(ftty, _PATH_DEV); while ((ut = getutxent()) != NULL) if (ut->ut_type == USER_PROCESS && strcmp(ut->ut_user, name) == 0) { if (*tty == '\0' || best != 0) { if (best == 0) status = PERMISSION_DENIED; /* no particular tty was requested */ (void) strcpy(ftty + sizeof(_PATH_DEV) - 1, ut->ut_line); if (stat(ftty, &statb) == 0) { if (!(statb.st_mode & 020)) continue; if (statb.st_atime > best) { best = statb.st_atime; (void) strcpy(tty, ut->ut_line); status = SUCCESS; continue; } } } if (strcmp(ut->ut_line, tty) == 0) { status = SUCCESS; break; } } endutxent(); return (status); } Index: head/libexec/talkd/table.c =================================================================== --- head/libexec/talkd/table.c (revision 241776) +++ head/libexec/talkd/table.c (revision 241777) @@ -1,237 +1,236 @@ /* * 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 #if 0 static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ /* * Routines to handle insertion, deletion, etc on the table * of requests kept by the daemon. Nothing fancy here, linear * search on a double-linked list. A time is kept with each * entry so that overly old invitations can be eliminated. * * Consider this a mis-guided attempt at modularity */ #include #include #include #include #include #include #include #include #include #include #include "extern.h" #define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ #define NIL ((TABLE_ENTRY *)0) -extern int debug; -struct timeval tp; +static struct timeval tp; typedef struct table_entry TABLE_ENTRY; struct table_entry { CTL_MSG request; long time; TABLE_ENTRY *next; TABLE_ENTRY *last; }; static void delete(TABLE_ENTRY *); -TABLE_ENTRY *table = NIL; +static TABLE_ENTRY *table = NIL; /* * Look in the table for an invitation that matches the current * request looking for an invitation */ CTL_MSG * find_match(CTL_MSG *request) { TABLE_ENTRY *ptr; time_t current_time; gettimeofday(&tp, NULL); current_time = tp.tv_sec; if (debug) print_request("find_match", request); for (ptr = table; ptr != NIL; ptr = ptr->next) { if ((ptr->time - current_time) > MAX_LIFE) { /* the entry is too old */ if (debug) print_request("deleting expired entry", &ptr->request); delete(ptr); continue; } if (debug) print_request("", &ptr->request); if (strcmp(request->l_name, ptr->request.r_name) == 0 && strcmp(request->r_name, ptr->request.l_name) == 0 && ptr->request.type == LEAVE_INVITE) return (&ptr->request); } return ((CTL_MSG *)0); } /* * Look for an identical request, as opposed to a complimentary * one as find_match does */ CTL_MSG * find_request(CTL_MSG *request) { TABLE_ENTRY *ptr; time_t current_time; gettimeofday(&tp, NULL); current_time = tp.tv_sec; /* * See if this is a repeated message, and check for * out of date entries in the table while we are it. */ if (debug) print_request("find_request", request); for (ptr = table; ptr != NIL; ptr = ptr->next) { if ((ptr->time - current_time) > MAX_LIFE) { /* the entry is too old */ if (debug) print_request("deleting expired entry", &ptr->request); delete(ptr); continue; } if (debug) print_request("", &ptr->request); if (strcmp(request->r_name, ptr->request.r_name) == 0 && strcmp(request->l_name, ptr->request.l_name) == 0 && request->type == ptr->request.type && request->pid == ptr->request.pid) { /* update the time if we 'touch' it */ ptr->time = current_time; return (&ptr->request); } } return ((CTL_MSG *)0); } void insert_table(CTL_MSG *request, CTL_RESPONSE *response) { TABLE_ENTRY *ptr; time_t current_time; gettimeofday(&tp, NULL); current_time = tp.tv_sec; request->id_num = new_id(); response->id_num = htonl(request->id_num); /* insert a new entry into the top of the list */ ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); if (ptr == NIL) { syslog(LOG_ERR, "insert_table: Out of memory"); _exit(1); } ptr->time = current_time; ptr->request = *request; ptr->next = table; if (ptr->next != NIL) ptr->next->last = ptr; ptr->last = NIL; table = ptr; } /* * Generate a unique non-zero sequence number */ int new_id(void) { static int current_id = 0; current_id = (current_id + 1) % MAX_ID; /* 0 is reserved, helps to pick up bugs */ if (current_id == 0) current_id = 1; return (current_id); } /* * Delete the invitation with id 'id_num' */ int delete_invite(u_int32_t id_num) { TABLE_ENTRY *ptr; ptr = table; if (debug) syslog(LOG_DEBUG, "delete_invite(%d)", id_num); for (ptr = table; ptr != NIL; ptr = ptr->next) { if (ptr->request.id_num == id_num) break; if (debug) print_request("", &ptr->request); } if (ptr != NIL) { delete(ptr); return (SUCCESS); } return (NOT_HERE); } /* * Classic delete from a double-linked list */ static void delete(TABLE_ENTRY *ptr) { if (debug) print_request("delete", &ptr->request); if (table == ptr) table = ptr->next; else if (ptr->last != NIL) ptr->last->next = ptr->next; if (ptr->next != NIL) ptr->next->last = ptr->last; free((char *)ptr); } Index: head/libexec/talkd/talkd.c =================================================================== --- head/libexec/talkd/talkd.c (revision 241776) +++ head/libexec/talkd/talkd.c (revision 241777) @@ -1,140 +1,140 @@ /* * 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 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[] = "@(#)talkd.c 8.1 (Berkeley) 6/4/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ /* * The top level of the daemon, the format is heavily borrowed * from rwhod.c. Basically: find out who and where you are; * disconnect all descriptors and ttys, and then endless * loop on waiting for and processing requests */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "extern.h" -CTL_MSG request; -CTL_RESPONSE response; +static CTL_MSG request; +static CTL_RESPONSE response; -int debug = 0; -long lastmsgtime; +int debug = 0; +static long lastmsgtime; -char hostname[MAXHOSTNAMELEN]; +char hostname[MAXHOSTNAMELEN]; #define TIMEOUT 30 #define MAXIDLE 120 int main(int argc, char *argv[]) { register CTL_MSG *mp = &request; int cc; struct sockaddr ctl_addr; #ifdef NOTDEF /* * removed so ntalkd can run in tty sandbox */ if (getuid()) errx(1, "getuid: not super-user"); #endif openlog("talkd", LOG_PID, LOG_DAEMON); if (gethostname(hostname, sizeof(hostname) - 1) < 0) { syslog(LOG_ERR, "gethostname: %m"); _exit(1); } hostname[sizeof(hostname) - 1] = '\0'; if (chdir(_PATH_DEV) < 0) { syslog(LOG_ERR, "chdir: %s: %m", _PATH_DEV); _exit(1); } if (argc > 1 && strcmp(argv[1], "-d") == 0) debug = 1; signal(SIGALRM, timeout); alarm(TIMEOUT); for (;;) { cc = recv(0, (char *)mp, sizeof(*mp), 0); if (cc != sizeof (*mp)) { if (cc < 0 && errno != EINTR) syslog(LOG_WARNING, "recv: %m"); continue; } lastmsgtime = time(0); (void)memcpy(&ctl_addr, &mp->ctl_addr, sizeof(ctl_addr)); ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family); ctl_addr.sa_len = sizeof(ctl_addr); process_request(mp, &response); /* can block here, is this what I want? */ cc = sendto(STDIN_FILENO, (char *)&response, sizeof(response), 0, &ctl_addr, sizeof(ctl_addr)); if (cc != sizeof (response)) syslog(LOG_WARNING, "sendto: %m"); } } void timeout(int sig __unused) { int save_errno = errno; if (time(0) - lastmsgtime >= MAXIDLE) _exit(0); alarm(TIMEOUT); errno = save_errno; } Index: head/usr.bin/cksum/extern.h =================================================================== --- head/usr.bin/cksum/extern.h (revision 241776) +++ head/usr.bin/cksum/extern.h (revision 241777) @@ -1,43 +1,46 @@ /*- * Copyright (c) 1991, 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. * 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. * * @(#)extern.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ #include +extern uint32_t crc_total; +extern uint32_t crc32_total; + __BEGIN_DECLS int crc(int, uint32_t *, off_t *); void pcrc(char *, uint32_t, off_t); void psum1(char *, uint32_t, off_t); void psum2(char *, uint32_t, off_t); int csum1(int, uint32_t *, off_t *); int csum2(int, uint32_t *, off_t *); int crc32(int, uint32_t *, off_t *); __END_DECLS Index: head/usr.bin/m4/expr.c =================================================================== --- head/usr.bin/m4/expr.c (revision 241776) +++ head/usr.bin/m4/expr.c (revision 241777) @@ -1,47 +1,47 @@ /* $OpenBSD: expr.c,v 1.18 2010/09/07 19:58:09 marco Exp $ */ /* * Copyright (c) 2004 Marc Espie * * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "mdef.h" #include "extern.h" int32_t end_result; -const char *copy_toeval; +static const char *copy_toeval; int yyerror(const char *msg); extern void yy_scan_string(const char *); extern int yyparse(void); int yyerror(const char *msg) { fprintf(stderr, "m4: %s in expr %s\n", msg, copy_toeval); return(0); } int expr(const char *toeval) { copy_toeval = toeval; yy_scan_string(toeval); yyparse(); return end_result; } Index: head/usr.bin/m4/extern.h =================================================================== --- head/usr.bin/m4/extern.h (revision 241776) +++ head/usr.bin/m4/extern.h (revision 241777) @@ -1,177 +1,178 @@ /* $OpenBSD: extern.h,v 1.51 2011/09/27 07:24:02 espie Exp $ */ /* $NetBSD: extern.h,v 1.3 1996/01/13 23:25:24 pk Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Ozan Yigit at York University. * * 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. 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. * * @(#)extern.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ /* eval.c */ extern void eval(const char *[], int, int, int); extern void dodefine(const char *, const char *); extern unsigned long expansion_id; /* expr.c */ extern int expr(const char *); +extern int32_t end_result; /* gnum4.c */ extern void addtoincludepath(const char *); extern struct input_file *fopen_trypath(struct input_file *, const char *); extern void doindir(const char *[], int); extern void dobuiltin(const char *[], int); extern void dopatsubst(const char *[], int); extern void doregexp(const char *[], int); extern void doprintlineno(struct input_file *); extern void doprintfilename(struct input_file *); extern void doesyscmd(const char *); extern void getdivfile(const char *); extern void doformat(const char *[], int); /* look.c */ #define FLAG_UNTRACED 0 #define FLAG_TRACED 1 #define FLAG_NO_TRACE 2 extern void init_macros(void); extern ndptr lookup(const char *); extern void mark_traced(const char *, int); extern struct ohash macros; extern struct macro_definition *lookup_macro_definition(const char *); extern void macro_define(const char *, const char *); extern void macro_pushdef(const char *, const char *); extern void macro_popdef(const char *); extern void macro_undefine(const char *); extern void setup_builtin(const char *, unsigned int); extern void macro_for_all(void (*)(const char *, struct macro_definition *)); #define macro_getdef(p) ((p)->d) #define macro_name(p) ((p)->name) #define macro_builtin_type(p) ((p)->builtin_type) #define is_traced(p) ((p)->trace_flags == FLAG_NO_TRACE ? (trace_flags & TRACE_ALL) : (p)->trace_flags) extern ndptr macro_getbuiltin(const char *); /* main.c */ extern void outputstr(const char *); extern void do_emit_synchline(void); extern int exit_code; #define emit_synchline() do { if (synch_lines) do_emit_synchline(); } while(0) /* misc.c */ extern void chrsave(int); extern char *compute_prevep(void); extern void getdiv(int); extern ptrdiff_t indx(const char *, const char *); extern void initspaces(void); extern void killdiv(void); extern void onintr(int); extern void pbnum(int); extern void pbnumbase(int, int, int); extern void pbunsigned(unsigned long); extern void pbstr(const char *); extern void pushback(int); extern void *xalloc(size_t, const char *fmt, ...); extern void *xrealloc(void *, size_t, const char *fmt, ...); extern char *xstrdup(const char *); extern void usage(void); extern void resizedivs(int); extern size_t buffer_mark(void); extern void dump_buffer(FILE *, size_t); extern void m4errx(int, const char *, ...); extern int obtain_char(struct input_file *); extern void set_input(struct input_file *, FILE *, const char *); extern void release_input(struct input_file *); /* speeded-up versions of chrsave/pushback */ #define PUSHBACK(c) \ do { \ if (bp >= endpbb) \ enlarge_bufspace(); \ *bp++ = (c); \ } while(0) #define CHRSAVE(c) \ do { \ if (ep >= endest) \ enlarge_strspace(); \ *ep++ = (c); \ } while(0) /* and corresponding exposure for local symbols */ extern void enlarge_bufspace(void); extern void enlarge_strspace(void); extern unsigned char *endpbb; extern char *endest; /* trace.c */ extern unsigned int trace_flags; #define TRACE_ALL 512 extern void trace_file(const char *); extern size_t trace(const char **, int, struct input_file *); extern void finish_trace(size_t); extern void set_trace_flags(const char *); extern FILE *traceout; extern stae *mstack; /* stack of m4 machine */ extern char *sstack; /* shadow stack, for string space extension */ extern FILE *active; /* active output file pointer */ extern struct input_file infile[];/* input file stack (0=stdin) */ extern FILE **outfile; /* diversion array(0=bitbucket) */ extern int maxout; /* maximum number of diversions */ extern int fp; /* m4 call frame pointer */ extern int ilevel; /* input file stack pointer */ extern int oindex; /* diversion index. */ extern int sp; /* current m4 stack pointer */ extern unsigned char *bp; /* first available character */ extern unsigned char *buf; /* push-back buffer */ extern unsigned char *bufbase; /* buffer base for this ilevel */ extern unsigned char *bbase[]; /* buffer base per ilevel */ extern char ecommt[MAXCCHARS+1];/* end character for comment */ extern char *ep; /* first free char in strspace */ extern char lquote[MAXCCHARS+1];/* left quote character (`) */ extern char **m4wraps; /* m4wrap string default. */ extern int maxwraps; /* size of m4wraps array */ extern int wrapindex; /* current index in m4wraps */ extern const char *null; /* as it says.. just a null. */ extern char rquote[MAXCCHARS+1];/* right quote character (') */ extern char scommt[MAXCCHARS+1];/* start character for comment */ extern int synch_lines; /* line synchronisation directives */ extern int mimic_gnu; /* behaves like gnu-m4 */ extern int prefix_builtins; /* prefix builtin macros with m4_ */ Index: head/usr.bin/m4/gnum4.c =================================================================== --- head/usr.bin/m4/gnum4.c (revision 241776) +++ head/usr.bin/m4/gnum4.c (revision 241777) @@ -1,665 +1,665 @@ /* $OpenBSD: gnum4.c,v 1.42 2011/11/06 12:25:43 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie * * 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. * * 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 __FBSDID("$FreeBSD$"); /* * functions needed to support gnu-m4 extensions, including a fake freezing */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mdef.h" #include "stdd.h" #include "extern.h" int mimic_gnu = 0; /* * Support for include path search * First search in the current directory. * If not found, and the path is not absolute, include path kicks in. * First, -I options, in the order found on the command line. * Then M4PATH env variable */ -struct path_entry { +static struct path_entry { char *name; struct path_entry *next; } *first, *last; static struct path_entry *new_path_entry(const char *); static void ensure_m4path(void); static struct input_file *dopath(struct input_file *, const char *); static struct path_entry * new_path_entry(const char *dirname) { struct path_entry *n; n = malloc(sizeof(struct path_entry)); if (!n) errx(1, "out of memory"); n->name = strdup(dirname); if (!n->name) errx(1, "out of memory"); n->next = 0; return n; } void addtoincludepath(const char *dirname) { struct path_entry *n; n = new_path_entry(dirname); if (last) { last->next = n; last = n; } else last = first = n; } static void ensure_m4path(void) { static int envpathdone = 0; char *envpath; char *sweep; char *path; if (envpathdone) return; envpathdone = TRUE; envpath = getenv("M4PATH"); if (!envpath) return; /* for portability: getenv result is read-only */ envpath = strdup(envpath); if (!envpath) errx(1, "out of memory"); for (sweep = envpath; (path = strsep(&sweep, ":")) != NULL;) addtoincludepath(path); free(envpath); } static struct input_file * dopath(struct input_file *i, const char *filename) { char path[MAXPATHLEN]; struct path_entry *pe; FILE *f; for (pe = first; pe; pe = pe->next) { snprintf(path, sizeof(path), "%s/%s", pe->name, filename); if ((f = fopen(path, "r")) != 0) { set_input(i, f, path); return i; } } return NULL; } struct input_file * fopen_trypath(struct input_file *i, const char *filename) { FILE *f; f = fopen(filename, "r"); if (f != NULL) { set_input(i, f, filename); return i; } if (filename[0] == '/') return NULL; ensure_m4path(); return dopath(i, filename); } void doindir(const char *argv[], int argc) { ndptr n; struct macro_definition *p = NULL; n = lookup(argv[2]); if (n == NULL || (p = macro_getdef(n)) == NULL) m4errx(1, "indir: undefined macro %s.", argv[2]); argv[1] = p->defn; eval(argv+1, argc-1, p->type, is_traced(n)); } void dobuiltin(const char *argv[], int argc) { ndptr p; argv[1] = NULL; p = macro_getbuiltin(argv[2]); if (p != NULL) eval(argv+1, argc-1, macro_builtin_type(p), is_traced(p)); else m4errx(1, "unknown builtin %s.", argv[2]); } /* We need some temporary buffer space, as pb pushes BACK and substitution * proceeds forward... */ static char *buffer; static size_t bufsize = 0; static size_t current = 0; static void addchars(const char *, size_t); static void addchar(int); static char *twiddle(const char *); static char *getstring(void); static void exit_regerror(int, regex_t *); static void do_subst(const char *, regex_t *, const char *, regmatch_t *); static void do_regexpindex(const char *, regex_t *, regmatch_t *); static void do_regexp(const char *, regex_t *, const char *, regmatch_t *); static void add_sub(int, const char *, regex_t *, regmatch_t *); static void add_replace(const char *, regex_t *, const char *, regmatch_t *); #define addconstantstring(s) addchars((s), sizeof(s)-1) static void addchars(const char *c, size_t n) { if (n == 0) return; while (current + n > bufsize) { if (bufsize == 0) bufsize = 1024; else bufsize *= 2; buffer = xrealloc(buffer, bufsize, NULL); } memcpy(buffer+current, c, n); current += n; } static void addchar(int c) { if (current +1 > bufsize) { if (bufsize == 0) bufsize = 1024; else bufsize *= 2; buffer = xrealloc(buffer, bufsize, NULL); } buffer[current++] = c; } static char * getstring(void) { addchar('\0'); current = 0; return buffer; } static void exit_regerror(int er, regex_t *re) { size_t errlen; char *errbuf; errlen = regerror(er, re, NULL, 0); errbuf = xalloc(errlen, "malloc in regerror: %lu", (unsigned long)errlen); regerror(er, re, errbuf, errlen); m4errx(1, "regular expression error: %s.", errbuf); } static void add_sub(int n, const char *string, regex_t *re, regmatch_t *pm) { if (n > (int)re->re_nsub) warnx("No subexpression %d", n); /* Subexpressions that did not match are * not an error. */ else if (pm[n].rm_so != -1 && pm[n].rm_eo != -1) { addchars(string + pm[n].rm_so, pm[n].rm_eo - pm[n].rm_so); } } /* Add replacement string to the output buffer, recognizing special * constructs and replacing them with substrings of the original string. */ static void add_replace(const char *string, regex_t *re, const char *replace, regmatch_t *pm) { const char *p; for (p = replace; *p != '\0'; p++) { if (*p == '&' && !mimic_gnu) { add_sub(0, string, re, pm); continue; } if (*p == '\\') { if (p[1] == '\\') { addchar(p[1]); p++; continue; } if (p[1] == '&') { if (mimic_gnu) add_sub(0, string, re, pm); else addchar(p[1]); p++; continue; } if (isdigit(p[1])) { add_sub(*(++p) - '0', string, re, pm); continue; } } addchar(*p); } } static void do_subst(const char *string, regex_t *re, const char *replace, regmatch_t *pm) { int error; int flags = 0; const char *last_match = NULL; while ((error = regexec(re, string, re->re_nsub+1, pm, flags)) == 0) { if (pm[0].rm_eo != 0) { if (string[pm[0].rm_eo-1] == '\n') flags = 0; else flags = REG_NOTBOL; } /* NULL length matches are special... We use the `vi-mode' * rule: don't allow a NULL-match at the last match * position. */ if (pm[0].rm_so == pm[0].rm_eo && string + pm[0].rm_so == last_match) { if (*string == '\0') return; addchar(*string); if (*string++ == '\n') flags = 0; else flags = REG_NOTBOL; continue; } last_match = string + pm[0].rm_so; addchars(string, pm[0].rm_so); add_replace(string, re, replace, pm); string += pm[0].rm_eo; } if (error != REG_NOMATCH) exit_regerror(error, re); pbstr(string); } static void do_regexp(const char *string, regex_t *re, const char *replace, regmatch_t *pm) { int error; switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) { case 0: add_replace(string, re, replace, pm); pbstr(getstring()); break; case REG_NOMATCH: break; default: exit_regerror(error, re); } } static void do_regexpindex(const char *string, regex_t *re, regmatch_t *pm) { int error; switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) { case 0: pbunsigned(pm[0].rm_so); break; case REG_NOMATCH: pbnum(-1); break; default: exit_regerror(error, re); } } /* In Gnu m4 mode, parentheses for backmatch don't work like POSIX 1003.2 * says. So we twiddle with the regexp before passing it to regcomp. */ static char * twiddle(const char *p) { /* + at start of regexp is a normal character for Gnu m4 */ if (*p == '^') { addchar(*p); p++; } if (*p == '+') { addchar('\\'); } /* This could use strcspn for speed... */ while (*p != '\0') { if (*p == '\\') { switch(p[1]) { case '(': case ')': case '|': addchar(p[1]); break; case 'w': addconstantstring("[_a-zA-Z0-9]"); break; case 'W': addconstantstring("[^_a-zA-Z0-9]"); break; case '<': addconstantstring("[[:<:]]"); break; case '>': addconstantstring("[[:>:]]"); break; default: addchars(p, 2); break; } p+=2; continue; } if (*p == '(' || *p == ')' || *p == '|') addchar('\\'); addchar(*p); p++; } return getstring(); } /* patsubst(string, regexp, opt replacement) */ /* argv[2]: string * argv[3]: regexp * argv[4]: opt rep */ void dopatsubst(const char *argv[], int argc) { if (argc <= 3) { warnx("Too few arguments to patsubst"); return; } /* special case: empty regexp */ if (argv[3][0] == '\0') { const char *s; size_t len; if (argc > 4 && argv[4]) len = strlen(argv[4]); else len = 0; for (s = argv[2]; *s != '\0'; s++) { addchars(argv[4], len); addchar(*s); } } else { int error; regex_t re; regmatch_t *pmatch; int mode = REG_EXTENDED; size_t l = strlen(argv[3]); if (!mimic_gnu || (argv[3][0] == '^') || (l > 0 && argv[3][l-1] == '$')) mode |= REG_NEWLINE; error = regcomp(&re, mimic_gnu ? twiddle(argv[3]) : argv[3], mode); if (error != 0) exit_regerror(error, &re); pmatch = xalloc(sizeof(regmatch_t) * (re.re_nsub+1), NULL); do_subst(argv[2], &re, argc > 4 && argv[4] != NULL ? argv[4] : "", pmatch); free(pmatch); regfree(&re); } pbstr(getstring()); } void doregexp(const char *argv[], int argc) { int error; regex_t re; regmatch_t *pmatch; if (argc <= 3) { warnx("Too few arguments to regexp"); return; } /* special gnu case */ if (argv[3][0] == '\0' && mimic_gnu) { if (argc == 4 || argv[4] == NULL) return; else pbstr(argv[4]); } error = regcomp(&re, mimic_gnu ? twiddle(argv[3]) : argv[3], REG_EXTENDED|REG_NEWLINE); if (error != 0) exit_regerror(error, &re); pmatch = xalloc(sizeof(regmatch_t) * (re.re_nsub+1), NULL); if (argc == 4 || argv[4] == NULL) do_regexpindex(argv[2], &re, pmatch); else do_regexp(argv[2], &re, argv[4], pmatch); free(pmatch); regfree(&re); } void doformat(const char *argv[], int argc) { const char *format = argv[2]; int pos = 3; int left_padded; long width; size_t l; const char *thisarg = NULL; char temp[2]; long extra; while (*format != 0) { if (*format != '%') { addchar(*format++); continue; } format++; if (*format == '%') { addchar(*format++); continue; } if (*format == 0) { addchar('%'); break; } if (*format == '*') { format++; if (pos >= argc) m4errx(1, "Format with too many format specifiers."); width = strtol(argv[pos++], NULL, 10); } else { width = strtol(format, __DECONST(char **,&format), 10); } if (width < 0) { left_padded = 1; width = -width; } else { left_padded = 0; } if (*format == '.') { format++; if (*format == '*') { format++; if (pos >= argc) m4errx(1, "Format with too many format specifiers."); extra = strtol(argv[pos++], NULL, 10); } else { extra = strtol(format, __DECONST(char **, &format), 10); } } else { extra = LONG_MAX; } if (pos >= argc) m4errx(1, "Format with too many format specifiers."); switch(*format) { case 's': thisarg = argv[pos++]; break; case 'c': temp[0] = strtoul(argv[pos++], NULL, 10); temp[1] = 0; thisarg = temp; break; default: m4errx(1, "Unsupported format specification: %s.", argv[2]); } format++; l = strlen(thisarg); if ((long)l > extra) l = extra; if (!left_padded) { while ((long)l < width--) addchar(' '); } addchars(thisarg, l); if (left_padded) { while ((long)l < width--) addchar(' '); } } pbstr(getstring()); } void doesyscmd(const char *cmd) { int p[2]; pid_t pid, cpid; char *argv[4]; int cc; int status; /* Follow gnu m4 documentation: first flush buffers. */ fflush(NULL); argv[0] = __DECONST(char *, "sh"); argv[1] = __DECONST(char *, "-c"); argv[2] = __DECONST(char *, cmd); argv[3] = NULL; /* Just set up standard output, share stderr and stdin with m4 */ if (pipe(p) == -1) err(1, "bad pipe"); switch(cpid = fork()) { case -1: err(1, "bad fork"); /* NOTREACHED */ case 0: (void) close(p[0]); (void) dup2(p[1], 1); (void) close(p[1]); execv(_PATH_BSHELL, argv); exit(1); default: /* Read result in two stages, since m4's buffer is * pushback-only. */ (void) close(p[1]); do { char result[BUFSIZE]; cc = read(p[0], result, sizeof result); if (cc > 0) addchars(result, cc); } while (cc > 0 || (cc == -1 && errno == EINTR)); (void) close(p[0]); while ((pid = wait(&status)) != cpid && pid >= 0) continue; pbstr(getstring()); } } void getdivfile(const char *name) { FILE *f; int c; f = fopen(name, "r"); if (!f) return; while ((c = getc(f))!= EOF) putc(c, active); (void) fclose(f); } Index: head/usr.bin/m4/main.c =================================================================== --- head/usr.bin/m4/main.c (revision 241776) +++ head/usr.bin/m4/main.c (revision 241777) @@ -1,634 +1,634 @@ /* $OpenBSD: main.c,v 1.80 2011/09/27 07:24:02 espie Exp $ */ /* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */ /*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Ozan Yigit at York University. * * 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. 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. */ /* * main.c * Facility: m4 macro processor * by: oz */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "mdef.h" #include "stdd.h" #include "extern.h" #include "pathnames.h" stae *mstack; /* stack of m4 machine */ char *sstack; /* shadow stack, for string space extension */ static size_t STACKMAX; /* current maximum size of stack */ int sp; /* current m4 stack pointer */ int fp; /* m4 call frame pointer */ struct input_file infile[MAXINP];/* input file stack (0=stdin) */ FILE **outfile; /* diversion array(0=bitbucket)*/ int maxout; FILE *active; /* active output file pointer */ int ilevel = 0; /* input file stack pointer */ int oindex = 0; /* diversion index.. */ const char *null = ""; /* as it says.. just a null.. */ char **m4wraps = NULL; /* m4wraps array. */ int maxwraps = 0; /* size of m4wraps array */ int wrapindex = 0; /* current offset in m4wraps */ char lquote[MAXCCHARS+1] = {LQUOTE}; /* left quote character (`) */ char rquote[MAXCCHARS+1] = {RQUOTE}; /* right quote character (') */ char scommt[MAXCCHARS+1] = {SCOMMT}; /* start character for comment */ char ecommt[MAXCCHARS+1] = {ECOMMT}; /* end character for comment */ int synch_lines = 0; /* line synchronisation for C preprocessor */ int prefix_builtins = 0; /* -P option to prefix builtin keywords */ struct keyblk { const char *knam; /* keyword name */ int ktyp; /* keyword type */ }; -struct keyblk keywrds[] = { /* m4 keywords to be installed */ +static struct keyblk keywrds[] = { /* m4 keywords to be installed */ { "include", INCLTYPE }, { "sinclude", SINCTYPE }, { "define", DEFITYPE }, { "defn", DEFNTYPE }, { "divert", DIVRTYPE | NOARGS }, { "expr", EXPRTYPE }, { "eval", EXPRTYPE }, { "substr", SUBSTYPE }, { "ifelse", IFELTYPE }, { "ifdef", IFDFTYPE }, { "len", LENGTYPE }, { "incr", INCRTYPE }, { "decr", DECRTYPE }, { "dnl", DNLNTYPE | NOARGS }, { "changequote", CHNQTYPE | NOARGS }, { "changecom", CHNCTYPE | NOARGS }, { "index", INDXTYPE }, #ifdef EXTENDED { "paste", PASTTYPE }, { "spaste", SPASTYPE }, /* Newer extensions, needed to handle gnu-m4 scripts */ { "indir", INDIRTYPE}, { "builtin", BUILTINTYPE}, { "patsubst", PATSTYPE}, { "regexp", REGEXPTYPE}, { "esyscmd", ESYSCMDTYPE}, { "__file__", FILENAMETYPE | NOARGS}, { "__line__", LINETYPE | NOARGS}, #endif { "popdef", POPDTYPE }, { "pushdef", PUSDTYPE }, { "dumpdef", DUMPTYPE | NOARGS }, { "shift", SHIFTYPE | NOARGS }, { "translit", TRNLTYPE }, { "undefine", UNDFTYPE }, { "undivert", UNDVTYPE | NOARGS }, { "divnum", DIVNTYPE | NOARGS }, { "maketemp", MKTMTYPE }, { "mkstemp", MKTMTYPE }, { "errprint", ERRPTYPE | NOARGS }, { "m4wrap", M4WRTYPE | NOARGS }, { "m4exit", EXITTYPE | NOARGS }, { "syscmd", SYSCTYPE }, { "sysval", SYSVTYPE | NOARGS }, { "traceon", TRACEONTYPE | NOARGS }, { "traceoff", TRACEOFFTYPE | NOARGS }, #if defined(unix) || defined(__unix__) { "unix", SELFTYPE | NOARGS }, #else #ifdef vms { "vms", SELFTYPE | NOARGS }, #endif #endif }; #define MAXKEYS (sizeof(keywrds)/sizeof(struct keyblk)) #define MAXRECORD 50 static struct position { char *name; unsigned long line; } quotes[MAXRECORD], paren[MAXRECORD]; static void record(struct position *, int); static void dump_stack(struct position *, int); static void macro(void); static void initkwds(void); static ndptr inspect(int, char *); static int do_look_ahead(int, const char *); static void reallyoutputstr(const char *); static void reallyputchar(int); static void enlarge_stack(void); int main(int, char *[]); int exit_code = 0; int main(int argc, char *argv[]) { int c; int n; char *p; if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, onintr); init_macros(); initspaces(); STACKMAX = INITSTACKMAX; mstack = (stae *)xalloc(sizeof(stae) * STACKMAX, NULL); sstack = (char *)xalloc(STACKMAX, NULL); maxout = 0; outfile = NULL; resizedivs(MAXOUT); while ((c = getopt(argc, argv, "gst:d:D:U:o:I:P")) != -1) switch(c) { case 'D': /* define something..*/ for (p = optarg; *p; p++) if (*p == '=') break; if (*p) *p++ = EOS; dodefine(optarg, p); break; case 'I': addtoincludepath(optarg); break; case 'P': prefix_builtins = 1; break; case 'U': /* undefine... */ macro_popdef(optarg); break; case 'g': mimic_gnu = 1; break; case 'd': set_trace_flags(optarg); break; case 's': synch_lines = 1; break; case 't': mark_traced(optarg, 1); break; case 'o': trace_file(optarg); break; case '?': usage(); } argc -= optind; argv += optind; initkwds(); if (mimic_gnu) setup_builtin("format", FORMATTYPE); active = stdout; /* default active output */ bbase[0] = bufbase; if (!argc) { sp = -1; /* stack pointer initialized */ fp = 0; /* frame pointer initialized */ set_input(infile+0, stdin, "stdin"); /* default input (naturally) */ macro(); } else for (; argc--; ++argv) { p = *argv; if (p[0] == '-' && p[1] == EOS) set_input(infile, stdin, "stdin"); else if (fopen_trypath(infile, p) == NULL) err(1, "%s", p); sp = -1; fp = 0; macro(); release_input(infile); } if (wrapindex) { int i; ilevel = 0; /* in case m4wrap includes.. */ bufbase = bp = buf; /* use the entire buffer */ if (mimic_gnu) { while (wrapindex != 0) { for (i = 0; i < wrapindex; i++) pbstr(m4wraps[i]); wrapindex =0; macro(); } } else { for (i = 0; i < wrapindex; i++) { pbstr(m4wraps[i]); macro(); } } } if (active != stdout) active = stdout; /* reset output just in case */ for (n = 1; n < maxout; n++) /* default wrap-up: undivert */ if (outfile[n] != NULL) getdiv(n); /* remove bitbucket if used */ if (outfile[0] != NULL) { (void) fclose(outfile[0]); } return exit_code; } /* * Look ahead for `token'. * (on input `t == token[0]') * Used for comment and quoting delimiters. * Returns 1 if `token' present; copied to output. * 0 if `token' not found; all characters pushed back */ static int do_look_ahead(int t, const char *token) { int i; assert((unsigned char)t == (unsigned char)token[0]); for (i = 1; *++token; i++) { t = gpbc(); if (t == EOF || (unsigned char)t != (unsigned char)*token) { pushback(t); while (--i) pushback(*--token); return 0; } } return 1; } #define LOOK_AHEAD(t, token) (t != EOF && \ (unsigned char)(t)==(unsigned char)(token)[0] && \ do_look_ahead(t,token)) /* * macro - the work horse.. */ static void macro(void) { char token[MAXTOK+1]; int t, l; ndptr p; int nlpar; cycle { t = gpbc(); if (LOOK_AHEAD(t,lquote)) { /* strip quotes */ nlpar = 0; record(quotes, nlpar++); /* * Opening quote: scan forward until matching * closing quote has been found. */ do { l = gpbc(); if (LOOK_AHEAD(l,rquote)) { if (--nlpar > 0) outputstr(rquote); } else if (LOOK_AHEAD(l,lquote)) { record(quotes, nlpar++); outputstr(lquote); } else if (l == EOF) { if (nlpar == 1) warnx("unclosed quote:"); else warnx("%d unclosed quotes:", nlpar); dump_stack(quotes, nlpar); exit(1); } else { if (nlpar > 0) { if (sp < 0) reallyputchar(l); else CHRSAVE(l); } } } while (nlpar != 0); } else if (sp < 0 && LOOK_AHEAD(t, scommt)) { reallyoutputstr(scommt); for(;;) { t = gpbc(); if (LOOK_AHEAD(t, ecommt)) { reallyoutputstr(ecommt); break; } if (t == EOF) break; reallyputchar(t); } } else if (t == '_' || isalpha(t)) { p = inspect(t, token); if (p != NULL) pushback(l = gpbc()); if (p == NULL || (l != LPAREN && (macro_getdef(p)->type & NEEDARGS) != 0)) outputstr(token); else { /* * real thing.. First build a call frame: */ pushf(fp); /* previous call frm */ pushf(macro_getdef(p)->type); /* type of the call */ pushf(is_traced(p)); pushf(0); /* parenthesis level */ fp = sp; /* new frame pointer */ /* * now push the string arguments: */ pushs1(macro_getdef(p)->defn); /* defn string */ pushs1((char *)macro_name(p)); /* macro name */ pushs(ep); /* start next..*/ if (l != LPAREN && PARLEV == 0) { /* no bracks */ chrsave(EOS); if (sp == (int)STACKMAX) errx(1, "internal stack overflow"); eval((const char **) mstack+fp+1, 2, CALTYP, TRACESTATUS); ep = PREVEP; /* flush strspace */ sp = PREVSP; /* previous sp.. */ fp = PREVFP; /* rewind stack...*/ } } } else if (t == EOF) { if (sp > -1 && ilevel <= 0) { warnx( "unexpected end of input, unclosed parenthesis:"); dump_stack(paren, PARLEV); exit(1); } if (ilevel <= 0) break; /* all done thanks.. */ release_input(infile+ilevel--); emit_synchline(); bufbase = bbase[ilevel]; continue; } else if (sp < 0) { /* not in a macro at all */ reallyputchar(t); /* output directly.. */ } else switch(t) { case LPAREN: if (PARLEV > 0) chrsave(t); while (isspace(l = gpbc())) /* skip blank, tab, nl.. */ if (PARLEV > 0) chrsave(l); pushback(l); record(paren, PARLEV++); break; case RPAREN: if (--PARLEV > 0) chrsave(t); else { /* end of argument list */ chrsave(EOS); if (sp == (int)STACKMAX) errx(1, "internal stack overflow"); eval((const char **) mstack+fp+1, sp-fp, CALTYP, TRACESTATUS); ep = PREVEP; /* flush strspace */ sp = PREVSP; /* previous sp.. */ fp = PREVFP; /* rewind stack...*/ } break; case COMMA: if (PARLEV == 1) { chrsave(EOS); /* new argument */ while (isspace(l = gpbc())) ; pushback(l); pushs(ep); } else chrsave(t); break; default: if (LOOK_AHEAD(t, scommt)) { char *cp; for (cp = scommt; *cp; cp++) chrsave(*cp); for(;;) { t = gpbc(); if (LOOK_AHEAD(t, ecommt)) { for (cp = ecommt; *cp; cp++) chrsave(*cp); break; } if (t == EOF) break; CHRSAVE(t); } } else CHRSAVE(t); /* stack the char */ break; } } } /* * output string directly, without pushing it for reparses. */ void outputstr(const char *s) { if (sp < 0) reallyoutputstr(s); else while (*s) CHRSAVE(*s++); } void reallyoutputstr(const char *s) { if (synch_lines) { while (*s) { fputc(*s, active); if (*s++ == '\n') { infile[ilevel].synch_lineno++; if (infile[ilevel].synch_lineno != infile[ilevel].lineno) do_emit_synchline(); } } } else fputs(s, active); } void reallyputchar(int c) { putc(c, active); if (synch_lines && c == '\n') { infile[ilevel].synch_lineno++; if (infile[ilevel].synch_lineno != infile[ilevel].lineno) do_emit_synchline(); } } /* * build an input token.. * consider only those starting with _ or A-Za-z. */ static ndptr inspect(int c, char *tp) { char *name = tp; char *etp = tp+MAXTOK; ndptr p; *tp++ = c; while ((isalnum(c = gpbc()) || c == '_') && tp < etp) *tp++ = c; if (c != EOF) PUSHBACK(c); *tp = EOS; /* token is too long, it won't match anything, but it can still * be output. */ if (tp == ep) { outputstr(name); while (isalnum(c = gpbc()) || c == '_') { if (sp < 0) reallyputchar(c); else CHRSAVE(c); } *name = EOS; return NULL; } p = ohash_find(¯os, ohash_qlookupi(¯os, name, (const char **)&tp)); if (p == NULL) return NULL; if (macro_getdef(p) == NULL) return NULL; return p; } /* * initkwds - initialise m4 keywords as fast as possible. * This very similar to install, but without certain overheads, * such as calling lookup. Malloc is not used for storing the * keyword strings, since we simply use the static pointers * within keywrds block. */ static void initkwds(void) { unsigned int type; int i; for (i = 0; i < (int)MAXKEYS; i++) { type = keywrds[i].ktyp & TYPEMASK; if ((keywrds[i].ktyp & NOARGS) == 0) type |= NEEDARGS; setup_builtin(keywrds[i].knam, type); } } static void record(struct position *t, int lev) { if (lev < MAXRECORD) { t[lev].name = CURRENT_NAME; t[lev].line = CURRENT_LINE; } } static void dump_stack(struct position *t, int lev) { int i; for (i = 0; i < lev; i++) { if (i == MAXRECORD) { fprintf(stderr, " ...\n"); break; } fprintf(stderr, " %s at line %lu\n", t[i].name, t[i].line); } } static void enlarge_stack(void) { STACKMAX += STACKMAX/2; mstack = xrealloc(mstack, sizeof(stae) * STACKMAX, "Evaluation stack overflow (%lu)", (unsigned long)STACKMAX); sstack = xrealloc(sstack, STACKMAX, "Evaluation stack overflow (%lu)", (unsigned long)STACKMAX); } Index: head/usr.bin/m4/parser.y =================================================================== --- head/usr.bin/m4/parser.y (revision 241776) +++ head/usr.bin/m4/parser.y (revision 241777) @@ -1,85 +1,92 @@ %{ /* $OpenBSD: parser.y,v 1.6 2008/08/21 21:00:14 espie Exp $ */ /* * Copyright (c) 2004 Marc Espie * * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. * * $FreeBSD$ */ + #include +#include +#include #include + +#include "mdef.h" +#include "extern.h" + #define YYSTYPE int32_t -extern int32_t end_result; + extern int yylex(void); extern int yyerror(const char *); %} %token NUMBER %token ERROR %left LOR %left LAND %left '|' %left '^' %left '&' %left EQ NE %left '<' LE '>' GE %left LSHIFT RSHIFT %left '+' '-' %left '*' '/' '%' %right EXPONENT %right UMINUS UPLUS '!' '~' %% top : expr { end_result = $1; } ; expr : expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr EXPONENT expr { $$ = pow($1, $3); } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { if ($3 == 0) { yyerror("division by zero"); exit(1); } $$ = $1 / $3; } | expr '%' expr { if ($3 == 0) { yyerror("modulo zero"); exit(1); } $$ = $1 % $3; } | expr LSHIFT expr { $$ = $1 << $3; } | expr RSHIFT expr { $$ = $1 >> $3; } | expr '<' expr { $$ = $1 < $3; } | expr '>' expr { $$ = $1 > $3; } | expr LE expr { $$ = $1 <= $3; } | expr GE expr { $$ = $1 >= $3; } | expr EQ expr { $$ = $1 == $3; } | expr NE expr { $$ = $1 != $3; } | expr '&' expr { $$ = $1 & $3; } | expr '^' expr { $$ = $1 ^ $3; } | expr '|' expr { $$ = $1 | $3; } | expr LAND expr { $$ = $1 && $3; } | expr LOR expr { $$ = $1 || $3; } | '(' expr ')' { $$ = $2; } | '-' expr %prec UMINUS { $$ = -$2; } | '+' expr %prec UPLUS { $$ = $2; } | '!' expr { $$ = !$2; } | '~' expr { $$ = ~$2; } | NUMBER ; %% Index: head/usr.sbin/mtree/mtree.c =================================================================== --- head/usr.sbin/mtree/mtree.c (revision 241776) +++ head/usr.sbin/mtree/mtree.c (revision 241777) @@ -1,190 +1,191 @@ /*- * Copyright (c) 1989, 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. 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) 1989, 1990, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "mtree.h" #include "extern.h" int ftsoptions = FTS_PHYSICAL; -int cflag, dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, Uflag, wflag; +int dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, wflag; +static int cflag, Uflag; u_int keys; char fullpath[MAXPATHLEN]; static void usage(void); int main(int argc, char *argv[]) { int ch; char *dir, *p; int status; FILE *spec1, *spec2; dir = NULL; keys = KEYDEFAULT; init_excludes(); spec1 = stdin; spec2 = NULL; while ((ch = getopt(argc, argv, "cdef:iK:k:LnPp:qrs:UuwxX:")) != -1) switch((char)ch) { case 'c': cflag = 1; break; case 'd': dflag = 1; break; case 'e': eflag = 1; break; case 'f': if (spec1 == stdin) { spec1 = fopen(optarg, "r"); if (spec1 == NULL) err(1, "%s", optarg); } else if (spec2 == NULL) { spec2 = fopen(optarg, "r"); if (spec2 == NULL) err(1, "%s", optarg); } else usage(); break; case 'i': iflag = 1; break; case 'K': while ((p = strsep(&optarg, " \t,")) != NULL) if (*p != '\0') keys |= parsekey(p, NULL); break; case 'k': keys = F_TYPE; while ((p = strsep(&optarg, " \t,")) != NULL) if (*p != '\0') keys |= parsekey(p, NULL); break; case 'L': ftsoptions &= ~FTS_PHYSICAL; ftsoptions |= FTS_LOGICAL; break; case 'n': nflag = 1; break; case 'P': ftsoptions &= ~FTS_LOGICAL; ftsoptions |= FTS_PHYSICAL; break; case 'p': dir = optarg; break; case 'q': qflag = 1; break; case 'r': rflag = 1; break; case 's': sflag = 1; crc_total = ~strtoul(optarg, &p, 0); if (*p) errx(1, "illegal seed value -- %s", optarg); break; case 'U': Uflag = 1; uflag = 1; break; case 'u': uflag = 1; break; case 'w': wflag = 1; break; case 'x': ftsoptions |= FTS_XDEV; break; case 'X': read_excludes_file(optarg); break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc) usage(); if (dir && chdir(dir)) err(1, "%s", dir); if ((cflag || sflag) && !getcwd(fullpath, sizeof(fullpath))) errx(1, "%s", fullpath); if (cflag) { cwalk(); exit(0); } if (spec2 != NULL) status = mtree_specspec(spec1, spec2); else status = mtree_verifyspec(spec1); if (Uflag & (status == MISMATCHEXIT)) status = 0; exit(status); } static void usage(void) { (void)fprintf(stderr, "usage: mtree [-LPUcdeinqruxw] [-f spec] [-f spec] [-K key] [-k key] [-p path] [-s seed]\n" "\t[-X excludes]\n"); exit(1); } Index: head/usr.sbin/newsyslog/newsyslog.c =================================================================== --- head/usr.sbin/newsyslog/newsyslog.c (revision 241776) +++ head/usr.sbin/newsyslog/newsyslog.c (revision 241777) @@ -1,2558 +1,2560 @@ /*- * ------+---------+---------+-------- + --------+---------+---------+---------* * This file includes significant modifications done by: * Copyright (c) 2003, 2004 - Garance Alistair Drosehn . * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * ------+---------+---------+-------- + --------+---------+---------+---------* */ /* * This file contains changes from the Open Software Foundation. */ /* * Copyright 1988, 1989 by the Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. and the M.I.T. * S.I.P.B. make no representations about the suitability of this software * for any purpose. It is provided "as is" without express or implied * warranty. * */ /* * newsyslog - roll over selected logs at the appropriate time, keeping the a * specified number of backup files around. */ #include __FBSDID("$FreeBSD$"); #define OSF #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" #include "extern.h" /* * Compression suffixes */ #ifndef COMPRESS_SUFFIX_GZ #define COMPRESS_SUFFIX_GZ ".gz" #endif #ifndef COMPRESS_SUFFIX_BZ2 #define COMPRESS_SUFFIX_BZ2 ".bz2" #endif #ifndef COMPRESS_SUFFIX_XZ #define COMPRESS_SUFFIX_XZ ".xz" #endif #define COMPRESS_SUFFIX_MAXLEN MAX(MAX(sizeof(COMPRESS_SUFFIX_GZ),sizeof(COMPRESS_SUFFIX_BZ2)),sizeof(COMPRESS_SUFFIX_XZ)) /* * Compression types */ #define COMPRESS_TYPES 4 /* Number of supported compression types */ #define COMPRESS_NONE 0 #define COMPRESS_GZIP 1 #define COMPRESS_BZIP2 2 #define COMPRESS_XZ 3 /* * Bit-values for the 'flags' parsed from a config-file entry. */ #define CE_BINARY 0x0008 /* Logfile is in binary, do not add status */ /* messages to logfile(s) when rotating. */ #define CE_NOSIGNAL 0x0010 /* There is no process to signal when */ /* trimming this file. */ #define CE_TRIMAT 0x0020 /* trim file at a specific time. */ #define CE_GLOB 0x0040 /* name of the log is file name pattern. */ #define CE_SIGNALGROUP 0x0080 /* Signal a process-group instead of a single */ /* process when trimming this file. */ #define CE_CREATE 0x0100 /* Create the log file if it does not exist. */ #define CE_NODUMP 0x0200 /* Set 'nodump' on newly created log file. */ #define CE_PID2CMD 0x0400 /* Replace PID file with a shell command.*/ #define MIN_PID 5 /* Don't touch pids lower than this */ #define MAX_PID 99999 /* was lower, see /usr/include/sys/proc.h */ #define kbytes(size) (((size) + 1023) >> 10) #define DEFAULT_MARKER "" #define DEBUG_MARKER "" #define INCLUDE_MARKER "" #define DEFAULT_TIMEFNAME_FMT "%Y%m%dT%H%M%S" #define MAX_OLDLOGS 65536 /* Default maximum number of old logfiles */ struct compress_types { const char *flag; /* Flag in configuration file */ const char *suffix; /* Compression suffix */ const char *path; /* Path to compression program */ }; -const struct compress_types compress_type[COMPRESS_TYPES] = { +static const struct compress_types compress_type[COMPRESS_TYPES] = { { "", "", "" }, /* no compression */ { "Z", COMPRESS_SUFFIX_GZ, _PATH_GZIP }, /* gzip compression */ { "J", COMPRESS_SUFFIX_BZ2, _PATH_BZIP2 }, /* bzip2 compression */ { "X", COMPRESS_SUFFIX_XZ, _PATH_XZ } /* xz compression */ }; struct conf_entry { STAILQ_ENTRY(conf_entry) cf_nextp; char *log; /* Name of the log */ char *pid_cmd_file; /* PID or command file */ char *r_reason; /* The reason this file is being rotated */ int firstcreate; /* Creating log for the first time (-C). */ int rotate; /* Non-zero if this file should be rotated */ int fsize; /* size found for the log file */ uid_t uid; /* Owner of log */ gid_t gid; /* Group of log */ int numlogs; /* Number of logs to keep */ int trsize; /* Size cutoff to trigger trimming the log */ int hours; /* Hours between log trimming */ struct ptime_data *trim_at; /* Specific time to do trimming */ unsigned int permissions; /* File permissions on the log */ int flags; /* CE_BINARY */ int compress; /* Compression */ int sig; /* Signal to send */ int def_cfg; /* Using the rule for this file */ }; struct sigwork_entry { SLIST_ENTRY(sigwork_entry) sw_nextp; int sw_signum; /* the signal to send */ int sw_pidok; /* true if pid value is valid */ pid_t sw_pid; /* the process id from the PID file */ const char *sw_pidtype; /* "daemon" or "process group" */ int run_cmd; /* run command or send PID to signal */ char sw_fname[1]; /* file the PID was read from or shell cmd */ }; struct zipwork_entry { SLIST_ENTRY(zipwork_entry) zw_nextp; const struct conf_entry *zw_conf; /* for chown/perm/flag info */ const struct sigwork_entry *zw_swork; /* to know success of signal */ int zw_fsize; /* size of the file to compress */ char zw_fname[1]; /* the file to compress */ }; struct include_entry { STAILQ_ENTRY(include_entry) inc_nextp; const char *file; /* Name of file to process */ }; struct oldlog_entry { char *fname; /* Filename of the log file */ time_t t; /* Parsed timestamp of the logfile */ }; typedef enum { FREE_ENT, KEEP_ENT } fk_entry; STAILQ_HEAD(cflist, conf_entry); -SLIST_HEAD(swlisthead, sigwork_entry) swhead = SLIST_HEAD_INITIALIZER(swhead); -SLIST_HEAD(zwlisthead, zipwork_entry) zwhead = SLIST_HEAD_INITIALIZER(zwhead); +static SLIST_HEAD(swlisthead, sigwork_entry) swhead = + SLIST_HEAD_INITIALIZER(swhead); +static SLIST_HEAD(zwlisthead, zipwork_entry) zwhead = + SLIST_HEAD_INITIALIZER(zwhead); STAILQ_HEAD(ilist, include_entry); int dbg_at_times; /* -D Show details of 'trim_at' code */ -int archtodir = 0; /* Archive old logfiles to other directory */ -int createlogs; /* Create (non-GLOB) logfiles which do not */ +static int archtodir = 0; /* Archive old logfiles to other directory */ +static int createlogs; /* Create (non-GLOB) logfiles which do not */ /* already exist. 1=='for entries with */ /* C flag', 2=='for all entries'. */ int verbose = 0; /* Print out what's going on */ -int needroot = 1; /* Root privs are necessary */ +static int needroot = 1; /* Root privs are necessary */ int noaction = 0; /* Don't do anything, just show it */ -int norotate = 0; /* Don't rotate */ -int nosignal; /* Do not send any signals */ -int enforcepid = 0; /* If PID file does not exist or empty, do nothing */ -int force = 0; /* Force the trim no matter what */ -int rotatereq = 0; /* -R = Always rotate the file(s) as given */ +static int norotate = 0; /* Don't rotate */ +static int nosignal; /* Do not send any signals */ +static int enforcepid = 0; /* If PID file does not exist or empty, do nothing */ +static int force = 0; /* Force the trim no matter what */ +static int rotatereq = 0; /* -R = Always rotate the file(s) as given */ /* on the command (this also requires */ /* that a list of files *are* given on */ /* the run command). */ -char *requestor; /* The name given on a -R request */ -char *timefnamefmt = NULL; /* Use time based filenames instead of .0 etc */ -char *archdirname; /* Directory path to old logfiles archive */ -char *destdir = NULL; /* Directory to treat at root for logs */ -const char *conf; /* Configuration file to use */ +static char *requestor; /* The name given on a -R request */ +static char *timefnamefmt = NULL;/* Use time based filenames instead of .0 */ +static char *archdirname; /* Directory path to old logfiles archive */ +static char *destdir = NULL; /* Directory to treat at root for logs */ +static const char *conf; /* Configuration file to use */ struct ptime_data *dbg_timenow; /* A "timenow" value set via -D option */ -struct ptime_data *timenow; /* The time to use for checking at-fields */ +static struct ptime_data *timenow; /* The time to use for checking at-fields */ #define DAYTIME_LEN 16 -char daytime[DAYTIME_LEN]; /* The current time in human readable form, - * used for rotation-tracking messages. */ -char hostname[MAXHOSTNAMELEN]; /* hostname */ +static char daytime[DAYTIME_LEN];/* The current time in human readable form, + * used for rotation-tracking messages. */ +static char hostname[MAXHOSTNAMELEN]; /* hostname */ -const char *path_syslogpid = _PATH_SYSLOGPID; +static const char *path_syslogpid = _PATH_SYSLOGPID; static struct cflist *get_worklist(char **files); static void parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p, struct conf_entry *defconf_p, struct ilist *inclist); static void add_to_queue(const char *fname, struct ilist *inclist); static char *sob(char *p); static char *son(char *p); static int isnumberstr(const char *); static int isglobstr(const char *); static char *missing_field(char *p, char *errline); static void change_attrs(const char *, const struct conf_entry *); static const char *get_logfile_suffix(const char *logfile); static fk_entry do_entry(struct conf_entry *); static fk_entry do_rotate(const struct conf_entry *); static void do_sigwork(struct sigwork_entry *); static void do_zipwork(struct zipwork_entry *); static struct sigwork_entry * save_sigwork(const struct conf_entry *); static struct zipwork_entry * save_zipwork(const struct conf_entry *, const struct sigwork_entry *, int, const char *); static void set_swpid(struct sigwork_entry *, const struct conf_entry *); static int sizefile(const char *); static void expand_globs(struct cflist *work_p, struct cflist *glob_p); static void free_clist(struct cflist *list); static void free_entry(struct conf_entry *ent); static struct conf_entry *init_entry(const char *fname, struct conf_entry *src_entry); static void parse_args(int argc, char **argv); static int parse_doption(const char *doption); static void usage(void); static int log_trim(const char *logname, const struct conf_entry *log_ent); static int age_old_log(char *file); static void savelog(char *from, char *to); static void createdir(const struct conf_entry *ent, char *dirpart); static void createlog(const struct conf_entry *ent); /* * All the following take a parameter of 'int', but expect values in the * range of unsigned char. Define wrappers which take values of type 'char', * whether signed or unsigned, and ensure they end up in the right range. */ #define isdigitch(Anychar) isdigit((u_char)(Anychar)) #define isprintch(Anychar) isprint((u_char)(Anychar)) #define isspacech(Anychar) isspace((u_char)(Anychar)) #define tolowerch(Anychar) tolower((u_char)(Anychar)) int main(int argc, char **argv) { struct cflist *worklist; struct conf_entry *p; struct sigwork_entry *stmp; struct zipwork_entry *ztmp; SLIST_INIT(&swhead); SLIST_INIT(&zwhead); parse_args(argc, argv); argc -= optind; argv += optind; if (needroot && getuid() && geteuid()) errx(1, "must have root privs"); worklist = get_worklist(argv); /* * Rotate all the files which need to be rotated. Note that * some users have *hundreds* of entries in newsyslog.conf! */ while (!STAILQ_EMPTY(worklist)) { p = STAILQ_FIRST(worklist); STAILQ_REMOVE_HEAD(worklist, cf_nextp); if (do_entry(p) == FREE_ENT) free_entry(p); } /* * Send signals to any processes which need a signal to tell * them to close and re-open the log file(s) we have rotated. * Note that zipwork_entries include pointers to these * sigwork_entry's, so we can not free the entries here. */ if (!SLIST_EMPTY(&swhead)) { if (noaction || verbose) printf("Signal all daemon process(es)...\n"); SLIST_FOREACH(stmp, &swhead, sw_nextp) do_sigwork(stmp); if (noaction) printf("\tsleep 10\n"); else { if (verbose) printf("Pause 10 seconds to allow daemon(s)" " to close log file(s)\n"); sleep(10); } } /* * Compress all files that we're expected to compress, now * that all processes should have closed the files which * have been rotated. */ if (!SLIST_EMPTY(&zwhead)) { if (noaction || verbose) printf("Compress all rotated log file(s)...\n"); while (!SLIST_EMPTY(&zwhead)) { ztmp = SLIST_FIRST(&zwhead); do_zipwork(ztmp); SLIST_REMOVE_HEAD(&zwhead, zw_nextp); free(ztmp); } } /* Now free all the sigwork entries. */ while (!SLIST_EMPTY(&swhead)) { stmp = SLIST_FIRST(&swhead); SLIST_REMOVE_HEAD(&swhead, sw_nextp); free(stmp); } while (wait(NULL) > 0 || errno == EINTR) ; return (0); } static struct conf_entry * init_entry(const char *fname, struct conf_entry *src_entry) { struct conf_entry *tempwork; if (verbose > 4) printf("\t--> [creating entry for %s]\n", fname); tempwork = malloc(sizeof(struct conf_entry)); if (tempwork == NULL) err(1, "malloc of conf_entry for %s", fname); if (destdir == NULL || fname[0] != '/') tempwork->log = strdup(fname); else asprintf(&tempwork->log, "%s%s", destdir, fname); if (tempwork->log == NULL) err(1, "strdup for %s", fname); if (src_entry != NULL) { tempwork->pid_cmd_file = NULL; if (src_entry->pid_cmd_file) tempwork->pid_cmd_file = strdup(src_entry->pid_cmd_file); tempwork->r_reason = NULL; tempwork->firstcreate = 0; tempwork->rotate = 0; tempwork->fsize = -1; tempwork->uid = src_entry->uid; tempwork->gid = src_entry->gid; tempwork->numlogs = src_entry->numlogs; tempwork->trsize = src_entry->trsize; tempwork->hours = src_entry->hours; tempwork->trim_at = NULL; if (src_entry->trim_at != NULL) tempwork->trim_at = ptime_init(src_entry->trim_at); tempwork->permissions = src_entry->permissions; tempwork->flags = src_entry->flags; tempwork->compress = src_entry->compress; tempwork->sig = src_entry->sig; tempwork->def_cfg = src_entry->def_cfg; } else { /* Initialize as a "do-nothing" entry */ tempwork->pid_cmd_file = NULL; tempwork->r_reason = NULL; tempwork->firstcreate = 0; tempwork->rotate = 0; tempwork->fsize = -1; tempwork->uid = (uid_t)-1; tempwork->gid = (gid_t)-1; tempwork->numlogs = 1; tempwork->trsize = -1; tempwork->hours = -1; tempwork->trim_at = NULL; tempwork->permissions = 0; tempwork->flags = 0; tempwork->compress = COMPRESS_NONE; tempwork->sig = SIGHUP; tempwork->def_cfg = 0; } return (tempwork); } static void free_entry(struct conf_entry *ent) { if (ent == NULL) return; if (ent->log != NULL) { if (verbose > 4) printf("\t--> [freeing entry for %s]\n", ent->log); free(ent->log); ent->log = NULL; } if (ent->pid_cmd_file != NULL) { free(ent->pid_cmd_file); ent->pid_cmd_file = NULL; } if (ent->r_reason != NULL) { free(ent->r_reason); ent->r_reason = NULL; } if (ent->trim_at != NULL) { ptime_free(ent->trim_at); ent->trim_at = NULL; } free(ent); } static void free_clist(struct cflist *list) { struct conf_entry *ent; while (!STAILQ_EMPTY(list)) { ent = STAILQ_FIRST(list); STAILQ_REMOVE_HEAD(list, cf_nextp); free_entry(ent); } free(list); list = NULL; } static fk_entry do_entry(struct conf_entry * ent) { #define REASON_MAX 80 int modtime; fk_entry free_or_keep; double diffsecs; char temp_reason[REASON_MAX]; int oversized; free_or_keep = FREE_ENT; if (verbose) printf("%s <%d%s>: ", ent->log, ent->numlogs, compress_type[ent->compress].flag); ent->fsize = sizefile(ent->log); oversized = ((ent->trsize > 0) && (ent->fsize >= ent->trsize)); modtime = age_old_log(ent->log); ent->rotate = 0; ent->firstcreate = 0; if (ent->fsize < 0) { /* * If either the C flag or the -C option was specified, * and if we won't be creating the file, then have the * verbose message include a hint as to why the file * will not be created. */ temp_reason[0] = '\0'; if (createlogs > 1) ent->firstcreate = 1; else if ((ent->flags & CE_CREATE) && createlogs) ent->firstcreate = 1; else if (ent->flags & CE_CREATE) strlcpy(temp_reason, " (no -C option)", REASON_MAX); else if (createlogs) strlcpy(temp_reason, " (no C flag)", REASON_MAX); if (ent->firstcreate) { if (verbose) printf("does not exist -> will create.\n"); createlog(ent); } else if (verbose) { printf("does not exist, skipped%s.\n", temp_reason); } } else { if (ent->flags & CE_TRIMAT && !force && !rotatereq && !oversized) { diffsecs = ptimeget_diff(timenow, ent->trim_at); if (diffsecs < 0.0) { /* trim_at is some time in the future. */ if (verbose) { ptime_adjust4dst(ent->trim_at, timenow); printf("--> will trim at %s", ptimeget_ctime(ent->trim_at)); } return (free_or_keep); } else if (diffsecs >= 3600.0) { /* * trim_at is more than an hour in the past, * so find the next valid trim_at time, and * tell the user what that will be. */ if (verbose && dbg_at_times) printf("\n\t--> prev trim at %s\t", ptimeget_ctime(ent->trim_at)); if (verbose) { ptimeset_nxtime(ent->trim_at); printf("--> will trim at %s", ptimeget_ctime(ent->trim_at)); } return (free_or_keep); } else if (verbose && noaction && dbg_at_times) { /* * If we are just debugging at-times, then * a detailed message is helpful. Also * skip "doing" any commands, since they * would all be turned off by no-action. */ printf("\n\t--> timematch at %s", ptimeget_ctime(ent->trim_at)); return (free_or_keep); } else if (verbose && ent->hours <= 0) { printf("--> time is up\n"); } } if (verbose && (ent->trsize > 0)) printf("size (Kb): %d [%d] ", ent->fsize, ent->trsize); if (verbose && (ent->hours > 0)) printf(" age (hr): %d [%d] ", modtime, ent->hours); /* * Figure out if this logfile needs to be rotated. */ temp_reason[0] = '\0'; if (rotatereq) { ent->rotate = 1; snprintf(temp_reason, REASON_MAX, " due to -R from %s", requestor); } else if (force) { ent->rotate = 1; snprintf(temp_reason, REASON_MAX, " due to -F request"); } else if (oversized) { ent->rotate = 1; snprintf(temp_reason, REASON_MAX, " due to size>%dK", ent->trsize); } else if (ent->hours <= 0 && (ent->flags & CE_TRIMAT)) { ent->rotate = 1; } else if ((ent->hours > 0) && ((modtime >= ent->hours) || (modtime < 0))) { ent->rotate = 1; } /* * If the file needs to be rotated, then rotate it. */ if (ent->rotate && !norotate) { if (temp_reason[0] != '\0') ent->r_reason = strdup(temp_reason); if (verbose) printf("--> trimming log....\n"); if (noaction && !verbose) printf("%s <%d%s>: trimming\n", ent->log, ent->numlogs, compress_type[ent->compress].flag); free_or_keep = do_rotate(ent); } else { if (verbose) printf("--> skipping\n"); } } return (free_or_keep); #undef REASON_MAX } static void parse_args(int argc, char **argv) { int ch; char *p; timenow = ptime_init(NULL); ptimeset_time(timenow, time(NULL)); strlcpy(daytime, ptimeget_ctime(timenow) + 4, DAYTIME_LEN); /* Let's get our hostname */ (void)gethostname(hostname, sizeof(hostname)); /* Truncate domain */ if ((p = strchr(hostname, '.')) != NULL) *p = '\0'; /* Parse command line options. */ while ((ch = getopt(argc, argv, "a:d:f:nrst:vCD:FNPR:S:")) != -1) switch (ch) { case 'a': archtodir++; archdirname = optarg; break; case 'd': destdir = optarg; break; case 'f': conf = optarg; break; case 'n': noaction++; break; case 'r': needroot = 0; break; case 's': nosignal = 1; break; case 't': if (optarg[0] == '\0' || strcmp(optarg, "DEFAULT") == 0) timefnamefmt = strdup(DEFAULT_TIMEFNAME_FMT); else timefnamefmt = strdup(optarg); break; case 'v': verbose++; break; case 'C': /* Useful for things like rc.diskless... */ createlogs++; break; case 'D': /* * Set some debugging option. The specific option * depends on the value of optarg. These options * may come and go without notice or documentation. */ if (parse_doption(optarg)) break; usage(); /* NOTREACHED */ case 'F': force++; break; case 'N': norotate++; break; case 'P': enforcepid++; break; case 'R': rotatereq++; requestor = strdup(optarg); break; case 'S': path_syslogpid = optarg; break; case 'm': /* Used by OpenBSD for "monitor mode" */ default: usage(); /* NOTREACHED */ } if (force && norotate) { warnx("Only one of -F and -N may be specified."); usage(); /* NOTREACHED */ } if (rotatereq) { if (optind == argc) { warnx("At least one filename must be given when -R is specified."); usage(); /* NOTREACHED */ } /* Make sure "requestor" value is safe for a syslog message. */ for (p = requestor; *p != '\0'; p++) { if (!isprintch(*p) && (*p != '\t')) *p = '.'; } } if (dbg_timenow) { /* * Note that the 'daytime' variable is not changed. * That is only used in messages that track when a * logfile is rotated, and if a file *is* rotated, * then it will still rotated at the "real now" time. */ ptime_free(timenow); timenow = dbg_timenow; fprintf(stderr, "Debug: Running as if TimeNow is %s", ptimeget_ctime(dbg_timenow)); } } /* * These debugging options are mainly meant for developer use, such * as writing regression-tests. They would not be needed by users * during normal operation of newsyslog... */ static int parse_doption(const char *doption) { const char TN[] = "TN="; int res; if (strncmp(doption, TN, sizeof(TN) - 1) == 0) { /* * The "TimeNow" debugging option. This might be off * by an hour when crossing a timezone change. */ dbg_timenow = ptime_init(NULL); res = ptime_relparse(dbg_timenow, PTM_PARSE_ISO8601, time(NULL), doption + sizeof(TN) - 1); if (res == -2) { warnx("Non-existent time specified on -D %s", doption); return (0); /* failure */ } else if (res < 0) { warnx("Malformed time given on -D %s", doption); return (0); /* failure */ } return (1); /* successfully parsed */ } if (strcmp(doption, "ats") == 0) { dbg_at_times++; return (1); /* successfully parsed */ } /* XXX - This check could probably be dropped. */ if ((strcmp(doption, "neworder") == 0) || (strcmp(doption, "oldorder") == 0)) { warnx("NOTE: newsyslog always uses 'neworder'."); return (1); /* successfully parsed */ } warnx("Unknown -D (debug) option: '%s'", doption); return (0); /* failure */ } static void usage(void) { fprintf(stderr, "usage: newsyslog [-CFNPnrsv] [-a directory] [-d directory] [-f config_file]\n" " [-S pidfile] [-t timefmt] [[-R tagname] file ...]\n"); exit(1); } /* * Parse a configuration file and return a linked list of all the logs * which should be processed. */ static struct cflist * get_worklist(char **files) { FILE *f; char **given; struct cflist *cmdlist, *filelist, *globlist; struct conf_entry *defconf, *dupent, *ent; struct ilist inclist; struct include_entry *inc; int gmatch, fnres; defconf = NULL; STAILQ_INIT(&inclist); filelist = malloc(sizeof(struct cflist)); if (filelist == NULL) err(1, "malloc of filelist"); STAILQ_INIT(filelist); globlist = malloc(sizeof(struct cflist)); if (globlist == NULL) err(1, "malloc of globlist"); STAILQ_INIT(globlist); inc = malloc(sizeof(struct include_entry)); if (inc == NULL) err(1, "malloc of inc"); inc->file = conf; if (inc->file == NULL) inc->file = _PATH_CONF; STAILQ_INSERT_TAIL(&inclist, inc, inc_nextp); STAILQ_FOREACH(inc, &inclist, inc_nextp) { if (strcmp(inc->file, "-") != 0) f = fopen(inc->file, "r"); else { f = stdin; inc->file = ""; } if (!f) err(1, "%s", inc->file); if (verbose) printf("Processing %s\n", inc->file); parse_file(f, filelist, globlist, defconf, &inclist); (void) fclose(f); } /* * All config-file information has been read in and turned into * a filelist and a globlist. If there were no specific files * given on the run command, then the only thing left to do is to * call a routine which finds all files matched by the globlist * and adds them to the filelist. Then return the worklist. */ if (*files == NULL) { expand_globs(filelist, globlist); free_clist(globlist); if (defconf != NULL) free_entry(defconf); return (filelist); /* NOTREACHED */ } /* * If newsyslog was given a specific list of files to process, * it may be that some of those files were not listed in any * config file. Those unlisted files should get the default * rotation action. First, create the default-rotation action * if none was found in a system config file. */ if (defconf == NULL) { defconf = init_entry(DEFAULT_MARKER, NULL); defconf->numlogs = 3; defconf->trsize = 50; defconf->permissions = S_IRUSR|S_IWUSR; } /* * If newsyslog was run with a list of specific filenames, * then create a new worklist which has only those files in * it, picking up the rotation-rules for those files from * the original filelist. * * XXX - Note that this will copy multiple rules for a single * logfile, if multiple entries are an exact match for * that file. That matches the historic behavior, but do * we want to continue to allow it? If so, it should * probably be handled more intelligently. */ cmdlist = malloc(sizeof(struct cflist)); if (cmdlist == NULL) err(1, "malloc of cmdlist"); STAILQ_INIT(cmdlist); for (given = files; *given; ++given) { /* * First try to find exact-matches for this given file. */ gmatch = 0; STAILQ_FOREACH(ent, filelist, cf_nextp) { if (strcmp(ent->log, *given) == 0) { gmatch++; dupent = init_entry(*given, ent); STAILQ_INSERT_TAIL(cmdlist, dupent, cf_nextp); } } if (gmatch) { if (verbose > 2) printf("\t+ Matched entry %s\n", *given); continue; } /* * There was no exact-match for this given file, so look * for a "glob" entry which does match. */ gmatch = 0; if (verbose > 2 && globlist != NULL) printf("\t+ Checking globs for %s\n", *given); STAILQ_FOREACH(ent, globlist, cf_nextp) { fnres = fnmatch(ent->log, *given, FNM_PATHNAME); if (verbose > 2) printf("\t+ = %d for pattern %s\n", fnres, ent->log); if (fnres == 0) { gmatch++; dupent = init_entry(*given, ent); /* This new entry is not a glob! */ dupent->flags &= ~CE_GLOB; STAILQ_INSERT_TAIL(cmdlist, dupent, cf_nextp); /* Only allow a match to one glob-entry */ break; } } if (gmatch) { if (verbose > 2) printf("\t+ Matched %s via %s\n", *given, ent->log); continue; } /* * This given file was not found in any config file, so * add a worklist item based on the default entry. */ if (verbose > 2) printf("\t+ No entry matched %s (will use %s)\n", *given, DEFAULT_MARKER); dupent = init_entry(*given, defconf); /* Mark that it was *not* found in a config file */ dupent->def_cfg = 1; STAILQ_INSERT_TAIL(cmdlist, dupent, cf_nextp); } /* * Free all the entries in the original work list, the list of * glob entries, and the default entry. */ free_clist(filelist); free_clist(globlist); free_entry(defconf); /* And finally, return a worklist which matches the given files. */ return (cmdlist); } /* * Expand the list of entries with filename patterns, and add all files * which match those glob-entries onto the worklist. */ static void expand_globs(struct cflist *work_p, struct cflist *glob_p) { int gmatch, gres; size_t i; char *mfname; struct conf_entry *dupent, *ent, *globent; glob_t pglob; struct stat st_fm; /* * The worklist contains all fully-specified (non-GLOB) names. * * Now expand the list of filename-pattern (GLOB) entries into * a second list, which (by definition) will only match files * that already exist. Do not add a glob-related entry for any * file which already exists in the fully-specified list. */ STAILQ_FOREACH(globent, glob_p, cf_nextp) { gres = glob(globent->log, GLOB_NOCHECK, NULL, &pglob); if (gres != 0) { warn("cannot expand pattern (%d): %s", gres, globent->log); continue; } if (verbose > 2) printf("\t+ Expanding pattern %s\n", globent->log); for (i = 0; i < pglob.gl_matchc; i++) { mfname = pglob.gl_pathv[i]; /* See if this file already has a specific entry. */ gmatch = 0; STAILQ_FOREACH(ent, work_p, cf_nextp) { if (strcmp(mfname, ent->log) == 0) { gmatch++; break; } } if (gmatch) continue; /* Make sure the named matched is a file. */ gres = lstat(mfname, &st_fm); if (gres != 0) { /* Error on a file that glob() matched?!? */ warn("Skipping %s - lstat() error", mfname); continue; } if (!S_ISREG(st_fm.st_mode)) { /* We only rotate files! */ if (verbose > 2) printf("\t+ . skipping %s (!file)\n", mfname); continue; } if (verbose > 2) printf("\t+ . add file %s\n", mfname); dupent = init_entry(mfname, globent); /* This new entry is not a glob! */ dupent->flags &= ~CE_GLOB; /* Add to the worklist. */ STAILQ_INSERT_TAIL(work_p, dupent, cf_nextp); } globfree(&pglob); if (verbose > 2) printf("\t+ Done with pattern %s\n", globent->log); } } /* * Parse a configuration file and update a linked list of all the logs to * process. */ static void parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p, struct conf_entry *defconf_p, struct ilist *inclist) { char line[BUFSIZ], *parse, *q; char *cp, *errline, *group; struct conf_entry *working; struct passwd *pwd; struct group *grp; glob_t pglob; int eol, ptm_opts, res, special; size_t i; errline = NULL; while (fgets(line, BUFSIZ, cf)) { if ((line[0] == '\n') || (line[0] == '#') || (strlen(line) == 0)) continue; if (errline != NULL) free(errline); errline = strdup(line); for (cp = line + 1; *cp != '\0'; cp++) { if (*cp != '#') continue; if (*(cp - 1) == '\\') { strcpy(cp - 1, cp); cp--; continue; } *cp = '\0'; break; } q = parse = missing_field(sob(line), errline); parse = son(line); if (!*parse) errx(1, "malformed line (missing fields):\n%s", errline); *parse = '\0'; /* * Allow people to set debug options via the config file. * (NOTE: debug options are undocumented, and may disappear * at any time, etc). */ if (strcasecmp(DEBUG_MARKER, q) == 0) { q = parse = missing_field(sob(++parse), errline); parse = son(parse); if (!*parse) warnx("debug line specifies no option:\n%s", errline); else { *parse = '\0'; parse_doption(q); } continue; } else if (strcasecmp(INCLUDE_MARKER, q) == 0) { if (verbose) printf("Found: %s", errline); q = parse = missing_field(sob(++parse), errline); parse = son(parse); if (!*parse) { warnx("include line missing argument:\n%s", errline); continue; } *parse = '\0'; if (isglobstr(q)) { res = glob(q, GLOB_NOCHECK, NULL, &pglob); if (res != 0) { warn("cannot expand pattern (%d): %s", res, q); continue; } if (verbose > 2) printf("\t+ Expanding pattern %s\n", q); for (i = 0; i < pglob.gl_matchc; i++) add_to_queue(pglob.gl_pathv[i], inclist); globfree(&pglob); } else add_to_queue(q, inclist); continue; } special = 0; working = init_entry(q, NULL); if (strcasecmp(DEFAULT_MARKER, q) == 0) { special = 1; if (defconf_p != NULL) { warnx("Ignoring duplicate entry for %s!", q); free_entry(working); continue; } defconf_p = working; } q = parse = missing_field(sob(++parse), errline); parse = son(parse); if (!*parse) errx(1, "malformed line (missing fields):\n%s", errline); *parse = '\0'; if ((group = strchr(q, ':')) != NULL || (group = strrchr(q, '.')) != NULL) { *group++ = '\0'; if (*q) { if (!(isnumberstr(q))) { if ((pwd = getpwnam(q)) == NULL) errx(1, "error in config file; unknown user:\n%s", errline); working->uid = pwd->pw_uid; } else working->uid = atoi(q); } else working->uid = (uid_t)-1; q = group; if (*q) { if (!(isnumberstr(q))) { if ((grp = getgrnam(q)) == NULL) errx(1, "error in config file; unknown group:\n%s", errline); working->gid = grp->gr_gid; } else working->gid = atoi(q); } else working->gid = (gid_t)-1; q = parse = missing_field(sob(++parse), errline); parse = son(parse); if (!*parse) errx(1, "malformed line (missing fields):\n%s", errline); *parse = '\0'; } else { working->uid = (uid_t)-1; working->gid = (gid_t)-1; } if (!sscanf(q, "%o", &working->permissions)) errx(1, "error in config file; bad permissions:\n%s", errline); q = parse = missing_field(sob(++parse), errline); parse = son(parse); if (!*parse) errx(1, "malformed line (missing fields):\n%s", errline); *parse = '\0'; if (!sscanf(q, "%d", &working->numlogs) || working->numlogs < 0) errx(1, "error in config file; bad value for count of logs to save:\n%s", errline); q = parse = missing_field(sob(++parse), errline); parse = son(parse); if (!*parse) errx(1, "malformed line (missing fields):\n%s", errline); *parse = '\0'; if (isdigitch(*q)) working->trsize = atoi(q); else if (strcmp(q, "*") == 0) working->trsize = -1; else { warnx("Invalid value of '%s' for 'size' in line:\n%s", q, errline); working->trsize = -1; } working->flags = 0; working->compress = COMPRESS_NONE; q = parse = missing_field(sob(++parse), errline); parse = son(parse); eol = !*parse; *parse = '\0'; { char *ep; u_long ul; ul = strtoul(q, &ep, 10); if (ep == q) working->hours = 0; else if (*ep == '*') working->hours = -1; else if (ul > INT_MAX) errx(1, "interval is too large:\n%s", errline); else working->hours = ul; if (*ep == '\0' || strcmp(ep, "*") == 0) goto no_trimat; if (*ep != '@' && *ep != '$') errx(1, "malformed interval/at:\n%s", errline); working->flags |= CE_TRIMAT; working->trim_at = ptime_init(NULL); ptm_opts = PTM_PARSE_ISO8601; if (*ep == '$') ptm_opts = PTM_PARSE_DWM; ptm_opts |= PTM_PARSE_MATCHDOM; res = ptime_relparse(working->trim_at, ptm_opts, ptimeget_secs(timenow), ep + 1); if (res == -2) errx(1, "nonexistent time for 'at' value:\n%s", errline); else if (res < 0) errx(1, "malformed 'at' value:\n%s", errline); } no_trimat: if (eol) q = NULL; else { q = parse = sob(++parse); /* Optional field */ parse = son(parse); if (!*parse) eol = 1; *parse = '\0'; } for (; q && *q && !isspacech(*q); q++) { switch (tolowerch(*q)) { case 'b': working->flags |= CE_BINARY; break; case 'c': /* * XXX - Ick! Ugly! Remove ASAP! * We want `c' and `C' for "create". But we * will temporarily treat `c' as `g', because * FreeBSD releases <= 4.8 have a typo of * checking ('G' || 'c') for CE_GLOB. */ if (*q == 'c') { warnx("Assuming 'g' for 'c' in flags for line:\n%s", errline); warnx("The 'c' flag will eventually mean 'CREATE'"); working->flags |= CE_GLOB; break; } working->flags |= CE_CREATE; break; case 'd': working->flags |= CE_NODUMP; break; case 'g': working->flags |= CE_GLOB; break; case 'j': working->compress = COMPRESS_BZIP2; break; case 'n': working->flags |= CE_NOSIGNAL; break; case 'r': working->flags |= CE_PID2CMD; break; case 'u': working->flags |= CE_SIGNALGROUP; break; case 'w': /* Depreciated flag - keep for compatibility purposes */ break; case 'x': working->compress = COMPRESS_XZ; break; case 'z': working->compress = COMPRESS_GZIP; break; case '-': break; case 'f': /* Used by OpenBSD for "CE_FOLLOW" */ case 'm': /* Used by OpenBSD for "CE_MONITOR" */ case 'p': /* Used by NetBSD for "CE_PLAIN0" */ default: errx(1, "illegal flag in config file -- %c", *q); } } if (eol) q = NULL; else { q = parse = sob(++parse); /* Optional field */ parse = son(parse); if (!*parse) eol = 1; *parse = '\0'; } working->pid_cmd_file = NULL; if (q && *q) { if (*q == '/') working->pid_cmd_file = strdup(q); else if (isdigit(*q)) goto got_sig; else errx(1, "illegal pid file or signal number in config file:\n%s", errline); } if (eol) q = NULL; else { q = parse = sob(++parse); /* Optional field */ *(parse = son(parse)) = '\0'; } working->sig = SIGHUP; if (q && *q) { if (isdigit(*q)) { got_sig: working->sig = atoi(q); } else { err_sig: errx(1, "illegal signal number in config file:\n%s", errline); } if (working->sig < 1 || working->sig >= NSIG) goto err_sig; } /* * Finish figuring out what pid-file to use (if any) in * later processing if this logfile needs to be rotated. */ if ((working->flags & CE_NOSIGNAL) == CE_NOSIGNAL) { /* * This config-entry specified 'n' for nosignal, * see if it also specified an explicit pid_cmd_file. * This would be a pretty pointless combination. */ if (working->pid_cmd_file != NULL) { warnx("Ignoring '%s' because flag 'n' was specified in line:\n%s", working->pid_cmd_file, errline); free(working->pid_cmd_file); working->pid_cmd_file = NULL; } } else if (working->pid_cmd_file == NULL) { /* * This entry did not specify the 'n' flag, which * means it should signal syslogd unless it had * specified some other pid-file (and obviously the * syslog pid-file will not be for a process-group). * Also, we should only try to notify syslog if we * are root. */ if (working->flags & CE_SIGNALGROUP) { warnx("Ignoring flag 'U' in line:\n%s", errline); working->flags &= ~CE_SIGNALGROUP; } if (needroot) working->pid_cmd_file = strdup(path_syslogpid); } /* * Add this entry to the appropriate list of entries, unless * it was some kind of special entry (eg: ). */ if (special) { ; /* Do not add to any list */ } else if (working->flags & CE_GLOB) { STAILQ_INSERT_TAIL(glob_p, working, cf_nextp); } else { STAILQ_INSERT_TAIL(work_p, working, cf_nextp); } } if (errline != NULL) free(errline); } static char * missing_field(char *p, char *errline) { if (!p || !*p) errx(1, "missing field in config file:\n%s", errline); return (p); } /* * In our sort we return it in the reverse of what qsort normally * would do, as we want the newest files first. If we have two * entries with the same time we don't really care about order. * * Support function for qsort() in delete_oldest_timelog(). */ static int oldlog_entry_compare(const void *a, const void *b) { const struct oldlog_entry *ola = a, *olb = b; if (ola->t > olb->t) return (-1); else if (ola->t < olb->t) return (1); else return (0); } /* * Delete the oldest logfiles, when using time based filenames. */ static void delete_oldest_timelog(const struct conf_entry *ent, const char *archive_dir) { char *logfname, *s, *dir, errbuf[80]; int dir_fd, i, logcnt, max_logcnt, valid; struct oldlog_entry *oldlogs; size_t logfname_len; struct dirent *dp; const char *cdir; struct tm tm; DIR *dirp; int c; oldlogs = malloc(MAX_OLDLOGS * sizeof(struct oldlog_entry)); max_logcnt = MAX_OLDLOGS; logcnt = 0; if (archive_dir != NULL && archive_dir[0] != '\0') cdir = archive_dir; else if ((cdir = dirname(ent->log)) == NULL) err(1, "dirname()"); if ((dir = strdup(cdir)) == NULL) err(1, "strdup()"); if ((s = basename(ent->log)) == NULL) err(1, "basename()"); if ((logfname = strdup(s)) == NULL) err(1, "strdup()"); logfname_len = strlen(logfname); if (strcmp(logfname, "/") == 0) errx(1, "Invalid log filename - became '/'"); if (verbose > 2) printf("Searching for old logs in %s\n", dir); /* First we create a 'list' of all archived logfiles */ if ((dirp = opendir(dir)) == NULL) err(1, "Cannot open log directory '%s'", dir); dir_fd = dirfd(dirp); while ((dp = readdir(dirp)) != NULL) { if (dp->d_type != DT_REG) continue; /* Ignore everything but files with our logfile prefix */ if (strncmp(dp->d_name, logfname, logfname_len) != 0) continue; /* Ignore the actual non-rotated logfile */ if (dp->d_namlen == logfname_len) continue; /* * Make sure we created have found a logfile, so the * postfix is valid, IE format is: '.