int main(int argc, char * argv[]) { tokenitem * locklist = NULL; spread_connect(); while (1) { tokenitem * t; spread_receive(); char * token = get_token(); char * sender = get_sender(); switch (get_message_type()) { case MSG_REQUEST_WRITE: // send lock or list of open read and write locks printf("%s requests write to %s\n", sender, token); t = token_find_add(&locklist, token); if (!t->readlocks && !t->writelocks) { addlock(&(t->writelocks), sender); spread_send(sender, "ack", token); } else { spread_send_list(sender, "client_list", token, format_locklist(t, 1)); } break; case MSG_REQUEST_READ: // send lock or list of open write locks printf("%s requests read to %s\n", sender, token); t = token_find_add(&locklist, token); if (!t->writelocks) { addlock(&(t->readlocks), sender); spread_send(sender, "ack", token); } else { spread_send_list(sender, "client_list", token, format_locklist(t, 0)); } break; case MSG_REVOKE_DONE: //update tables(this client has write, reads are gone) -> send ack printf("%s says revoke is done for %s\n", sender, token); t = token_find_add(&locklist, token); if (t->writelocks) { free_locklist(t->writelocks); t->writelocks = NULL; } if (t->readlocks) { free_locklist(t->readlocks); t->readlocks = NULL; } addlock(&(t->writelocks), sender); spread_send(sender, "ack", token); break; case MSG_DOWNGRADE_DONE: //updates tables(this client has read, writes are now reads) -> send ack printf("%s says downgrade is done for %s\n", sender, token); t = token_find_add(&locklist, token); if (t->writelocks) { movelocks(&(t->writelocks), &(t->readlocks)); } if (t->readlocks) { removelock(&(t->readlocks), sender); } addlock(&(t->readlocks), sender); spread_send(sender, "ack", token); break; case MSG_CLOSE: //remove any locks for this token for this client printf("%s says it is closing %s\n", sender, token); t = token_find(&locklist, token); if (t) { if (t->readlocks) { removelock(&(t->readlocks), sender); } if (t->writelocks) { removelock(&(t->writelocks), sender); } if (!t->readlocks && !t->writelocks) { removetoken(&locklist, token); } } spread_send(sender, "ack", token); break; case MSG_UNKNOWN: printf("unknown message! (%s, %s)\n", sender, token); } print_locklist(locklist); } return 0; }
/*--------------------------------------- | | | createlock()/2 | | | +--------------------------------------*/ int createlock(char *filepath, int type) { char lockprimary[MAXPATHL], locksecondary[MAXPATHL], HostName[MAXPATHL]; int iter, lfd; FILE *lkfptr, *fopen(); (void) strcpy(lockprimary, filepath); (void) strcpy(locksecondary, filepath); (void) strcat(lockprimary, ".lock1"); (void) strcat(locksecondary, ".lock2"); /******************************** * Create secondary lock file. * ********************************/ for (iter = 0; iter < MAX_LOCK_ITER; iter++) { if ( (lfd = open(locksecondary, (O_CREAT|O_EXCL), 0666 )) >= 0 ) { (void) close(lfd); iter = MAX_LOCK_ITER; } else { switch (type) { case INFO_LFILE: sleep(1); if ( (iter - 1) == MAX_LOCK_ITER ) return(ERROR); break; case DATA_LFILE: return(LOCKED_DFILE); default: return(ERROR); } } } /******************************* * Create primary lock file. * *******************************/ if ( access(lockprimary, F_OK) == 0 ) { if ( removelock(filepath) ) { unlink(locksecondary); switch (type) { case DATA_LFILE: return(LOCKED_DFILE); case INFO_LFILE: default: return(ERROR); } } } if ( (lkfptr = fopen(lockprimary, "w")) == NULL ) { unlink(locksecondary); return(ERROR); } (void) gethostname(HostName, sizeof(HostName)); (void) fprintf( lkfptr, "%s %d\n", HostName, getpid() ); (void) fclose(lkfptr); /******************************** * Remove secondary lock file. * ********************************/ if ( unlink(locksecondary) ) { unlink(lockprimary); return(ERROR); } return(COMPLETE); }
int main(int argc, char *argv[]) { const char *action = NULL; struct sigaction sa; ARGBEGIN { case 'l': case 'r': case 's': if (writefifo(fifofile, ARGC()) == -1) die("cannot write to fifo\n"); exit(EXIT_SUCCESS); default: usage(); } ARGEND; if (argc > 1) usage(); if (getuid() != 0) die("only root can run this program\n"); if (getlock(pidfile) == -1) die("cannot get exclusive lock\n"); if (createfifo(fifofile, 0666) == -1) die("cannot create fifo\n"); sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = catchsignal; sigemptyset(&sa.sa_mask); sigaction(SIGCHLD, &sa, NULL); signal(SIGINT, catchsignal); signal(SIGHUP, catchsignal); signal(SIGQUIT, catchsignal); signal(SIGTERM, catchsignal); signal(SIGKILL, catchsignal); signal(SIGPIPE, catchsignal); startserver(server, display); do { const char *user, *pass; char c; if (autologin && authenticate(autologin, NULL)) { autologin = NULL; goto login; } creategui(); do { rungui(&user, &pass); if (!strcmp(user, "reboot")) action = rebootcmd; else if (!strcmp(user, "shutdown")) action = shutdowncmd; } while (!action && !authenticate(user, pass)); destroygui(); if (action) break; login: childpid = startsession(child, env); c = readfifo(fifofile); if (c == 'r') action = rebootcmd; else if (c == 's') action = shutdowncmd; else if (!c) while (childpid) sleep(10); stopsession(); } while (!action); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTERM, SIG_DFL); signal(SIGKILL, SIG_DFL); signal(SIGCHLD, SIG_DFL); signal(SIGPIPE, SIG_IGN); stopserver(); removefifo(fifofile); removelock(pidfile); return system(action); }
int main(int argc, char *argv[]) { char * message; lockitem * pendingclients = NULL; if (argc < 3) { printf("usage: %s filename.txt [R|W]\n", argv[0]); return 0; } if (argv[2][0] == 'R') { last_message = MSG_REQUEST_READ; message = "request_read"; } else if (argv[2][0] == 'W') { last_message = MSG_REQUEST_WRITE; message = "request_write"; } else { printf("lock type must be R or W\n"); return 0; } spread_connect(); server = argv[1]; spread_send(SERVER_NAME, message, server); set_alarm_handler(); printf("SIGINT to quit\n"); while (1) { spread_receive(); char * token = get_token(); char * sender = get_sender(); char * list = get_list(); switch(get_message_type()) { case MSG_REVOKE: printf("got a revoke message. quitting.\n"); spread_send(sender, "ack", token); exit(0); break; case MSG_DOWNGRADE: //TODO: write blocks to server //TODO: downgrade to read (currently no internal state of this) printf("got a downgrade message. doin it.\n"); spread_send(sender, "ack", token); break; case MSG_CLIENT_LIST: if (last_message == MSG_REQUEST_WRITE) { printf("got a client list in response to a write request\n"); parse_client_list(&pendingclients, list); last_message = MSG_REVOKE; message_others(pendingclients, "revoke", token); } else if (last_message == MSG_REQUEST_READ) { printf("got a client list in response to a read request\n"); parse_client_list(&pendingclients, list); last_message = MSG_DOWNGRADE; message_others(pendingclients, "downgrade", token); } else { printf("don't know why we got a client list now\n"); } break; case MSG_ACK: if (last_message == MSG_REQUEST_READ || last_message == MSG_REQUEST_WRITE || last_message == MSG_DOWNGRADE_DONE || last_message == MSG_REVOKE_DONE) { printf("got lock!\n"); } else if (last_message == MSG_CLOSE) { //TODO: write blocks to server printf("got ack and quitting\n"); return 0; } else if (last_message == MSG_DOWNGRADE) { printf("got ack for downgrade, removing from list\n"); removelock(&pendingclients, sender); if (!pendingclients) { printf("downgrade is done!\n"); last_message = MSG_DOWNGRADE_DONE; spread_send(SERVER_NAME, "downgrade_done", token); } } else if (last_message == MSG_REVOKE) { printf("got ack for revoke, removing from list\n"); removelock(&pendingclients, sender); if (!pendingclients) { printf("revoke is done!\n"); last_message = MSG_REVOKE_DONE; spread_send(SERVER_NAME, "revoke_done", token); } } else { printf("got ack for something other than close\n"); } break; default: printf("got a message for me, but what does it mean?\n"); } } return 0; }