/********************************************************************\ Name: elog.c Created by: Stefan Ritt Contents: Electronic logbook utility $Log$ Revision 1.10 2002/10/14 08:26:26 midas Made attachment size variable Revision 1.9 2002/08/02 11:01:34 midas Added -r for replies Revision 1.8 2002/07/23 11:31:08 midas Fixed problems with password cookie Revision 1.7 2002/07/08 08:39:38 midas Fixed return code Revision 1.6 2002/06/12 07:52:41 midas Increased text size Revision 1.5 2002/06/11 12:01:45 midas Added -s for subdirectory Revision 1.4 2002/02/25 15:28:01 midas Require -l flag, output better error messages Revision 1.3 2001/12/21 15:28:51 midas Initial version as separate package, corresponds to V1.3.2 \********************************************************************/ #include #include #include #include #include #include #ifdef _MSC_VER #include #include #else #include #include #include #include #include #include #define closesocket(s) close(s) #ifndef O_BINARY #define O_BINARY 0 #endif #endif typedef int INT; #define MAX_ATTACHMENTS 10 #define NAME_LENGTH 100 #define MAX_N_ATTR 20 #define TEXT_SIZE 100000 int verbose; /*------------------------------------------------------------------*/ char *map= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; void base64_encode(char *s, char *d) { unsigned int t, pad; pad = 3 - strlen(s) % 3; while (*s) { t = (*s++) << 16; if (*s) t |= (*s++) << 8; if (*s) t |= (*s++) << 0; *(d+3) = map[t & 63]; t >>= 6; *(d+2) = map[t & 63]; t >>= 6; *(d+1) = map[t & 63]; t >>= 6; *(d+0) = map[t & 63]; d += 4; } *d = 0; while (pad--) *(--d) = '='; } /*------------------------------------------------------------------*/ void sgets(char *string, int size) { char *p; do { p = fgets(string, size, stdin); } while (p == NULL); if (strlen(p) > 0 && p[strlen(p)-1] == '\n') p[strlen(p)-1] = 0; } /*------------------------------------------------------------------*/ char request[100000], response[100000], *content; INT submit_elog(char *host, int port, char *subdir, char *experiment, char *passwd, char *uname, char *upwd, int reply, char attrib_name[MAX_N_ATTR][NAME_LENGTH], char attrib[MAX_N_ATTR][NAME_LENGTH], int n_attr, char *text, char afilename[MAX_ATTACHMENTS][256], char *buffer[MAX_ATTACHMENTS], INT buffer_size[MAX_ATTACHMENTS]) /********************************************************************\ Routine: submit_elog Purpose: Submit an ELog entry Input: char *host Host name where ELog server runs in port ELog server port number char *subdir Subdirectoy to elog server char *passwd Write password char *uname User name char *upwd User password int reply Reply to existing message char *attrib_name Attribute names char *attrib Attribute values char *text Message text char afilename[] File names of attachments char *buffer[] Attachment contents INT buffer_size[] Size of buffer in bytes Function value: EL_SUCCESS Successful completion \********************************************************************/ { int status, sock, i, n, header_length, content_length; struct hostent *phe; struct sockaddr_in bind_addr; char host_name[256], boundary[80], str[80], *p; #if defined( _MSC_VER ) { WSADATA WSAData; /* Start windows sockets */ if ( WSAStartup(MAKEWORD(1,1), &WSAData) != 0) return -1; } #endif /* get local host name */ gethostname(host_name, sizeof(host_name)); phe = gethostbyname(host_name); if (phe == NULL) { perror("Cannot retrieve host name"); return -1; } phe = gethostbyaddr(phe->h_addr, sizeof(int), AF_INET); if (phe == NULL) { perror("Cannot retrieve host name"); return -1; } /* if domain name is not in host name, hope to get it from phe */ if (strchr(host_name, '.') == NULL) strcpy(host_name, phe->h_name); /* create socket */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("cannot create socket"); return -1; } /* compose remote address */ memset(&bind_addr, 0, sizeof(bind_addr)); bind_addr.sin_family = AF_INET; bind_addr.sin_addr.s_addr = 0; bind_addr.sin_port = htons((unsigned short)port); phe = gethostbyname(host); if (phe == NULL) { perror("cannot get host name"); return -1; } memcpy((char *)&(bind_addr.sin_addr), phe->h_addr, phe->h_length); /* connect to server */ status = connect(sock, (void *) &bind_addr, sizeof(bind_addr)); if (status != 0) { printf("Cannot connect to host %s, port %d\n", host, port); return -1; } if (verbose) printf("Successfully connected to host %s, port %d\n", host, port); content_length = 100000; for (i=0 ; i 0) { i = recv(sock, response+n, 10000, 0); if (i > 0) n += i; } response[n] = 0; closesocket(sock); if (verbose) { printf("Response received:\n"); puts(response); } /* check response status */ if (strstr(response, "302 Found")) { if (strstr(response, "Location:")) { strncpy(str, strstr(response, "Location:")+10, sizeof(str)); if (strchr(str, '?')) *strchr(str, '?') = 0; if (strchr(str, '\n')) *strchr(str, '\n') = 0; if (strchr(str, '\r')) *strchr(str, '\r') = 0; printf("Message successfully transmitted, ID=%s\n", str); } else printf("Message successfully transmitted\n"); } else if (strstr(response, "Logbook Selection")) printf("No logbook specified\n"); else if (strstr(response, "enter password")) printf("Missing or invalid password\n"); else if (strstr(response, "login")) printf("Missing or invalid user name/password\n"); else if (strstr(response, "Error: Attribute")) { strncpy(str, strstr(response, "Error: Attribute")+20, sizeof(str)); if (strchr(str, '<')) *strchr(str, '<') = 0; printf("Missing required attribute \"%s\"\n", str); } else printf("Error transmitting message\n"); return 1; } /*------------------------------------------------------------------*/ int main(int argc, char *argv[]) { char str[1000], text[TEXT_SIZE], uname[80], upwd[80]; char host_name[256], logbook[32], textfile[256], password[80], subdir[256]; char *buffer[MAX_ATTACHMENTS], attachment[MAX_ATTACHMENTS][256]; INT att_size[MAX_ATTACHMENTS]; INT i, n, fh, n_att, n_attr, size, port, reply; char attr_name[MAX_N_ATTR][NAME_LENGTH], attrib[MAX_N_ATTR][NAME_LENGTH]; text[0] = textfile[0] = uname[0] = upwd[0] = 0; host_name[0] = logbook[0] = password[0] = subdir[0] = n_att = n_attr = reply = 0; port = 80; for (i=0 ; i= argc || argv[i+1][0] == '-') goto usage; if (argv[i][1] == 'h') strcpy(host_name, argv[++i]); else if (argv[i][1] == 'p') port = atoi(argv[++i]); else if (argv[i][1] == 'l') strcpy(logbook, argv[++i]); else if (argv[i][1] == 'w') strcpy(password, argv[++i]); else if (argv[i][1] == 's') strcpy(subdir, argv[++i]); else if (argv[i][1] == 'u') { strcpy(uname, argv[++i]); strcpy(upwd, argv[++i]); } else if (argv[i][1] == 'a') { strcpy(str, argv[++i]); if (strchr(str, '=')) { strcpy(attrib[n_attr], strchr(str, '=')+1); *strchr(str, '=') = 0; strcpy(attr_name[n_attr], str); n_attr++; } else { printf("Error: Attributes must be supplied in the form \"-a =\".\n"); return 1; } } else if (argv[i][1] == 'f') strcpy(attachment[n_att++], argv[++i]); else if (argv[i][1] == 'r') reply = atoi(argv[++i]); else if (argv[i][1] == 'm') strcpy(textfile, argv[++i]); else { usage: printf("\nusage: elog\n"); printf(" -h [-p port] [-s subdir] Name of host where elogd is running\n"); printf(" -l logbook/experiment Name of logbook or experiment\n"); printf(" [-v] for verbose output\n"); printf(" [-w password] write password defined on server\n"); printf(" [-u username password] user name and password\n"); printf(" [-f ] (up to %d times)\n", MAX_ATTACHMENTS); printf(" -a = (up to %d times)\n", MAX_N_ATTR); printf(" [-r ] Reply to existing message\n"); printf(" -m ] | \n"); printf("\nArguments with blanks must be enclosed in quotes\n"); printf("The elog message can either be submitted on the command line\n"); printf("or in a file with the -m flag. Multiple attributes and attachments\n"); printf("can be supplied\n"); return 1; } } else strcpy(text, argv[i]); } } if (host_name[0] == 0) { printf("Please specify hostname.\n"); return 1; } if (logbook[0] == 0) { printf("Please specify logbook with the \"-l\" flag.\n"); return 1; } if (n_attr == 0) { printf("Please specify attribute(s) with the \"-a\" flag.\n"); return 1; } if (text[0] == 0 && textfile[0] == 0) { printf("Please specify message text either with the \"-m\" flag or directly.\n"); return 1; } /*---- open text file ----*/ if (textfile[0]) { fh = open(textfile, O_RDONLY | O_BINARY); if (fh < 0) { printf("Message file \"%s\" does not exist.\n", textfile); return 1; } size = lseek(fh, 0, SEEK_END); lseek(fh, 0, SEEK_SET); if (size > sizeof(text)-1) { printf("Message file \"%s\" is too long (%d bytes max).\n", textfile, sizeof(text)); return 1; } memset(text, 0, sizeof(text)); i = read(fh, text, size); if (i < size) { printf("Cannot fully read message file \"%s\".\n", textfile); return 1; } close(fh); } /*---- open attachment file ----*/ for (i = 0 ; i 500*1024) { printf("Attachment file \"%s\" is too long (500k max).\n", attachment[i]); return 1; } */ n = read(fh, buffer[i], att_size[i]); if (n < att_size[i]) { printf("Cannot fully read attachment file \"%s\".\n", attachment[i]); return 1; } buffer[i][n] = 0; close(fh); } /* now submit message */ submit_elog(host_name, port, subdir, logbook, password, uname, upwd, reply, attr_name, attrib, n_attr, text, attachment, buffer, att_size); for (i=0 ; i