"Fossies" - the Fresh Open Source Software Archive

Member "smbnetfs-0.6.3/src/process.c" (10 Jan 2015, 8629 Bytes) of package /linux/misc/smbnetfs-0.6.3.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "process.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.5.3b_vs_0.6.0.

    1 #include "config.h"
    2 #include <errno.h>
    3 #include <stdlib.h>
    4 #include <string.h>
    5 #include <unistd.h>
    6 #include <sys/types.h>
    7 #include <sys/wait.h>
    8 #include <sys/socket.h>
    9 #include <signal.h>
   10 #include <pthread.h>
   11 #include <langinfo.h>
   12 
   13 #include "common.h"
   14 #include "list.h"
   15 #include "smb_conn_proto.h"
   16 #include "process.h"
   17 
   18 #define CHARSET_LEN 64
   19 
   20 struct process_rec{
   21     LIST    entries;
   22     int     child_fd;
   23     pid_t   child_pid;
   24 };
   25 
   26 static char process_system_charset[CHARSET_LEN]     = "UTF-8";
   27 static char process_server_local_charset[CHARSET_LEN]   = "UTF-8";
   28 static char process_server_samba_charset[CHARSET_LEN]   = "UTF-8";
   29 static int  process_server_listen_timeout           = 300;
   30 static int  process_server_smb_timeout          = 20000;
   31 static int  process_server_smb_debug_level          = 0;
   32 static int  process_start_enabled               = 1;
   33 
   34 static LIST     process_list        = STATIC_LIST_INITIALIZER(process_list);
   35 static pthread_mutex_t  m_process       = PTHREAD_MUTEX_INITIALIZER;
   36 
   37 
   38 int process_init(void){
   39     static int      initialized = 0;
   40 
   41     char        *charset;
   42 
   43     if (! initialized){
   44     if ((charset = nl_langinfo(CODESET)) == NULL){
   45         DPRINTF(0, "Can't find system charset, use utf-8 instead. Check your locale.\n");
   46         charset = "UTF-8";
   47     }else{
   48         initialized = 1;
   49     }
   50     strncpy(process_system_charset, charset, CHARSET_LEN);
   51     process_system_charset[CHARSET_LEN - 1] = '\0';
   52     DPRINTF(5, "system_charset=%s\n", process_system_charset);
   53     }
   54     pthread_mutex_lock(&m_process);
   55     strncpy(process_server_local_charset, process_system_charset, CHARSET_LEN);
   56     process_server_local_charset[CHARSET_LEN - 1] = '\0';
   57     strncpy(process_server_samba_charset, "UTF-8", CHARSET_LEN);
   58     process_server_samba_charset[CHARSET_LEN - 1] = '\0';
   59     pthread_mutex_unlock(&m_process);
   60     return initialized;
   61 }
   62 
   63 void process_disable_new_smb_conn_starting(void){
   64     DPRINTF(7, "disable new process starting at %u\n", (unsigned int) time(NULL));
   65     pthread_mutex_lock(&m_process);
   66     process_start_enabled = 0;
   67     pthread_mutex_unlock(&m_process);
   68 }
   69 
   70 int process_set_server_listen_timeout(int timeout){
   71     if (timeout < 30) return 0;
   72     DPRINTF(7, "timeout=%d\n", timeout);
   73     pthread_mutex_lock(&m_process);
   74     process_server_listen_timeout = timeout;
   75     pthread_mutex_unlock(&m_process);
   76     return 1;
   77 }
   78 
   79 int process_set_server_smb_timeout(int timeout){
   80     if (timeout < 1000) return 0;
   81     DPRINTF(7, "smb_timeout=%d\n", timeout);
   82     pthread_mutex_lock(&m_process);
   83     process_server_smb_timeout = timeout;
   84     pthread_mutex_unlock(&m_process);
   85     return 1;
   86 }
   87 
   88 int process_set_server_smb_debug_level(int level){
   89     if ((level < 0) || (level > 10)) return 0;
   90     DPRINTF(7, "level=%d\n", level);
   91     pthread_mutex_lock(&m_process);
   92     process_server_smb_debug_level = level;
   93     pthread_mutex_unlock(&m_process);
   94     return 1;
   95 }
   96 
   97 int process_set_server_local_charset(const char *charset){
   98     if ((charset == NULL) || (*charset == '\0'))
   99     charset = process_system_charset;
  100 
  101     DPRINTF(7, "local_charset=%s\n", charset);
  102     pthread_mutex_lock(&m_process);
  103     strncpy(process_server_local_charset, charset, CHARSET_LEN);
  104     process_server_local_charset[CHARSET_LEN - 1] = '\0';
  105     pthread_mutex_unlock(&m_process);
  106     return 1;
  107 }
  108 
  109 int process_set_server_samba_charset(const char *charset){
  110     if ((charset == NULL) || (*charset == '\0')) charset = "UTF-8";
  111 
  112     DPRINTF(7, "samba_charset=%s\n", charset);
  113     pthread_mutex_lock(&m_process);
  114     strncpy(process_server_samba_charset, charset, CHARSET_LEN);
  115     process_server_samba_charset[CHARSET_LEN - 1] = '\0';
  116     pthread_mutex_unlock(&m_process);
  117     return 1;
  118 }
  119 
  120 int process_start_new_smb_conn(char *shmem_ptr, size_t shmem_size){
  121     int         error;
  122     int         debug_level;
  123     int         pair[2];
  124     pid_t       pid;
  125     struct process_rec  *rec;
  126 
  127     if ((shmem_ptr == NULL) || (shmem_size < (size_t) getpagesize())){
  128     errno = EINVAL;
  129     return -1;
  130     }
  131 
  132     error = 0;
  133     pid = (pid_t) (-1);
  134     pthread_mutex_lock(&m_process);
  135     if (process_start_enabled != 1){
  136     error = EPERM;
  137     pair[0] = -1;
  138     goto error;
  139     }
  140     if ((rec = malloc(sizeof(struct process_rec))) == NULL){
  141     error = errno;
  142     pair[0] = -1;
  143     DPRINTF(6, "starting new child failed on malloc(): errno=%d, %s\n",
  144         errno, strerror(errno));
  145     goto error;
  146     }
  147     if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0){
  148     DPRINTF(6, "using SOCK_DGRAM instead of SOCK_SEQPACKET\n");
  149     if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0){
  150         error = errno;
  151         free(rec);
  152         pair[0] = -1;
  153         DPRINTF(6, "starting new child failed on socketpair(): errno=%d, %s\n",
  154         errno, strerror(errno));
  155         goto error;
  156     }
  157     }
  158 
  159     memset(rec, 0, sizeof(struct process_rec));
  160     debug_level = common_get_smbnetfs_debug_level();
  161 
  162     if ((pid = fork()) == -1){
  163     error = errno;
  164     close(pair[0]);
  165     close(pair[1]);
  166     free(rec);
  167     pair[0] = -1;
  168     DPRINTF(6, "starting new child failed on fork(): errno=%d, %s\n",
  169         errno, strerror(errno));
  170     goto error;
  171     }
  172 
  173     if (pid == 0){
  174     struct smb_conn_srv_ctx srv_ctx;
  175 
  176     pthread_mutex_unlock(&m_process);
  177     close(pair[0]);
  178 
  179     /* We are after fork here, so we are in single thread situation. *
  180      * This mean we may read any variable without acquiring locks.   *
  181      * Moreover, we can NOT use safely any mutex protected code,     *
  182      * as the mutexes after the fork() are in UNKNOWN state          */
  183     srv_ctx.conn_fd         = pair[1];
  184     srv_ctx.shmem_ptr       = shmem_ptr;
  185     srv_ctx.shmem_size      = shmem_size;
  186     srv_ctx.timeout         = process_server_listen_timeout;
  187     srv_ctx.smb_timeout     = process_server_smb_timeout;
  188     srv_ctx.debug_level     = debug_level;
  189     srv_ctx.smb_debug_level = process_server_smb_debug_level;
  190     srv_ctx.samba_charset   = process_server_samba_charset;
  191     srv_ctx.local_charset   = process_server_local_charset;
  192     smb_conn_srv_listen(&srv_ctx);
  193     exit(EXIT_SUCCESS);
  194     }
  195 
  196     close(pair[1]);
  197     rec->child_pid = pid;
  198     rec->child_fd  = pair[0];
  199     add_to_list(&process_list, &rec->entries);
  200     DPRINTF(6, "starting new child with pid=%d, fd=%d\n", (int) pid, pair[0]);
  201 
  202   error:
  203     pthread_mutex_unlock(&m_process);
  204     errno = error;
  205     return pair[0];
  206 }
  207 
  208 int process_is_smb_conn_alive(int fd){
  209     int         result;
  210     LIST        *elem;
  211     struct process_rec  *rec;
  212 
  213     result = 0;
  214     pthread_mutex_lock(&m_process);
  215     elem = first_list_elem(&process_list);
  216     while(is_valid_list_elem(&process_list, elem)){
  217     rec = list_entry(elem, struct process_rec, entries);
  218     elem = elem->next;
  219 
  220     if ((rec->child_fd  == fd) &&
  221         (rec->child_pid != (pid_t) (-1))){
  222         result = 1;
  223         break;
  224     }
  225     }
  226     pthread_mutex_unlock(&m_process);
  227     return result;
  228 }
  229 
  230 void process_kill_all(void){
  231     LIST        *elem;
  232     struct process_rec  *rec;
  233 
  234     pthread_mutex_lock(&m_process);
  235     elem = first_list_elem(&process_list);
  236     while(is_valid_list_elem(&process_list, elem)){
  237     rec = list_entry(elem, struct process_rec, entries);
  238     elem = elem->next;
  239 
  240     if (rec->child_pid != (pid_t) (-1)){
  241         DPRINTF(6, "kill child with pid=%d, fd=%d\n",
  242             (int) rec->child_pid, rec->child_fd);
  243         kill(rec->child_pid, SIGKILL);
  244     }
  245     }
  246     pthread_mutex_unlock(&m_process);
  247 }
  248 
  249 void process_kill_by_smb_conn_fd(int fd){
  250     LIST        *elem;
  251     struct process_rec  *rec;
  252 
  253     pthread_mutex_lock(&m_process);
  254     elem = first_list_elem(&process_list);
  255     while(is_valid_list_elem(&process_list, elem)){
  256     rec = list_entry(elem, struct process_rec, entries);
  257     elem = elem->next;
  258 
  259     if (rec->child_fd == fd){
  260         DPRINTF(6, "closing child connection with pid=%d, fd=%d\n",
  261                 (int) rec->child_pid, rec->child_fd);
  262         close(rec->child_fd);
  263         rec->child_fd = -1;
  264         if (rec->child_pid == (pid_t) (-1)){
  265         DPRINTF(6, "cleanup child record with fd=%d\n", fd);
  266         remove_from_list(&process_list, &rec->entries);
  267         free(rec);
  268         }else
  269         kill(rec->child_pid, SIGKILL);
  270         break;
  271     }
  272     }
  273     pthread_mutex_unlock(&m_process);
  274 }
  275 
  276 void process_cleanup_from_zombies(void){
  277     pid_t       pid;
  278     LIST        *elem;
  279     struct process_rec  *rec;
  280 
  281     pthread_mutex_lock(&m_process);
  282     while(1){
  283     pid = waitpid((pid_t) (-1), NULL, WNOHANG);
  284     if (pid <= 0) break;
  285 
  286     elem = first_list_elem(&process_list);
  287     while(is_valid_list_elem(&process_list, elem)){
  288         rec = list_entry(elem, struct process_rec, entries);
  289         elem = elem->next;
  290 
  291         if (rec->child_pid == pid){
  292         DPRINTF(6, "R.I.P. child with pid=%d, fd=%d\n",
  293                 (int) rec->child_pid, rec->child_fd);
  294         rec->child_pid = (pid_t) (-1);
  295         if (rec->child_fd == -1){
  296             DPRINTF(6, "cleanup child record with pid=%d\n", (int) pid);
  297             remove_from_list(&process_list, &rec->entries);
  298             free(rec);
  299         }
  300         break;
  301         }
  302     }
  303     }
  304     pthread_mutex_unlock(&m_process);
  305 }