00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025  
00026 #ifdef HAVE_CONFIG_H
00027 #  include <config.h>
00028 #endif
00029 
00030 #include <sys/types.h>
00031 #include <pwd.h>
00032 #include <grp.h>
00033 #include <sys/time.h>
00034 #include <sys/resource.h>
00035 #include <unistd.h>
00036 #include <sys/socket.h>
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 #include <errno.h>
00040 #include <syslog.h>
00041 
00042 #include "file.h"
00043 #include "errmanager.h"
00044 #include "daemonize.h"
00045 #include "dbug_mem.h"
00046 
00047 
00048 
00049 extern int errno;
00050 
00051 
00052 
00053 int
00054 sb_daemon_drop_privileges(void)
00055 {
00056     uid_t uid = getuid();
00057     gid_t gid = getgid();
00058     uid_t euid = geteuid();
00059     gid_t egid = getegid();
00060 
00061     
00062     if (egid != gid && (setgid(gid) == -1 || getegid() != getgid())) {
00063         return -1;
00064     }
00065 
00066     
00067     if (euid != uid && (setuid(uid) == -1 || geteuid() != getuid())) {
00068         return -1;
00069     }
00070 
00071     
00072     endpwent();
00073     
00074     endgrent();
00075 
00076     return 0;
00077 }
00078 
00079 
00080 
00081 int
00082 sb_daemon_no_corefile(void)
00083 {
00084     struct rlimit limit[1] = {{ 0, 0 }};
00085 
00086     if (getrlimit(RLIMIT_CORE, limit) == -1) {
00087         return -1;
00088     }
00089 
00090     limit->rlim_cur = 0;
00091 
00092     if (setrlimit(RLIMIT_CORE, limit) != 0) {
00093         return -1;
00094     }
00095     
00096     return 0;
00097 }
00098 
00099 
00100 
00101 int
00102 sb_daemon_is_started_by_init(void)
00103 {
00104     
00105     if (getppid() == 1) {
00106         return 1;
00107     }
00108     
00109     return 0;
00110 }
00111 
00112 
00113 
00114 int
00115 sb_daemon_is_started_by_inetd(void)
00116 {
00117     size_t param_length = sizeof(int);
00118     int socket_type;
00119 
00120     
00121     if (getsockopt(STDIN_FILENO, SOL_SOCKET, SO_TYPE, 
00122                         &socket_type, (void *)¶m_length) == 0) {
00123         return 1;
00124     }
00125     
00126     return 0;
00127 }
00128 
00129 
00130 
00131 int
00132 sb_daemon_is_started_by_root(void)
00133 {
00134     if (getuid() != 0) {
00135         return 0;
00136     }
00137     
00138     return 1;
00139 }
00140 
00141 
00142 
00143 int
00144 sb_daemon_is_started_suid(void)
00145 {
00146     
00147 
00148     
00149     if (getgid() != getegid()) {
00150         return 1;
00151     }
00152     
00153     
00154     if (getuid() != geteuid()) {
00155         return 1;
00156     }
00157     
00158     return 0;
00159 }
00160 
00161 
00162 
00163 int
00164 sb_daemon_create_fd(int fd, int mode)
00165 {
00166     int i;
00167     
00168     
00169     if ((i = open("/dev/null", mode)) == -1) {
00170         return -1;
00171     }
00172     
00173     if (i != fd) {
00174         if (dup2(i, fd) == -1) {
00175             return -1;
00176         }
00177         close(i);
00178     }
00179 
00180     return fd;
00181 }
00182 
00183 
00184 
00185 int
00186 sb_daemon_change_user(uid_t uid, gid_t gid)
00187 {
00188     
00189     if (sb_daemon_is_started_by_root() == 0) {
00190         return -1;
00191     }
00192     
00193     
00194     if ((setgid(gid) == -1) || (getgid() != gid) || (getegid() != gid)) {
00195         return -1;
00196     }
00197     
00198     
00199     if ((setuid(uid) == -1) || (getuid() != uid) || (geteuid() != uid)) {
00200         return -1;
00201     }
00202     
00203     return 0;
00204 }
00205 
00206 
00207 
00208 int
00209 sb_daemon_detach(const char *rundir)
00210 {
00211     long i;
00212     pid_t pid;
00213 
00214     
00215     if (sb_daemon_is_started_by_root() == 0) {
00216         return -1;
00217     }
00218     
00219     
00220     
00221     
00222     
00223     
00224     
00225     
00226     
00227     
00228     if ((!sb_daemon_is_started_by_init()) && (!sb_daemon_is_started_by_inetd())) {
00229         
00230         
00231         
00232         
00233         
00234         
00235         pid = fork();
00236         if (pid == -1) {
00237             return -1;
00238         }
00239         if (pid != 0) {
00240             exit(EXIT_SUCCESS);
00241         }
00242 
00243         
00244         
00245         
00246         
00247         
00248         setsid();
00249 
00250         
00251         
00252         
00253         signal(SIGHUP, SIG_IGN);
00254 
00255         
00256         
00257         
00258         pid = fork();
00259         if (pid == -1) {
00260             return -1;
00261         }
00262         if (pid != 0) {
00263             exit(EXIT_SUCCESS);
00264         }
00265 
00266     }
00267 
00268     
00269     
00270     
00271     
00272     
00273     
00274     if (rundir != NULL) {
00275         struct stat st;
00276         if ((stat(rundir, &st) == 0) && (S_ISDIR(st.st_mode))) {
00277             chdir(rundir);
00278         } else {
00279             return -1;
00280         }
00281     } else {
00282         chdir("/");
00283     }
00284     
00285     
00286     
00287     umask(0);
00288 
00289     
00290     
00291     
00292     
00293     
00294     
00295     
00296     
00297     
00298     if (sb_daemon_is_started_by_inetd() == 1) {
00299         
00300         for (i = 0; i < sysconf(_SC_OPEN_MAX); i++) {
00301             if ((i!=STDIN_FILENO) && (i!=STDOUT_FILENO) && (i!=STDERR_FILENO)) {
00302                 close(i);
00303             }
00304         }
00305     } else {
00306         
00307         for (i = 0; i < sysconf(_SC_OPEN_MAX); i++) {
00308             close(i);
00309         }
00310     }
00311 
00312     
00313     
00314     
00315     
00316     
00317     
00318     
00319     
00320     if (sb_daemon_is_started_by_inetd() == 0) {
00321         
00322         
00323         
00324         if (sb_daemon_create_fd(STDIN_FILENO, O_RDONLY) == -1) {
00325             return -1;
00326         }
00327         
00328         
00329         if (sb_daemon_create_fd(STDOUT_FILENO, O_WRONLY) == -1) {
00330             return -1;
00331         }
00332         
00333         
00334         if (sb_daemon_create_fd(STDERR_FILENO, O_WRONLY) == -1) {
00335             return -1;
00336         }
00337     }
00338     
00339     return 0;
00340 }
00341 
00342 
00343 
00344 int
00345 sb_daemon_init(const char *name,
00346                     const char *rundir,
00347                     const char *pidfile)
00348 {
00349     int fd = -1;
00350 
00351     if (sb_daemon_is_running(pidfile) == 1) {
00352         return -1;
00353     }
00354     
00355     
00356     emClose();
00357 
00358     
00359     if (sb_daemon_detach(rundir) != 0) {
00360         
00361         emInit(LOG_DEBUG, EM_TYPE_SYSLOG, NULL, NULL, NULL, name);
00362         return -1;
00363     }
00364     
00365     
00366     emInit(LOG_DEBUG, EM_TYPE_SYSLOG, NULL, NULL, NULL, name);
00367 
00368     
00369     if (pidfile != NULL) {
00370         if ((fd = sb_daemon_pidfile_create_and_lock(pidfile)) == -1) {
00371             return -1;
00372         }
00373         if (sb_daemon_pidfile_write(fd) == -1) {
00374             return -1;
00375         }
00376     }
00377     
00378     return 0;
00379 }
00380 
00381 
00382 
00383 int 
00384 sb_daemon_is_running(const char *pidfile)
00385 {
00386     int fd = -1;
00387     
00388     
00389     if (pidfile == NULL) {
00390         return ERRNO(EINVAL);
00391     }
00392     
00393     
00394     if ((fd = sb_daemon_pidfile_create_and_lock(pidfile)) == -1) {
00395         if ((errno == EACCES) || (errno == EAGAIN)) {
00396             
00397             return 1;
00398         }
00399         
00400         return -1;
00401     }
00402     
00403     
00404     sb_file_close(fd);
00405     sb_file_remove(pidfile);
00406     
00407     return 0;
00408 }
00409 
00410 
00411 
00412 int 
00413 sb_daemon_destroy(const char *pidfile)
00414 {
00415     
00416     sb_file_remove(pidfile);
00417     
00418     return 0;
00419 }
00420 
00421 
00422 
00423 int
00424 sb_daemon_pidfile_create_and_lock(const char *pidfile)
00425 {
00426     int fd = -1;
00427     
00428     
00429     
00430     
00431     
00432     
00433     if ((fd = sb_file_open_ext(pidfile, 
00434                             O_RDWR | O_SYNC | O_CREAT | O_EXCL, 
00435                             S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
00436     {
00437         
00438         if (errno != EEXIST) {
00439             return -1;
00440         }
00441         
00442         
00443         
00444         if ((fd = sb_file_open(pidfile, O_RDWR | O_SYNC)) == -1) {
00445             return -1;
00446         }
00447     }
00448     
00449     
00450     if (sb_file_lock_acquire_write(fd) == -1) {
00451         return -1;
00452     }
00453     
00454     return fd;
00455 }
00456 
00457 
00458 
00459 int
00460 sb_daemon_pidfile_write(int fd)
00461 {
00462     ssize_t written = 0;
00463     char data[MAX_PIDDATA_LENGTH];
00464     
00465     
00466     memset(data, 0, sizeof(data));
00467     snprintf(data, MAX_PIDDATA_LENGTH, "%d\n", (int)getpid());
00468     data[MAX_PIDDATA_LENGTH-1] = '\0';
00469     
00470     
00471     lseek(fd, 0, SEEK_SET);
00472     
00473     
00474     if ((written = write(fd, data, strlen(data))) == -1) {
00475         return -1;
00476     }
00477     if ((size_t)written < strlen(data)) {
00478         return -1;
00479     }
00480     
00481     
00482     fsync(fd);
00483     sync();
00484     
00485     return 0;
00486 }
00487 
00488 
00489 
00490 pid_t
00491 sb_daemon_pidfile_read(const char *pidfile)
00492 {
00493     int fd = -1;
00494     char data[MAX_PIDDATA_LENGTH];
00495     int pid = -1;
00496     
00497     if ((fd = sb_file_open(pidfile, O_RDONLY)) == -1) {
00498         return -1;
00499     }
00500     
00501     memset(data, 0, sizeof(data));
00502     if (read(fd, &data, MAX_PIDDATA_LENGTH) == -1) {
00503         return -1;
00504     }
00505     
00506     if (sscanf(data, "%d", &pid) != 1) {
00507         return -1;
00508     }
00509     
00510     return pid;
00511 }