Ejemplo n.º 1
0
void on_write(struct ev_loop *loop, struct ev_io *watcher, int revents) 
{
    Request *request = (Request *)watcher;
    RequestLine *request_line = &(request->request_line);
    int fd = watcher->fd;
    char *method = request_line->method;
    char *uri = request_line->uri;
    if (!strncasecmp(method,"GET",MAXLINE)) {
        /* get不区分大小写 */
        do_get(fd, uri);
        ev_io_stop(loop, watcher);
        return;
    }
    else if (!strncasecmp(method,"HEAD",MAXLINE)) {
        do_head(fd, uri);
        ev_io_stop(loop, watcher);
        return;
    }
    else if (!strncasecmp(method,"POST",MAXLINE)) {
        do_post(fd, uri);
        ev_io_stop(loop, watcher);
        return;
    }
    send_error(fd, method, "501","Not Implemented");
    ev_io_stop(loop, watcher);
}
/**
 * Post operation
 *
 * @param[in] node node number
 * @param[in] tag  tag
 */
void _xmp_mpi_post(const int node, int tag)
{
  if(node == _XMP_world_rank){
    do_post(_XMP_world_rank, tag);
  } else{
    //XACC_DEBUG("post (node=%d, tag=%d)", node, tag);
    MPI_Send(&tag, 1, MPI_INT, node, _XMP_N_MPI_TAG_POSTREQ, MPI_COMM_WORLD);
  }
}
Ejemplo n.º 3
0
static void menu_select_callback(MenuLayer *menu_layer, MenuIndex *cell_index, void *data) {
  switch (cell_index->section) {
    case 0:
      if (numMenuItems > 0) {
        do_post(_latestUrl[cell_index->row]);
        APP_LOG(APP_LOG_LEVEL_DEBUG, _latestUrl[cell_index->row]);
        APP_LOG(APP_LOG_LEVEL_DEBUG, _latest[cell_index->row]);
        light_enable_interaction();
        show_animation();
      }
    break;
  }
}
Ejemplo n.º 4
0
void strand_service::post(strand_service::implementation_type& impl,
    Handler handler)
{
  // Allocate and construct an operation to wrap the handler.
  typedef completion_handler<Handler> op;
  typename op::ptr p = { boost::addressof(handler),
    boost_asio_handler_alloc_helpers::allocate(
      sizeof(op), handler), 0 };
  p.p = new (p.v) op(handler);

  BOOST_ASIO_HANDLER_CREATION((p.p, "strand", impl, "post"));

  do_post(impl, p.p);
  p.v = p.p = 0;
}
/**
 * Wait operation with node-ref
 *
 * @param[in] node node number
 */
void _xmp_mpi_wait_node(const int node)
{
  if(remove_request_node(node)){
    return;
  }

  while(1){
    int recv_tag;
    int recv_node;
    receive_request(&recv_node, &recv_tag);
    if(recv_node == node){
      return;
    }
    do_post(recv_node, recv_tag);
  }
}
Ejemplo n.º 6
0
void strand_service::post(strand_service::implementation_type& impl,
    Handler& handler)
{
  bool is_continuation =
    asio_handler_cont_helpers::is_continuation(handler);

  // Allocate and construct an operation to wrap the handler.
  typedef completion_handler<Handler> op;
  typename op::ptr p = { asio::detail::addressof(handler),
    op::ptr::allocate(handler), 0 };
  p.p = new (p.v) op(handler);

  ASIO_HANDLER_CREATION((p.p, "strand", impl, "post"));

  do_post(impl, p.p, is_continuation);
  p.v = p.p = 0;
}
/**
 * Wait operation with node-ref and tag
 *
 * @param[in] node node number
 * @param[in] tag  tag
 */
void _xmp_mpi_wait(const int node, const int tag)
{
  XACC_DEBUG("wait (%d,%d)", node,tag);
  if(remove_request(node, tag)){
    XACC_DEBUG("wait end (already recved)");
    return;
  }

  while(1){
    int recv_tag;
    int recv_node;
    receive_request(&recv_node, &recv_tag);
    if(recv_node == node && recv_tag == tag){
      XACC_DEBUG("wait end (recved)");
      return;
    }
    do_post(recv_node, recv_tag);
  }
}
Ejemplo n.º 8
0
int main(int argc, char *argv[])
{
	/* Don't bother checking for privilege if they only want usage() */
	if (argc < 2)
		goto usage;
	
	vbetool_init();
	
	if (!strcmp(argv[1], "vbestate")) {
		/* VBE save/restore tends to break when done underneath X */
		int err = check_console();

		if (err) {
			return err;
		}

		if (!strcmp(argv[2], "save")) {
			save_state();
		} else if (!strcmp(argv[2], "restore")) {
			restore_state();
		} else {
			goto usage;
		}
	} else if (!strcmp(argv[1], "dpms")) {
		if (!strcmp(argv[2], "on")) {
			return do_blank(DPMS_STATE_ON);
		} else if (!strcmp(argv[2], "suspend")) {
			return do_blank(DPMS_STATE_SUSPEND);
		} else if (!strcmp(argv[2], "standby")) {
			return do_blank(DPMS_STATE_STANDBY);
		} else if (!strcmp(argv[2], "off")) {
			return do_blank(DPMS_STATE_OFF);
		} else if (!strcmp(argv[2], "reduced")) {
			return do_blank(DPMS_STATE_LOW);
		} else {
			goto usage;
		}
	} else if (!strcmp(argv[1], "vbemode")) {
		if (!strcmp(argv[2], "set")) {
			return do_set_mode(atoi(argv[3]),0);
		} else if (!strcmp(argv[2], "get")) {
			return do_get_mode();
		} else {
			goto usage;
		}
	} else if (!strcmp(argv[1], "vgamode")) {
		if (!strcmp(argv[2], "set")) {
			return do_set_mode(atoi(argv[3]),1);
		} else {
			return do_set_mode(atoi(argv[2]),1);
		}
	} else if (!strcmp(argv[1], "post")) {
		/* Again, we don't really want to do this while X is in 
		   control */
		int err = check_console();

		if (err) {
			return err;
		}

		return do_post();
	} else if (!strcmp(argv[1], "vgastate")) {
		if (!strcmp(argv[2], "on")) {
			return enable_vga();
		} else {
			return disable_vga();
		}
	} else if (!strcmp(argv[1], "vbefp")) {
		if (!strcmp(argv[2], "id") || !strcmp(argv[2], "panelid")) {
			return do_get_panel_id(0);
		} else if (!strcmp(argv[2], "panelsize")) {
			return do_get_panel_id(1);
		} else if (!strcmp(argv[2], "getbrightness")) {
			return do_get_panel_brightness();
		} else if (!strcmp(argv[2], "setbrightness")) {
			return do_set_panel_brightness(atoi(argv[3]));
		} else if (!strcmp(argv[2], "invert")) {
			return do_invert_panel();
		} else {
			return 1;
		}
	} else {
	      usage:
		fprintf(stderr,
			"%s: Usage %s [[vbestate save|restore]|[vbemode set|get]|[vgamode]|[dpms on|off|standby|suspend|reduced]|[post]|[vgastate on|off]|[vbefp panelid|panelsize|getbrightness|setbrightness|invert]]\n",
			argv[0], argv[0]);
		return 1;
	}

	return 0;
}
Ejemplo n.º 9
0
static void *response_thread(void *args)
{
    pthread_t		thread_id;
    int				has_method, sockfd;
    unsigned int	n;
    ghd_task_t*		task;
    ghd_method		method;
    ghd_request_fields_t	Connection_field;
    volatile p_read_data	received_data = NULL;


	// 注册线程意外退出回调函数
	// 强制类型转换,make gcc happy.
    pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock,
			(void *)&mutex);

    thread_id = pthread_self();
    syslog(LOG_INFO, "Thread ID: %ld", thread_id);
    /* 处理线程就在这个while 里循环, 
     * 等待信号, 有信号就处理,处理完毕继续等待
     */
    while ( 1 ) {
		/* 在使用前一定要确保mutex已初始化 */
		pthread_mutex_lock(&mutex);

		while(task_queue_head == NULL)
			pthread_cond_wait(&cond, &mutex);

		sockfd = task_queue_head->sockfd;
		task = task_queue_head;
		task_queue_head = task_queue_head->next;
		if (task_queue_head == NULL)
			task_queue_tail = NULL;
		geekhttpd_task_free(task);

		pthread_mutex_unlock(&mutex);

		received_data = alloc_read_data();
		if (received_data == NULL) {
			syslog(LOG_INFO, "Cannot alloc memory for received_data");
			goto closefd;
		}

		has_method = 0;
		/* 读取从客户端发来的清求 */
		while (1) {
			/* 重置errno */
			errno = 0;
			if ( received_data->len < MAXHEADERLEN)
				n = read(sockfd, received_data->data + received_data->len,
						MAXHEADERLEN - received_data->len);
			else
				break;

			if (n < 0) {
				if ( errno == EINTR) {
					continue;
				}
				/* 处理有问题的链接 */
				syslog(LOG_INFO, "brower closed connection");
				goto closefd;
			} else if (n == 0) {
				break;
			} else {
				if ( errno == EAGAIN ) 
					break;
				received_data->len += n;
				if (!has_method && received_data->len > 7){
					get_request_method(received_data->data, &method);
					has_method = 1;
				}
			}
		} 

		syslog(LOG_INFO, "[Request] Size %d, Content: %s",  received_data->len, \
			(char *)received_data->data);

		/* 
		 * 根据方法响应请求,向浏览器发送消息和数据
		 */
		switch (method) {
			case GET:
				do_get(sockfd, received_data);
				break;
			case POST:
				do_post(sockfd, received_data);
				break;
			case HEAD:
				do_head(sockfd, received_data);
				break;
			case PUT:
			case DELETE:
			case TRACE:
			case CONNECT:
			case OPTIONS:
				do_not_implement(sockfd);
				break;
			case UNKNOWN:
				/* send 405 */
				do_unknown_method(sockfd);
				break;
			default:
				break;
		}
		/* TODO:
		 * Connection: Keep-Alive 
		 * 没有处理
		 */
		
closefd:
		close(sockfd);
		/* free read_data */
		free_read_data(received_data);
		received_data = NULL;
    }
    pthread_cleanup_pop(0);
}
Ejemplo n.º 10
0
static void user_login() {
    char ans[4], i;
    char genbuf[200];
    struct tm *ptime, *tmp;
    time_t now;
    int a;
    /*** Heat:廣告詞
	 char *ADV[17] = {
	 "記得唷!! 5/12在台大二活地下室見~~~",
	 "你知道Ptt之夜是什麼嗎? 5/12號就要上演耶 快去問吧!",
	 "5/12 Ptt之夜即將引爆 能不去嗎? 在台大二活地下室咩",
	 "不來就落伍了 啥? 就Ptt之夜啊 很棒的晚會唷 時間:5/12",
	 "差點忘了提醒你 5/12我們有約 就台大二活地下室咩!!",
	 "Ptt是啥 想知嗎? 5/12在台大二活地下室告訴你唷",
	 "來來來....5/12快到台大二活地下室去拿獎品吧~~",
	 "去去去...到台大二活地下室去 就5/12麻 有粉多獎品耶",
	 "喂喂喂 怎還楞在這!!快呼朋引伴大鬧ptt",
	 "Ptt最佳豬腳 換你幹幹看 5/12來吧....*^_^*",
	 "幹什麼幹什麼?? 你怎麼不曉得啥是Ptt之夜..老土唷",
	 "累了嗎? 讓我們來為你來一段精采表演吧.. 5/12 Ptt之夜",
	 "世紀末最屁力的晚會 就在台大二活地下室 5/12不見不散 gogo",
	 "到底誰比較帥(美) 來比比吧 5/12Ptt之夜 一較高下",       
	 "台大二活地下室 5/12 聽說會有一場很棒的晚會唷 Ptt之夜",
	 "台大二活地下室 5/12 你能不來嗎?粉多網友等著你耶",
	 "5/12 台大二活地下室 是各約網友見面的好地方呢",
	 }; 
	 char *ADV[] = {
	 "7/17 @LIVE 亂彈, 何欣穗 的 入場卷要送給 ptt 的愛用者!",
	 "欲知詳情請看 PttAct 板!!",
	 }; ***/

    log_usies("ENTER", getenv("RFC931") /* fromhost */ );
    setproctitle("%s: %s", margs, cuser.userid);
    
    /* resolve all cache */
    resolve_garbage();	/* get ptt cache */
    resolve_fcache();
    resolve_boards();
    
    /* 初始化 uinfo、flag、mode */
    setup_utmp(LOGIN);
    mysrand();		/* 初始化: random number 增加user跟時間的差異 */
    currmode = MODE_STARTED;
    enter_uflag = cuser.uflag;

    /* get local time */
    time(&now);
    ptime = localtime(&now);
    tmp = localtime(&cuser.lastlogin);
    
    if((a = utmpshm->number) > fcache->max_user) {
	sem_init(FROMSEM_KEY, &fcache_semid);
	sem_lock(SEM_ENTER, fcache_semid);
	fcache->max_user = a;
	fcache->max_time = now;
	sem_lock(SEM_LEAVE, fcache_semid);
    }
#ifdef INITIAL_SETUP
    if(!getbnum(DEFAULT_BOARD)) {
	strcpy(currboard, "尚未選定");
    } else
#endif
    {
	brc_initial(DEFAULT_BOARD);
	set_board();
    }

    /* 畫面處理開始 */
    if(!(HAS_PERM(PERM_SYSOP) && HAS_PERM(PERM_DENYPOST)))
	do_aloha("<<上站通知>> -- 我來啦!");
    if(ptime->tm_mday == cuser.day && ptime->tm_mon + 1 == cuser.month) {
	more("etc/Welcome_birth", NA);
	currutmp->birth = 1;
    } else {
	more("etc/Welcome_login", NA);
//	pressanykey();
//    more("etc/CSIE_Week", NA);
	currutmp->birth = 0;
    }
    
    if(cuser.userlevel) {	/* not guest */
	move(t_lines - 4, 0);
	prints("      歡迎您第 \033[1;33m%d\033[0;37m 度拜訪本站,"
	       "上次您是從 \033[1;33m%s\033[0;37m 連往本站,\n"
	       "     我記得那天是 \033[1;33m%s\033[0;37m。\n",
	       ++cuser.numlogins, cuser.lasthost, Cdate(&cuser.lastlogin));
	currutmp->mind=rand()%8;  /* 初始心情 */
	pressanykey();
 	
	if(currutmp->birth && tmp->tm_mday != ptime->tm_mday) {
	    more("etc/birth.post", YEA);
	    brc_initial("WhoAmI");
	    set_board();
	    do_post();
	}
	setuserfile(genbuf, str_badlogin);
	if(more(genbuf, NA) != -1) {
	    getdata(b_lines - 1, 0, "您要刪除以上錯誤嘗試的記錄嗎(Y/N)?[Y]",
		    ans, 3, LCECHO);
	    if(*ans != 'n')
		unlink(genbuf);
	}
	check_register();
	strncpy(cuser.lasthost, fromhost, 16);
	cuser.lasthost[15] = '\0';
	restore_backup();
    } else if(!strcmp(cuser.userid, STR_GUEST)) {
	char *nick[13] = {
	    "椰子", "貝殼", "內衣", "寶特瓶", "翻車魚",
	    "樹葉", "浮萍", "鞋子", "潛水艇", "魔王",
	    "鐵罐", "考卷", "大美女"};
	char *name[13] = {
	    "大王椰子", "鸚鵡螺", "比基尼", "可口可樂", "仰泳的魚",
	    "憶", "高岡屋", "AIR Jordon", "紅色十月號", "批踢踢",
	    "SASAYA椰奶", "鴨蛋", "布魯克鱈魚香絲"};
	char *addr[13] = {
	    "天堂樂園", "大海", "綠島小夜曲", "美國", "綠色珊瑚礁",
	    "遠方", "原本海", "NIKE", "蘇聯", "男八618室",
	    "愛之味", "天上", "藍色珊瑚礁"};
	i = login_start_time % 13;
	sprintf(cuser.username, "海邊漂來的%s", nick[(int)i]);
	sprintf(currutmp->username, cuser.username);
	sprintf(cuser.realname, name[(int)i]);
	sprintf(currutmp->realname, cuser.realname);
	sprintf(cuser.address, addr[(int)i]);
	cuser.sex = i % 8;
	currutmp->pager = 2;
	pressanykey();
    } else
	pressanykey();
    
    if(!PERM_HIDE(currutmp))
	cuser.lastlogin = login_start_time;
    
    reload_money();
    passwd_update(usernum, &cuser);
    
    for(i = 0; i < NUMVIEWFILE; i++)
	if((cuser.loginview >> i) & 1)
	    more(loginview_file[(int)i][0], YEA);
	
	
}
Ejemplo n.º 11
0
HTTP_Status
server_dispatch(ArgumentList *al, task_t *tsk)
{
  int thrindex = TASK_THRINDEX(tsk);
  int agg = 0;
  int nfound;
  HTTP_Status retcode = HTTP_NO_ERR;
  Request *hp = (Request *)TASK_DATA(tsk);
#ifdef LOGGING
  struct loginfo *lo = hp->lo;
#endif

  INST_set_thread_state(thrindex, THR_CACHE);

  /*
   *  If we got here, we know the request is either GET or POST,
   *  or this is a URL in the frontend's namespace
   */

  tsk->task_age = 0;            /* no pipe stages done yet */

  /*if (*hp->url == '/' || 
      strncasecmp(hp->url, fe_agg_string, strlen(fe_agg_string)) == 0) {*/
  if (is_server_url(hp->url)==gm_True) {
    /* this is a URL in the frontend's namespace, or an aggregator URL */
    const char *workerName, *val;
    int val_len, len, to_copy, already_read;
    char *orig_hdrs, *eoh, *new_hdrs, *body;
    extern Options runtime_options;

    orig_hdrs = DistillerBufferData(&hp->cli_hdrs);
    eoh = strstr(orig_hdrs, "\r\n\r\n");
    if (eoh==NULL) {
      retcode = HTTP_ERR_MALFORMED_REQUEST;
      goto DISPATCH_RETURN;
    }
    eoh += 4;

    /* clone the headers */
    DistillerBufferAlloc(&hp->svr_hdrs, eoh-orig_hdrs+1);
    new_hdrs = DistillerBufferData(&hp->svr_hdrs);
    memcpy(new_hdrs, orig_hdrs, eoh-orig_hdrs);
    *(new_hdrs+(eoh-orig_hdrs)) = '\0';
    DistillerBufferSetLength(&hp->svr_hdrs, eoh - orig_hdrs);
    DistillerBufferFreeMe(&hp->svr_hdrs, gm_True);

    /* 
     * look for the content-length field; 
     * if found, read the rest of the data and create svr_data 
     */
    if ((val = get_header_value(&hp->cli_hdrs, "content-length", &val_len,
				NULL, NULL)) != NULL) {
      len = strtoul(val, NULL, 0);
      if (len < 0) {
	retcode = HTTP_ERR_MALFORMED_REQUEST;
	goto DISPATCH_RETURN;
      }

      already_read = DistillerBufferLength(&hp->cli_hdrs) - (eoh - orig_hdrs);
      if (len <= already_read) {
	to_copy = len;
      } else {
	to_copy = already_read;
      }

      DistillerBufferAlloc(&hp->svr_data, len+1);
      body = DistillerBufferData(&hp->svr_data);
      memcpy(body, eoh, to_copy);
      
      /* get the rest of the data from the socket */
      if (to_copy < len) {
	if (readline_or_timeout(hp, len - to_copy, body+to_copy)
	    != (len-to_copy)) {
	  retcode = HTTP_ERR_MALFORMED_REQUEST;
	  goto DISPATCH_RETURN;
	}
      }

      /* add a trailing '\0' */
      *(body+len) = '\0';
      DistillerBufferSetLength(&hp->svr_data, len);
    }
    
    workerName = Options_Find(runtime_options, "frontend.myurl.dispatch");
    if (workerName==NULL) workerName = "myurl/dispatch";

    insert_header(&hp->svr_hdrs, "X-Route", workerName, 1);
    hp->svr_http_status = 200; /* everything's ok with this HTTP request */
  }
  else {
    INST_timestamp(thrindex, m_cachestart);
    if (hp->method[0] == 'g' || hp->method[0] == 'G') {
      /* handle GET */

#ifdef OLD
      /*
       *  HACK HACK HACK - this should be replaced with the real interface that
       *  does a regexp match on URL to determine if any aggregator should get
       *  dibs before the original content is fetched.
       *
       *  Any references in this function to variable 'agg' represent a place
       *  where the hack was spliced in.
       */
      if (strncasecmp(hp->url, fe_agg_string, strlen(fe_agg_string)) != 0) {
	/* not an aggregator call */
#endif
	agg = 0;
	retcode = do_get(hp, al);
	if (retcode != HTTP_NO_ERR) {
	  goto DISPATCH_RETURN;
	}
#ifdef OLD
      } else {
	/* aggregator call */
	abort();
	agg = 1;
	/* don't clone the client headers - just point to them. */
	DistillerBufferSetStatic(&hp->svr_hdrs,
				 DistillerBufferData(&hp->cli_hdrs),
				 DistillerBufferLength(&hp->cli_hdrs));
	/* since we're pointing to a copy, don't try to free */
	DistillerBufferFreeMe(&hp->svr_hdrs, gm_False);
      }
#endif
    } else {
      /* handle POST */
      retcode = do_post(hp, al);
      if (retcode != HTTP_NO_ERR) {
	/* post failed! report error to client */
	goto DISPATCH_RETURN;
      }
    }

    INST_timestamp(thrindex, m_cachedone);

    /*
     *  if there was an HTTP-level error (response code not "200"), bypass
     *  the remainder straight to client.
     */
    
    nfound = sscanf(DistillerBufferData(&hp->svr_hdrs), "%*s %lu",
		    &hp->svr_http_status);
    if (nfound < 1) {             /* no status found */
      retcode = HTTP_ERR_GET_FAILED;
      hp->svr_http_status = 0;
    } else {
      retcode = HTTP_NO_ERR;
    }
  }

#ifdef LOGGING
  lo->http_response = hp->svr_http_status;;      /* log HTTP server response */
#endif /* LOGGING */

  /*
   *  Note that HTTP_NO_ERR means "transaction to server succeeded" (ie
   *  at the transport level).  it does NOT necessarily mean that the
   *  HTTP *operation* (eg GET) succeeded -- the HTTP status code tells that.
   */

DISPATCH_RETURN:
  return retcode;
}
Ejemplo n.º 12
0
static void
user_login()
{
	char		genbuf    [200];
	struct tm      *ptime, *tmp;
	time_t		now = time(0);
	int		a;

	extern struct FROMCACHE *fcache;
	extern int	fcache_semid;

	log_usies("ENTER", fromhost);
	setproctitle("%s: %s", cuser.userid, fromhost);

	/* ------------------------ */
	/* 初始化 uinfo、flag、mode */
	/* ------------------------ */

	setup_utmp(LOGIN);
	currmode = MODE_STARTED;
	enter_uflag = cuser.uflag;

	/* get local time */
	tmp = localtime(&cuser.lastlogin);

	update_data();		/* wildcat: update user data */
	/* Ptt check 同時上線人數 */
	resolve_fcache();
	resolve_utmp();

	if ((a = utmpshm->number) > fcache->max_user) {
		sem_init(FROMSEM_KEY, &fcache_semid);
		sem_lock(SEM_ENTER, fcache_semid);
		fcache->max_user = a;
		fcache->max_time = now;
		sem_lock(SEM_LEAVE, fcache_semid);
	}
#ifdef  INITIAL_SETUP
	if (getbnum(DEFAULT_BOARD) == 0) {
		strcpy(currboard, "尚未選定");
	} else
#endif

	{
		brc_initial(DEFAULT_BOARD);
		set_board();
	}

	/* ------------ */
	/* 畫面處理開始 */
	/* ------------ */

	if (!(HAS_PERM(PERM_SYSOP) && HAS_PERM(PERM_DENYPOST))) {
		char		buf       [256];
		time_t		now;

		time(&now);
		sprintf(buf, "<<上站通知>> -- 我來囉! - %s", Etime(&now));
		do_aloha(buf);
	}
	time(&now);
	ptime = localtime(&now);

#ifdef CAMERA
	film_out(FILM_LOGIN, 0);
#else
	more("etc/Welcome_login", NA);
#endif

#if 0
	/* wildcat : 搬家通知用 */
	if (belong(BBSHOME "/etc/oldip", fromhost)) {
		more(BBSHOME "/etc/removal");
		abort_bbs();
	}
#endif

	if ((cuser.day == ptime->tm_mday) && (cuser.month == (ptime->tm_mon + 1)))
		currutmp->birth = 1;
	else
		currutmp->birth = 0;

	if (cuser.userlevel) {	/* not guest */
		move(t_lines - 3, 0);
		prints("      歡迎您第 %d 度拜訪本站,\
上次您是從 %s 連往本站,\n\
     我記得那天是 %s。\n",
		       ++cuser.numlogins, cuser.lasthost,
		       Etime(&cuser.lastlogin));
		pressanykey(NULL);


		/* Ptt */
		if (currutmp->birth == 1) {
#ifdef CAMERA
			film_out(FILM_WEL_BIRTH, 0);
#else
			more("etc/Welcome_birth", YEA);
#endif
			brc_initial("Greeting");
			set_board();
			do_post();
		}
		sethomefile(genbuf, cuser.userid, str_badlogin);
		if (more(genbuf, NA) != -1) {
			if (getans2(b_lines, 0, "您要刪除以上錯誤嘗試的記錄嗎?", 0, 2, 'y') != 'n')
				unlink(genbuf);
		}
		check_register();
		strncpy(cuser.lasthost, fromhost, 24);
		substitute_record(fn_passwd, &cuser, sizeof(cuser), usernum);
		cuser.lasthost[23] = '\0';
		restore_backup();
	}