/* Opens the UDP socket, binds to the bootpc port and drops root privileges */ int init_socket() { struct sockaddr_in addr; struct protoent *proto; int sock; int bcast = 1; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = get_port("bootpc"); if ((proto = getprotobyname("udp")) == NULL || (sock = socket(AF_INET, SOCK_DGRAM, proto->p_proto)) == -1) exit(1); if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) == -1 || setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &bcast, sizeof(bcast)) == -1 || bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) exit(1); if (set_gid(getgid()) != 0 || /* we don't need it anymore */ set_uid(getuid()) != 0) exit(1); return sock; }
/*}}}*/ void A1_p() {/*{{{*/ // Procesy A1 generują kolejne liczby parzyste, jeżeli produkowana liczba // będzie mniejsza niż największa liczba z obu buforów, i wstawiają // wygenerowaną liczbę do tego bufora, w którym jest mniej liczb. shm_at(); int number = 2; while(1) { // printf("While iteration\\n"); P(mutex); int max1 = max(FIFO_1); int max2 = max(FIFO_2); int max = max1 > max2 ? max1 : max2; V(mutex); if ( number < max ) { P(mutex); if ( count(FIFO_1) < count(FIFO_2) ) put(FIFO_1, number); else put(FIFO_2, number); V(mutex); number += 2; } else { P(a1); } sleep(1); } }/*}}}*/ void A2_p() {/*{{{*/ // Procesy A2 generują do bufora 1 kolejne liczby nieparzyste jeżeli w // buforze 1 jest mniej niż 30 liczb shm_at(); int number = 1; while(1) { printf("A2 loop\n"); if ( *count(FIFO_1) < 30 ) { P(mutex); put(FIFO_1, number); V(mutex); number += 2; } else { P(a2); } sleep(1); } }/*}}}*/ void A3_p() {/*{{{*/ // Procesy A3 generują do bufora 2 kolejne liczby nieparzyste jeżeli w // buforze 2 jest mniej niż 20 liczb shm_at(); int number = 1; while(1) { // printf("A3 loop\\n"); if ( *count(FIFO_2) < 20 ) { P(mutex); put(FIFO_2, number); V(mutex); number += 2; } else { P(a3); } sleep(1); } }/*}}}*/ void B1_p() {/*{{{*/ // Procesy B1 zjadają liczby parzyste (z dowolnego bufora), pod warunkiem // że dany bufor zawiera co najmniej 6 liczb. shm_at(); while(1) { // printf("B1 loop\\n"); if ( (*count(FIFO_1) >= 6) && (top(FIFO_1) % 2 == 0) ) { P(mutex); get(FIFO_1); V(mutex); } else P(b1_1); if ( (*count(FIFO_2) >= 6) && (top(FIFO_2) % 2 == 0) ) { P(mutex); get(FIFO_2); V(mutex); } else P(b1_2); sleep(1); } }/*}}}*/ void B2_p() {/*{{{*/ // Procesy B2 zjadają liczby nieparzyste (z dowolnego bufora), pod // warunkiem że dany bufor zawiera co najmniej 7 liczb. shm_at(); while(1) { // printf("B2\\n"); if ( (*count(FIFO_1) >= 7) && (top(FIFO_1) % 2 != 0) ) { P(mutex); get(FIFO_1); V(mutex); } else P(b2_1); if ( (*count(FIFO_2) >= 7) && (top(FIFO_2) % 2 != 0) ) { P(mutex); get(FIFO_2); V(mutex); } else P(b2_2); sleep(1); } }/*}}}*/ void generate() {/*{{{*/ shm_at(); int number = 1; while(1) { P(mutex); put(FIFO_1, number); number += 1; V(mutex); sleep(1); } }/*}}}*/ void consume() {/*{{{*/ shm_at(); int number = 1; while(1) { P(mutex); get(FIFO_1); V(mutex); sleep(1); } }/*}}}*/ void parent() {/*{{{*/ while (1) { print_fifo(FIFO_1); printf("\n"); print_fifo(FIFO_2); printf("\n"); printf("-------------------------------\n"); printf("\n"); sleep(1); } }/*}}}*/ void decrease_remaining() {/*{{{*/ if ( remaining_A1 > 0 ) remaining_A1--; else if ( remaining_A2 > 0 ) remaining_A2--; else if ( remaining_A3 > 0 ) remaining_A3--; else if ( remaining_B1 > 0 ) remaining_B1--; else if ( remaining_B2 > 0 ) remaining_B2--; }/*}}}*/ void set_gid() {/*{{{*/ if ( remaining_A1 > 0 ) { setgid(A1); --remaining_A1; } else if ( remaining_A2 > 0 ) { setgid(A2); --remaining_A2; } else if ( remaining_A3 > 0 ) { setgid(A3); --remaining_A3; } else if ( remaining_B1 > 0 ) { setgid(B1); --remaining_B1; } else if ( remaining_B2 > 0 ) { setgid(B2); --remaining_B2; } }/*}}}*/ int main(int argc, char** argv) {/*{{{*/ pid_t pid; int i; // Attach shm segment to process shm_at(); // Init fifos init_fifo(); i = 0; for ( int i = 0; i < PCOUNT; ++i ) { pid = fork(); if ( pid == 0 ) { // Child set_gid(); // printf("Child process gid: %d\\n", getgid()); int gid = getgid(); switch (gid) { case A1: A1_p(); break; case A2: A2_p(); // generate(); break; case A3: A3_p(); // consume(); break; case B1: B1_p(); break; case B2: B2_p(); break; } break; } else { // Used for proper group id assignment decrease_remaining(); } } if ( pid != 0 ) parent(); /* if ( (pid = fork()) == 0 ) { // Child setgid(A1); printf("Child process group: %d\n", getgid()); } else { printf("Parent process group: %d\n", getgid()); wait(); } */ }/*}}}*/