📄 lockdaemon.c.noinetd
字号:
/*-------------------------------------------------------------------------| lfd is a lock file server.| Copyright 2002-2004 by Trent Jarvi taj@www.linux.org.uk|| This software is free software; you can redistribute it and/or| modify it under the terms of the GNU General Public| License as published by the Free Software Foundation; either| version 2 of the License, or (at your option) any later version.|| This library is distributed in the hope that it will be useful,| but WITHOUT ANY WARRANTY; without even the implied warranty of| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU| Library General Public License for more details.|| You should have received a copy of the GNU General Public| License along with this software; if not, write to the Free| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA--------------------------------------------------------------------------*/#include <sys/types.h>#include <unistd.h>#include <sys/stat.h>#include <fcntl.h>#include <syslog.h>#include <sys/socket.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <arpa/inet.h>#include <errno.h>#include <signal.h>#include <pwd.h>#define LOCK fhs_lock#define UNLOCK fhs_unlock#define LOCKDIR "/var/lock"char hostname[256];#define M200 "200 Command okay.\n"#define M202 "202 Command not implemented\n"#define M220 "220 %s Lock File Server (Version rxtx-1.5-9) ready\n", hostname#define M221 "221 Thank you for using the Lock File service on %s\n", hostname#define M450 "450 : File busy.\n"#define M500 "500 '%s': command not understood\n", str#define M550 "550 : Permission denied.\n"int is_device_locked( const char * );int check_group_uucp();int check_lock_status( const char * );int check_lock_pid( const char *, int );#define UNEXPECTED_LOCK_FILE "RXTX Error: Unexpected lock file: %s\n Please report to the RXTX developers\n"#define UUCP_ERROR "\n\n\nRXTX WARNING: This library requires the user running applications to be in\ngroup uucp. Please consult the INSTALL documentation. More information is\navaiable under the topic 'How can I use Lock Files with rxtx?'\n" extern int errno;/*---------------------------------------------------------- fhs_lock accept: The name of the device to try to lock termios struct perform: Create a lock file if there is not one already. return: 1 on failure 0 on success exceptions: none comments: This is for linux and freebsd only currently. I see SVR4 does this differently and there are other proposed changes to the Filesystem Hierachy Standard more reading:----------------------------------------------------------*/int fhs_lock( const char *filename, int pid ){ /* * There is a zoo of lockdir possibilities * Its possible to check for stale processes with most of them. * for now we will just check for the lockfile on most * Problem lockfiles will be dealt with. Some may not even be in use. * */ int fd,j; char lockinfo[12], message[80]; char file[80], *p; j = strlen( filename ); p = ( char * ) filename + j; /* FIXME need to handle subdirectories /dev/cua/... SCO Unix use lowercase all the time taj */ while( *( p - 1 ) != '/' && j-- != 1 ) {#if defined ( __unixware__ ) *p = tolower( *p );#endif /* __unixware__ */ p--; } sprintf( file, "%s/LCK..%s", LOCKDIR, p ); if ( check_lock_status( filename ) ) { syslog( LOG_INFO, "fhs_lock() lockstatus fail\n" ); return 1; } fd = open( file, O_CREAT | O_WRONLY | O_EXCL, 0444 ); if( fd < 0 ) { sprintf( message, "RXTX fhs_lock() Error: creating lock file: %s: %s\n", file, strerror(errno) ); syslog( LOG_INFO, message ); return 1; } sprintf( lockinfo, "%10d\n", pid ); sprintf( message, "fhs_lock: creating lockfile: %s\n", lockinfo ); syslog( LOG_INFO, message ); write( fd, lockinfo, 11 ); close( fd ); return 0;}/*---------------------------------------------------------- uucp_lock accept: char * filename. Device to be locked perform: Try to get a uucp_lock return: int 0 on success exceptions: none comments: The File System Hierarchy Standard http://www.pathname.com/fhs/ UUCP Lock Files http://docs.freebsd.org/info/uucp/uucp.info.UUCP_Lock_Files.html FSSTND ftp://tsx-11.mit.edu/pub/linux/docs/linux-standards/fsstnd/ Proposed Changes to the File System Hierarchy Standard ftp://scicom.alphacdc.com/pub/linux/devlock-0.X.tgz "UNIX Network Programming", W. Richard Stevens, Prentice-Hall, 1990, pages 96-101. There is much to do here. 1) UUCP style locks (done) /var/spool/uucp 2) SVR4 locks /var/spool/locks 3) FSSTND locks (done) /var/lock 4) handle stale locks (done except kermit locks) 5) handle minicom lockfile contents (FSSTND?) " 16929 minicom root\n" (done) 6) there are other Lock conventions that use Major and Minor numbers... 7) Stevens recommends LCK..<pid> most are caught above. If they turn out to be problematic rather than an exercise, we will handle them.----------------------------------------------------------*/int uucp_lock( const char *filename, int pid ){ char lockfilename[80], lockinfo[12], message[80]; char name[80]; int fd; struct stat buf; sprintf( message, "uucp_lock( %s );\n", filename ); syslog( LOG_INFO, message ); if ( check_lock_status( filename ) ) { syslog( LOG_INFO, "RXTX uucp check_lock_status true\n" ); return 1; } if ( stat( LOCKDIR, &buf ) != 0 ) { syslog( LOG_INFO, "RXTX uucp_lock() could not find lock directory.\n" ); return 1; } if ( stat( filename, &buf ) != 0 ) { syslog( LOG_INFO, "RXTX uucp_lock() could not find device.\n" ); sprintf( message, "uucp_lock: device was %s\n", name ); syslog( LOG_INFO, message ); sprintf( message, "Filename is : %s \n", filename ); syslog( LOG_INFO, message ); return 1; } sprintf( lockfilename, "%s/LK.%03d.%03d.%03d", LOCKDIR, (int) major( buf.st_dev ), (int) major( buf.st_rdev ), (int) minor( buf.st_rdev ) ); sprintf( lockinfo, "%10d\n", pid ); if ( stat( lockfilename, &buf ) == 0 ) { sprintf( message, "RXTX uucp_lock() %s is there\n", lockfilename ); syslog( LOG_INFO, message ); syslog( LOG_INFO, message ); return 1; } fd = open( lockfilename, O_CREAT | O_WRONLY | O_EXCL, 0444 ); if( fd < 0 ) { sprintf( message, "RXTX uucp_lock() Error: creating lock file: %s\n", lockfilename ); syslog( LOG_INFO, message ); return 1; } write( fd, lockinfo,11 ); close( fd );/* setgid( nobody ); setuid( nobody );*/ return 0;}/*---------------------------------------------------------- check_lock_status accept: the lock name in question perform: Make sure everything is sane return: 0 on success exceptions: none comments: ----------------------------------------------------------*/int check_lock_status( const char *filename ){ struct stat buf; /* First, can we find the directory? */ if ( stat( LOCKDIR, &buf ) != 0 ) { syslog( LOG_INFO, "check_lock_status: could not find lock directory.\n" ); return 1; } /* OK. Are we able to write to it? If not lets bail */ if ( check_group_uucp() ) { syslog( LOG_INFO, "check_lock_status: No permission to create lock file. please see: How can I use Lock Files with rxtx? in INSTALL\n" ); return 1; } /* is the device alread locked */ if ( is_device_locked( filename ) ) { syslog( LOG_INFO, "check_lock_status: device is locked by another application\n" ); return 1; } return 0; }/*---------------------------------------------------------- fhs_unlock accept: The name of the device to unlock perform: delete the lock file return: none exceptions: none comments: This is for linux only currently. I see SVR4 does this differently and there are other proposed changes to the Filesystem Hierachy Standard----------------------------------------------------------*/int fhs_unlock( const char *filename, int openpid ){ char file[80],*p; struct stat buf; int i; i = strlen( filename ); p = ( char * ) filename + i; /* FIXME need to handle subdirectories /dev/cua/... */ while( *( p - 1 ) != '/' && i-- != 1 ) p--; sprintf( file, "%s/LCK..%s", LOCKDIR, p ); if ( ! check_lock_status( p ) ) { return 0; } if ( stat( filename, &buf ) != 0 ) { /* hmm the file is not there? */ syslog( LOG_INFO, "uucp_unlock() no such device\n" ); return(0); } if( !check_lock_pid( file, openpid ) ) { unlink(file); syslog( LOG_INFO,"fhs_unlock: Removing LockFile\n"); return( 0 ); } else { syslog( LOG_INFO,"fhs_unlock: Unable to remove LockFile\n"); return( 1 ); }}/*---------------------------------------------------------- uucp_unlock accept: char *filename the device that is locked perform: remove the uucp lockfile if it exists return: none exceptions: none comments: http://docs.freebsd.org/info/uucp/uucp.info.UUCP_Lock_Files.html ----------------------------------------------------------*/void uucp_unlock( const char *filename, int openpid ){ struct stat buf; char file[80], message[80]; /* FIXME */ sprintf( message, "uucp_unlock( %s );\n", filename ); syslog( LOG_INFO, message ); if ( stat( filename, &buf ) != 0 ) { /* hmm the file is not there? */ syslog( LOG_INFO, "uucp_unlock() no such device\n" ); return; } sprintf( file, LOCKDIR"/LK.%03d.%03d.%03d", (int) major( buf.st_dev ), (int) major( buf.st_rdev ), (int) minor( buf.st_rdev ) ); if ( stat( file, &buf ) != 0 ) { /* hmm the file is not there? */ syslog( LOG_INFO, "uucp_unlock no such lockfile\n" ); return; } if( !check_lock_pid( file, openpid ) ) { sprintf( message, "uucp_unlock: unlinking %s\n", file ); syslog( LOG_INFO, message ); unlink(file); } else { sprintf( message, "uucp_unlock: unlinking failed %s\n", file ); syslog( LOG_INFO, message ); }}/*---------------------------------------------------------- check_lock_pid accept: the name of the lockfile perform: make sure the lock file is ours. return: 0 on success exceptions: none comments: ----------------------------------------------------------*/int check_lock_pid( const char *file, int openpid ){ int fd, lockpid; char pid_buffer[12]; char message[80]; fd=open( file, O_RDONLY ); if ( fd < 0 ) { return( 1 ); } if ( read( fd, pid_buffer, 11 ) < 0 ) { close( fd ); return( 1 ); } close( fd ); pid_buffer[11] = '\0'; lockpid = atol( pid_buffer ); if ( lockpid != openpid ) { if( kill( (pid_t) lockpid, 0 ) && errno==ESRCH ) { return( 0 ); } sprintf(message, "check_lock_pid: lock = %s pid = %i gpid=%i openpid=%i\n", pid_buffer, (int) getpid(), (int) getppid(), openpid ); syslog( LOG_INFO, message ); return( 1 ); } return( 0 );}/*---------------------------------------------------------- check_group_uucp accept: none perform: check if the user is root or in group uucp return: 0 on success exceptions: none comments: This checks if the effective user is in group uucp so we can create lock files. If not we give them a warning and bail. If its root we just skip the test. if someone really wants to override this they can use the USER_LOCK_DIRECTORY --not recommended. In a recent change RedHat 7.2 decided to use group lock. In order to get around this we just check the group id of the lock directory.----------------------------------------------------------*/int check_group_uucp(){#ifndef USER_LOCK_DIRECTORY int group_count; struct passwd *user = getpwuid( geteuid() ); struct stat buf; char msg[80];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -