/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos720 src/bos/usr/bin/errlg/samples/syscatch/syscatch.c.S 1.1 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* Restricted Materials of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 1995 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ static char sccsid[] = "@(#)77 1.1 src/bos/usr/bin/errlg/samples/syscatch/syscatch.c.S, cmderrlg, bos720 7/28/95 15:51:40"; /* * COMPONENT_NAME: (CMDERRLG) Error catcher sample * * FUNCTIONS: Setup the modem and catch a call from an MP's * Service processor * * ORIGINS: 27 * * (C) COPYRIGHT International Business Machines Corp. 1995 * All Rights Reserved * Licensed Materials - Property of IBM * * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sysguard.h" /* function prototypes */ int make_ready(char *tty_name, char *baud_rate); void get_initstr(char *msg); void monitor_modem(int filedesc); int process_call(int filedesc); data_holder *receive_prb_data(int fd); char *assemble_data(data_holder *first); void freeholder(data_holder *first); void hangup(int filedesc); void send_nak(); int initialize_port(int fd, int action, int baud); void exit_syscatch(); /* globals */ int gfd; int nak_cnt; int nak_err; char gport[256]; char gbaud[256]; main(argc, argv) int argc; char *argv[]; { int filedesc; if(argc < 3) { fprintf(stderr,"Usage: sysguardcatch ttyX baud\n"); exit(1); } if((filedesc = make_ready(argv[1], argv[2])) < 0) { exit(1); } strcpy(gbaud, argv[2]); signal(SIGTERM, exit_syscatch); signal(SIGDANGER, exit_syscatch); gfd = filedesc; monitor_modem(filedesc); } int make_ready(char *tty_name, char *baud_rate) { int filedesc; int baud; unsigned int size; char port[30]; char msg[256]; int i, rc; FILE *fp; strcpy(port, "/dev/"); strcat(port, tty_name); strcpy(gport, port); /* make port name global */ fprintf(stderr,"Making port %s ready\n", port); /* first attempt to lock the port for our exclusive use */ if(ttylock(port) < 0) { fprintf(stderr,"Unable to lock port %s for syscatch.\n", port); fprintf(stderr,"Device may be in use by another process.\n"); fprintf(stderr,"Should we try anyway? (Y or [N]) "); scanf("%c", msg); if(msg[0] != 'Y') return(DATA_ERR_RETURN); } filedesc = open(port, O_RDWR | O_NONBLOCK, 0); if(filedesc < 0) { fprintf(stderr,"%s %s %s\n", "Device open returned", strerror(errno), tty_name); return(DATA_ERR_RETURN); } baud = atoi(baud_rate); initialize_port(filedesc, CLOCAL, baud); /* Initialize the modem. */ alarm(10); get_initstr(msg); /* Write init to modem */ fprintf(stderr,"Modem Init string is %s\n",msg); rc = write(filedesc, msg, strlen(msg)); if(rc < 0) { if(errno == EINTR) { fprintf(stderr,"Time out writing init string\n"); } else { fprintf(stderr,"Failure writing init string, %s\n", strerror(errno)); } ttyunlock(port); exit(1); } alarm(0); /* turn off the alarm */ sleep(1); initialize_port(filedesc, 0, baud); /* drop DTR, hang up the phone */ if(ioctl(filedesc, TIOCMBIC, TIOCM_DTR) < 0) { fprintf(stderr,"Turn OFF of DTR failure"); return(DATA_ERR_RETURN); } sleep(1); /* pause briefly */ /* reassert DTR, make modem ready to answer incoming calls */ if(ioctl(filedesc, TIOCMBIS, TIOCM_DTR) < 0) { fprintf(stderr,"%s %s\n", "Turn on DTR failure", strerror(errno)); return(DATA_ERR_RETURN); } sleep(1); /* pause briefly */ return(filedesc); } void get_initstr(char *str) { #define INITFILE "syscatch_init" #define DFLT_INITSTR "ATE0 Q1 &C1 &D2\r" int i; FILE *fp; i = 0; /* 0 will mean nothing was read in. */ if((fp = fopen(INITFILE, "r")) != NULL) { while(fgets(str,255,fp)) { /* Check for a comment line */ if ((str[0] != '\0') && (str[0] != '\n') && (str[0] != '#')) { /* Not null or a comment, use it. */ strcat(str, "\n"); while((i < 256) && (str[i] != '\0')) { if(str[i] == '\n') str[i] = '\r'; i++; } break; } } /* Make sure we got a message */ if (i==0) { fprintf(stderr,"Could not find an initialization string.\n Using %s\n",DFLT_INITSTR); strcpy(str,DFLT_INITSTR); } fclose(fp); } else { /* Didn't open */ perror(INITFILE); fprintf(stderr,"Using %s\n",DFLT_INITSTR); strcpy(str,DFLT_INITSTR); } } void monitor_modem(int filedesc) { int status; int rc; while(1) /* loop forever */ { if(ioctl(filedesc, TIOCMGET, &status) < 0) { fprintf(stderr,"ERROR on ioctl\n"); return; } if((status & TIOCM_CAR) != 0) { #ifdef DEBUG fprintf(stderr,"Incoming call detected\n"); #endif if(process_call(filedesc) != NORMAL_RETURN) { hangup(filedesc); sleep(5); } } else { sleep(2); } } } int process_call(int filedesc) { data_holder *first_data; sysguard_prob_type *sysguard_prob_data; char *problem_data; unsigned int magic; first_data = receive_prb_data(filedesc); /* don't hangup yet */ if(first_data != NULL) { problem_data = (char *)assemble_data(first_data); } else /* we got an error */ { return(DATA_ERR_RETURN); /* can't do much without the data */ } memcpy(&magic, problem_data, sizeof(unsigned int)); if(magic == BUMP_MAGIC_NUMBER) { hangup(filedesc); /* sysguard can't receive status */ sysguard_prob_data = (sysguard_prob_type *)problem_data; /* now print the received data out */ printf("\nSysguard problem reported:\n"); printf("Login ID: %12.12s Password: %16.16s\n", sysguard_prob_data->login_id, sysguard_prob_data->passwd); printf("Voice Phone: %20.20s Dial In: %20.20s\n", sysguard_prob_data->voice_phone, sysguard_prob_data->callback); printf("Timestamp: %8.8s Error Code: %4.4s\n", sysguard_prob_data->time, sysguard_prob_data->error_code); printf("Type: %4.4s Model: %3.3s Serial: %5.5s\n", sysguard_prob_data->device_type, &sysguard_prob_data->device_type[4], &sysguard_prob_data->device_type[8]); printf("Uname: %10.10s\n", sysguard_prob_data->serial_no); printf("SRN: %64.64s\n", sysguard_prob_data->SRN_LCD); printf("%64.64s\n", sysguard_prob_data->abstract); free(sysguard_prob_data); return(NORMAL_RETURN); } else { fprintf(stderr,"Invalid magic number\n"); hangup(filedesc); /* sysguard can't receive status */ free(problem_data); return(NORMAL_RETURN); } } data_holder *receive_prb_data(int fd) { char ch; char buffer[BUFSIZE]; char ackbuff[10]; int i, j, errcount; int testcnt; int k; int sect; /* sector number received */ int total_sects; int rc; data_holder *first; data_holder *current; sleep(1); ch = NAK; sect = 1; /* start with sector 1 */ total_sects = 0; first = NULL; testcnt = 0; if(write(fd, &ch, 1) < 0) { fprintf(stderr,"Write NAK failure\n"); return(NULL); } do { nak_cnt = 0; signal(SIGALRM, send_nak); alarm(NAK_INTERVAL); nak_err = 0; while(ch != SOH) { if(nak_err) { alarm(0); fprintf(stderr,"Aborting Transfer\n"); sleep(10); return(NULL); } if(read(fd, &ch, 1) < 0) { if(nak_cnt > MAX_NAKS) { fprintf(stderr,"No data received, timing out\n"); return(NULL); } if(errno == EAGAIN) { continue; /* no data was available */ } fprintf(stderr,"%s %s\n", "error reading port", strerror(errno)); return(NULL); } ch = ch & RECEIVE_MASK; if(ch == EOT) { #ifdef DEBUG fprintf(stderr,"Download completed\n"); #endif ch = ACK; #ifdef FAULT_TOLERANCE memset(ackbuff, ch, 10); write(fd, ackbuff, 10); #else write(fd, &ch, 1); #endif sleep(1); alarm(0); return(first); } else { #ifdef DEBUG fprintf(stderr,"%x ", ch); testcnt++; if(testcnt > 20) { testcnt = 0; fprintf(stderr,"\n"); } #endif } } #ifdef DEBUG fprintf(stderr,"SOH received\n"); #endif if(sect > MAX_SECTORS) { fprintf(stderr,"Maximum number of sectors exceeded"); return(first); } i = 0; errcount = 0; alarm(0); do { j = read(fd,&buffer[i],(BUFSIZE - i)); if(j > 0) /* if data was received */ { for(k = i; k < (i + j); k++) buffer[k] &= RECEIVE_MASK; i = i+j; } if(j <= 0) { if(errno != EAGAIN) /* don't count this error */ errcount++; } if(errcount > 10) { fprintf(stderr,"Read error maximum exceeded\n"); return(NULL); } } while (i < BUFSIZE); if((rc = perform_checks(sect, buffer, 1)) == NORMAL_RETURN) { if(total_sects == 0) { first = (data_holder *)malloc(sizeof(data_holder)); if(first == NULL) { fprintf(stderr,"Unable to malloc space for first sector\n"); return(NULL); } first->prev = NULL; current = first; } else { current->nxt = (data_holder *)malloc(sizeof(data_holder)); if(current->nxt == NULL) { fprintf(stderr,"Unable to malloc space for subsequent sector\n"); freeholder(first); /* Free storage */ return(NULL); } current->nxt->prev = current; current = current->nxt; current->nxt = NULL; } memcpy(current->buffer, &buffer[2], SECSIZE); ch = ACK; sect++; total_sects++; if(sect > 255) /* make this work with big data */ { sect = 1; } } else if(rc == DATA_ERR_RETURN) { ch = NAK; } else { ch = ACK; /* used for duplicate sectors only */ } #ifdef FAULT_TOLERANCE memset(ackbuff, ch, 10); if(write(fd, ackbuff, 10) < 0) #else if(write(fd, &ch, 1) < 0) #endif { fprintf(stderr,"Unable to write acknowledgment\n"); freeholder(first); /* Free storage */ return(NULL); } } while(1); } char *assemble_data(data_holder *first) { char *data; data_holder *next; int i; int j; int sectors; /* first count the number of sectors */ sectors = 0; for(next = first; next != NULL; next = next->nxt) sectors++; data = (char *)malloc((sectors + 1) * SECSIZE * sizeof(char)); for(i = 0, next = first; next != NULL; i++) { for(j = 0; j < SECSIZE; j++) { if(next->buffer[j] == '') { next->buffer[j] = '\0'; } } memcpy(&data[i * SECSIZE], next->buffer, SECSIZE); next = next->nxt; } /* now free the linked list */ freeholder(first); return(data); } /* Free the data_holder chain */ void freeholder(data_holder *first) { #ifdef DEBUG fprintf(stderr,"Freeing data_holders\n"); #endif for (; first; first=first->nxt) free(first); } void hangup(int filedesc) { int status; int baud; int attempts; /* drop DTR, hang up the phone */ #ifdef DEBUG fprintf(stderr,"Running hangup\n"); #endif alarm(0); /* turn off alarm clock */ if(ioctl(filedesc, TIOCMBIC, TIOCM_DTR) < 0) { fprintf(stderr,"Turn OFF of DTR failure while hanging up\n"); return; } sleep(1); if(ioctl(filedesc, TIOCMBIS, TIOCM_DTR) < 0) { fprintf(stderr,"Turn ON of DTR failure while hanging up\n"); return; } sleep(1); if(ioctl(filedesc, TIOCMGET, &status) < 0) { fprintf(stderr,"ERROR on ioctl\n"); return; } attempts = 0; while((status & TIOCM_CAR) != 0) { attempts++; if(attempts > 5) { exit_syscatch(); } #ifdef DEBUG fprintf(stderr,"Failure to hang up, exiting...\n"); fprintf(stderr,"We were unable to successfully hang up the phone.\n"); fprintf(stderr,"It may be necessary to hang up manually and restart.\n"); fprintf(stderr,"Attempting software hangup sequence\n"); #endif baud = atoi(gbaud); initialize_port(filedesc, CLOCAL, baud); write(filedesc, "+++", 3); sleep(2); write(filedesc, "ATH\r", 4); sleep(2); initialize_port(filedesc, 0, baud); if(ioctl(filedesc, TIOCMBIC, TIOCM_DTR) < 0) { } if(ioctl(filedesc, TIOCMGET, &status) < 0) { fprintf(stderr,"ERROR on ioctl\n"); return; } } } void send_nak() { char ch; ch = NAK; if(write(gfd, &ch, 1) < 0) { fprintf(stderr,"Error sending NAK\n"); nak_err = 1; return; } nak_cnt++; signal(SIGALRM, send_nak); alarm(NAK_INTERVAL); } int initialize_port(int fd, int action, int baud) { int i; struct termios tty_ctrl; tty_ctrl.c_iflag = IGNPAR | IGNBRK; /* ignore parity errors */ tty_ctrl.c_oflag = 0; /* clear output flag */ tty_ctrl.c_cflag = CREAD; tty_ctrl.c_cc[VINTR] = -1; tty_ctrl.c_cc[VQUIT] = -1; tty_ctrl.c_cc[VERASE] = -1; tty_ctrl.c_cc[VKILL] = -1; tty_ctrl.c_cc[VMIN] = 1; /* minimum number of characters to be read */ tty_ctrl.c_cc[VTIME] = 0; tty_ctrl.c_cc[VEOL2] = -1; for(i = VSUSP; i < NCCS; i++) tty_ctrl.c_cc[i] = -1; switch(baud) { case 1200: tty_ctrl.c_cflag |= B1200; break; case 2400: tty_ctrl.c_cflag |= B2400; break; case 4800: tty_ctrl.c_cflag |= B4800; break; case 9600: tty_ctrl.c_cflag |= B9600; break; case 19200: tty_ctrl.c_cflag |= B19200; break; case 38400: tty_ctrl.c_cflag |= B38400; break; default: tty_ctrl.c_cflag |= B9600; /* set baud */ } tty_ctrl.c_cflag |= CS8; /* 8 data bits */ tty_ctrl.c_cflag &= ~PARENB; /* no parity */ tty_ctrl.c_lflag &= ~ECHO; /* don't echo */ tty_ctrl.c_iflag &= ~(IXON+IXOFF); /* turn off software flow control */ tty_ctrl.c_cc[VSTART] = (char)0x11; /* ctrl-Q */ tty_ctrl.c_cc[VSTOP] = (char)0x13; /* ctrl-S */ if(action == CLOCAL) tty_ctrl.c_cflag |= CLOCAL; if(action == HUPCL) tty_ctrl.c_cflag |= HUPCL; return(tcsetattr(fd, TCSANOW, &tty_ctrl)); } int perform_checks(int sector, char *buffer, int log) { int sectornum; /* received sector number */ int sectornumcomp; /* 1's complement of sector number */ int checksum, calsum; /* received and calculated checksums */ char *bufptr; char msgbuf[80]; sectornum = buffer[0] & RECEIVE_MASK; sectornumcomp = buffer[1] & RECEIVE_MASK; checksum = buffer[BUFSIZE - 1] & RECEIVE_MASK; /* first check sector numbers */ if((sectornum + sectornumcomp) != RECEIVE_MASK) { if(log) { fprintf(stderr,"Invalid sector and complement\n"); } else { fprintf(stderr, "Invalid sector and complement\n"); } return(DATA_ERR_RETURN); } if(sectornum < sector) /* did we already get this one? */ { #ifdef DEBUG fprintf(stderr,"sectornum = %d, sector = %d\n", sectornum, sector); #endif if(log) { fprintf(stderr,"Duplicate sector received, expected %d, received %d", sector, sectornum); } else { fprintf(stderr, "Duplicate sector\n"); } return(DUP_RETURN); /* just go on */ } if(sectornum > sector) { if(log) { fprintf(stderr,"Sector missing\n"); } else { fprintf(stderr, "Sector Missing\n"); } return(DATA_ERR_RETURN); } /* calculate the checksum */ calsum = 0; bufptr = &buffer[2]; while(bufptr < &buffer[2] + SECSIZE) { *bufptr = *bufptr & RECEIVE_MASK; /* keep it to eight bits */ calsum = (calsum + *bufptr); bufptr++; } calsum &= RECEIVE_MASK; if(checksum != calsum) { if(log) { fprintf(stderr,"Checksum error\n"); } else { fprintf(stderr, "Checksum error\n"); } return(DATA_ERR_RETURN); } return(NORMAL_RETURN); } void exit_syscatch() { if(ioctl(gfd, TIOCMBIC, TIOCM_DTR) < 0) { fprintf(stderr,"Turn OFF of DTR failure while hanging up\n"); } close(gfd); if(ttyunlock(gport) < 0) { fprintf(stderr,"Unable to unlock port\n"); } else { fprintf(stderr,"Port %s unlocked, exiting.....\n", gport); } exit(0); }