root/source3/lib/pidfile.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pidfile_pid
  2. pidfile_create
  3. pidfile_unlink

   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 3 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, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 
  24 #ifndef O_NONBLOCK
  25 #define O_NONBLOCK
  26 #endif
  27 
  28 static char *pidFile_name = NULL;
  29 
  30 /* return the pid in a pidfile. return 0 if the process (or pidfile)
  31    does not exist */
  32 pid_t pidfile_pid(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
  33 {
  34         int fd;
  35         char pidstr[20];
  36         pid_t pid;
  37         unsigned int ret;
  38         char * pidFile;
  39 
  40         if (asprintf(&pidFile, "%s/%s.pid", lp_piddir(), name) == -1) {
  41                 return 0;
  42         }
  43 
  44         fd = sys_open(pidFile, O_NONBLOCK | O_RDONLY, 0644);
  45         if (fd == -1) {
  46                 SAFE_FREE(pidFile);
  47                 return 0;
  48         }
  49 
  50         ZERO_ARRAY(pidstr);
  51 
  52         if (read(fd, pidstr, sizeof(pidstr)-1) <= 0) {
  53                 goto noproc;
  54         }
  55 
  56         ret = atoi(pidstr);
  57 
  58         if (ret == 0) {
  59                 /* Obviously we had some garbage in the pidfile... */
  60                 DEBUG(1, ("Could not parse contents of pidfile %s\n",
  61                           pidFile));
  62                 goto noproc;
  63         }
  64         
  65         pid = (pid_t)ret;
  66         if (!process_exists_by_pid(pid)) {
  67                 goto noproc;
  68         }
  69 
  70         if (fcntl_lock(fd,SMB_F_SETLK,0,1,F_RDLCK)) {
  71                 /* we could get the lock - it can't be a Samba process */
  72                 goto noproc;
  73         }
  74 
  75         SAFE_FREE(pidFile);
  76         close(fd);
  77         return (pid_t)ret;
  78 
  79  noproc:
  80         close(fd);
  81         unlink(pidFile);
  82         SAFE_FREE(pidFile);
  83         return 0;
  84 }
  85 
  86 /* create a pid file in the pid directory. open it and leave it locked */
  87 void pidfile_create(const char *program_name)
     /* [<][>][^][v][top][bottom][index][help] */
  88 {
  89         int     fd;
  90         char    buf[20];
  91         const char    *short_configfile;
  92         char *name;
  93         pid_t pid;
  94 
  95         /* Add a suffix to the program name if this is a process with a
  96          * none default configuration file name. */
  97         if (strcmp( CONFIGFILE, get_dyn_CONFIGFILE()) == 0) {
  98                 name = SMB_STRDUP(program_name);
  99         } else {
 100                 short_configfile = strrchr( get_dyn_CONFIGFILE(), '/');
 101                 if (short_configfile == NULL) {
 102                         /* conf file in current directory */
 103                         short_configfile = get_dyn_CONFIGFILE();
 104                 } else {
 105                         /* full/relative path provided */
 106                         short_configfile++;
 107                 }
 108                 if (asprintf(&name, "%s-%s", program_name,
 109                              short_configfile) == -1) {
 110                         smb_panic("asprintf failed");
 111                 }
 112         }
 113 
 114         if (asprintf(&pidFile_name, "%s/%s.pid", lp_piddir(), name) == -1) {
 115                 smb_panic("asprintf failed");
 116         }
 117 
 118         pid = pidfile_pid(name);
 119         if (pid != 0) {
 120                 DEBUG(0,("ERROR: %s is already running. File %s exists and process id %d is running.\n", 
 121                          name, pidFile_name, (int)pid));
 122                 exit(1);
 123         }
 124 
 125         fd = sys_open(pidFile_name, O_NONBLOCK | O_CREAT | O_WRONLY | O_EXCL,
 126                       0644);
 127         if (fd == -1) {
 128                 DEBUG(0,("ERROR: can't open %s: Error was %s\n", pidFile_name,
 129                          strerror(errno)));
 130                 exit(1);
 131         }
 132 
 133         if (fcntl_lock(fd,SMB_F_SETLK,0,1,F_WRLCK)==False) {
 134                 DEBUG(0,("ERROR: %s : fcntl lock of file %s failed. Error was %s\n",  
 135                          name, pidFile_name, strerror(errno)));
 136                 exit(1);
 137         }
 138 
 139         memset(buf, 0, sizeof(buf));
 140         slprintf(buf, sizeof(buf) - 1, "%u\n", (unsigned int) sys_getpid());
 141         if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) {
 142                 DEBUG(0,("ERROR: can't write to file %s: %s\n", 
 143                          pidFile_name, strerror(errno)));
 144                 exit(1);
 145         }
 146         /* Leave pid file open & locked for the duration... */
 147         SAFE_FREE(name);
 148 }
 149 
 150 void pidfile_unlink(void)
     /* [<][>][^][v][top][bottom][index][help] */
 151 {
 152         if (pidFile_name == NULL) {
 153                 return;
 154         }
 155         unlink(pidFile_name);
 156         SAFE_FREE(pidFile_name);
 157 }

/* [<][>][^][v][top][bottom][index][help] */