void rebuildSignal(int signal) {
	if(signal == SIGALRM) {
		// possivel tentativa de reconstrucao do anel
		if(rebuild() == -1) {
			puterror("não foi possível reconstruir o anel\n");
			putmessage("vai ser feito um reset ao nó\n");

			//fechar todas as ligações com predi e succi
			closeConnection(&succiNode.fd);
			closeConnection(&prediNode.fd);

			curNode.id = succiNode.id = prediNode.id = -1;

			if(iAmStartNode) {
				//remover anel do servidor
				unregisterRing(curRing);
				curRing = -1;
				iAmStartNode = FALSE;
			}

		}
	}
}
示例#2
0
int
main(int argc, char *argv[])
{
    int mtype, size, c,
	list = FALSE, limit = -1, deflt = -1;
    int fd;
    char *userlist = 0, *user, **users, *p;
    short status;
    struct user_priority *ppri_tbl, *ld_priority_file();
    extern char *optarg;
    extern int optind, opterr, optopt, errno;

    setlocale(LC_ALL, "");

#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
    (void) textdomain(TEXT_DOMAIN);


    if(argc == 1) {
usage:
	(void) printf(gettext("usage: \n"));	
  	(void) printf(gettext("(assign priority limit to users)\n"));
	(void) printf(gettext("\tlpusers -q priority -u user-list\n"));

  	(void) printf(gettext(
		"(assign default priority limit for balance of users)\n"));
	(void) printf(gettext("\tlpusers -q priority\n"));

  	(void) printf(gettext("(put users back to default priority limit)\n"));
	(void) printf(gettext("\tlpusers -u user-list\n"));

  	(void) printf(gettext("(assign default priority)\n"));
	(void) printf(gettext("\tlpusers -d priority\n"));

  	(void) printf(gettext("(examine priority limits, defaults)\n"));
	(void) printf(gettext("\tlpusers -l\n"));

	exit(argc == 1);
    }

    opterr = 0; /* disable printing of errors by getopt */
    while ((c = getopt(argc, argv, "ld:q:u:")) != -1)
	switch(c) {
	case 'l':
	    if (list)
		LP_ERRMSG1(WARNING, E_LP_2MANY, 'l');
	    list = TRUE;
	    break;
	case 'd':
	    if (deflt != -1)
		LP_ERRMSG1(WARNING, E_LP_2MANY, 'd');
	    deflt = (int)strtol(optarg,&p,10);
	    if (*p || deflt<PRI_MIN || deflt>PRI_MAX) {
		LP_ERRMSG1(ERROR, E_LP_BADPRI, optarg);
		exit(1);
	    }
	    break;
	case 'q':
	    if (limit != -1)
		LP_ERRMSG1(WARNING, E_LP_2MANY, 'q');
	    limit = (int)strtol(optarg,&p,10);
	    if (*p || limit<PRI_MIN || limit>PRI_MAX) {
		LP_ERRMSG1(ERROR, E_LP_BADPRI, optarg);
		exit(1);
	    }
	    break;
	case 'u':
	    if (userlist)
		LP_ERRMSG1(WARNING, E_LP_2MANY, 'u');
	    userlist = optarg;
	    break;
	case '?':
	    if (optopt == '?') goto usage;
	    (p = "-X")[1] = optopt;
	    if (strchr("ldqu", optopt))
		LP_ERRMSG1(ERROR, E_LP_OPTARG, p);
	    else
		LP_ERRMSG1(ERROR, E_LP_OPTION, p);
	    exit(1);
	}

    if (optind < argc) {
	LP_ERRMSG1(ERROR, E_LP_EXTRA, argv[optind]);
	exit(1);
    }

    if (((list || deflt != -1) && (limit != -1 || userlist))
	|| (list && deflt != -1)) {
	LP_ERRMSG(ERROR, E_LP_OPTCOMB);
	/* invalid combination of options */
	exit(1);
    }

    PRIORITY = Lp_Users;

    /* load existing priorities from file */
    if (!(ppri_tbl = ld_priority_file(PRIORITY))) {
	switch (errno) {
	case EBADF:
	    LP_ERRMSG1(ERROR, E_LPU_BADFORM, PRIORITY);
	    break;
	default:
	    LP_ERRMSG2(ERROR, E_LPU_BADFILE, PRIORITY, errno);
	}
	exit(1);
    }

    if (list) {
	print_tbl(ppri_tbl);
	exit (0);
    } else {
	if (userlist) {
	    users = getlist(userlist, " \t", ",");
	    if (users)
		while (user = *users++) {
		    if (del_user(ppri_tbl, user) && (limit == -1))
			LP_ERRMSG1(WARNING, E_LPU_NOUSER, user);
		    if (limit != -1) {
			if (add_user(ppri_tbl, user, limit))
			    LP_ERRMSG1(WARNING, E_LPU_BADU, user);
		    }
		}
	} else if (deflt != -1)
	    ppri_tbl->deflt = deflt;
	else
	    ppri_tbl->deflt_limit = limit;

	if ((fd = open_locked(PRIORITY, "w", LPU_MODE)) < 0) {
	    LP_ERRMSG1(ERROR, E_LP_ACCESS, PRIORITY);
	    exit(1);
	}
	output_tbl(fd, ppri_tbl);
	close(fd);
    }

    if (mopen()) /* error on mopen == no spooler, exit quietly */
	exit(0);

    (void)putmessage (message, S_LOAD_USER_FILE);

    if (msend(message))
	goto Error;
    if (mrecv(reply, sizeof(reply)) == -1)
	goto Error;
    mtype = getmessage(reply, R_LOAD_USER_FILE, &status);
    if (mtype != R_LOAD_USER_FILE) {
	LP_ERRMSG1 (ERROR, E_LP_BADREPLY, mtype);
	goto NoError;
    }

    if (status == 0)
	goto NoError;

Error:	LP_ERRMSG (ERROR, E_LPU_NOLOAD);

NoError:(void)mclose ();
    return (0);
}
int main(int argc, char const *argv[]) {

	//inicializacao
	if(initializeCommunication(argc, argv) != 0) exit(-1); //inicailizacao falhou
	putdebug("inicialização completa\n");

	//inicializar conjunto de ligacoes
	initializeConnectionSet();

	int maxFd = curNode.fd;	//descritor com valor mais elevado
	char buffer[BUFSIZE];	//buffer utilizado para fazer a leitura dos descritores
	int inputReady = 0;		//indica se existe input disponivel para ler
	int quit = FALSE;
	while(!quit) {

		//reinicializar conjunto de fds de leitura
		FD_ZERO(&readFds);
		//adicionar ligacoes no conjunto de fds
		copySet(&readFds);
		//adicionar listen fd ao conjunto de fds
		FD_SET(curNode.fd, &readFds);
		//adicionar stdin ao conjunto de fds
		FD_SET(STDIN_FILENO, &readFds);

		putdebug("CurNode - ring: %d id: %d ip: %s port: %s fd: %d",
				curRing, curNode.id, curNode.ip, curNode.port, curNode.fd);
		putdebug("SucciNode - id: %d ip: %s port: %s fd: %d",
						succiNode.id, succiNode.ip, succiNode.port, succiNode.fd);
		putdebug("PrediNode - id: %d ip: %s port: %s fd: %d",
						prediNode.id, prediNode.ip, prediNode.port, prediNode.fd);

		if(maxFd < getMaxConnection()) {
			maxFd = getMaxConnection();
		}

		//esperar por descritor pronto para ler
		putmessage("\r> ");
		inputReady = select(maxFd + 1, &readFds, NULL, NULL, NULL);
		if(inputReady <= 0) {
			putdebugError("main", "select falhou");
			continue;
		}

		if(FD_ISSET(curNode.fd, &readFds)) {	//testar se o listen fd esta pronto para leitura
			struct sockaddr_in addr;
			socklen_t addrlen = sizeof(addr);
			bzero(&addr, addrlen);

			//aceitar ligacao
			int connectionFd;
			if( (connectionFd = accept(curNode.fd, (struct sockaddr*)&addr, &addrlen)) == -1) {
				putdebugError("main", "ligação não foi aceite");
			} else {
				putdebug("nova ligação %d com endereço: %s", connectionFd, inet_ntoa(addr.sin_addr));
				//adicionar descritor ao conjunto de descritores de ligacao
				addConnection(connectionFd);

				//definir um timeout para as comunicações
				struct timeval tv;
				tv.tv_sec = 5;
				setsockopt(connectionFd, SOL_SOCKET, SO_SNDTIMEO,(struct timeval *)&tv,sizeof(struct timeval));
				setsockopt(connectionFd, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval));
			}
		}

		if(FD_ISSET(STDIN_FILENO, &readFds)) { //testar se o utilizador executou um comando

			//ler comando do utilizador
			bzero(buffer, sizeof(buffer));
			if(fgets(buffer, BUFSIZE, stdin) != NULL) {
				//executar comando do utilizador
				putdebug("processar comando do utilizador");

				int errorCode = executeUserCommand(buffer);
				switch(errorCode) {
					case 0: 	putdebug("comando de utilizador processado com sucesso"); break;
					case -1: 	putdebugError("main", "falha no processamento do comando de utilizador"); break;
					case 1:
					{
						putmessage("programa vai sair\n");

						//fechar todos os sockets
						int fd = getFirstConnection();
						while(fd >= 0) {
							close(fd);
							rmConnection(fd);
							//proxima ligacao
							fd = getNextConnection(fd);
						}

						//fechar socket de escuta e socket do servidor de arranque
						closeSockets();

						quit = TRUE;
						continue;
					}
				}
			}
		}

		//ler fds de ligacoes actuais com o nó
		int connectionFd = getFirstConnection();
		while(connectionFd >= 0) {
			if(FD_ISSET(connectionFd, &readFds)) {
				//limpar buffer de rececao
				bzero(buffer, sizeof(buffer));

				//ler mensagem
				if(readMessage(connectionFd, buffer, sizeof(buffer)) <= 0) {
					close(connectionFd);		//fechar ligacao
					rmConnection(connectionFd);	//remover no do conjunto de ligacoes
					putdebug("ligacao %d terminada", connectionFd);

					if(connectionFd == prediNode.fd) {
						prediNode.fd = -1;
						prediNode.id = -1;
						putdebug("ligação terminada com predi");

						if(succiNode.fd == -1 && !iAmStartNode) {
							//estou sozinha mas não sou o nó de arranque
							//isto significa que houve uma saida abrupta

							//registar  num novo anel
							if(registerNewRing() == -1) {
								putdebugError("handleEND", "não foi possível registar novo anel");
								return -1;
							}
						}
					}

					if(connectionFd == succiNode.fd) {
						succiNode.fd = -1;
						succiNode.id = -1;
						putdebug("ligação terminada com succi");

						//colocar um alarme de 2 segundos para garnatir que todas as ligações
						//que são par ser terminadas têm efeito no estado do nó
						signal(SIGALRM, rebuildSignal);
						alarm(REBUILD_INTERVAL);
					}

				} else {
					//tratar mensagem recebida
					putdebug("mensagem recebida pela ligacao %d: %s", connectionFd, buffer);

					//remover \n
					int length = strlen(buffer);
					if(buffer[length - 1] == '\n')
						buffer[length - 1] = '\0';

					if(strcmp(buffer, "ERROR") == 0) {
						//houve um erro na comunicação TCP
						puterror("ocorreu um erro na comunicação entre nós\n");
						closeConnection(&connectionFd);
						continue;
					}

					if(handleMessage(buffer, connectionFd) == -1) {
						//notificar quem enviou o pedido que ocorreu um erro
						char answer[] = "ERROR\n";
						sendMessage(connectionFd, answer);

						if(connectionFd == prediNode.fd) {
							prediNode.fd = -1;
							prediNode.id = -1;
							putdebug("ligação terminada com predi por causa de erro");
						}

						if(connectionFd == succiNode.fd) {
							succiNode.fd = -1;
							succiNode.id = -1;
							putdebug("ligação terminada com succi por causa de erro");
						}

						//terminar ligacao
						closeConnection(&connectionFd);
					}
				}
			}

			//proxima ligacao
			connectionFd = getNextConnection(connectionFd);
		}
	}

	return 0;
}
示例#4
0
void take_message(void)
{
    int		bytes;
    int		i;
    MESG *	md;

    for (EVER) {	/* not really forever...returns are in the loop */
	if ((md = mlisten()) == NULL)
	    switch(errno) {
	      case EAGAIN:
	      case EINTR:
		return;

	      case ENOMEM:
		mallocfail();
		/* NOTREACHED */

	      default:
		fail ("Unexpected streams error in mlisten (%s).\n" , PERROR);
	    }
	
	/*
	 * Check for a dropped connection to a child.
	 * Normally a child should tell us that it is dying
	 * (with S_SHUTDOWN or S_SEND_CHILD), but it may have
	 * died a fast death. We'll simulate the message we
	 * wanted to get so we can use the same code to clean up.
	 */
	if ((md->event & POLLHUP) && !(md->event & POLLIN) ||
	    (md->event & (POLLERR|POLLNVAL))) {
		switch (md->type) {

		case MD_CHILD:
			/*
			 * If the message descriptor is found in the
			 * exec table, it must be an interface pgm,
			 * notification, etc. Otherwise, it must be
			 * a network child.
			 */
			for (i = 0; Exec_Table[i] != NULL; i++)
				if (Exec_Table[i]->md == md)
					break;

			if (Exec_Table[i] != NULL) {
				(void) putmessage(Message, S_CHILD_DONE,
					Exec_Table[i]->key, 0, 0);
			} else {
				(void) putmessage(Message, S_SHUTDOWN, 1);
			}
			bytes = 1;
			break;

		default:
			bytes = -1;
			break;

		}

	} else {
		if (md->readfd == -1) { /* something happened to the readfd */
			syslog(LOG_DEBUG, "take_message: readfd is -1");
			return;
		}
		bytes = mread(md, Message, MSGMAX);
	}

	switch (bytes) {
	  case -1:
	    if (errno == EINTR)
		return;
	    else
		fail ("Unexpected streams error (%s).\n" , PERROR);
	    break;

	  case 0:
	    break;

	  default:
	    if (do_msg(md))
		return;
	    break;
	}
    }
}