⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 forking.c

📁 一个功能全面的电子邮件客户端
💻 C
📖 第 1 页 / 共 3 页
字号:
/* TradeClient <http://tradeclient.sourceforge.net> * $Id: forking.c,v 1.77 2001/03/20 22:19:33 ttabner Exp $ * * Copyright (C) 1999-2000 Bynari Inc. * Copyright (C) 2001 Project TradeClient * * LGPL * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "puma.h"#include "ipc.h"/* * Notice that our queue implementation is actually a FIFO! */static QueList *quelist = NULL ;static int queSafe = -1 ; /* * Init the mutex used by the queue here */voidque_sem_init( void ){  queSafe = initSem() ;  return ;}/* * Release the system resource held by the IPC semaphore */voidque_sem_deinit( void ){  deInitSem( queSafe ) ;  return ;}/* These functions are now thread/process safe.  It seems * Alex and Andrew had no concept of concurrent/parallel programming. * As such, everything they touched is broken from a concurrent/SMP * perspective.  On top of that, it's poorly written!!!  We shouldn't * be making yet ANOTHER copy of the message.  We should be storing * a pointer to it, whereby, we become the owners of it. */void que_message (char *msg) {  QueList *queseek ;#if DEBUG > 4  int depth = 0 ;#endif  lockSem( queSafe ) ;  queseek = quelist ;#ifdef DMALLOC  dmalloc_verify( 0 ) ;#endif  if (queseek==NULL) {    quelist=(QueList *)calloc (1, sizeof(QueList));    quelist -> data = msg ;    quelist -> length = strlen( msg ) ;#if DEBUG > 4  depth++ ;#endif  } else {    while( queseek -> next ) {#if DEBUG > 4      depth++ ;#endif      queseek = queseek -> next ;    }    queseek -> next = (QueList *)calloc ( 1, sizeof(QueList) ) ;    queseek -> next -> data = msg ;    queseek -> length = strlen( msg ) ;  }#ifdef DMALLOC  dmalloc_verify( 0 ) ;#endif#if DEBUG > 4  printf( "********************************> Message queue depth of %d.\n", depth ) ;#endif  unlockSem( queSafe ) ;  return ;}/* These functions are now thread/process safe.  It seems * Alex and Andrew had no concept of concurrent/parallel programming. * As such, everything they touched is broken from a concurrent/SMP * perspective.  On top of that, it's poorly written!!!  We shouldn't * be making yet ANOTHER copy of the message.  We should be storing * a pointer to it, whereby, we become the owners of it. * This function takes the message on the head of the list, removes * it from the queue and returns a pointer to it.  At this point in * time, the caller becomes the owner of the message. */char *deque_message( void ) {  QueList *q ;  char *ptr ;  lockSem( queSafe ) ;  q = quelist ;  if( q ) {    quelist = q -> next ;  }  unlockSem( queSafe ) ;#if DEBUG > 4  printf( "Dequeing a message of %ld bytes long...\n", q -> length ) ;  printf( "Dequeing a message of %ld bytes long...\n", q -> length ) ;  printf( "Dequeing a message of %ld bytes long...\n", q -> length ) ;  printf( "Dequeing a message of %ld bytes long...\n", q -> length ) ;  printf( "Dequeing a message of %ld bytes long...\n", q -> length ) ;  printf( "Dequeing a message of %ld bytes long...\n", q -> length ) ;#endif  ptr = q -> data ;  free( q ) ;#ifdef DMALLOC  dmalloc_verify( 0 ) ;#endif  return ptr ;}/* These functions are now thread/process safe.  It seems * Alex and Andrew had no concept of concurrent/parallel programming. * As such, everything they touched is broken from a concurrent/SMP * perspective.  On top of that, it's poorly written!!!  We shouldn't * be making yet ANOTHER copy of the message.  We should be storing * a pointer to it, whereby, we become the owners of it. */voidque_remove( void ) {  long cnt ;  QueList *qtemp;  cnt = 0 ;  lockSem( queSafe ) ;#ifdef DEBUG  if( quelist ) printf( "We have at least one message to remove.\n" ) ;  else printf( "No messages to remove!\n" ) ;#endif  while( quelist ) {    qtemp = quelist ;    quelist = quelist -> next ;    free( qtemp -> data ) ;    free( qtemp ) ;    cnt++ ;  }  unlockSem( queSafe ) ;#ifdef DMALLOC  dmalloc_verify( 0 ) ;#endif#ifdef DEBUG  printf( "que_remove() purged %ld messages.\n", cnt ) ;#endif  return ;}#ifdef DEBUG#define DEBUGFORK 0#endif/* Loop through all of the accounts and take action if needed. * Notice that we will not be having a duplicated effort of what * fork_receive_message1() does (duh...that would be **VERY** stupid). * In fact, we will make use of it to keep it simple!!!! */void fork_receive_messages( int id ){  int pid ;#if DEBUGFORK > 0  int debugger ;#endif  char *snum ;  int childStat ;  PopAccount *curpop ;  /* See if we need to process any OOOREAD requests */  get_message_timeout( NULL ) ;  /* Synch fix? */  if( tm_globs -> pid != -1 ) return ;  /* Now, create a child process to get junk for all accounts */  if( (pid = fork()) == 0 ) {#if DEBUGFORK > 0    /* Here for debugging only - this requires the debugger to change the value!!!! */    debugger = 1 ;    while( debugger )       {	printf( "Waiting on the debugger to save me on pid #%d in fork_receive_messages().\n", getpid() ) ;	sleep( 1 ) ;      }#endif    /* Get the first account record */    curpop = (id ? seek_popaccount (id) : first_popaccount());    /* Now, walk through the list and fetch any mail on accounts that are requesting it */    while( curpop ) {      //if( (curpop -> flags & CHECK_WITH_ALL) && (curpop->type != IMAP) )      if( (curpop -> flags & CHECK_WITH_ALL) )	{		if (curpop->type == POP3) {	  /* If we are supposed to process this account, do so, forking	   * a child process.  Once we return here, having forked, wait	   * for it to finish before we continue.  Otherwise, we'll wind	   * up with lots of concurrent account activity.	   */#ifdef DEBUG	  printf( "****>Forking receiving on account #%d from %d.\n", curpop -> id, getpid() ) ;#endif	  /* Make sure everyone knows what account we are on */	  snum = disassemble_long( (unsigned long)curpop -> id ) ;#ifdef DEBUG	  printf( "****>ANNOUNCING ACCOUNT #%d from %d.\n", curpop -> id, getpid() ) ;#endif	  pipe_parent_stat_put( CURACCOUNT, snum, 4 ) ;	  free( snum ) ;	  /* Now, got get the messages */	  pid = fork_receive_message1( curpop -> id, 0 ) ;#ifdef DEBUG	  printf( "****>Waiting on child process (forked %d) on account #%d.\n", pid, curpop -> id ) ;#endif	  /* Wait for the child to finish.  Once it does, reset the value and let everyone know */	  waitpid( pid, &childStat, 0 ) ;	  if( WIFSIGNALED( childStat ) ) {	    printf( "**********Child died because of %d.\n", WTERMSIG(childStat) ) ;	    /*	     * Test to see if this is a SIGKILL.  If it is, someone doesn't want us to continue!	     * We'll exit with a 1 to let everyone know we've been harshly talked to.  ;P~	     */	    if( WTERMSIG(childStat) == 9 ) _exit( 1 ) ;	    else {	      /*	       * If we are here, something bad happened which caused the child to die.	       * As such, we'll notify the parent that this happened via a DONE message.  This	       * will prevent the parent from hanging on child that would otherwise never report	       * in.	       */#ifdef DEBUG	      printf( "[Dead Child Process]****>ANNOUNCING DONE\n" ) ;#endif	    }	  }	  #ifdef DEBUG	  else printf( "Child on account #%d exited normally.\n", curpop -> id ) ;#endif	}	}      if (id) {        curpop = NULL;      } else {      curpop = curpop -> next ;      }    }#ifdef DEBUG    printf( "****>ANNOUNCING DONE\n" ) ;#endif    pipe_parent_stat_put( DONE, "", 0 ) ;    /* Okay, since all accounts have been serviced, let's kill exit this one */#ifdef DEBUG    printf( "Returning from fork_receive_messages() since all accounts have been processed on pid %d\n",	    getpid() ) ;#endif    _exit( 0 ) ;  } else {    /* Since we are the parent, let's wait on child (the above fork) to finish elsewhere, this      * way, we don't get bunches of zombies...brains....     */    tm_globs -> pid = pid ;  }#ifdef DEBUG  printf( "Child process has been created to monitor background receiving...\n" ) ;#endif  return ;}#ifdef DEBUG#undef DEBUGFORK#define DEBUGFORK 0#endifint fork_receive_message1( int popid, int announce ) {  int pid=0, newmsgs=0, count=0, error=0;  char *snum, *msg;  PopAccount *curpop ;  MAILSTREAM *stream = NULL ;  int loggedIn ;  int index ;#if DEBUGFORK > 0  int debugger ;#endif  /* Get the current account record */  curpop = seek_popaccount( popid ) ;  /* Now, make sure we only have a single connection per account */  if( curpop -> pid < 1 ) {    /* Now, fork and let the messaging session run in the backgorund */    if( ( pid = fork() ) == 0 ) {#if DEBUGFORK > 0      /* Here for debugging only - this requires the debugger to change the value!!!! */      debugger = 1 ;      while( debugger ) 	{	  printf( "Waiting on the debugger to save me on pid #%d in fork_receive_message1().\n", getpid() ) ;	  sleep( 1 ) ;	}#endif      /* Locate the current account info and create a MAIL stream for it */      loggedIn = 0 ;      /* Now that we have the correct account, send it to the parent process */      if( announce ) {#if DEBUG > 5	printf( "Sending 'CURACCOUNT' to parent with id = %d.\n", curpop -> id ) ;#endif	snum = disassemble_long( (unsigned long)curpop -> id ) ;	if( announce ) pipe_parent_stat_put( CURACCOUNT, snum, 4 ) ;	free( snum ) ;      }          pid = getpid() ;#ifdef DEBUG      printf( "****>ANNOUNCING CURPID %d from %d.\n", pid, curpop -> id ) ;#endif      snum = disassemble_long( (unsigned long)pid ) ;      pipe_parent_stat_put( CURPID, snum, 4 ) ;      free( snum ) ;            /* Now, figure out how many new messages we have while we are logging into the account */      newmsgs = new_pop3_login( &stream, curpop -> id ) ;#if DEBUG > 3      printf( "Looks like we logged in and have %d new messages that need attention.\n", newmsgs ) ;#endif      /* Make sure we have messages to process, if not, report the error */      snum = disassemble_long( (unsigned long)newmsgs ) ;      if( newmsgs < 0 ) {	pipe_parent_stat_put( PIPEERROR, snum, 4 ) ;	free( snum ) ;	pipe_data_put( OOOREAD, "", 0 ) ;#if DEBUG > 4	printf( "Requesting an Out Of Order Read.\n" ) ;#endif	/* Log out if we have an odd error except when the connection	 * has already been closed, we don't know the host, or CONNREF	 */	if( (newmsgs != CONNREF) && (newmsgs != CONNCLOSED) &&	    (newmsgs != UNKNOWNHOST) ) {#ifdef DEBUG	  printf( "calling logout in %d.\n", getpid() ) ;#endif	  if( loggedIn ) {	    new_pop3_logout( curpop -> id, stream ) ;	    loggedIn = 0 ;	  }	}      } else {	/* Okay, this means we have messages to process */	pipe_parent_stat_put( NEWMESSAGES, snum, 4 ) ;	free( snum ) ;	/* Now that we know we have messages, let's fetch them! */	loggedIn = 1 ;	index = curpop -> popcmsg ;	/* Remember, msg numbers are base 1 and not base 0 */	for( count = 1 ; count <= newmsgs ; count++ ) {#ifdef DMALLOC	  dmalloc_verify( 0 ) ;#endif	  /* If we are deleting messages, we need to fetch all of them */	  if( curpop -> flags & DELETEFROMSERVER ) {	    msg = new_pop3_get_message( curpop -> id, count, &error, stream ) ;	  } else {	    msg = new_pop3_get_message( curpop -> id, (index + count), &error, stream ) ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -