1/* this code is broken - there is a race condition with the unlink (tridge) */ 2 3/* 4 Unix SMB/CIFS implementation. 5 pidfile handling 6 Copyright (C) Andrew Tridgell 1998 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21*/ 22 23#include "includes.h" 24 25#ifndef O_NONBLOCK 26#define O_NONBLOCK 27#endif 28 29/* return the pid in a pidfile. return 0 if the process (or pidfile) 30 does not exist */ 31pid_t pidfile_pid(const char *name) 32{ 33 int fd; 34 char pidstr[20]; 35 unsigned ret; 36 pstring pidFile; 37 38 slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name); 39 40 fd = sys_open(pidFile, O_NONBLOCK | O_RDONLY, 0644); 41 if (fd == -1) { 42 return 0; 43 } 44 45 ZERO_ARRAY(pidstr); 46 47 if (read(fd, pidstr, sizeof(pidstr)-1) <= 0) { 48 goto noproc; 49 } 50 51 ret = atoi(pidstr); 52 53 if (ret == 0) { 54 /* Obviously we had some garbage in the pidfile... */ 55 DEBUG(1, ("Could not parse contents of pidfile %s\n", 56 pidFile)); 57 goto noproc; 58 } 59 60 if (!process_exists((pid_t)ret)) { 61 goto noproc; 62 } 63 64 if (fcntl_lock(fd,SMB_F_SETLK,0,1,F_RDLCK)) { 65 /* we could get the lock - it can't be a Samba process */ 66 goto noproc; 67 } 68 69 close(fd); 70 return (pid_t)ret; 71 72 noproc: 73 close(fd); 74 unlink(pidFile); 75 return 0; 76} 77 78/* create a pid file in the pid directory. open it and leave it locked */ 79void pidfile_create(const char *name) 80{ 81 int fd; 82 char buf[20]; 83 pstring pidFile; 84 pid_t pid; 85 86 slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name); 87 88 pid = pidfile_pid(name); 89 if (pid != 0) { 90 DEBUG(0,("ERROR: %s is already running. File %s exists and process id %d is running.\n", 91 name, pidFile, (int)pid)); 92 exit(1); 93 } 94 95 fd = sys_open(pidFile, O_NONBLOCK | O_CREAT | O_WRONLY | O_EXCL, 0644); 96 if (fd == -1) { 97 DEBUG(0,("ERROR: can't open %s: Error was %s\n", pidFile, 98 strerror(errno))); 99 exit(1); 100 } 101 102 if (fcntl_lock(fd,SMB_F_SETLK,0,1,F_WRLCK)==False) { 103 DEBUG(0,("ERROR: %s : fcntl lock of file %s failed. Error was %s\n", 104 name, pidFile, strerror(errno))); 105 exit(1); 106 } 107 108 memset(buf, 0, sizeof(buf)); 109 slprintf(buf, sizeof(buf) - 1, "%u\n", (unsigned int) sys_getpid()); 110 if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) { 111 DEBUG(0,("ERROR: can't write to file %s: %s\n", 112 pidFile, strerror(errno))); 113 exit(1); 114 } 115 /* Leave pid file open & locked for the duration... */ 116} 117