Back to index

avfs  1.0.1
server.c
Go to the documentation of this file.
00001 /*
00002     AVFS: A Virtual File System Library
00003     Copyright (C) 1998-2001  Miklos Szeredi <miklos@szeredi.hu>
00004 
00005     This program can be distributed under the terms of the GNU GPL.
00006     See the file COPYING.
00007 */
00008 
00009 #include "send.h"
00010 #include "avfs.h"
00011 
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <unistd.h>
00015 #include <pwd.h>
00016 #include <errno.h>
00017 #include <fcntl.h>
00018 #include <signal.h>
00019 #include <string.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #include <sys/socket.h>
00023 #include <sys/un.h>
00024 
00025 static int get_sockname(char *sockname)
00026 {
00027     int res;
00028     char username[33];
00029     char sockdir[128];
00030     char lockfile[128];
00031     struct passwd *pw;
00032     int uid;
00033     int lockfd;
00034     struct flock flock;
00035     char *variant;
00036     char varbuf[32];
00037     
00038     uid = getuid();
00039     pw = getpwuid(uid);
00040     if(pw != NULL) {
00041         strncpy(username, pw->pw_name, 32);
00042         username[32] = '\0';
00043     }
00044     else 
00045         sprintf(username, "%i", uid);
00046 
00047     varbuf[0] = '\0';
00048     variant = getenv("AVFS_VARIANT");
00049     if(variant != NULL) {
00050         unsigned long i = strtol(variant, NULL, 10);
00051         sprintf(varbuf, "-%lu", i);
00052     }
00053 
00054     sprintf(sockdir, "/tmp/.avfsconn-%s%s", username, varbuf);
00055     sprintf(sockname, "%s/server", sockdir);
00056     sprintf(lockfile, "%s/lock", sockdir);
00057 
00058     res = mkdir(sockdir, 0700);
00059     if(res == -1) {
00060         struct stat stbuf;
00061 
00062         if(errno != EEXIST) {
00063             perror("mkdir()");
00064             exit(1);
00065         }
00066         res = stat(sockdir, &stbuf);
00067         if(res == -1) {
00068             perror(sockdir);
00069             exit(1);
00070         }
00071         if(stbuf.st_uid != uid || (stbuf.st_mode & 0077) != 0) {
00072             fprintf(stderr, "Bad owner or permissons on %s\n", sockdir);
00073             exit(1);
00074         }
00075     }
00076 
00077     lockfd = open(lockfile, O_CREAT | O_RDWR, 0644);
00078     if(lockfd == -1) {
00079         perror(lockfile);
00080         exit(1);
00081     }
00082     fcntl(lockfd, F_SETFD, FD_CLOEXEC);
00083 
00084     memset(&flock, 0, sizeof(flock));
00085     flock.l_type = F_WRLCK;
00086     flock.l_whence = 0;
00087     flock.l_start = 0;
00088     flock.l_len = 0;
00089 
00090     res = fcntl(lockfd, F_SETLK, &flock);
00091     if(res == -1) {
00092         if(errno == EAGAIN || errno == EACCES)
00093             return -1;
00094 
00095         perror("fcntl(F_SETLK)");
00096         exit(1);
00097     }
00098 
00099     unlink(sockname);
00100     
00101     return 0;
00102 }
00103 
00104 
00105 static int socket_init(const char *sockname)
00106 {
00107     int sock;
00108     int res;
00109     struct sockaddr_un addr;
00110     unsigned int addrlen;
00111     
00112     sock = socket(AF_UNIX, SOCK_STREAM, 0);
00113     if(sock == -1) {
00114         perror("socket()");
00115         exit(1);
00116     }
00117 
00118     addr.sun_family = AF_UNIX;
00119     strcpy(addr.sun_path, sockname);
00120     
00121     addrlen = (size_t) (((struct sockaddr_un *) 0)->sun_path)
00122         + strlen(addr.sun_path);
00123     
00124     res = bind(sock, (struct sockaddr *) &addr, addrlen);
00125     if(res == -1) {
00126         perror("bind()");
00127         exit(1);
00128     }
00129     
00130     res = listen(sock, 5);
00131     if(res == -1) {
00132         perror("listen()");
00133         exit(1);
00134     }
00135 
00136     return sock;
00137 }
00138 
00139 static void exit_handler(int sig)
00140 {
00141     exit(0);
00142 }
00143 
00144 #if 0
00145 static void bad_handler(int sig)
00146 {
00147     av_log(AVLOG_ERROR, "%s, Exiting",
00148              strsignal(sig));
00149     _exit(1);
00150 }
00151 #endif
00152 
00153 int server_init()
00154 {
00155     int res;
00156     int pip[2];
00157     int pid;
00158     int nullfd;
00159     int i;
00160     char sockname[128];
00161     int numfd;
00162     sigset_t newset;
00163     struct sigaction act;
00164 
00165     sigemptyset(&newset);
00166     sigprocmask(SIG_SETMASK, &newset, NULL);
00167 
00168     for(i = 0; i < 3; i++) {
00169         nullfd = open("/dev/null", O_RDONLY);
00170         if(nullfd == -1) {
00171             perror("avfs_server: open(/dev/null)");
00172             exit(1);
00173         }
00174     }
00175 
00176     res = pipe(pip);
00177     if(res == -1) {
00178         perror("avfs_server: pipe()");
00179         exit(1);
00180     }
00181 
00182     pid = fork();
00183     if(pid == -1) {
00184         perror("avfs_server: fork()");
00185         exit(1);
00186     }
00187 
00188     if(pid != 0) {
00189         int res;
00190         char c;
00191 
00192         close(pip[1]);
00193         res = read(pip[0], &c, 1);
00194         if(res == -1) {
00195             perror("avfs_server: read()");
00196             exit(1);
00197         }
00198         if(res == 0)
00199             exit(1);
00200         
00201         exit(0);
00202     }
00203     
00204     setuid(getuid());
00205     setgid(getgid());
00206 //    chdir("/");
00207     chdir("/tmp");
00208     setsid();
00209 
00210     numfd = getdtablesize();
00211     for(i = 0; i < numfd; i++) {
00212         if(i != pip[1])
00213             close(i);
00214     }
00215 
00216     nullfd = open("/dev/null", O_RDWR);
00217     if(nullfd == -1)
00218         exit(1);
00219     
00220     for(i = 0; i < 3; i++)
00221         res = dup2(nullfd, i);
00222 
00223     res = get_sockname(sockname);
00224     if(res != -1)
00225         res = socket_init(sockname);
00226 
00227     if(write(pip[1], "m", 1) != 1)
00228         exit(1);
00229 
00230     if(res == -1)
00231         exit(0);
00232     
00233     close(pip[1]);
00234 
00235     act.sa_handler = exit_handler;
00236     sigemptyset(&act.sa_mask);
00237     act.sa_flags = 0;
00238     sigaction(SIGTERM, &act, NULL);
00239     sigaction(SIGHUP, &act, NULL);
00240     sigaction(SIGINT, &act, NULL);
00241 
00242     act.sa_handler = SIG_IGN;
00243     sigaction(SIGPIPE, &act, NULL);
00244 
00245 #if 0
00246     act.sa_handler = bad_handler;
00247     sigfillset(&act.sa_mask);
00248     sigaction(SIGQUIT, &act, NULL);
00249     sigaction(SIGILL, &act, NULL);
00250     sigaction(SIGFPE, &act, NULL);
00251     sigaction(SIGABRT, &act, NULL);
00252     sigaction(SIGBUS, &act, NULL);
00253     sigaction(SIGSEGV, &act, NULL);
00254 #endif
00255 
00256     return res;
00257 }
00258